From f2f5742ba5f6598383075373985be0641a355e59 Mon Sep 17 00:00:00 2001 From: gangphon Date: Tue, 18 Apr 2023 14:14:46 +0800 Subject: [PATCH] ledok --- LedOK/7z/readme.txt | 102 +- LedOK/LedOK.pro | 613 +- .../etc/resources/qsimpleupdater.qrc | 10 +- .../etc/scripts/format-code.bat | 40 +- .../QSimpleUpdater/etc/scripts/format-code.sh | 4 +- LedOK/QSimpleUpdater/include/QSimpleUpdater.h | 238 +- LedOK/QSimpleUpdater/src/Downloader.cpp | 876 +- LedOK/QSimpleUpdater/src/Downloader.h | 202 +- LedOK/QSimpleUpdater/src/Downloader.ui | 428 +- LedOK/QSimpleUpdater/src/QSimpleUpdater.cpp | 866 +- LedOK/QSimpleUpdater/src/Updater.cpp | 996 +-- LedOK/QSimpleUpdater/src/Updater.h | 312 +- LedOK/QSimpleUpdater/tests/Test_Downloader.h | 68 +- .../tests/Test_QSimpleUpdater.h | 68 +- LedOK/QSimpleUpdater/tests/Test_Updater.h | 68 +- LedOK/QSimpleUpdater/tests/main.cpp | 82 +- LedOK/QSimpleUpdater/tutorial/src/Window.cpp | 274 +- LedOK/QSimpleUpdater/tutorial/src/Window.h | 80 +- LedOK/QSimpleUpdater/tutorial/src/main.cpp | 42 +- LedOK/base/aboutdlg.cpp | 86 +- LedOK/base/aboutdlg.h | 24 +- LedOK/base/changepasswordform.cpp | 168 +- LedOK/base/changepasswordform.h | 32 +- LedOK/base/customprogressindicator.cpp | 274 +- LedOK/base/customprogressindicator.h | 232 +- LedOK/base/extendedgroupbox.cpp | 124 +- LedOK/base/extendedgroupbox.h | 64 +- LedOK/base/ffutil.cpp | 196 +- LedOK/base/ffutil.h | 1 - LedOK/base/locolorselector.cpp | 9 +- LedOK/base/lodateselector.cpp | 4 +- LedOK/base/loemptydialog.cpp | 156 +- LedOK/base/loemptydialog.h | 74 +- LedOK/base/loqtreewidget.cpp | 8 +- LedOK/base/pixbmpshowdialog.cpp | 82 +- LedOK/base/pixbmpshowdialog.h | 60 +- LedOK/base/pixbmpshowdialog.ui | 176 +- LedOK/base/qexcel.cpp | 670 +- LedOK/base/qexcel.h | 164 +- LedOK/base/qiplineedit.cpp | 570 +- LedOK/base/qiplineedit.h | 74 +- LedOK/base/readexcel.cpp | 338 +- LedOK/base/readexcel.h | 156 +- LedOK/base/softconfigdialog.cpp | 116 +- LedOK/base/softconfigdialog.h | 30 +- LedOK/base/switchcontrol.cpp | 968 +-- LedOK/base/switchcontrol.h | 460 +- LedOK/base/table.cpp | 18 - LedOK/base/table.h | 67 - LedOK/base/taesclass.cpp | 944 +-- LedOK/base/taesclass.h | 266 +- LedOK/base/updateledset3dialog.cpp | 162 +- LedOK/base/updateledset3dialog.h | 60 +- LedOK/base/updateledset3dialog.ui | 408 +- LedOK/base/updaterdialog.cpp | 38 - LedOK/base/updaterdialog.h | 26 - LedOK/base/updaterdialog.ui | 193 - LedOK/base/waitingdlg.cpp | 111 +- LedOK/base/waitingdlg.h | 50 +- LedOK/base/x_checkboxdelegate.cpp | 232 +- LedOK/base/x_checkboxdelegate.h | 146 +- LedOK/base/x_spinboxdelegate.cpp | 70 +- LedOK/base/x_spinboxdelegate.h | 134 +- LedOK/base/x_timeeditdelegate.cpp | 124 +- LedOK/base/x_timeeditdelegate.h | 150 +- LedOK/base/x_uimsgboxok.cpp | 120 +- LedOK/base/x_uimsgboxok.h | 48 +- LedOK/base/x_uimsgboxok.ui | 486 +- LedOK/basedlg.cpp | 2 +- LedOK/basewin.cpp | 2 +- LedOK/communication/hpptclient.cpp | 386 +- LedOK/communication/hpptclient.h | 92 +- LedOK/communication/taserialthread.cpp | 260 +- LedOK/communication/taserialthread.h | 72 +- LedOK/css.css | 176 + .../controlpowerschedule.cpp | 1112 ++- .../controlpowerschedule.h | 154 +- .../controlpowerschedule.ui | 510 +- LedOK/device/controlpowerwidget.cpp | 155 + LedOK/device/controlpowerwidget.h | 29 + .../controltestwidget.cpp | 1103 ++- .../controltestwidget.h | 134 +- .../controltestwidget.ui | 2032 ++--- .../controlvolumeschedule.cpp | 1058 ++- .../controlvolumeschedule.h | 120 +- .../controlvolumeschedule.ui | 502 +- LedOK/device/controlvolumewidget.cpp | 154 + LedOK/device/controlvolumewidget.h | 31 + LedOK/device/ctrladvancedpanel.cpp | 2436 ++++++ LedOK/device/ctrladvancedpanel.h | 119 + .../ctrlbrightpanel.cpp | 1884 +++-- .../ctrlbrightpanel.h | 12 +- LedOK/device/ctrlhdmipanel.cpp | 424 + LedOK/device/ctrlhdmipanel.h | 38 + LedOK/device/ctrlnetworkpanel.cpp | 1021 +++ LedOK/device/ctrlnetworkpanel.h | 88 + LedOK/device/ctrlpwdpanel.cpp | 253 + LedOK/device/ctrlpwdpanel.h | 30 + .../ctrlverifyclockpanel.cpp | 1818 ++-- .../ctrlverifyclockpanel.h | 6 +- LedOK/{wDevicesManager => device}/ledcard.cpp | 96 +- LedOK/{wDevicesManager => device}/ledcard.h | 118 +- .../specialdlg - 副本.cpp | 150 +- .../specialdlg - 副本.h | 24 +- LedOK/device/upgradeapkdialog.cpp | 647 ++ .../upgradeapkdialog.h | 50 +- LedOK/device/wupgradeapkitem.cpp | 138 + LedOK/device/wupgradeapkitem.h | 68 + LedOK/devicectrlpanel.cpp | 289 +- LedOK/devicectrlpanel.h | 4 +- LedOK/deviceitem.cpp | 300 +- LedOK/deviceitem.h | 6 +- LedOK/devicepanel.cpp | 169 +- LedOK/devicepanel.h | 3 +- LedOK/ffplayer.cpp | 1290 +-- LedOK/ffplayer.h | 525 +- LedOK/globaldefine.cpp | 329 +- LedOK/globaldefine.h | 626 +- LedOK/gqt.h | 244 +- LedOK/gutil/qcore.cpp | 1 + LedOK/gutil/qcore.h | 33 + LedOK/gutil/qgui.cpp | 33 + LedOK/gutil/qgui.h | 301 + LedOK/gutil/qnetwork.cpp | 83 + LedOK/gutil/qnetwork.h | 90 + LedOK/importbninprogramdlg.cpp | 28 +- LedOK/importbninprogramdlg.h | 44 +- LedOK/importbninprogramdlg.ui | 136 +- LedOK/importprogramdlg.ui | 160 +- LedOK/main.cpp | 12 +- LedOK/mainwindow.cpp | 146 +- LedOK/mainwindow.h | 3 +- LedOK/mguangyingpinwidget.cpp | 1734 ++-- LedOK/mguangyingpinwidget.h | 190 +- LedOK/mguangyingpinwidget.ui | 3048 +++---- LedOK/oescreenshot/oeamplifier.cpp | 306 +- LedOK/oescreenshot/oeamplifier.h | 186 +- LedOK/oescreenshot/oecommonhelper.cpp | 282 +- LedOK/oescreenshot/oecommonhelper.h | 256 +- LedOK/oescreenshot/oemodelview.cpp | 172 +- LedOK/oescreenshot/oemodelview.h | 122 +- LedOK/oescreenshot/oescreenshot.cpp | 1536 ++-- LedOK/oescreenshot/oescreenshot.h | 1016 +-- LedOK/passwordindlg.cpp | 74 +- LedOK/passwordindlg.h | 36 +- LedOK/player/digiclock.cpp | 480 +- LedOK/player/digiclock.h | 134 +- LedOK/player/eleanaclock.cpp | 156 +- LedOK/player/eleanaclock.h | 51 +- LedOK/player/elebase.cpp | 2 +- LedOK/player/elebase.h | 40 +- LedOK/player/eleborder.cpp | 152 +- LedOK/player/eleborder.h | 38 +- LedOK/player/elegif.cpp | 64 +- LedOK/player/elegif.h | 42 +- LedOK/player/eleimg.cpp | 28 +- LedOK/player/eleimg.h | 30 +- LedOK/player/elemultipng.cpp | 202 +- LedOK/player/elemultipng.h | 61 +- LedOK/player/elescroll.cpp | 152 +- LedOK/player/elescroll.h | 51 +- LedOK/player/eletimer.cpp | 130 +- LedOK/player/eletimer.h | 62 +- LedOK/player/elevideo - qt.cpp | 76 +- LedOK/player/elevideo - qt.h | 32 +- LedOK/player/elevideo - vlc.cpp | 122 +- LedOK/player/elevideo - vlc.h | 58 +- LedOK/player/elevideo.cpp | 90 +- LedOK/player/elevideo.h | 40 +- LedOK/player/playwin.cpp | 487 +- LedOK/player/playwin.h | 112 +- LedOK/player/posdlg.cpp | 86 +- LedOK/player/posdlg.h | 26 +- LedOK/progpanel.cpp | 207 +- LedOK/progpanel.h | 40 +- LedOK/program/copydirthread.cpp | 32 + LedOK/program/copydirthread.h | 21 + .../{wProgramManager => program}/eaclock.cpp | 396 +- LedOK/program/eaclock.h | 67 + LedOK/{wProgramManager => program}/eaudio.cpp | 7 +- LedOK/{wProgramManager => program}/eaudio.h | 0 LedOK/{wProgramManager => program}/ebase.cpp | 18 +- LedOK/{wProgramManager => program}/ebase.h | 2 +- .../{wProgramManager => program}/edclock.cpp | 50 +- LedOK/{wProgramManager => program}/edclock.h | 6 +- .../{wProgramManager => program}/eenviron.cpp | 56 +- LedOK/{wProgramManager => program}/eenviron.h | 0 LedOK/{wProgramManager => program}/egif.cpp | 0 LedOK/{wProgramManager => program}/egif.h | 0 .../emultiwin.cpp | 62 +- .../{wProgramManager => program}/emultiwin.h | 0 LedOK/{wProgramManager => program}/ephoto.cpp | 12 +- LedOK/{wProgramManager => program}/ephoto.h | 0 LedOK/program/etext.cpp | 819 ++ LedOK/program/etext.h | 56 + LedOK/{wProgramManager => program}/etimer.cpp | 35 +- LedOK/{wProgramManager => program}/etimer.h | 0 LedOK/{wProgramManager => program}/evideo.cpp | 20 +- LedOK/{wProgramManager => program}/evideo.h | 0 LedOK/{wProgramManager => program}/eweb.cpp | 2 +- LedOK/{wProgramManager => program}/eweb.h | 2 +- .../gentmpthread.cpp | 211 +- .../gentmpthread.h | 4 +- .../pageeditor.cpp | 66 +- .../{wProgramManager => program}/pageeditor.h | 0 .../pagelistitem.cpp | 67 +- .../pagelistitem.h | 0 .../progcreatedlg.cpp | 26 +- .../progcreatedlg.h | 4 +- .../progeditorwin.cpp | 170 +- .../progeditorwin.h | 2 +- .../{wProgramManager => program}/progitem.cpp | 92 +- LedOK/{wProgramManager => program}/progitem.h | 5 +- .../sendprogramdialog.cpp | 543 +- .../sendprogramdialog.h | 62 +- .../sendprogthread.cpp | 449 +- .../sendprogthread.h | 1 - .../usbdetectdialog.cpp | 186 +- .../usbdetectdialog.h | 50 +- .../videosplitthread.cpp | 417 +- .../videosplitthread.h | 5 +- .../wplanitem.cpp | 0 .../{wProgramManager => program}/wplanitem.h | 0 .../{wProgramManager => program}/wplanitem.ui | 0 .../wplanlist.cpp | 0 .../{wProgramManager => program}/wplanlist.h | 0 .../wprogrampublishitem.cpp | 4 +- .../wprogrampublishitem.h | 2 +- LedOK/qss.qrc | 6 - LedOK/qss/00_Common.css | 125 - LedOK/qss/10_MainWindow.css | 70 - LedOK/res.qrc | 410 +- LedOK/res/128_128.png | Bin 6983 -> 0 bytes LedOK/res/CheckBoxChecked - 副本 - 副本.png | Bin 617 -> 0 bytes LedOK/res/CheckBoxChecked.png | Bin 479 -> 617 bytes LedOK/res/CheckBoxChecked24.png | Bin 698 -> 0 bytes LedOK/res/CheckBoxUnchecked - 副本 - 副本.png | Bin 177 -> 0 bytes LedOK/res/CheckBoxUnchecked.png | Bin 241 -> 177 bytes LedOK/res/CheckBoxUnchecked24.png | Bin 280 -> 0 bytes LedOK/res/DeviceManager/Lock - 副本.png | Bin 30357 -> 0 bytes LedOK/res/DeviceManager/Transparent.png | Bin 2821 -> 0 bytes LedOK/res/DeviceManager/UnLock - 副本.png | Bin 24287 -> 0 bytes LedOK/res/DeviceManager/图层 4(1).png | Bin 627 -> 0 bytes LedOK/res/DeviceManager/图层 4.png | Bin 973 -> 0 bytes LedOK/res/DeviceManager/图层 5 拷贝.png | Bin 206 -> 0 bytes LedOK/res/DeviceManager/图层 5.png | Bin 203 -> 0 bytes LedOK/res/DeviceManager/矩形 20.png | Bin 114 -> 0 bytes LedOK/res/Logo2.png | Bin 5152 -> 0 bytes LedOK/res/Logo3.png | Bin 5873 -> 0 bytes LedOK/res/Logo44.ico | Bin 67646 -> 0 bytes LedOK/res/Lora.psd | Bin 50845 -> 0 bytes .../EditProgram/AClock/AClock/Aclock1.png | Bin 121264 -> 0 bytes .../EditProgram/AClock/AClock/Aclock10.png | Bin 71759 -> 0 bytes .../EditProgram/AClock/AClock/Aclock2.png | Bin 323913 -> 0 bytes .../EditProgram/AClock/AClock/Aclock3.png | Bin 84814 -> 0 bytes .../EditProgram/AClock/AClock/Aclock4.png | Bin 114215 -> 0 bytes .../EditProgram/AClock/AClock/Aclock5.png | Bin 104043 -> 0 bytes .../EditProgram/AClock/AClock/Aclock6.png | Bin 89846 -> 0 bytes .../EditProgram/AClock/AClock/Aclock7.png | Bin 215941 -> 0 bytes .../EditProgram/AClock/AClock/Aclock9.png | Bin 92283 -> 0 bytes .../EditProgram/AClock/AClock/lang_zh-cn.xml | 459 - .../AClock/AClock/language_zh-cn.xml | 907 -- .../EditProgram/AClock/Aclock1.jpg | Bin 30634 -> 0 bytes .../EditProgram/AClock/Aclock10.jpg | Bin 24229 -> 0 bytes .../EditProgram/AClock/Aclock2.jpg | Bin 50104 -> 0 bytes .../EditProgram/AClock/Aclock3.jpg | Bin 26021 -> 0 bytes .../EditProgram/AClock/Aclock4.jpg | Bin 182501 -> 0 bytes .../EditProgram/AClock/Aclock5.jpg | Bin 80020 -> 0 bytes .../EditProgram/AClock/Aclock6.jpg | Bin 45110 -> 0 bytes .../EditProgram/AClock/Aclock7.jpg | Bin 36848 -> 0 bytes .../EditProgram/AClock/Aclock8.jpg | Bin 17762 -> 0 bytes .../res/ProgramManager/EditProgram/Audio.psd | Bin 33144 -> 0 bytes .../EditProgram/DocAlignHC_s.png | Bin 143 -> 0 bytes .../EditProgram/DocAlignHC_u.png | Bin 148 -> 0 bytes .../EditProgram/DocAlignHL_s.png | Bin 140 -> 0 bytes .../EditProgram/DocAlignHL_u.png | Bin 144 -> 0 bytes .../EditProgram/DocAlignHR_s.png | Bin 141 -> 0 bytes .../EditProgram/DocAlignHR_u.png | Bin 142 -> 0 bytes .../EditProgram/DocAlignVB_s.png | Bin 137 -> 0 bytes .../EditProgram/DocAlignVB_u.png | Bin 140 -> 0 bytes .../EditProgram/DocAlignVC_s.png | Bin 137 -> 0 bytes .../EditProgram/DocAlignVC_u.png | Bin 141 -> 0 bytes .../EditProgram/DocAlignVT_s.png | Bin 136 -> 0 bytes .../EditProgram/DocAlignVT_u.png | Bin 140 -> 0 bytes .../ProgramManager/EditProgram/FontBold_s.png | Bin 407 -> 0 bytes .../ProgramManager/EditProgram/FontBold_u.png | Bin 369 -> 0 bytes .../EditProgram/FontItalics_s.png | Bin 340 -> 0 bytes .../EditProgram/FontItalics_u.png | Bin 315 -> 0 bytes .../EditProgram/FontUnderline_s.png | Bin 333 -> 0 bytes .../EditProgram/FontUnderline_u.png | Bin 305 -> 0 bytes .../EditProgram/RadioChecked.png | Bin 820 -> 0 bytes .../EditProgram/RadioUnchecked.png | Bin 616 -> 0 bytes .../res/ProgramManager/EditProgram/check.png | Bin 880 -> 0 bytes .../EditProgram/preview - 副本.png | Bin 1613 -> 0 bytes .../ProgramManager/EditProgram/uncheck.png | Bin 189 -> 0 bytes LedOK/res/ProgramManager/EditProgram/勾.png | Bin 491 -> 0 bytes .../ProgramManager/EditProgram/图层 11.png | Bin 385 -> 0 bytes .../ProgramManager/EditProgram/圆角矩形 3.png | Bin 177 -> 0 bytes .../EditProgram/圆角矩形 30.png | Bin 1124 -> 0 bytes .../ProgramManager/EditProgram/矩形 17.png | Bin 89 -> 0 bytes .../ProgramManager/EditProgram/矩形 18.png | Bin 75 -> 0 bytes .../EditProgram/矩形 51 拷贝.png | Bin 407 -> 0 bytes .../ProgramManager/EditProgram/矩形 57.png | Bin 114 -> 0 bytes .../res/ProgramManager/EditProgram/组 37.png | Bin 109 -> 0 bytes .../res/ProgramManager/EditProgram/组 41.png | Bin 809 -> 0 bytes .../ProgramManager/EditProgram/组 57(1).png | Bin 182 -> 0 bytes LedOK/res/RadioChecked.png | Bin 343 -> 0 bytes LedOK/res/{DeviceManager => device}/Add.png | Bin .../DeviceNum_All.png | Bin .../DeviceNum_Offline.png | Bin .../DeviceNum_Online.png | Bin .../DeviceNum_Unlogin.png | Bin LedOK/res/{DeviceManager => device}/Equal.png | Bin .../{DeviceManager => device}/FlashArrow.png | Bin LedOK/res/{DeviceManager => device}/Lock.png | Bin .../{DeviceManager => device}/O_Offline.png | Bin .../{DeviceManager => device}/O_Online.png | Bin .../{DeviceManager => device}/O_Unlogin.png | Bin .../res/{DeviceManager => device}/UnLock.png | Bin .../{DeviceManager => device}/bnDetail.png | Bin .../deviceReadbackPic.png | Bin LedOK/res/groupbox-checked.png | Bin 0 -> 571 bytes LedOK/res/groupbox-unchecked.png | Bin 0 -> 860 bytes LedOK/res/{资源 6@10x.png => logo-raw.png} | Bin LedOK/res/next.psd | Bin 114811 -> 0 bytes .../EditProgram => program}/AClock.png | Bin .../EditProgram => program}/Add.png | Bin .../EditProgram => program}/AddPlan.png | Bin .../EditProgram => program}/ArrayBottom.png | Bin .../EditProgram => program}/ArrayHCenter.png | Bin .../EditProgram => program}/ArrayLeft.png | Bin .../EditProgram => program}/ArrayRight.png | Bin .../EditProgram => program}/ArrayTop.png | Bin .../EditProgram => program}/ArrayVCenter.png | Bin .../EditProgram => program}/Audio.png | Bin .../EditProgram => program}/Clean.png | Bin .../EditProgram => program}/CleanPlan.png | Bin .../EditProgram => program}/ColorText.png | Bin .../EditProgram => program}/Copy.png | Bin .../EditProgram => program}/Cut.png | Bin .../EditProgram => program}/DClock.png | Bin .../EditProgram => program}/DateSelect.png | Bin .../EditProgram => program}/DateSelect_e.png | Bin .../DateSelect_enable.png | Bin .../EditProgram => program}/Delete.png | Bin .../EditProgram => program}/Gif.png | Bin .../EditProgram => program}/GoDown.png | Bin .../EditProgram => program}/GoUp.png | Bin .../EditProgram => program}/LayerBottom.png | Bin .../EditProgram => program}/LayerDown.png | Bin .../EditProgram => program}/LayerTop.png | Bin .../EditProgram => program}/LayerUp.png | Bin .../EditProgram => program}/Movie.png | Bin .../EditProgram => program}/Office.png | Bin .../EditProgram => program}/Photo.png | Bin .../EditProgram => program}/Rss.png | Bin .../EditProgram => program}/Save.png | Bin .../EditProgram => program}/SaveAs.png | Bin .../EditProgram => program}/ScaleDown.png | Bin .../EditProgram => program}/ScaleOrg.png | Bin .../EditProgram => program}/ScaleUp.png | Bin .../EditProgram => program}/Send.png | Bin .../EditProgram => program}/Setting.png | Bin .../EditProgram => program}/Temp.png | Bin .../EditProgram => program}/Text.png | Bin LedOK/res/program/TextAlignHC.png | Bin 0 -> 384 bytes LedOK/res/program/TextAlignHL.png | Bin 0 -> 380 bytes LedOK/res/program/TextAlignHR.png | Bin 0 -> 379 bytes LedOK/res/program/TextAlignVB.png | Bin 0 -> 380 bytes LedOK/res/program/TextAlignVC.png | Bin 0 -> 381 bytes LedOK/res/program/TextAlignVT.png | Bin 0 -> 381 bytes .../EditProgram => program}/TileFull.png | Bin .../EditProgram => program}/TileH.png | Bin .../EditProgram => program}/TileV.png | Bin .../EditProgram => program}/Timer.png | Bin .../EditProgram => program}/Weather.png | Bin .../EditProgram => program}/Web.png | Bin .../EditProgram => program}/Window.png | Bin .../bnExport_s.png | Bin .../bnExport_u.png | Bin .../{ProgramManager => program}/bnSearch.png | Bin .../{ProgramManager => program}/bnSend_s.png | Bin .../{ProgramManager => program}/bnSend_u.png | Bin .../EditProgram => program}/preview.png | Bin .../EditProgram => program}/previewStop.png | Bin LedOK/res/random.png | Bin 0 -> 1695 bytes LedOK/res/signal-0.png | Bin 0 -> 730 bytes LedOK/res/signal-1.png | Bin 0 -> 740 bytes LedOK/res/signal-2.png | Bin 0 -> 779 bytes LedOK/res/signal-3.png | Bin 0 -> 826 bytes LedOK/res/signal-4.png | Bin 0 -> 932 bytes LedOK/res/signal-5.png | Bin 0 -> 968 bytes LedOK/synctimer.cpp | 58 +- LedOK/tcpsocket - 副本.cpp | 256 +- LedOK/tcpsocket - 副本.h | 58 +- LedOK/tcpsocket.cpp | 46 - LedOK/tcpsocket.h | 39 - LedOK/test.cpp | 186 +- LedOK/tipdialog.cpp | 416 - LedOK/tipdialog.h | 40 - LedOK/tipdialog.ui | 210 - LedOK/tools.cpp | 331 +- LedOK/tools.h | 14 +- LedOK/translations/app_en.ts | 7276 ++++++++-------- LedOK/translations/app_ja.ts | 7272 ++++++++-------- LedOK/translations/app_zh_CN.ts | 7278 ++++++++-------- LedOK/translations/app_zh_TW.ts | 7380 ++++++++--------- .../wDevicesManager/controlencryptwidget.cpp | 290 - LedOK/wDevicesManager/controlencryptwidget.h | 47 - LedOK/wDevicesManager/controlencryptwidget.ui | 336 - LedOK/wDevicesManager/controlhdmischedule.cpp | 523 -- LedOK/wDevicesManager/controlhdmischedule.h | 76 - LedOK/wDevicesManager/controlhdmischedule.ui | 214 - LedOK/wDevicesManager/controlhdmiwidget.cpp | 172 - LedOK/wDevicesManager/controlhdmiwidget.h | 43 - .../controlnetconfigwidget.cpp | 1571 ---- .../wDevicesManager/controlnetconfigwidget.h | 182 - LedOK/wDevicesManager/controlpowermanual.cpp | 222 - LedOK/wDevicesManager/controlpowermanual.h | 48 - LedOK/wDevicesManager/controlpowermanual.ui | 162 - LedOK/wDevicesManager/controlpowerwidget.cpp | 61 - LedOK/wDevicesManager/controlpowerwidget.h | 36 - LedOK/wDevicesManager/controlpowerwidget.ui | 145 - LedOK/wDevicesManager/controlvolumemanual.cpp | 184 - LedOK/wDevicesManager/controlvolumemanual.h | 48 - LedOK/wDevicesManager/controlvolumemanual.ui | 123 - LedOK/wDevicesManager/controlvolumewidget.cpp | 62 - LedOK/wDevicesManager/controlvolumewidget.h | 34 - LedOK/wDevicesManager/controlvolumewidget.ui | 154 - LedOK/wDevicesManager/ctrladvancedpanel.cpp | 2044 ----- LedOK/wDevicesManager/ctrladvancedpanel.h | 163 - LedOK/wDevicesManager/threadupgradeapk.cpp | 182 - LedOK/wDevicesManager/threadupgradeapk.h | 51 - LedOK/wDevicesManager/upgradeapkdialog.cpp | 493 -- LedOK/wDevicesManager/upgradeapkdialog.ui | 468 -- LedOK/wDevicesManager/wupgradeapkitem.cpp | 525 -- LedOK/wDevicesManager/wupgradeapkitem.h | 91 - LedOK/wProgramManager/eaclock.h | 66 - LedOK/wProgramManager/etext.cpp | 1644 ---- LedOK/wProgramManager/etext.h | 116 - .../threadexportprogrampro.cpp | 161 - .../wProgramManager/threadexportprogrampro.h | 32 - LedOK/wProgramManager/wexportprogramitem.cpp | 64 - LedOK/wProgramManager/wexportprogramitem.h | 24 - LedOK/x_uimsgonlyclosebtn.cpp | 28 +- LedOK/x_uimsgonlyclosebtn.h | 44 +- LedOK/x_uimsgonlyclosebtn.ui | 38 +- .../1080x1920(30hz)/rk_lcd_parameters | 35 + .../1280x720(60hz)/rk_lcd_parameters | 35 + .../1920x1080(30hz)/rk_lcd_parameters | 35 + .../1920x512(60hz)/rk_lcd_parameters | 35 + .../512x1920(60hz)/rk_lcd_parameters | 35 + .../720x1280(60hz)/rk_lcd_parameters | 35 + .../768x1280(60hz)/rk_lcd_parameters | 35 + 454 files changed, 44213 insertions(+), 52971 deletions(-) delete mode 100644 LedOK/base/table.cpp delete mode 100644 LedOK/base/table.h delete mode 100644 LedOK/base/updaterdialog.cpp delete mode 100644 LedOK/base/updaterdialog.h delete mode 100644 LedOK/base/updaterdialog.ui create mode 100644 LedOK/css.css rename LedOK/{wDevicesManager => device}/controlpowerschedule.cpp (97%) rename LedOK/{wDevicesManager => device}/controlpowerschedule.h (95%) rename LedOK/{wDevicesManager => device}/controlpowerschedule.ui (96%) create mode 100644 LedOK/device/controlpowerwidget.cpp create mode 100644 LedOK/device/controlpowerwidget.h rename LedOK/{wDevicesManager => device}/controltestwidget.cpp (97%) rename LedOK/{wDevicesManager => device}/controltestwidget.h (95%) rename LedOK/{wDevicesManager => device}/controltestwidget.ui (97%) rename LedOK/{wDevicesManager => device}/controlvolumeschedule.cpp (97%) rename LedOK/{wDevicesManager => device}/controlvolumeschedule.h (95%) rename LedOK/{wDevicesManager => device}/controlvolumeschedule.ui (96%) create mode 100644 LedOK/device/controlvolumewidget.cpp create mode 100644 LedOK/device/controlvolumewidget.h create mode 100644 LedOK/device/ctrladvancedpanel.cpp create mode 100644 LedOK/device/ctrladvancedpanel.h rename LedOK/{wDevicesManager => device}/ctrlbrightpanel.cpp (74%) rename LedOK/{wDevicesManager => device}/ctrlbrightpanel.h (86%) create mode 100644 LedOK/device/ctrlhdmipanel.cpp create mode 100644 LedOK/device/ctrlhdmipanel.h create mode 100644 LedOK/device/ctrlnetworkpanel.cpp create mode 100644 LedOK/device/ctrlnetworkpanel.h create mode 100644 LedOK/device/ctrlpwdpanel.cpp create mode 100644 LedOK/device/ctrlpwdpanel.h rename LedOK/{wDevicesManager => device}/ctrlverifyclockpanel.cpp (89%) rename LedOK/{wDevicesManager => device}/ctrlverifyclockpanel.h (95%) rename LedOK/{wDevicesManager => device}/ledcard.cpp (97%) rename LedOK/{wDevicesManager => device}/ledcard.h (91%) rename LedOK/{wDevicesManager => device}/specialdlg - 副本.cpp (97%) rename LedOK/{wDevicesManager => device}/specialdlg - 副本.h (93%) create mode 100644 LedOK/device/upgradeapkdialog.cpp rename LedOK/{wDevicesManager => device}/upgradeapkdialog.h (85%) create mode 100644 LedOK/device/wupgradeapkitem.cpp create mode 100644 LedOK/device/wupgradeapkitem.h create mode 100644 LedOK/gutil/qcore.cpp create mode 100644 LedOK/gutil/qcore.h create mode 100644 LedOK/gutil/qgui.cpp create mode 100644 LedOK/gutil/qgui.h create mode 100644 LedOK/gutil/qnetwork.cpp create mode 100644 LedOK/gutil/qnetwork.h create mode 100644 LedOK/program/copydirthread.cpp create mode 100644 LedOK/program/copydirthread.h rename LedOK/{wProgramManager => program}/eaclock.cpp (63%) create mode 100644 LedOK/program/eaclock.h rename LedOK/{wProgramManager => program}/eaudio.cpp (96%) rename LedOK/{wProgramManager => program}/eaudio.h (100%) rename LedOK/{wProgramManager => program}/ebase.cpp (98%) rename LedOK/{wProgramManager => program}/ebase.h (98%) rename LedOK/{wProgramManager => program}/edclock.cpp (89%) rename LedOK/{wProgramManager => program}/edclock.h (88%) rename LedOK/{wProgramManager => program}/eenviron.cpp (94%) rename LedOK/{wProgramManager => program}/eenviron.h (100%) rename LedOK/{wProgramManager => program}/egif.cpp (100%) rename LedOK/{wProgramManager => program}/egif.h (100%) rename LedOK/{wProgramManager => program}/emultiwin.cpp (80%) rename LedOK/{wProgramManager => program}/emultiwin.h (100%) rename LedOK/{wProgramManager => program}/ephoto.cpp (95%) rename LedOK/{wProgramManager => program}/ephoto.h (100%) create mode 100644 LedOK/program/etext.cpp create mode 100644 LedOK/program/etext.h rename LedOK/{wProgramManager => program}/etimer.cpp (89%) rename LedOK/{wProgramManager => program}/etimer.h (100%) rename LedOK/{wProgramManager => program}/evideo.cpp (94%) rename LedOK/{wProgramManager => program}/evideo.h (100%) rename LedOK/{wProgramManager => program}/eweb.cpp (98%) rename LedOK/{wProgramManager => program}/eweb.h (87%) rename LedOK/{wProgramManager => program}/gentmpthread.cpp (78%) rename LedOK/{wProgramManager => program}/gentmpthread.h (91%) rename LedOK/{wProgramManager => program}/pageeditor.cpp (76%) rename LedOK/{wProgramManager => program}/pageeditor.h (100%) rename LedOK/{wProgramManager => program}/pagelistitem.cpp (91%) rename LedOK/{wProgramManager => program}/pagelistitem.h (100%) rename LedOK/{wProgramManager => program}/progcreatedlg.cpp (80%) rename LedOK/{wProgramManager => program}/progcreatedlg.h (81%) rename LedOK/{wProgramManager => program}/progeditorwin.cpp (82%) rename LedOK/{wProgramManager => program}/progeditorwin.h (94%) rename LedOK/{wProgramManager => program}/progitem.cpp (60%) rename LedOK/{wProgramManager => program}/progitem.h (88%) rename LedOK/{wProgramManager => program}/sendprogramdialog.cpp (92%) rename LedOK/{wProgramManager => program}/sendprogramdialog.h (71%) rename LedOK/{wProgramManager => program}/sendprogthread.cpp (96%) rename LedOK/{wProgramManager => program}/sendprogthread.h (96%) rename LedOK/{wProgramManager => program}/usbdetectdialog.cpp (97%) rename LedOK/{wProgramManager => program}/usbdetectdialog.h (95%) rename LedOK/{wProgramManager => program}/videosplitthread.cpp (76%) rename LedOK/{wProgramManager => program}/videosplitthread.h (72%) rename LedOK/{wProgramManager => program}/wplanitem.cpp (100%) rename LedOK/{wProgramManager => program}/wplanitem.h (100%) rename LedOK/{wProgramManager => program}/wplanitem.ui (100%) rename LedOK/{wProgramManager => program}/wplanlist.cpp (100%) rename LedOK/{wProgramManager => program}/wplanlist.h (100%) rename LedOK/{wProgramManager => program}/wprogrampublishitem.cpp (95%) rename LedOK/{wProgramManager => program}/wprogrampublishitem.h (97%) delete mode 100644 LedOK/qss.qrc delete mode 100644 LedOK/qss/00_Common.css delete mode 100644 LedOK/qss/10_MainWindow.css delete mode 100644 LedOK/res/128_128.png delete mode 100644 LedOK/res/CheckBoxChecked - 副本 - 副本.png delete mode 100644 LedOK/res/CheckBoxChecked24.png delete mode 100644 LedOK/res/CheckBoxUnchecked - 副本 - 副本.png delete mode 100644 LedOK/res/CheckBoxUnchecked24.png delete mode 100644 LedOK/res/DeviceManager/Lock - 副本.png delete mode 100644 LedOK/res/DeviceManager/Transparent.png delete mode 100644 LedOK/res/DeviceManager/UnLock - 副本.png delete mode 100644 LedOK/res/DeviceManager/图层 4(1).png delete mode 100644 LedOK/res/DeviceManager/图层 4.png delete mode 100644 LedOK/res/DeviceManager/图层 5 拷贝.png delete mode 100644 LedOK/res/DeviceManager/图层 5.png delete mode 100644 LedOK/res/DeviceManager/矩形 20.png delete mode 100644 LedOK/res/Logo2.png delete mode 100644 LedOK/res/Logo3.png delete mode 100644 LedOK/res/Logo44.ico delete mode 100644 LedOK/res/Lora.psd delete mode 100644 LedOK/res/ProgramManager/EditProgram/AClock/AClock/Aclock1.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/AClock/AClock/Aclock10.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/AClock/AClock/Aclock2.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/AClock/AClock/Aclock3.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/AClock/AClock/Aclock4.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/AClock/AClock/Aclock5.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/AClock/AClock/Aclock6.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/AClock/AClock/Aclock7.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/AClock/AClock/Aclock9.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/AClock/AClock/lang_zh-cn.xml delete mode 100644 LedOK/res/ProgramManager/EditProgram/AClock/AClock/language_zh-cn.xml delete mode 100644 LedOK/res/ProgramManager/EditProgram/AClock/Aclock1.jpg delete mode 100644 LedOK/res/ProgramManager/EditProgram/AClock/Aclock10.jpg delete mode 100644 LedOK/res/ProgramManager/EditProgram/AClock/Aclock2.jpg delete mode 100644 LedOK/res/ProgramManager/EditProgram/AClock/Aclock3.jpg delete mode 100644 LedOK/res/ProgramManager/EditProgram/AClock/Aclock4.jpg delete mode 100644 LedOK/res/ProgramManager/EditProgram/AClock/Aclock5.jpg delete mode 100644 LedOK/res/ProgramManager/EditProgram/AClock/Aclock6.jpg delete mode 100644 LedOK/res/ProgramManager/EditProgram/AClock/Aclock7.jpg delete mode 100644 LedOK/res/ProgramManager/EditProgram/AClock/Aclock8.jpg delete mode 100644 LedOK/res/ProgramManager/EditProgram/Audio.psd delete mode 100644 LedOK/res/ProgramManager/EditProgram/DocAlignHC_s.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/DocAlignHC_u.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/DocAlignHL_s.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/DocAlignHL_u.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/DocAlignHR_s.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/DocAlignHR_u.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/DocAlignVB_s.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/DocAlignVB_u.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/DocAlignVC_s.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/DocAlignVC_u.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/DocAlignVT_s.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/DocAlignVT_u.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/FontBold_s.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/FontBold_u.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/FontItalics_s.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/FontItalics_u.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/FontUnderline_s.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/FontUnderline_u.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/RadioChecked.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/RadioUnchecked.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/check.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/preview - 副本.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/uncheck.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/勾.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/图层 11.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/圆角矩形 3.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/圆角矩形 30.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/矩形 17.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/矩形 18.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/矩形 51 拷贝.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/矩形 57.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/组 37.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/组 41.png delete mode 100644 LedOK/res/ProgramManager/EditProgram/组 57(1).png delete mode 100644 LedOK/res/RadioChecked.png rename LedOK/res/{DeviceManager => device}/Add.png (100%) rename LedOK/res/{DeviceManager => device}/DeviceNum_All.png (100%) rename LedOK/res/{DeviceManager => device}/DeviceNum_Offline.png (100%) rename LedOK/res/{DeviceManager => device}/DeviceNum_Online.png (100%) rename LedOK/res/{DeviceManager => device}/DeviceNum_Unlogin.png (100%) rename LedOK/res/{DeviceManager => device}/Equal.png (100%) rename LedOK/res/{DeviceManager => device}/FlashArrow.png (100%) rename LedOK/res/{DeviceManager => device}/Lock.png (100%) rename LedOK/res/{DeviceManager => device}/O_Offline.png (100%) rename LedOK/res/{DeviceManager => device}/O_Online.png (100%) rename LedOK/res/{DeviceManager => device}/O_Unlogin.png (100%) rename LedOK/res/{DeviceManager => device}/UnLock.png (100%) rename LedOK/res/{DeviceManager => device}/bnDetail.png (100%) rename LedOK/res/{DeviceManager => device}/deviceReadbackPic.png (100%) create mode 100644 LedOK/res/groupbox-checked.png create mode 100644 LedOK/res/groupbox-unchecked.png rename LedOK/res/{资源 6@10x.png => logo-raw.png} (100%) delete mode 100644 LedOK/res/next.psd rename LedOK/res/{ProgramManager/EditProgram => program}/AClock.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/Add.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/AddPlan.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/ArrayBottom.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/ArrayHCenter.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/ArrayLeft.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/ArrayRight.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/ArrayTop.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/ArrayVCenter.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/Audio.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/Clean.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/CleanPlan.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/ColorText.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/Copy.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/Cut.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/DClock.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/DateSelect.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/DateSelect_e.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/DateSelect_enable.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/Delete.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/Gif.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/GoDown.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/GoUp.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/LayerBottom.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/LayerDown.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/LayerTop.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/LayerUp.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/Movie.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/Office.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/Photo.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/Rss.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/Save.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/SaveAs.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/ScaleDown.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/ScaleOrg.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/ScaleUp.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/Send.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/Setting.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/Temp.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/Text.png (100%) create mode 100644 LedOK/res/program/TextAlignHC.png create mode 100644 LedOK/res/program/TextAlignHL.png create mode 100644 LedOK/res/program/TextAlignHR.png create mode 100644 LedOK/res/program/TextAlignVB.png create mode 100644 LedOK/res/program/TextAlignVC.png create mode 100644 LedOK/res/program/TextAlignVT.png rename LedOK/res/{ProgramManager/EditProgram => program}/TileFull.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/TileH.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/TileV.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/Timer.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/Weather.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/Web.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/Window.png (100%) rename LedOK/res/{ProgramManager => program}/bnExport_s.png (100%) rename LedOK/res/{ProgramManager => program}/bnExport_u.png (100%) rename LedOK/res/{ProgramManager => program}/bnSearch.png (100%) rename LedOK/res/{ProgramManager => program}/bnSend_s.png (100%) rename LedOK/res/{ProgramManager => program}/bnSend_u.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/preview.png (100%) rename LedOK/res/{ProgramManager/EditProgram => program}/previewStop.png (100%) create mode 100644 LedOK/res/random.png create mode 100644 LedOK/res/signal-0.png create mode 100644 LedOK/res/signal-1.png create mode 100644 LedOK/res/signal-2.png create mode 100644 LedOK/res/signal-3.png create mode 100644 LedOK/res/signal-4.png create mode 100644 LedOK/res/signal-5.png delete mode 100644 LedOK/tcpsocket.cpp delete mode 100644 LedOK/tcpsocket.h delete mode 100644 LedOK/tipdialog.cpp delete mode 100644 LedOK/tipdialog.h delete mode 100644 LedOK/tipdialog.ui delete mode 100644 LedOK/wDevicesManager/controlencryptwidget.cpp delete mode 100644 LedOK/wDevicesManager/controlencryptwidget.h delete mode 100644 LedOK/wDevicesManager/controlencryptwidget.ui delete mode 100644 LedOK/wDevicesManager/controlhdmischedule.cpp delete mode 100644 LedOK/wDevicesManager/controlhdmischedule.h delete mode 100644 LedOK/wDevicesManager/controlhdmischedule.ui delete mode 100644 LedOK/wDevicesManager/controlhdmiwidget.cpp delete mode 100644 LedOK/wDevicesManager/controlhdmiwidget.h delete mode 100644 LedOK/wDevicesManager/controlnetconfigwidget.cpp delete mode 100644 LedOK/wDevicesManager/controlnetconfigwidget.h delete mode 100644 LedOK/wDevicesManager/controlpowermanual.cpp delete mode 100644 LedOK/wDevicesManager/controlpowermanual.h delete mode 100644 LedOK/wDevicesManager/controlpowermanual.ui delete mode 100644 LedOK/wDevicesManager/controlpowerwidget.cpp delete mode 100644 LedOK/wDevicesManager/controlpowerwidget.h delete mode 100644 LedOK/wDevicesManager/controlpowerwidget.ui delete mode 100644 LedOK/wDevicesManager/controlvolumemanual.cpp delete mode 100644 LedOK/wDevicesManager/controlvolumemanual.h delete mode 100644 LedOK/wDevicesManager/controlvolumemanual.ui delete mode 100644 LedOK/wDevicesManager/controlvolumewidget.cpp delete mode 100644 LedOK/wDevicesManager/controlvolumewidget.h delete mode 100644 LedOK/wDevicesManager/controlvolumewidget.ui delete mode 100644 LedOK/wDevicesManager/ctrladvancedpanel.cpp delete mode 100644 LedOK/wDevicesManager/ctrladvancedpanel.h delete mode 100644 LedOK/wDevicesManager/threadupgradeapk.cpp delete mode 100644 LedOK/wDevicesManager/threadupgradeapk.h delete mode 100644 LedOK/wDevicesManager/upgradeapkdialog.cpp delete mode 100644 LedOK/wDevicesManager/upgradeapkdialog.ui delete mode 100644 LedOK/wDevicesManager/wupgradeapkitem.cpp delete mode 100644 LedOK/wDevicesManager/wupgradeapkitem.h delete mode 100644 LedOK/wProgramManager/eaclock.h delete mode 100644 LedOK/wProgramManager/etext.cpp delete mode 100644 LedOK/wProgramManager/etext.h delete mode 100644 LedOK/wProgramManager/threadexportprogrampro.cpp delete mode 100644 LedOK/wProgramManager/threadexportprogrampro.h delete mode 100644 LedOK/wProgramManager/wexportprogramitem.cpp delete mode 100644 LedOK/wProgramManager/wexportprogramitem.h create mode 100644 LedOK/y50 param/1080x1920(30hz)/rk_lcd_parameters create mode 100644 LedOK/y50 param/1280x720(60hz)/rk_lcd_parameters create mode 100644 LedOK/y50 param/1920x1080(30hz)/rk_lcd_parameters create mode 100644 LedOK/y50 param/1920x512(60hz)/rk_lcd_parameters create mode 100644 LedOK/y50 param/512x1920(60hz)/rk_lcd_parameters create mode 100644 LedOK/y50 param/720x1280(60hz)/rk_lcd_parameters create mode 100644 LedOK/y50 param/768x1280(60hz)/rk_lcd_parameters diff --git a/LedOK/7z/readme.txt b/LedOK/7z/readme.txt index 4437a5c..1f7c2a3 100644 --- a/LedOK/7z/readme.txt +++ b/LedOK/7z/readme.txt @@ -1,51 +1,51 @@ -7-Zip 21.07 ------------ - -7-Zip is a file archiver for Windows. - -7-Zip Copyright (C) 1999-2021 Igor Pavlov. - -The main features of 7-Zip: - - - High compression ratio in the new 7z format - - Supported formats: - - Packing / unpacking: 7z, XZ, BZIP2, GZIP, TAR, ZIP and WIM. - - Unpacking only: AR, ARJ, Base64, CAB, CHM, CPIO, CramFS, DMG, EXT, FAT, GPT, HFS, - IHEX, ISO, LZH, LZMA, MBR, MSI, NSIS, NTFS, QCOW2, RAR, - RPM, SquashFS, UDF, UEFI, VDI, VHD, VHDX, VMDK, XAR and Z. - - Fast compression and decompression - - Self-extracting capability for 7z format - - Strong AES-256 encryption in 7z and ZIP formats - - Integration with Windows Shell - - Powerful File Manager - - Powerful command line version - - Localizations for 90 languages - - -7-Zip is free software distributed under the GNU LGPL (except for unRar code). -Read License.txt for more information about license. - - - This distribution package contains the following files: - - 7zFM.exe - 7-Zip File Manager - 7-zip.dll - Plugin for Windows Shell - 7-zip32.dll - Plugin for Windows Shell (32-bit plugin for 64-bit system) - 7zg.exe - GUI module - 7z.exe - Command line version - 7z.dll - 7-Zip engine module - 7z.sfx - SFX module (Windows version) - 7zCon.sfx - SFX module (Console version) - - License.txt - License information - readme.txt - This file - History.txt - History of 7-Zip - 7-zip.chm - User's Manual in HTML Help format - descript.ion - Description for files - - Lang\en.ttt - English (base) localization file - Lang\*.txt - Localization files - - ---- -End of document +7-Zip 21.07 +----------- + +7-Zip is a file archiver for Windows. + +7-Zip Copyright (C) 1999-2021 Igor Pavlov. + +The main features of 7-Zip: + + - High compression ratio in the new 7z format + - Supported formats: + - Packing / unpacking: 7z, XZ, BZIP2, GZIP, TAR, ZIP and WIM. + - Unpacking only: AR, ARJ, Base64, CAB, CHM, CPIO, CramFS, DMG, EXT, FAT, GPT, HFS, + IHEX, ISO, LZH, LZMA, MBR, MSI, NSIS, NTFS, QCOW2, RAR, + RPM, SquashFS, UDF, UEFI, VDI, VHD, VHDX, VMDK, XAR and Z. + - Fast compression and decompression + - Self-extracting capability for 7z format + - Strong AES-256 encryption in 7z and ZIP formats + - Integration with Windows Shell + - Powerful File Manager + - Powerful command line version + - Localizations for 90 languages + + +7-Zip is free software distributed under the GNU LGPL (except for unRar code). +Read License.txt for more information about license. + + + This distribution package contains the following files: + + 7zFM.exe - 7-Zip File Manager + 7-zip.dll - Plugin for Windows Shell + 7-zip32.dll - Plugin for Windows Shell (32-bit plugin for 64-bit system) + 7zg.exe - GUI module + 7z.exe - Command line version + 7z.dll - 7-Zip engine module + 7z.sfx - SFX module (Windows version) + 7zCon.sfx - SFX module (Console version) + + License.txt - License information + readme.txt - This file + History.txt - History of 7-Zip + 7-zip.chm - User's Manual in HTML Help format + descript.ion - Description for files + + Lang\en.ttt - English (base) localization file + Lang\*.txt - Localization files + + +--- +End of document diff --git a/LedOK/LedOK.pro b/LedOK/LedOK.pro index 9a7adde..baeca29 100644 --- a/LedOK/LedOK.pro +++ b/LedOK/LedOK.pro @@ -1,313 +1,300 @@ -QT += core gui widgets -QT += multimedia -QT += network -QT += concurrent -QT += serialport -QT += opengl -QT += webenginewidgets - -CONFIG += c++20 -CONFIG += lrelease -CONFIG += embed_translations -# CONFIG += console - -# You can also make your code fail to compile if you use deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -TARGET = $$quote(LedOK Express) -VERSION = 1.3.0 -DEFINES += APP_VERSION=\\\"$$VERSION\\\" -msvc { - QMAKE_CXXFLAGS += -execution-charset:utf-8 - QMAKE_CXXFLAGS += -source-charset:utf-8 - - CONFIG += force_debug_info - CONFIG += separate_debug_info -} -win* { - LIBS += -lwinmm - LIBS += -lDbghelp -} -win32 { -QMAKE_LFLAGS += /LARGEADDRESSAWARE -#QMAKE_LFLAGS += -Wl,--large-address-aware -} - -SOURCES += \ - base/aboutdlg.cpp \ - base/changepasswordform.cpp \ - base/customprogressindicator.cpp \ - base/loemptydialog.cpp \ - base/pixbmpshowdialog.cpp \ - base/qiplineedit.cpp \ - base/softconfigdialog.cpp \ - base/switchcontrol.cpp \ - base/taesclass.cpp \ - base/updateledset3dialog.cpp \ - base/updaterdialog.cpp \ - base/x_checkboxdelegate.cpp \ - base/x_spinboxdelegate.cpp \ - base/x_timeeditdelegate.cpp \ - base/x_uimsgboxok.cpp \ - base/extendedgroupbox.cpp \ - base/ffutil.cpp \ - base/locolorselector.cpp \ - base/lodateselector.cpp \ - base/loqtitlebar.cpp \ - base/loqtreewidget.cpp \ - base/table.cpp \ - base/waitingdlg.cpp \ - basedlg.cpp \ - basewin.cpp \ - cfg.cpp \ - communication/hpptclient.cpp \ - communication/taserialthread.cpp \ - devicectrlpanel.cpp \ - deviceitem.cpp \ - devicepanel.cpp \ - ffplayer.cpp \ - globaldefine.cpp \ - main.cpp \ - mainwindow.cpp \ - mguangyingpinwidget.cpp \ - passwordindlg.cpp \ - player/digiclock.cpp \ - player/eleanaclock.cpp \ - player/elebase.cpp \ - player/eleborder.cpp \ - player/elegif.cpp \ - player/eleimg.cpp \ - player/elemultipng.cpp \ - player/elescroll.cpp \ - player/eletimer.cpp \ - player/elevideo.cpp \ - player/playwin.cpp \ - player/posdlg.cpp \ - progpanel.cpp \ - synctimer.cpp \ - tcpsocket.cpp \ - test.cpp \ - tipdialog.cpp \ - tools.cpp \ - wDevicesManager/controlencryptwidget.cpp \ - wDevicesManager/controlhdmischedule.cpp \ - wDevicesManager/controlhdmiwidget.cpp \ - wDevicesManager/controlnetconfigwidget.cpp \ - wDevicesManager/controlpowermanual.cpp \ - wDevicesManager/controlpowerschedule.cpp \ - wDevicesManager/controlpowerwidget.cpp \ - wDevicesManager/controltestwidget.cpp \ - wDevicesManager/controlvolumemanual.cpp \ - wDevicesManager/controlvolumeschedule.cpp \ - wDevicesManager/controlvolumewidget.cpp \ - wDevicesManager/ctrladvancedpanel.cpp \ - wDevicesManager/ctrlbrightpanel.cpp \ - wDevicesManager/ctrlverifyclockpanel.cpp \ - wDevicesManager/ledcard.cpp \ - wDevicesManager/threadupgradeapk.cpp \ - wDevicesManager/upgradeapkdialog.cpp \ - wDevicesManager/wupgradeapkitem.cpp \ - wProgramManager/eaclock.cpp \ - wProgramManager/eaudio.cpp \ - wProgramManager/ebase.cpp \ - wProgramManager/edclock.cpp \ - wProgramManager/eenviron.cpp \ - wProgramManager/egif.cpp \ - wProgramManager/emultiwin.cpp \ - wProgramManager/ephoto.cpp \ - wProgramManager/etext.cpp \ - wProgramManager/etimer.cpp \ - wProgramManager/evideo.cpp \ - wProgramManager/eweb.cpp \ - wProgramManager/gentmpthread.cpp \ - wProgramManager/pageeditor.cpp \ - wProgramManager/pagelistitem.cpp \ - wProgramManager/progcreatedlg.cpp \ - wProgramManager/progeditorwin.cpp \ - wProgramManager/progitem.cpp \ - wProgramManager/sendprogramdialog.cpp \ - wProgramManager/sendprogthread.cpp \ - wProgramManager/threadexportprogrampro.cpp \ - wProgramManager/usbdetectdialog.cpp \ - wProgramManager/videosplitthread.cpp \ - wProgramManager/wexportprogramitem.cpp \ - wProgramManager/wplanitem.cpp \ - wProgramManager/wplanlist.cpp \ - wProgramManager/wprogrampublishitem.cpp \ - -HEADERS += \ - base/aboutdlg.h \ - base/changepasswordform.h \ - base/customprogressindicator.h \ - base/loemptydialog.h \ - base/pixbmpshowdialog.h \ - base/qiplineedit.h \ - base/softconfigdialog.h \ - base/switchcontrol.h \ - base/taesclass.h \ - base/updateledset3dialog.h \ - base/updaterdialog.h \ - base/x_checkboxdelegate.h \ - base/x_spinboxdelegate.h \ - base/x_timeeditdelegate.h \ - base/x_uimsgboxok.h \ - base/extendedgroupbox.h \ - base/locolorselector.h \ - base/lodateselector.h \ - base/loqtitlebar.h \ - base/loqtreewidget.h \ - base/table.h \ - base/waitingdlg.h \ - basedlg.h \ - basewin.h \ - cfg.h \ - communication/hpptclient.h \ - communication/taserialthread.h \ - devicectrlpanel.h \ - deviceitem.h \ - devicepanel.h \ - ffplayer.h \ - globaldefine.h \ - gqt.h \ - mainwindow.h \ - mguangyingpinwidget.h \ - passwordindlg.h \ - player/digiclock.h \ - player/eleanaclock.h \ - player/elebase.h \ - player/eleborder.h \ - player/elegif.h \ - player/eleimg.h \ - player/elemultipng.h \ - player/elescroll.h \ - player/eletimer.h \ - player/elevideo.h \ - player/playwin.h \ - player/posdlg.h \ - progpanel.h \ - synctimer.h \ - tcpsocket.h \ - tipdialog.h \ - tools.h \ - wDevicesManager/controlencryptwidget.h \ - wDevicesManager/controlhdmischedule.h \ - wDevicesManager/controlhdmiwidget.h \ - wDevicesManager/controlnetconfigwidget.h \ - wDevicesManager/controlpowermanual.h \ - wDevicesManager/controlpowerschedule.h \ - wDevicesManager/controlpowerwidget.h \ - wDevicesManager/controltestwidget.h \ - wDevicesManager/controlvolumemanual.h \ - wDevicesManager/controlvolumeschedule.h \ - wDevicesManager/controlvolumewidget.h \ - wDevicesManager/ctrladvancedpanel.h \ - wDevicesManager/ctrlbrightpanel.h \ - wDevicesManager/ctrlverifyclockpanel.h \ - wDevicesManager/ledcard.h \ - wDevicesManager/threadupgradeapk.h \ - wDevicesManager/upgradeapkdialog.h \ - wDevicesManager/wupgradeapkitem.h \ - wProgramManager/eaclock.h \ - wProgramManager/eaudio.h \ - wProgramManager/ebase.h \ - wProgramManager/edclock.h \ - wProgramManager/eenviron.h \ - wProgramManager/egif.h \ - wProgramManager/emultiwin.h \ - wProgramManager/ephoto.h \ - wProgramManager/etext.h \ - wProgramManager/etimer.h \ - wProgramManager/evideo.h \ - wProgramManager/eweb.h \ - wProgramManager/gentmpthread.h \ - wProgramManager/pageeditor.h \ - wProgramManager/pagelistitem.h \ - wProgramManager/progcreatedlg.h \ - wProgramManager/progeditorwin.h \ - wProgramManager/progitem.h \ - wProgramManager/sendprogramdialog.h \ - wProgramManager/sendprogthread.h \ - wProgramManager/threadexportprogrampro.h \ - wProgramManager/usbdetectdialog.h \ - wProgramManager/videosplitthread.h \ - wProgramManager/wexportprogramitem.h \ - wProgramManager/wplanitem.h \ - wProgramManager/wplanlist.h \ - wProgramManager/wprogrampublishitem.h \ - -FORMS += \ - base/pixbmpshowdialog.ui \ - base/updateledset3dialog.ui \ - base/updaterdialog.ui \ - base/x_uimsgboxok.ui \ - mguangyingpinwidget.ui \ - tipdialog.ui \ - wDevicesManager/controlencryptwidget.ui \ - wDevicesManager/controlhdmischedule.ui \ - wDevicesManager/controlpowermanual.ui \ - wDevicesManager/controlpowerschedule.ui \ - wDevicesManager/controlpowerwidget.ui \ - wDevicesManager/controltestwidget.ui \ - wDevicesManager/controlvolumemanual.ui \ - wDevicesManager/controlvolumeschedule.ui \ - wDevicesManager/controlvolumewidget.ui \ - wDevicesManager/upgradeapkdialog.ui \ - wProgramManager/wplanitem.ui \ - -TRANSLATIONS += \ - translations/app_zh_CN.ts \ - translations/app_zh_TW.ts \ - translations/app_ja.ts \ - translations/app_en.ts - -EXTRA_TRANSLATIONS += \ - translations/qt_zh_CN.ts \ - translations/qt_zh_TW.ts \ - translations/qt_ja.ts \ - translations/qt_en.ts - -RESOURCES += \ - res.qrc \ - qss.qrc - -win32:RC_ICONS = res/Logo.ico -osx:ICON = res/Logo.icns - - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - - - -INCLUDEPATH += $$PWD/ffmpeg/include -LIBS += -L$$PWD/ffmpeg/lib/\ - -lavcodec \ - -lavdevice \ - -lavfilter \ - -lavformat \ - -lavutil \ - -lswresample \ - -lswscale - -copy.files += $$files(ffmpeg/bin/*.dll) -copy.files += ffmpeg/bin/ffmpeg.exe - -include(./xlsx/qtxlsx.pri) -include(./QSimpleUpdater/QSimpleUpdater.pri) - -# for https requests -copy2.files += $$files(OpenSSL/*.dll) - -copy.files += 7z/7z.dll -copy.files += 7z/7z.exe - -copy.path = $$OUT_PWD -copy2.path = $$OUT_PWD/release - -CONFIG += file_copies -COPIES += copy -COPIES += copy2 +QT += core gui widgets +QT += multimedia +QT += network +QT += concurrent +QT += serialport +QT += opengl +QT += webenginewidgets + +CONFIG += c++20 +CONFIG += lrelease +CONFIG += embed_translations +# CONFIG += console + +# You can also make your code fail to compile if you use deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +TARGET = $$quote(LedOK Express) +VERSION = 1.3.5 +DEFINES += APP_VERSION=\\\"$$VERSION\\\" +msvc { + QMAKE_CXXFLAGS += -execution-charset:utf-8 + QMAKE_CXXFLAGS += -source-charset:utf-8 + + CONFIG += force_debug_info + CONFIG += separate_debug_info + +# QMAKE_LFLAGS_RELEASE += /MAP +# QMAKE_CFLAGS_RELEASE += /Zi +# QMAKE_LFLAGS_RELEASE += /debug /opt:ref + +# QMAKE_CXXFLAGS_RELEASE += $$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO +# QMAKE_LFLAGS_RELEASE += $$QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO + + LIBS += -lDbgHelp +} +win* { + LIBS += -lwinmm + LIBS += -lDbghelp +} +win32 { +QMAKE_LFLAGS += /LARGEADDRESSAWARE +#QMAKE_LFLAGS += -Wl,--large-address-aware +} + +SOURCES += \ + base/aboutdlg.cpp \ + base/changepasswordform.cpp \ + base/customprogressindicator.cpp \ + base/loemptydialog.cpp \ + base/pixbmpshowdialog.cpp \ + base/qiplineedit.cpp \ + base/softconfigdialog.cpp \ + base/switchcontrol.cpp \ + base/taesclass.cpp \ + base/updateledset3dialog.cpp \ + base/x_checkboxdelegate.cpp \ + base/x_spinboxdelegate.cpp \ + base/x_timeeditdelegate.cpp \ + base/x_uimsgboxok.cpp \ + base/extendedgroupbox.cpp \ + base/ffutil.cpp \ + base/locolorselector.cpp \ + base/lodateselector.cpp \ + base/loqtitlebar.cpp \ + base/loqtreewidget.cpp \ + base/waitingdlg.cpp \ + basedlg.cpp \ + basewin.cpp \ + cfg.cpp \ + communication/hpptclient.cpp \ + communication/taserialthread.cpp \ + device/ctrlhdmipanel.cpp \ + device/ctrlnetworkpanel.cpp \ + device/ctrlpwdpanel.cpp \ + devicectrlpanel.cpp \ + deviceitem.cpp \ + devicepanel.cpp \ + ffplayer.cpp \ + globaldefine.cpp \ + gutil/qgui.cpp \ + gutil/qnetwork.cpp \ + main.cpp \ + mainwindow.cpp \ + mguangyingpinwidget.cpp \ + passwordindlg.cpp \ + player/digiclock.cpp \ + player/eleanaclock.cpp \ + player/elebase.cpp \ + player/eleborder.cpp \ + player/elegif.cpp \ + player/eleimg.cpp \ + player/elemultipng.cpp \ + player/elescroll.cpp \ + player/eletimer.cpp \ + player/elevideo.cpp \ + player/playwin.cpp \ + player/posdlg.cpp \ + progpanel.cpp \ + synctimer.cpp \ + test.cpp \ + tools.cpp \ + device/controlpowerschedule.cpp \ + device/controlpowerwidget.cpp \ + device/controltestwidget.cpp \ + device/controlvolumeschedule.cpp \ + device/controlvolumewidget.cpp \ + device/ctrladvancedpanel.cpp \ + device/ctrlbrightpanel.cpp \ + device/ctrlverifyclockpanel.cpp \ + device/ledcard.cpp \ + device/upgradeapkdialog.cpp \ + device/wupgradeapkitem.cpp \ + program/copydirthread.cpp \ + program/eaclock.cpp \ + program/eaudio.cpp \ + program/ebase.cpp \ + program/edclock.cpp \ + program/eenviron.cpp \ + program/egif.cpp \ + program/emultiwin.cpp \ + program/ephoto.cpp \ + program/etext.cpp \ + program/etimer.cpp \ + program/evideo.cpp \ + program/eweb.cpp \ + program/gentmpthread.cpp \ + program/pageeditor.cpp \ + program/pagelistitem.cpp \ + program/progcreatedlg.cpp \ + program/progeditorwin.cpp \ + program/progitem.cpp \ + program/sendprogramdialog.cpp \ + program/sendprogthread.cpp \ + program/usbdetectdialog.cpp \ + program/videosplitthread.cpp \ + program/wplanitem.cpp \ + program/wplanlist.cpp \ + program/wprogrampublishitem.cpp \ + +HEADERS += \ + base/aboutdlg.h \ + base/changepasswordform.h \ + base/customprogressindicator.h \ + base/loemptydialog.h \ + base/pixbmpshowdialog.h \ + base/qiplineedit.h \ + base/softconfigdialog.h \ + base/switchcontrol.h \ + base/taesclass.h \ + base/updateledset3dialog.h \ + base/x_checkboxdelegate.h \ + base/x_spinboxdelegate.h \ + base/x_timeeditdelegate.h \ + base/x_uimsgboxok.h \ + base/extendedgroupbox.h \ + base/locolorselector.h \ + base/lodateselector.h \ + base/loqtitlebar.h \ + base/loqtreewidget.h \ + base/waitingdlg.h \ + basedlg.h \ + basewin.h \ + cfg.h \ + communication/hpptclient.h \ + communication/taserialthread.h \ + device/ctrlhdmipanel.h \ + device/ctrlnetworkpanel.h \ + device/ctrlpwdpanel.h \ + devicectrlpanel.h \ + deviceitem.h \ + devicepanel.h \ + ffplayer.h \ + globaldefine.h \ + gutil/qgui.h \ + gutil/qnetwork.h \ + mainwindow.h \ + mguangyingpinwidget.h \ + passwordindlg.h \ + player/digiclock.h \ + player/eleanaclock.h \ + player/elebase.h \ + player/eleborder.h \ + player/elegif.h \ + player/eleimg.h \ + player/elemultipng.h \ + player/elescroll.h \ + player/eletimer.h \ + player/elevideo.h \ + player/playwin.h \ + player/posdlg.h \ + progpanel.h \ + synctimer.h \ + tools.h \ + device/controlpowerschedule.h \ + device/controlpowerwidget.h \ + device/controltestwidget.h \ + device/controlvolumeschedule.h \ + device/controlvolumewidget.h \ + device/ctrladvancedpanel.h \ + device/ctrlbrightpanel.h \ + device/ctrlverifyclockpanel.h \ + device/ledcard.h \ + device/upgradeapkdialog.h \ + device/wupgradeapkitem.h \ + program/copydirthread.h \ + program/eaclock.h \ + program/eaudio.h \ + program/ebase.h \ + program/edclock.h \ + program/eenviron.h \ + program/egif.h \ + program/emultiwin.h \ + program/ephoto.h \ + program/etext.h \ + program/etimer.h \ + program/evideo.h \ + program/eweb.h \ + program/gentmpthread.h \ + program/pageeditor.h \ + program/pagelistitem.h \ + program/progcreatedlg.h \ + program/progeditorwin.h \ + program/progitem.h \ + program/sendprogramdialog.h \ + program/sendprogthread.h \ + program/usbdetectdialog.h \ + program/videosplitthread.h \ + program/wplanitem.h \ + program/wplanlist.h \ + program/wprogrampublishitem.h \ + +FORMS += \ + base/pixbmpshowdialog.ui \ + base/updateledset3dialog.ui \ + base/x_uimsgboxok.ui \ + mguangyingpinwidget.ui \ + device/controlpowerschedule.ui \ + device/controltestwidget.ui \ + device/controlvolumeschedule.ui \ + program/wplanitem.ui \ + +TRANSLATIONS += \ + translations/app_zh_CN.ts \ + translations/app_zh_TW.ts \ + translations/app_ja.ts \ + translations/app_en.ts + +EXTRA_TRANSLATIONS += \ + translations/qt_zh_CN.ts \ + translations/qt_zh_TW.ts \ + translations/qt_ja.ts \ + translations/qt_en.ts + +RESOURCES += res.qrc + +win32:RC_ICONS = res/Logo.ico +osx:ICON = res/Logo.icns + + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + + + +INCLUDEPATH += $$PWD/ffmpeg/include +LIBS += -L$$PWD/ffmpeg/lib/\ + -lavcodec \ + -lavdevice \ + -lavfilter \ + -lavformat \ + -lavutil \ + -lswresample \ + -lswscale + +copy.files += $$files(ffmpeg/bin/*.dll) +copy.files += ffmpeg/bin/ffmpeg.exe + +include(./xlsx/qtxlsx.pri) +include(./QSimpleUpdater/QSimpleUpdater.pri) + +# for https requests +copy2.files += $$files(OpenSSL/*.dll) + +copy.files += 7z/7z.dll +copy.files += 7z/7z.exe + +copy.path = $$OUT_PWD +copy2.path = $$OUT_PWD/release + +copy3.files += $$quote(y50 param) +copy3.path = $$OUT_PWD/release + +CONFIG += file_copies +COPIES += copy +COPIES += copy2 +COPIES += copy3 diff --git a/LedOK/QSimpleUpdater/etc/resources/qsimpleupdater.qrc b/LedOK/QSimpleUpdater/etc/resources/qsimpleupdater.qrc index ac0c9e0..19dbb83 100644 --- a/LedOK/QSimpleUpdater/etc/resources/qsimpleupdater.qrc +++ b/LedOK/QSimpleUpdater/etc/resources/qsimpleupdater.qrc @@ -1,5 +1,5 @@ - - - update.png - - + + + update.png + + diff --git a/LedOK/QSimpleUpdater/etc/scripts/format-code.bat b/LedOK/QSimpleUpdater/etc/scripts/format-code.bat index 28ad63f..941bfda 100644 --- a/LedOK/QSimpleUpdater/etc/scripts/format-code.bat +++ b/LedOK/QSimpleUpdater/etc/scripts/format-code.bat @@ -1,20 +1,20 @@ -:: Description: This script changes the style format of -:: all the source code of the project. - -:: Setup the command line -@echo off -title Code Formatter - -:: Go to the directory where the script is run -cd /d %~dp0 - -:: Style and format the source code recursively -astyle --style=linux --indent=spaces --align-pointer=type --indent-preproc-block --indent-preproc-define --indent-col1-comments --pad-first-paren-out --pad-oper --attach-namespaces --remove-brackets --convert-tabs --close-templates --max-code-length=100 --max-instatement-indent=50 --lineend=windows --suffix=none --recursive ../../*.h ../../*.cpp ../../*.c - -:: Notify the user that we have finished -echo. -echo Code styling complete! -echo. - -:: Let the user see the output -pause +:: Description: This script changes the style format of +:: all the source code of the project. + +:: Setup the command line +@echo off +title Code Formatter + +:: Go to the directory where the script is run +cd /d %~dp0 + +:: Style and format the source code recursively +astyle --style=linux --indent=spaces --align-pointer=type --indent-preproc-block --indent-preproc-define --indent-col1-comments --pad-first-paren-out --pad-oper --attach-namespaces --remove-brackets --convert-tabs --close-templates --max-code-length=100 --max-instatement-indent=50 --lineend=windows --suffix=none --recursive ../../*.h ../../*.cpp ../../*.c + +:: Notify the user that we have finished +echo. +echo Code styling complete! +echo. + +:: Let the user see the output +pause diff --git a/LedOK/QSimpleUpdater/etc/scripts/format-code.sh b/LedOK/QSimpleUpdater/etc/scripts/format-code.sh index 5e3408f..8e9e418 100644 --- a/LedOK/QSimpleUpdater/etc/scripts/format-code.sh +++ b/LedOK/QSimpleUpdater/etc/scripts/format-code.sh @@ -1,2 +1,2 @@ -# Style and format recursively -astyle --style=linux --indent=spaces --align-pointer=type --indent-preproc-block --indent-preproc-define --indent-col1-comments --pad-first-paren-out --pad-oper --attach-namespaces --remove-brackets --convert-tabs --close-templates --max-code-length=100 --max-instatement-indent=50 --lineend=windows --suffix=none --recursive ../../*.h ../../*.cpp ../../*.cc +# Style and format recursively +astyle --style=linux --indent=spaces --align-pointer=type --indent-preproc-block --indent-preproc-define --indent-col1-comments --pad-first-paren-out --pad-oper --attach-namespaces --remove-brackets --convert-tabs --close-templates --max-code-length=100 --max-instatement-indent=50 --lineend=windows --suffix=none --recursive ../../*.h ../../*.cpp ../../*.cc diff --git a/LedOK/QSimpleUpdater/include/QSimpleUpdater.h b/LedOK/QSimpleUpdater/include/QSimpleUpdater.h index e5b4da7..673e05d 100644 --- a/LedOK/QSimpleUpdater/include/QSimpleUpdater.h +++ b/LedOK/QSimpleUpdater/include/QSimpleUpdater.h @@ -1,119 +1,119 @@ -/* - * Copyright (c) 2014-2016 Alex Spataru - * - * This file is part of the QSimpleUpdater library, which is released under - * the DBAD license, you can read a copy of it below: - * - * DON'T BE A DICK PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, - * DISTRIBUTION AND MODIFICATION: - * - * Do whatever you like with the original work, just don't be a dick. - * Being a dick includes - but is not limited to - the following instances: - * - * 1a. Outright copyright infringement - Don't just copy this and change the - * name. - * 1b. Selling the unmodified original with no work done what-so-ever, that's - * REALLY being a dick. - * 1c. Modifying the original work to contain hidden harmful content. - * That would make you a PROPER dick. - * - * If you become rich through modifications, related works/services, or - * supporting the original work, share the love. - * Only a dick would make loads off this work and not buy the original works - * creator(s) a pint. - * - * Code is provided with no warranty. Using somebody else's code and bitching - * when it goes wrong makes you a DONKEY dick. - * Fix the problem yourself. A non-dick would submit the fix back. - */ - -#ifndef _QSIMPLEUPDATER_MAIN_H -#define _QSIMPLEUPDATER_MAIN_H - -#include -#include -#include - -#if defined (QSU_SHARED) - #define QSU_DECL Q_DECL_EXPORT -#elif defined (QSU_IMPORT) - #define QSU_DECL Q_DECL_IMPORT -#else - #define QSU_DECL -#endif - -class Updater; - -/** - * \brief Manages the updater instances - * - * The \c QSimpleUpdater class manages the updater system and allows for - * parallel application modules to check for updates and download them. - * - * The behavior of each updater can be regulated by specifying the update - * definitions URL (from where we download the individual update definitions) - * and defining the desired options by calling the individual "setter" - * functions (e.g. \c setNotifyOnUpdate()). - * - * The \c QSimpleUpdater also implements an integrated downloader. - * If you need to use a custom install procedure/code, just create a function - * that is called when the \c downloadFinished() signal is emitted to - * implement your own install procedures. - * - * By default, the downloader will try to open the file as if you opened it - * from a file manager or a web browser (with the "file:*" url). - */ -class QSU_DECL QSimpleUpdater : public QObject -{ - Q_OBJECT - -signals: - void checkingFinished (const QString& url); - void appcastDownloaded (const QString& url, const QByteArray& data); - void downloadFinished (const QString& url, const QString& filepath); - -public: - static QSimpleUpdater* getInstance(); - - bool usesCustomAppcast (const QString& url) const; - bool getNotifyOnUpdate (const QString& url) const; - bool getNotifyOnFinish (const QString& url) const; - bool getUpdateAvailable (const QString& url) const; - bool getUpdateSameVersionAvailable (const QString& url) const; - - bool getDownloaderEnabled (const QString& url) const; - bool usesCustomInstallProcedures (const QString& url) const; - - QString getOpenUrl (const QString& url) const; - QString getChangelog (const QString& url) const; - QString getModuleName (const QString& url) const; - QString getDownloadUrl (const QString& url) const; - QString getPlatformKey (const QString& url) const; - QString getLatestVersion (const QString& url) const; - QString getModuleVersion (const QString& url) const; - QString getUserAgentString (const QString& url) const; - -public slots: - void checkForUpdates (const QString& url); - void setModuleName (const QString& url, const QString& name); - void setNotifyOnUpdate (const QString& url, const bool notify); - void setNotifyOnFinish (const QString& url, const bool notify); - void setPlatformKey (const QString& url, const QString& platform); - void setModuleVersion (const QString& url, const QString& version); - void setDownloaderEnabled (const QString& url, const bool enabled); - void setUserAgentString (const QString& url, const QString& agent); - void setUseCustomAppcast (const QString& url, const bool customAppcast); - void setUseCustomInstallProcedures (const QString& url, const bool custom); - void setNoNotifyDownload (const QString& url, const bool custom); - void setCompareBySameString (const QString& url, const bool custom); - - void setMandatoryUpdate (const QString& url, const bool mandatory_update); - -protected: - ~QSimpleUpdater(); - -private: - Updater* getUpdater (const QString& url) const; -}; - -#endif +/* + * Copyright (c) 2014-2016 Alex Spataru + * + * This file is part of the QSimpleUpdater library, which is released under + * the DBAD license, you can read a copy of it below: + * + * DON'T BE A DICK PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, + * DISTRIBUTION AND MODIFICATION: + * + * Do whatever you like with the original work, just don't be a dick. + * Being a dick includes - but is not limited to - the following instances: + * + * 1a. Outright copyright infringement - Don't just copy this and change the + * name. + * 1b. Selling the unmodified original with no work done what-so-ever, that's + * REALLY being a dick. + * 1c. Modifying the original work to contain hidden harmful content. + * That would make you a PROPER dick. + * + * If you become rich through modifications, related works/services, or + * supporting the original work, share the love. + * Only a dick would make loads off this work and not buy the original works + * creator(s) a pint. + * + * Code is provided with no warranty. Using somebody else's code and bitching + * when it goes wrong makes you a DONKEY dick. + * Fix the problem yourself. A non-dick would submit the fix back. + */ + +#ifndef _QSIMPLEUPDATER_MAIN_H +#define _QSIMPLEUPDATER_MAIN_H + +#include +#include +#include + +#if defined (QSU_SHARED) + #define QSU_DECL Q_DECL_EXPORT +#elif defined (QSU_IMPORT) + #define QSU_DECL Q_DECL_IMPORT +#else + #define QSU_DECL +#endif + +class Updater; + +/** + * \brief Manages the updater instances + * + * The \c QSimpleUpdater class manages the updater system and allows for + * parallel application modules to check for updates and download them. + * + * The behavior of each updater can be regulated by specifying the update + * definitions URL (from where we download the individual update definitions) + * and defining the desired options by calling the individual "setter" + * functions (e.g. \c setNotifyOnUpdate()). + * + * The \c QSimpleUpdater also implements an integrated downloader. + * If you need to use a custom install procedure/code, just create a function + * that is called when the \c downloadFinished() signal is emitted to + * implement your own install procedures. + * + * By default, the downloader will try to open the file as if you opened it + * from a file manager or a web browser (with the "file:*" url). + */ +class QSU_DECL QSimpleUpdater : public QObject +{ + Q_OBJECT + +signals: + void checkingFinished (const QString& url); + void appcastDownloaded (const QString& url, const QByteArray& data); + void downloadFinished (const QString& url, const QString& filepath); + +public: + static QSimpleUpdater* getInstance(); + + bool usesCustomAppcast (const QString& url) const; + bool getNotifyOnUpdate (const QString& url) const; + bool getNotifyOnFinish (const QString& url) const; + bool getUpdateAvailable (const QString& url) const; + bool getUpdateSameVersionAvailable (const QString& url) const; + + bool getDownloaderEnabled (const QString& url) const; + bool usesCustomInstallProcedures (const QString& url) const; + + QString getOpenUrl (const QString& url) const; + QString getChangelog (const QString& url) const; + QString getModuleName (const QString& url) const; + QString getDownloadUrl (const QString& url) const; + QString getPlatformKey (const QString& url) const; + QString getLatestVersion (const QString& url) const; + QString getModuleVersion (const QString& url) const; + QString getUserAgentString (const QString& url) const; + +public slots: + void checkForUpdates (const QString& url); + void setModuleName (const QString& url, const QString& name); + void setNotifyOnUpdate (const QString& url, const bool notify); + void setNotifyOnFinish (const QString& url, const bool notify); + void setPlatformKey (const QString& url, const QString& platform); + void setModuleVersion (const QString& url, const QString& version); + void setDownloaderEnabled (const QString& url, const bool enabled); + void setUserAgentString (const QString& url, const QString& agent); + void setUseCustomAppcast (const QString& url, const bool customAppcast); + void setUseCustomInstallProcedures (const QString& url, const bool custom); + void setNoNotifyDownload (const QString& url, const bool custom); + void setCompareBySameString (const QString& url, const bool custom); + + void setMandatoryUpdate (const QString& url, const bool mandatory_update); + +protected: + ~QSimpleUpdater(); + +private: + Updater* getUpdater (const QString& url) const; +}; + +#endif diff --git a/LedOK/QSimpleUpdater/src/Downloader.cpp b/LedOK/QSimpleUpdater/src/Downloader.cpp index 4f24641..77821ad 100644 --- a/LedOK/QSimpleUpdater/src/Downloader.cpp +++ b/LedOK/QSimpleUpdater/src/Downloader.cpp @@ -1,438 +1,438 @@ -/* - * Copyright (c) 2014-2016 Alex Spataru - * Copyright (c) 2017 Gilmanov Ildar - * - * This file is part of the QSimpleUpdater library, which is released under - * the DBAD license, you can read a copy of it below: - * - * DON'T BE A DICK PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, - * DISTRIBUTION AND MODIFICATION: - * - * Do whatever you like with the original work, just don't be a dick. - * Being a dick includes - but is not limited to - the following instances: - * - * 1a. Outright copyright infringement - Don't just copy this and change the - * name. - * 1b. Selling the unmodified original with no work done what-so-ever, that's - * REALLY being a dick. - * 1c. Modifying the original work to contain hidden harmful content. - * That would make you a PROPER dick. - * - * If you become rich through modifications, related works/services, or - * supporting the original work, share the love. - * Only a dick would make loads off this work and not buy the original works - * creator(s) a pint. - * - * Code is provided with no warranty. Using somebody else's code and bitching - * when it goes wrong makes you a DONKEY dick. - * Fix the problem yourself. A non-dick would submit the fix back. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "Downloader.h" - -static const QString PARTIAL_DOWN (".part"); -extern QWidget *gMainWin; - -Downloader::Downloader (QWidget* parent) : QDialog (parent) { - setWindowFlag(Qt::WindowContextHelpButtonHint, false); - m_ui = new Ui::Downloader; - m_ui->setupUi (this); - //m_ui->label->setText(tr("Software update")); - /* Initialize private members */ - m_manager = new QNetworkAccessManager(); - - /* Initialize internal values */ - m_url = ""; - m_fileName = ""; - m_startTime = 0; - m_useCustomProcedures = false; - m_mandatoryUpdate = false; - - /* Set download directory */ - //m_downloadDir.setPath(QDir::homePath() + "/Downloads/"); - m_downloadDir.setPath(QCoreApplication::applicationDirPath() + "/Downloads/"); - - /* Make the window look like a modal dialog */ - // setWindowIcon (QIcon()); - // setWindowFlags (Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint); - - /* Configure the appearance and behavior of the buttons */ - m_ui->openButton->setEnabled (false); - m_ui->openButton->setVisible (false); - connect (m_ui->stopButton, SIGNAL (clicked()), - this, SLOT (cancelDownload())); - connect (m_ui->openButton, SIGNAL (clicked()), - this, SLOT (installUpdate())); - - /* Resize to fit */ - setFixedSize (minimumSizeHint()); - setStyleSheet("background-color: #D8D8D8"); -} - -Downloader::~Downloader() -{ - delete m_ui; - delete m_reply; - delete m_manager; -} - -/** - * Returns \c true if the updater shall not intervene when the download has - * finished (you can use the \c QSimpleUpdater signals to know when the - * download is completed). - */ -bool Downloader::useCustomInstallProcedures() const -{ - return m_useCustomProcedures; -} - -/** - * Changes the URL, which is used to indentify the downloader dialog - * with an \c Updater instance - * - * \note the \a url parameter is not the download URL, it is the URL of - * the AppCast file - */ -void Downloader::setUrlId (const QString& url) -{ - m_url = url; -} - -/** - * Begins downloading the file at the given \a url - */ -void Downloader::startDownload (const QUrl& url) -{ - - /* Reset UI */ - m_ui->progressBar->setValue (0); - m_ui->stopButton->setText (tr ("Stop")); - m_ui->downloadLabel->setText (tr ("Downloading updates")); - m_ui->timeLabel->setText (tr ("Time remaining") + ": " + tr ("unknown")); - - /* Configure the network request */ - QNetworkRequest request (url); - if (!m_userAgentString.isEmpty()) - request.setRawHeader ("User-Agent", m_userAgentString.toUtf8()); - - /* Start download */ - m_reply = m_manager->get (request); - m_startTime = QDateTime::currentDateTime().toTime_t(); - - /* Ensure that downloads directory exists */ - if (!m_downloadDir.exists()) - m_downloadDir.mkpath("."); - - /* Remove old downloads */ - QFile::remove (m_downloadDir.filePath (m_fileName)); - QFile::remove (m_downloadDir.filePath (m_fileName + PARTIAL_DOWN)); - - /* Update UI when download progress changes or download finishes */ - connect (m_reply, SIGNAL (downloadProgress (qint64, qint64)), - this, SLOT (updateProgress (qint64, qint64))); - connect (m_reply, SIGNAL (finished ()), - this, SLOT (finished ())); - connect (m_reply, SIGNAL (redirected (QUrl)), - this, SLOT (startDownload (QUrl))); - - showNormal(); -} - -/** - * Changes the name of the downloaded file - */ -void Downloader::setFileName (const QString& file) -{ - m_fileName = file; - - if (m_fileName.isEmpty()) - m_fileName = "QSU_Update.bin"; -} - -/** - * Changes the user-agent string used to communicate with the remote HTTP server - */ -void Downloader::setUserAgentString (const QString& agent) -{ - m_userAgentString = agent; -} -void Downloader::finished() -{ - /* Rename file */ - QFile::rename (m_downloadDir.filePath (m_fileName + PARTIAL_DOWN), - m_downloadDir.filePath (m_fileName)); - - /* Notify application */ - emit downloadFinished (m_url, m_downloadDir.filePath (m_fileName)); - /* Install the update */ - m_reply->close(); - installUpdate(); - setVisible (false); -} - -/** - * Opens the downloaded file. - * \note If the downloaded file is not found, then the function will alert the - * user about the error. - */ -void Downloader::openDownload() { - if(!m_fileName.isEmpty()) QDesktopServices::openUrl(QUrl::fromLocalFile(m_downloadDir.filePath(m_fileName))); - else QMessageBox::critical (gMainWin, tr("Error"), tr("Cannot find downloaded update!"), QMessageBox::Close); -} - -/** - * Instructs the OS to open the downloaded file. - * - * \note If \c useCustomInstallProcedures() returns \c true, the function will - * not instruct the OS to open the downloaded file. You can use the - * signals fired by the \c QSimpleUpdater to install the update with your - * own implementations/code. - */ -void Downloader::installUpdate(){ - if (useCustomInstallProcedures()){ - return; - } - - /* Update labels */ - m_ui->stopButton->setText (tr ("Close")); - m_ui->downloadLabel->setText (tr ("Download complete!")); - m_ui->timeLabel->setText (tr ("The installer will open separately") - + "..."); - - /* Ask the user to install the download */ -// QMessageBox box; -// box.setIcon (QMessageBox::Question); -// box.setDefaultButton (QMessageBox::Ok); -// box.setStandardButtons (QMessageBox::Ok | QMessageBox::Cancel); -// box.setInformativeText (tr ("Click \"OK\" to begin installing the update")); - - QString text = m_mandatoryUpdate ? tr("In order to install the update, you may need to quit the application. This is a mandatory update, exiting now will close the application") : tr("In order to install the update "); - auto res = QMessageBox::information(gMainWin, tr("Tip Info"), text, QMessageBox::Ok, QMessageBox::Cancel); - if(m_mandatoryUpdate) QApplication::quit(); - if(res == QMessageBox::Ok) { - if(!useCustomInstallProcedures()) openDownload(); - } else { - m_ui->openButton->setEnabled (true); - m_ui->openButton->setVisible (true); - m_ui->timeLabel->setText (tr ("Click the \"Open\" button to " - "apply the update")); - } -} - -/** - * Prompts the user if he/she wants to cancel the download and cancels the - * download if the user agrees to do that. - */ -void Downloader::cancelDownload() -{ - if (!m_reply->isFinished()) { - QMessageBox box; - box.setWindowTitle (tr ("Updater")); - box.setIcon (QMessageBox::Question); - box.setStandardButtons (QMessageBox::Yes | QMessageBox::No); - - QString text = tr("Are you sure you want to cancel the download?"); - if (m_mandatoryUpdate) - { - text = tr("Are you sure you want to cancel the download? This is a mandatory update, exiting now will close the application"); - } - box.setText (text); - - if (box.exec() == QMessageBox::Yes) { - hide(); - m_reply->abort(); - if(m_mandatoryUpdate) - QApplication::quit(); - } - } - else - { - if(m_mandatoryUpdate) - QApplication::quit(); - - hide(); - } -} - -/** - * Writes the downloaded data to the disk - */ -void Downloader::saveFile (qint64 received, qint64 total) -{ - Q_UNUSED (received); - Q_UNUSED (total); - - /* Check if we need to redirect */ - QUrl url = m_reply->attribute ( - QNetworkRequest::RedirectionTargetAttribute).toUrl(); - if (!url.isEmpty()) { - startDownload (url); - return; - } - - /* Save downloaded data to disk */ - QFile file (m_downloadDir.filePath (m_fileName + PARTIAL_DOWN)); - if (file.open (QIODevice::WriteOnly | QIODevice::Append)) { - file.write (m_reply->readAll()); - file.close(); - } -} - - -/** - * Calculates the appropiate size units (bytes, KB or MB) for the received - * data and the total download size. Then, this function proceeds to update the - * dialog controls/UI. - */ -void Downloader::calculateSizes (qint64 received, qint64 total) -{ - QString totalSize; - QString receivedSize; - - if (total < 1024) - totalSize = tr ("%1 bytes").arg (total); - - else if (total < 1048576) - totalSize = tr ("%1 KB").arg (round (total / 1024)); - - else - totalSize = tr ("%1 MB").arg (round (total / 1048576)); - - if (received < 1024) - receivedSize = tr ("%1 bytes").arg (received); - - else if (received < 1048576) - receivedSize = tr ("%1 KB").arg (received / 1024); - - else - receivedSize = tr ("%1 MB").arg (received / 1048576); - - m_ui->downloadLabel->setText (tr ("Downloading updates") - + " (" + receivedSize + " " + tr ("of") - + " " + totalSize + ")"); -} - -/** - * Uses the \a received and \a total parameters to get the download progress - * and update the progressbar value on the dialog. - */ -void Downloader::updateProgress (qint64 received, qint64 total) -{ - if (total > 0) { - m_ui->progressBar->setMinimum (0); - m_ui->progressBar->setMaximum (100); - m_ui->progressBar->setValue ((received * 100) / total); - - calculateSizes (received, total); - calculateTimeRemaining (received, total); - saveFile (received, total); - } - - else { - m_ui->progressBar->setMinimum (0); - m_ui->progressBar->setMaximum (0); - m_ui->progressBar->setValue (-1); - m_ui->downloadLabel->setText (tr ("Downloading Updates") + "..."); - m_ui->timeLabel->setText (QString ("%1: %2") - .arg (tr ("Time Remaining")) - .arg (tr ("Unknown"))); - } -} - -/** - * Uses two time samples (from the current time and a previous sample) to - * calculate how many bytes have been downloaded. - * - * Then, this function proceeds to calculate the appropiate units of time - * (hours, minutes or seconds) and constructs a user-friendly string, which - * is displayed in the dialog. - */ -void Downloader::calculateTimeRemaining (qint64 received, qint64 total) -{ - uint difference = QDateTime::currentDateTime().toTime_t() - m_startTime; - - if (difference > 0) { - QString timeString; - qreal timeRemaining = (total - received) / (received / difference); - - if (timeRemaining > 7200) { - timeRemaining /= 3600; - int hours = int (timeRemaining + 0.5); - - if (hours > 1) - timeString = tr ("about %1 hours").arg (hours); - else - timeString = tr ("about one hour"); - } - - else if (timeRemaining > 60) { - timeRemaining /= 60; - int minutes = int (timeRemaining + 0.5); - - if (minutes > 1) - timeString = tr ("%1 minutes").arg (minutes); - else - timeString = tr ("1 minute"); - } - - else if (timeRemaining <= 60) { - int seconds = int (timeRemaining + 0.5); - - if (seconds > 1) - timeString = tr ("%1 seconds").arg (seconds); - else - timeString = tr ("1 second"); - } - - m_ui->timeLabel->setText (tr ("Time remaining") + ": " + timeString); - } -} - -/** - * Rounds the given \a input to two decimal places - */ -qreal Downloader::round (const qreal& input) -{ - return static_cast(roundf (static_cast(input) * 100) / 100); -} - -QString Downloader::downloadDir() const -{ - return m_downloadDir.absolutePath(); -} - -void Downloader::setDownloadDir (const QString& downloadDir) -{ - if (m_downloadDir.absolutePath() != downloadDir) - m_downloadDir.setPath(downloadDir); -} - -/** - * If the \a mandatory_update is set to \c true, the \c Downloader has to download and install the - * update. If the user cancels or exits, the application will close - */ -void Downloader::setMandatoryUpdate(const bool mandatory_update) -{ - m_mandatoryUpdate = mandatory_update; -} - -/** - * If the \a custom parameter is set to \c true, then the \c Downloader will not - * attempt to open the downloaded file. - * - * Use the signals fired by the \c QSimpleUpdater to implement your own install - * procedures. - */ -void Downloader::setUseCustomInstallProcedures (const bool custom) -{ - m_useCustomProcedures = custom; -} +/* + * Copyright (c) 2014-2016 Alex Spataru + * Copyright (c) 2017 Gilmanov Ildar + * + * This file is part of the QSimpleUpdater library, which is released under + * the DBAD license, you can read a copy of it below: + * + * DON'T BE A DICK PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, + * DISTRIBUTION AND MODIFICATION: + * + * Do whatever you like with the original work, just don't be a dick. + * Being a dick includes - but is not limited to - the following instances: + * + * 1a. Outright copyright infringement - Don't just copy this and change the + * name. + * 1b. Selling the unmodified original with no work done what-so-ever, that's + * REALLY being a dick. + * 1c. Modifying the original work to contain hidden harmful content. + * That would make you a PROPER dick. + * + * If you become rich through modifications, related works/services, or + * supporting the original work, share the love. + * Only a dick would make loads off this work and not buy the original works + * creator(s) a pint. + * + * Code is provided with no warranty. Using somebody else's code and bitching + * when it goes wrong makes you a DONKEY dick. + * Fix the problem yourself. A non-dick would submit the fix back. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Downloader.h" + +static const QString PARTIAL_DOWN (".part"); +extern QWidget *gMainWin; + +Downloader::Downloader (QWidget* parent) : QDialog (parent) { + setWindowFlag(Qt::WindowContextHelpButtonHint, false); + m_ui = new Ui::Downloader; + m_ui->setupUi (this); + //m_ui->label->setText(tr("Software update")); + /* Initialize private members */ + m_manager = new QNetworkAccessManager(); + + /* Initialize internal values */ + m_url = ""; + m_fileName = ""; + m_startTime = 0; + m_useCustomProcedures = false; + m_mandatoryUpdate = false; + + /* Set download directory */ + //m_downloadDir.setPath(QDir::homePath() + "/Downloads/"); + m_downloadDir.setPath(QCoreApplication::applicationDirPath() + "/Downloads/"); + + /* Make the window look like a modal dialog */ + // setWindowIcon (QIcon()); + // setWindowFlags (Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint); + + /* Configure the appearance and behavior of the buttons */ + m_ui->openButton->setEnabled (false); + m_ui->openButton->setVisible (false); + connect (m_ui->stopButton, SIGNAL (clicked()), + this, SLOT (cancelDownload())); + connect (m_ui->openButton, SIGNAL (clicked()), + this, SLOT (installUpdate())); + + /* Resize to fit */ + setFixedSize (minimumSizeHint()); + setStyleSheet("background-color: #D8D8D8"); +} + +Downloader::~Downloader() +{ + delete m_ui; + delete m_reply; + delete m_manager; +} + +/** + * Returns \c true if the updater shall not intervene when the download has + * finished (you can use the \c QSimpleUpdater signals to know when the + * download is completed). + */ +bool Downloader::useCustomInstallProcedures() const +{ + return m_useCustomProcedures; +} + +/** + * Changes the URL, which is used to indentify the downloader dialog + * with an \c Updater instance + * + * \note the \a url parameter is not the download URL, it is the URL of + * the AppCast file + */ +void Downloader::setUrlId (const QString& url) +{ + m_url = url; +} + +/** + * Begins downloading the file at the given \a url + */ +void Downloader::startDownload (const QUrl& url) +{ + + /* Reset UI */ + m_ui->progressBar->setValue (0); + m_ui->stopButton->setText (tr ("Stop")); + m_ui->downloadLabel->setText (tr ("Downloading updates")); + m_ui->timeLabel->setText (tr ("Time remaining") + ": " + tr ("unknown")); + + /* Configure the network request */ + QNetworkRequest request (url); + if (!m_userAgentString.isEmpty()) + request.setRawHeader ("User-Agent", m_userAgentString.toUtf8()); + + /* Start download */ + m_reply = m_manager->get (request); + m_startTime = QDateTime::currentDateTime().toTime_t(); + + /* Ensure that downloads directory exists */ + if (!m_downloadDir.exists()) + m_downloadDir.mkpath("."); + + /* Remove old downloads */ + QFile::remove (m_downloadDir.filePath (m_fileName)); + QFile::remove (m_downloadDir.filePath (m_fileName + PARTIAL_DOWN)); + + /* Update UI when download progress changes or download finishes */ + connect (m_reply, SIGNAL (downloadProgress (qint64, qint64)), + this, SLOT (updateProgress (qint64, qint64))); + connect (m_reply, SIGNAL (finished ()), + this, SLOT (finished ())); + connect (m_reply, SIGNAL (redirected (QUrl)), + this, SLOT (startDownload (QUrl))); + + showNormal(); +} + +/** + * Changes the name of the downloaded file + */ +void Downloader::setFileName (const QString& file) +{ + m_fileName = file; + + if (m_fileName.isEmpty()) + m_fileName = "QSU_Update.bin"; +} + +/** + * Changes the user-agent string used to communicate with the remote HTTP server + */ +void Downloader::setUserAgentString (const QString& agent) +{ + m_userAgentString = agent; +} +void Downloader::finished() +{ + /* Rename file */ + QFile::rename (m_downloadDir.filePath (m_fileName + PARTIAL_DOWN), + m_downloadDir.filePath (m_fileName)); + + /* Notify application */ + emit downloadFinished (m_url, m_downloadDir.filePath (m_fileName)); + /* Install the update */ + m_reply->close(); + installUpdate(); + setVisible (false); +} + +/** + * Opens the downloaded file. + * \note If the downloaded file is not found, then the function will alert the + * user about the error. + */ +void Downloader::openDownload() { + if(!m_fileName.isEmpty()) QDesktopServices::openUrl(QUrl::fromLocalFile(m_downloadDir.filePath(m_fileName))); + else QMessageBox::critical (gMainWin, tr("Error"), tr("Cannot find downloaded update!"), QMessageBox::Close); +} + +/** + * Instructs the OS to open the downloaded file. + * + * \note If \c useCustomInstallProcedures() returns \c true, the function will + * not instruct the OS to open the downloaded file. You can use the + * signals fired by the \c QSimpleUpdater to install the update with your + * own implementations/code. + */ +void Downloader::installUpdate(){ + if (useCustomInstallProcedures()){ + return; + } + + /* Update labels */ + m_ui->stopButton->setText (tr ("Close")); + m_ui->downloadLabel->setText (tr ("Download complete!")); + m_ui->timeLabel->setText (tr ("The installer will open separately") + + "..."); + + /* Ask the user to install the download */ +// QMessageBox box; +// box.setIcon (QMessageBox::Question); +// box.setDefaultButton (QMessageBox::Ok); +// box.setStandardButtons (QMessageBox::Ok | QMessageBox::Cancel); +// box.setInformativeText (tr ("Click \"OK\" to begin installing the update")); + + QString text = m_mandatoryUpdate ? tr("In order to install the update, you may need to quit the application. This is a mandatory update, exiting now will close the application") : tr("In order to install the update "); + auto res = QMessageBox::information(gMainWin, tr("Tip Info"), text, QMessageBox::Ok, QMessageBox::Cancel); + if(m_mandatoryUpdate) QApplication::quit(); + if(res == QMessageBox::Ok) { + if(!useCustomInstallProcedures()) openDownload(); + } else { + m_ui->openButton->setEnabled (true); + m_ui->openButton->setVisible (true); + m_ui->timeLabel->setText (tr ("Click the \"Open\" button to " + "apply the update")); + } +} + +/** + * Prompts the user if he/she wants to cancel the download and cancels the + * download if the user agrees to do that. + */ +void Downloader::cancelDownload() +{ + if (!m_reply->isFinished()) { + QMessageBox box; + box.setWindowTitle (tr ("Updater")); + box.setIcon (QMessageBox::Question); + box.setStandardButtons (QMessageBox::Yes | QMessageBox::No); + + QString text = tr("Are you sure you want to cancel the download?"); + if (m_mandatoryUpdate) + { + text = tr("Are you sure you want to cancel the download? This is a mandatory update, exiting now will close the application"); + } + box.setText (text); + + if (box.exec() == QMessageBox::Yes) { + hide(); + m_reply->abort(); + if(m_mandatoryUpdate) + QApplication::quit(); + } + } + else + { + if(m_mandatoryUpdate) + QApplication::quit(); + + hide(); + } +} + +/** + * Writes the downloaded data to the disk + */ +void Downloader::saveFile (qint64 received, qint64 total) +{ + Q_UNUSED (received); + Q_UNUSED (total); + + /* Check if we need to redirect */ + QUrl url = m_reply->attribute ( + QNetworkRequest::RedirectionTargetAttribute).toUrl(); + if (!url.isEmpty()) { + startDownload (url); + return; + } + + /* Save downloaded data to disk */ + QFile file (m_downloadDir.filePath (m_fileName + PARTIAL_DOWN)); + if (file.open (QIODevice::WriteOnly | QIODevice::Append)) { + file.write (m_reply->readAll()); + file.close(); + } +} + + +/** + * Calculates the appropiate size units (bytes, KB or MB) for the received + * data and the total download size. Then, this function proceeds to update the + * dialog controls/UI. + */ +void Downloader::calculateSizes (qint64 received, qint64 total) +{ + QString totalSize; + QString receivedSize; + + if (total < 1024) + totalSize = tr ("%1 bytes").arg (total); + + else if (total < 1048576) + totalSize = tr ("%1 KB").arg (round (total / 1024)); + + else + totalSize = tr ("%1 MB").arg (round (total / 1048576)); + + if (received < 1024) + receivedSize = tr ("%1 bytes").arg (received); + + else if (received < 1048576) + receivedSize = tr ("%1 KB").arg (received / 1024); + + else + receivedSize = tr ("%1 MB").arg (received / 1048576); + + m_ui->downloadLabel->setText (tr ("Downloading updates") + + " (" + receivedSize + " " + tr ("of") + + " " + totalSize + ")"); +} + +/** + * Uses the \a received and \a total parameters to get the download progress + * and update the progressbar value on the dialog. + */ +void Downloader::updateProgress (qint64 received, qint64 total) +{ + if (total > 0) { + m_ui->progressBar->setMinimum (0); + m_ui->progressBar->setMaximum (100); + m_ui->progressBar->setValue ((received * 100) / total); + + calculateSizes (received, total); + calculateTimeRemaining (received, total); + saveFile (received, total); + } + + else { + m_ui->progressBar->setMinimum (0); + m_ui->progressBar->setMaximum (0); + m_ui->progressBar->setValue (-1); + m_ui->downloadLabel->setText (tr ("Downloading Updates") + "..."); + m_ui->timeLabel->setText (QString ("%1: %2") + .arg (tr ("Time Remaining")) + .arg (tr ("Unknown"))); + } +} + +/** + * Uses two time samples (from the current time and a previous sample) to + * calculate how many bytes have been downloaded. + * + * Then, this function proceeds to calculate the appropiate units of time + * (hours, minutes or seconds) and constructs a user-friendly string, which + * is displayed in the dialog. + */ +void Downloader::calculateTimeRemaining (qint64 received, qint64 total) +{ + uint difference = QDateTime::currentDateTime().toTime_t() - m_startTime; + + if (difference > 0) { + QString timeString; + qreal timeRemaining = (total - received) / (received / difference); + + if (timeRemaining > 7200) { + timeRemaining /= 3600; + int hours = int (timeRemaining + 0.5); + + if (hours > 1) + timeString = tr ("about %1 hours").arg (hours); + else + timeString = tr ("about one hour"); + } + + else if (timeRemaining > 60) { + timeRemaining /= 60; + int minutes = int (timeRemaining + 0.5); + + if (minutes > 1) + timeString = tr ("%1 minutes").arg (minutes); + else + timeString = tr ("1 minute"); + } + + else if (timeRemaining <= 60) { + int seconds = int (timeRemaining + 0.5); + + if (seconds > 1) + timeString = tr ("%1 seconds").arg (seconds); + else + timeString = tr ("1 second"); + } + + m_ui->timeLabel->setText (tr ("Time remaining") + ": " + timeString); + } +} + +/** + * Rounds the given \a input to two decimal places + */ +qreal Downloader::round (const qreal& input) +{ + return static_cast(roundf (static_cast(input) * 100) / 100); +} + +QString Downloader::downloadDir() const +{ + return m_downloadDir.absolutePath(); +} + +void Downloader::setDownloadDir (const QString& downloadDir) +{ + if (m_downloadDir.absolutePath() != downloadDir) + m_downloadDir.setPath(downloadDir); +} + +/** + * If the \a mandatory_update is set to \c true, the \c Downloader has to download and install the + * update. If the user cancels or exits, the application will close + */ +void Downloader::setMandatoryUpdate(const bool mandatory_update) +{ + m_mandatoryUpdate = mandatory_update; +} + +/** + * If the \a custom parameter is set to \c true, then the \c Downloader will not + * attempt to open the downloaded file. + * + * Use the signals fired by the \c QSimpleUpdater to implement your own install + * procedures. + */ +void Downloader::setUseCustomInstallProcedures (const bool custom) +{ + m_useCustomProcedures = custom; +} diff --git a/LedOK/QSimpleUpdater/src/Downloader.h b/LedOK/QSimpleUpdater/src/Downloader.h index 00c9f11..40e9b11 100644 --- a/LedOK/QSimpleUpdater/src/Downloader.h +++ b/LedOK/QSimpleUpdater/src/Downloader.h @@ -1,101 +1,101 @@ -/* - * Copyright (c) 2014-2016 Alex Spataru - * Copyright (c) 2017 Gilmanov Ildar - * - * This file is part of the QSimpleUpdater library, which is released under - * the DBAD license, you can read a copy of it below: - * - * DON'T BE A DICK PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, - * DISTRIBUTION AND MODIFICATION: - * - * Do whatever you like with the original work, just don't be a dick. - * Being a dick includes - but is not limited to - the following instances: - * - * 1a. Outright copyright infringement - Don't just copy this and change the - * name. - * 1b. Selling the unmodified original with no work done what-so-ever, that's - * REALLY being a dick. - * 1c. Modifying the original work to contain hidden harmful content. - * That would make you a PROPER dick. - * - * If you become rich through modifications, related works/services, or - * supporting the original work, share the love. - * Only a dick would make loads off this work and not buy the original works - * creator(s) a pint. - * - * Code is provided with no warranty. Using somebody else's code and bitching - * when it goes wrong makes you a DONKEY dick. - * Fix the problem yourself. A non-dick would submit the fix back. - */ - -#ifndef DOWNLOAD_DIALOG_H -#define DOWNLOAD_DIALOG_H - -#include -#include -#include - -namespace Ui { -class Downloader; -} - -class QNetworkReply; -class QNetworkAccessManager; - -/** - * \brief Implements an integrated file downloader with a nice UI - */ -class Downloader : public QDialog//QWidget -{ - Q_OBJECT - -signals: - void downloadFinished (const QString& url, const QString& filepath); - -public: - explicit Downloader (QWidget* parent = 0); - ~Downloader(); - - bool useCustomInstallProcedures() const; - QString m_strVersion=""; - - QString downloadDir() const; - void setDownloadDir (const QString& downloadDir); - -public slots: - void setUrlId (const QString& url); - void startDownload (const QUrl& url); - void setFileName (const QString& file); - void setUserAgentString (const QString& agent); - void setUseCustomInstallProcedures (const bool custom); - void setMandatoryUpdate (const bool mandatory_update); - -private slots: - void finished(); - void openDownload(); - void installUpdate(); - void cancelDownload(); - void saveFile (qint64 received, qint64 total); - void calculateSizes (qint64 received, qint64 total); - void updateProgress (qint64 received, qint64 total); - void calculateTimeRemaining (qint64 received, qint64 total); - -private: - qreal round (const qreal& input); - -private: - QString m_url; - uint m_startTime; - QDir m_downloadDir; - QString m_fileName; - Ui::Downloader* m_ui; - QNetworkReply* m_reply; - QString m_userAgentString; - - bool m_useCustomProcedures; - bool m_mandatoryUpdate; - - QNetworkAccessManager* m_manager; -}; - -#endif +/* + * Copyright (c) 2014-2016 Alex Spataru + * Copyright (c) 2017 Gilmanov Ildar + * + * This file is part of the QSimpleUpdater library, which is released under + * the DBAD license, you can read a copy of it below: + * + * DON'T BE A DICK PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, + * DISTRIBUTION AND MODIFICATION: + * + * Do whatever you like with the original work, just don't be a dick. + * Being a dick includes - but is not limited to - the following instances: + * + * 1a. Outright copyright infringement - Don't just copy this and change the + * name. + * 1b. Selling the unmodified original with no work done what-so-ever, that's + * REALLY being a dick. + * 1c. Modifying the original work to contain hidden harmful content. + * That would make you a PROPER dick. + * + * If you become rich through modifications, related works/services, or + * supporting the original work, share the love. + * Only a dick would make loads off this work and not buy the original works + * creator(s) a pint. + * + * Code is provided with no warranty. Using somebody else's code and bitching + * when it goes wrong makes you a DONKEY dick. + * Fix the problem yourself. A non-dick would submit the fix back. + */ + +#ifndef DOWNLOAD_DIALOG_H +#define DOWNLOAD_DIALOG_H + +#include +#include +#include + +namespace Ui { +class Downloader; +} + +class QNetworkReply; +class QNetworkAccessManager; + +/** + * \brief Implements an integrated file downloader with a nice UI + */ +class Downloader : public QDialog//QWidget +{ + Q_OBJECT + +signals: + void downloadFinished (const QString& url, const QString& filepath); + +public: + explicit Downloader (QWidget* parent = 0); + ~Downloader(); + + bool useCustomInstallProcedures() const; + QString m_strVersion=""; + + QString downloadDir() const; + void setDownloadDir (const QString& downloadDir); + +public slots: + void setUrlId (const QString& url); + void startDownload (const QUrl& url); + void setFileName (const QString& file); + void setUserAgentString (const QString& agent); + void setUseCustomInstallProcedures (const bool custom); + void setMandatoryUpdate (const bool mandatory_update); + +private slots: + void finished(); + void openDownload(); + void installUpdate(); + void cancelDownload(); + void saveFile (qint64 received, qint64 total); + void calculateSizes (qint64 received, qint64 total); + void updateProgress (qint64 received, qint64 total); + void calculateTimeRemaining (qint64 received, qint64 total); + +private: + qreal round (const qreal& input); + +private: + QString m_url; + uint m_startTime; + QDir m_downloadDir; + QString m_fileName; + Ui::Downloader* m_ui; + QNetworkReply* m_reply; + QString m_userAgentString; + + bool m_useCustomProcedures; + bool m_mandatoryUpdate; + + QNetworkAccessManager* m_manager; +}; + +#endif diff --git a/LedOK/QSimpleUpdater/src/Downloader.ui b/LedOK/QSimpleUpdater/src/Downloader.ui index 06c36bb..c1aa537 100644 --- a/LedOK/QSimpleUpdater/src/Downloader.ui +++ b/LedOK/QSimpleUpdater/src/Downloader.ui @@ -1,214 +1,214 @@ - - - Downloader - - - Qt::ApplicationModal - - - - 0 - 0 - 472 - 227 - - - - - 0 - 0 - - - - Updater - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - 0 - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 30 - 24 - - - - X - - - - - - - - - border-top: 2px solid gray; - - - Qt::Horizontal - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 96 - 96 - - - - - - - :/icons/update.png - - - - - - - - 0 - - - - - - 75 - true - - - - Downloading updates - - - - - - - - 320 - 0 - - - - 0 - - - false - - - - - - - Time remaining: 0 minutes - - - - - - - - - - - - - - 12 - - - 12 - - - 12 - - - 12 - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Open - - - - - - - Stop - - - - - - - - - - - - - - - - + + + Downloader + + + Qt::ApplicationModal + + + + 0 + 0 + 472 + 227 + + + + + 0 + 0 + + + + Updater + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + 0 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 30 + 24 + + + + X + + + + + + + + + border-top: 2px solid gray; + + + Qt::Horizontal + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 96 + 96 + + + + + + + :/icons/update.png + + + + + + + + 0 + + + + + + 75 + true + + + + Downloading updates + + + + + + + + 320 + 0 + + + + 0 + + + false + + + + + + + Time remaining: 0 minutes + + + + + + + + + + + + + + 12 + + + 12 + + + 12 + + + 12 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Open + + + + + + + Stop + + + + + + + + + + + + + + + + diff --git a/LedOK/QSimpleUpdater/src/QSimpleUpdater.cpp b/LedOK/QSimpleUpdater/src/QSimpleUpdater.cpp index 11c02e5..afbd86a 100644 --- a/LedOK/QSimpleUpdater/src/QSimpleUpdater.cpp +++ b/LedOK/QSimpleUpdater/src/QSimpleUpdater.cpp @@ -1,433 +1,433 @@ -/* - * Copyright (c) 2014-2016 Alex Spataru - * - * This file is part of the QSimpleUpdater library, which is released under - * the DBAD license, you can read a copy of it below: - * - * DON'T BE A DICK PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, - * DISTRIBUTION AND MODIFICATION: - * - * Do whatever you like with the original work, just don't be a dick. - * Being a dick includes - but is not limited to - the following instances: - * - * 1a. Outright copyright infringement - Don't just copy this and change the - * name. - * 1b. Selling the unmodified original with no work done what-so-ever, that's - * REALLY being a dick. - * 1c. Modifying the original work to contain hidden harmful content. - * That would make you a PROPER dick. - * - * If you become rich through modifications, related works/services, or - * supporting the original work, share the love. - * Only a dick would make loads off this work and not buy the original works - * creator(s) a pint. - * - * Code is provided with no warranty. Using somebody else's code and bitching - * when it goes wrong makes you a DONKEY dick. - * Fix the problem yourself. A non-dick would submit the fix back. - */ - -#include "Updater.h" -#include "QSimpleUpdater.h" - -static QList URLS; -static QList UPDATERS; - -QSimpleUpdater::~QSimpleUpdater() -{ - URLS.clear(); - - foreach (Updater* updater, UPDATERS) - updater->deleteLater(); - - UPDATERS.clear(); -} - -/** - * Returns the only instance of the class - */ -QSimpleUpdater* QSimpleUpdater::getInstance() -{ - static QSimpleUpdater updater; - return &updater; -} - -/** - * Returns \c true if the \c Updater instance registered with the given \a url - * uses a custom appcast format and/or allows the application to read and - * interpret the downloaded appcast file - * - * \note If an \c Updater instance registered with the given \a url is not - * found, that \c Updater instance will be initialized automatically - */ -bool QSimpleUpdater::usesCustomAppcast (const QString& url) const -{ - return getUpdater (url)->customAppcast(); -} - -/** - * Returns \c true if the \c Updater instance registered with the given \a url - * shall notify the user when an update is available. - * - * \note If an \c Updater instance registered with the given \a url is not - * found, that \c Updater instance will be initialized automatically - */ -bool QSimpleUpdater::getNotifyOnUpdate (const QString& url) const -{ - return getUpdater (url)->notifyOnUpdate(); -} - -/** - * Returns \c true if the \c Updater instance registered with the given \a url - * shall notify the user when it finishes checking for updates. - * - * \note If an \c Updater instance registered with the given \a url is not - * found, that \c Updater instance will be initialized automatically - */ -bool QSimpleUpdater::getNotifyOnFinish (const QString& url) const -{ - return getUpdater (url)->notifyOnFinish(); -} - -/** - * Returns \c true if the \c Updater instance registered with the given \a url - * has an update available. - * - * \warning You should call \c checkForUpdates() before using this function - * \note If an \c Updater instance registered with the given \a url is not - * found, that \c Updater instance will be initialized automatically - */ -bool QSimpleUpdater::getUpdateAvailable (const QString& url) const -{ - return getUpdater (url)->updateAvailable(); -} -bool QSimpleUpdater::getUpdateSameVersionAvailable (const QString& url) const -{ - return getUpdater (url)->updateSameVersionAvailable(); -} - -/** - * Returns \c true if the \c Updater instance registered with the given \a url - * has the integrated downloader enabled. - * - * \note If an \c Updater instance registered with the given \a url is not - * found, that \c Updater instance will be initialized automatically - */ -bool QSimpleUpdater::getDownloaderEnabled (const QString& url) const -{ - return getUpdater (url)->downloaderEnabled(); -} - -/** - * Returns \c true if the \c Updater instance registered with the given \a url - * shall try to open the downloaded file. - * - * If you want to implement your own way to handle the downloaded file, just - * bind to the \c downloadFinished() signal and disable the integrated - * downloader with the \c setUseCustomInstallProcedures() function. - * - * \note If an \c Updater instance registered with the given \a url is not - * found, that \c Updater instance will be initialized automatically - */ -bool QSimpleUpdater::usesCustomInstallProcedures (const QString& url) const -{ - return getUpdater (url)->useCustomInstallProcedures(); -} - -/** - * Returns the URL to open in a web browser of the \c Updater instance - * registered with the given \a url. - * - * \note If the module name is empty, then the \c Updater will use the - * application name as its module name. - * \note If an \c Updater instance registered with the given \a url is not - * found, that \c Updater instance will be initialized automatically - */ -QString QSimpleUpdater::getOpenUrl (const QString& url) const -{ - return getUpdater (url)->openUrl(); -} - -/** - * Returns the changelog of the \c Updater instance registered with the given - * \a url. - * - * \warning You should call \c checkForUpdates() before using this function - * \note If an \c Updater instance registered with the given \a url is not - * found, that \c Updater instance will be initialized automatically - */ -QString QSimpleUpdater::getChangelog (const QString& url) const -{ - return getUpdater (url)->changelog(); -} - -/** - * Returns the module name of the \c Updater instance registered with the given - * \a url. - * - * \note If the module name is empty, then the \c Updater will use the - * application name as its module name. - * \note If an \c Updater instance registered with the given \a url is not - * found, that \c Updater instance will be initialized automatically - */ -QString QSimpleUpdater::getModuleName (const QString& url) const -{ - return getUpdater (url)->moduleName(); -} - -/** - * Returns the download URL of the \c Updater instance registered with the given - * \a url. - * - * \warning You should call \c checkForUpdates() before using this function - * \note If an \c Updater instance registered with the given \a url is not - * found, that \c Updater instance will be initialized automatically - */ -QString QSimpleUpdater::getDownloadUrl (const QString& url) const -{ - return getUpdater (url)->downloadUrl(); -} - -/** - * Returns the platform key of the \c Updater registered with the given \a url. - * If you do not define a platform key, the system will assign the following - * platform key: - * - On iOS: \c ios - * - On Mac OSX: \c osx - * - On Android: \c android - * - On GNU/Linux: \c linux - * - On Microsoft Windows: \c windows - * - * \note If an \c Updater instance registered with the given \a url is not - * found, that \c Updater instance will be initialized automatically - */ -QString QSimpleUpdater::getPlatformKey (const QString& url) const -{ - return getUpdater (url)->platformKey(); -} - -/** - * Returns the remote module version of the \c Updater instance registered with - * the given \a url. - * - * \warning You should call \c checkForUpdates() before using this function - * \note If an \c Updater instance registered with the given \a url is not - * found, that \c Updater instance will be initialized automatically - */ -QString QSimpleUpdater::getLatestVersion (const QString& url) const -{ - return getUpdater (url)->latestVersion(); -} - -/** - * Returns the module version of the \c Updater instance registered with the - * given \a url. - * - * \note If the module version is empty, then the \c Updater will use the - * application version as its module version. - * \note If an \c Updater instance registered with the given \a url is not - * found, that \c Updater instance will be initialized automatically - */ -QString QSimpleUpdater::getModuleVersion (const QString& url) const -{ - return getUpdater (url)->moduleVersion(); -} - -/** - * Returns the user-agent string used by the updater to communicate with - * the remote HTTP(S) server. - * - * \note If an \c Updater instance registered with the given \a url is not - * found, that \c Updater instance will be initialized automatically - */ -QString QSimpleUpdater::getUserAgentString (const QString& url) const -{ - return getUpdater (url)->userAgentString(); -} - -/** - * Instructs the \c Updater instance with the registered \c url to download and - * interpret the update definitions file. - * - * \note If an \c Updater instance registered with the given \a url is not - * found, that \c Updater instance will be initialized automatically - */ -void QSimpleUpdater::checkForUpdates (const QString& url) -{ - getUpdater (url)->checkForUpdates(); -} - -/** - * Changes the module \a name of the \c Updater instance registered at the - * given \a url. - * - * \note If an \c Updater instance registered with the given \a url is not - * found, that \c Updater instance will be initialized automatically - * \note The module name is used on the user prompts. If the module name is - * empty, then the prompts will show the name of the application. - */ -void QSimpleUpdater::setModuleName (const QString& url, const QString& name) -{ - getUpdater (url)->setModuleName (name); -} - -/** - * If \a notify is set to \c true, then the \c Updater instance registered with - * the given \a url will notify the user when an update is available. - * - * \note If an \c Updater instance registered with the given \a url is not - * found, that \c Updater instance will be initialized automatically - */ -void QSimpleUpdater::setNotifyOnUpdate (const QString& url, - const bool notify) -{ - getUpdater (url)->setNotifyOnUpdate (notify); -} - -/** - * If \a notify is set to \c true, then the \c Updater instance registered with - * the given \a url will notify the user when it has finished interpreting the - * update definitions file. - * - * \note If an \c Updater instance registered with the given \a url is not - * found, that \c Updater instance will be initialized automatically - */ -void QSimpleUpdater::setNotifyOnFinish (const QString& url, - const bool notify) -{ - getUpdater (url)->setNotifyOnFinish (notify); -} - -/** - * Changes the platform key of the \c Updater isntance registered at the given - * \a url. - * - * If the platform key is empty, then the system will use the following keys: - * - On iOS: \c ios - * - On Mac OSX: \c osx - * - On Android: \c android - * - On GNU/Linux: \c linux - * - On Microsoft Windows: \c windows - * - * \note If an \c Updater instance registered with the given \a url is not - * found, that \c Updater instance will be initialized automatically - */ -void QSimpleUpdater::setPlatformKey (const QString& url, - const QString& platform) -{ - getUpdater (url)->setPlatformKey (platform); -} - -/** - * Changes the module \version of the \c Updater instance registered at the - * given \a url. - * - * \note The module version is used to compare it with the remove version. - * If the module name is empty, then the \c Updater instance will use the - * application version. - */ -void QSimpleUpdater::setModuleVersion (const QString& url, - const QString& version) -{ - getUpdater (url)->setModuleVersion (version); -} - -/** - * If the \a enabled parameter is set to \c true, the \c Updater instance - * registered with the given \a url will open the integrated downloader - * if the user agrees to install the update (if any). - * - * \note If an \c Updater instance registered with the given \a url is not - * found, that \c Updater instance will be initialized automatically - */ -void QSimpleUpdater::setDownloaderEnabled (const QString& url, - const bool enabled) -{ - getUpdater (url)->setDownloaderEnabled (enabled); -} - -/** - * Changes the user-agent string used by the updater to communicate - * with the remote server - * - * \note If an \c Updater instance registered with the given \a url is not - * found, that \c Updater instance will be initialized automatically - */ -void QSimpleUpdater::setUserAgentString (const QString& url, - const QString& agent) -{ - getUpdater (url)->setUserAgentString (agent); -} - -/** - * If the \a customAppcast parameter is set to \c true, then the \c Updater - * will not try to read the network reply from the server, instead, it will - * emit the \c appcastDownloaded() signal, which allows the application to - * read and interpret the appcast file by itself. - * - * \note If an \c Updater instance registered with the given \a url is not - * found, that \c Updater instance will be initialized automatically - */ -void QSimpleUpdater::setUseCustomAppcast (const QString& url, - const bool customAppcast) -{ - getUpdater (url)->setUseCustomAppcast (customAppcast); -} - -/** - * If the \a custom parameter is set to \c true, the \c Updater instance - * registered with the given \a url will not try to open the downloaded file. - * - * If you want to implement your own way to handle the downloaded file, just - * bind to the \c downloadFinished() signal and disable the integrated - * downloader with the \c setUseCustomInstallProcedures() function. - * - * \note If an \c Updater instance registered with the given \a url is not - * found, that \c Updater instance will be initialized automatically - */ -void QSimpleUpdater::setUseCustomInstallProcedures (const QString& url, - const bool custom) -{ - getUpdater (url)->setUseCustomInstallProcedures (custom); -} -void QSimpleUpdater::setNoNotifyDownload (const QString& url, - const bool custom) -{ - getUpdater (url)->setNoNotifyDownload (custom); -} -void QSimpleUpdater::setCompareBySameString (const QString& url, - const bool custom) -{ - getUpdater (url)->setCompareBySameString (custom); -} -void QSimpleUpdater::setMandatoryUpdate(const QString& url, - const bool mandatory_update) -{ - getUpdater (url)->setMandatoryUpdate(mandatory_update); -} - -/** - * Returns the \c Updater instance registered with the given \a url. - * - * If an \c Updater instance registered with teh given \a url does not exist, - * this function will create it and configure it automatically. - */ -Updater* QSimpleUpdater::getUpdater (const QString& url) const -{ - if (!URLS.contains (url)) { - Updater* updater = new Updater; - updater->setUrl (url); - - URLS.append (url); - UPDATERS.append (updater); - - connect (updater, SIGNAL (checkingFinished (QString)), - this, SIGNAL (checkingFinished (QString))); - connect (updater, SIGNAL (downloadFinished (QString, QString)), - this, SIGNAL (downloadFinished (QString, QString))); - connect (updater, SIGNAL (appcastDownloaded (QString, QByteArray)), - this, SIGNAL (appcastDownloaded (QString, QByteArray))); - } - - return UPDATERS.at (URLS.indexOf (url)); -} +/* + * Copyright (c) 2014-2016 Alex Spataru + * + * This file is part of the QSimpleUpdater library, which is released under + * the DBAD license, you can read a copy of it below: + * + * DON'T BE A DICK PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, + * DISTRIBUTION AND MODIFICATION: + * + * Do whatever you like with the original work, just don't be a dick. + * Being a dick includes - but is not limited to - the following instances: + * + * 1a. Outright copyright infringement - Don't just copy this and change the + * name. + * 1b. Selling the unmodified original with no work done what-so-ever, that's + * REALLY being a dick. + * 1c. Modifying the original work to contain hidden harmful content. + * That would make you a PROPER dick. + * + * If you become rich through modifications, related works/services, or + * supporting the original work, share the love. + * Only a dick would make loads off this work and not buy the original works + * creator(s) a pint. + * + * Code is provided with no warranty. Using somebody else's code and bitching + * when it goes wrong makes you a DONKEY dick. + * Fix the problem yourself. A non-dick would submit the fix back. + */ + +#include "Updater.h" +#include "QSimpleUpdater.h" + +static QList URLS; +static QList UPDATERS; + +QSimpleUpdater::~QSimpleUpdater() +{ + URLS.clear(); + + foreach (Updater* updater, UPDATERS) + updater->deleteLater(); + + UPDATERS.clear(); +} + +/** + * Returns the only instance of the class + */ +QSimpleUpdater* QSimpleUpdater::getInstance() +{ + static QSimpleUpdater updater; + return &updater; +} + +/** + * Returns \c true if the \c Updater instance registered with the given \a url + * uses a custom appcast format and/or allows the application to read and + * interpret the downloaded appcast file + * + * \note If an \c Updater instance registered with the given \a url is not + * found, that \c Updater instance will be initialized automatically + */ +bool QSimpleUpdater::usesCustomAppcast (const QString& url) const +{ + return getUpdater (url)->customAppcast(); +} + +/** + * Returns \c true if the \c Updater instance registered with the given \a url + * shall notify the user when an update is available. + * + * \note If an \c Updater instance registered with the given \a url is not + * found, that \c Updater instance will be initialized automatically + */ +bool QSimpleUpdater::getNotifyOnUpdate (const QString& url) const +{ + return getUpdater (url)->notifyOnUpdate(); +} + +/** + * Returns \c true if the \c Updater instance registered with the given \a url + * shall notify the user when it finishes checking for updates. + * + * \note If an \c Updater instance registered with the given \a url is not + * found, that \c Updater instance will be initialized automatically + */ +bool QSimpleUpdater::getNotifyOnFinish (const QString& url) const +{ + return getUpdater (url)->notifyOnFinish(); +} + +/** + * Returns \c true if the \c Updater instance registered with the given \a url + * has an update available. + * + * \warning You should call \c checkForUpdates() before using this function + * \note If an \c Updater instance registered with the given \a url is not + * found, that \c Updater instance will be initialized automatically + */ +bool QSimpleUpdater::getUpdateAvailable (const QString& url) const +{ + return getUpdater (url)->updateAvailable(); +} +bool QSimpleUpdater::getUpdateSameVersionAvailable (const QString& url) const +{ + return getUpdater (url)->updateSameVersionAvailable(); +} + +/** + * Returns \c true if the \c Updater instance registered with the given \a url + * has the integrated downloader enabled. + * + * \note If an \c Updater instance registered with the given \a url is not + * found, that \c Updater instance will be initialized automatically + */ +bool QSimpleUpdater::getDownloaderEnabled (const QString& url) const +{ + return getUpdater (url)->downloaderEnabled(); +} + +/** + * Returns \c true if the \c Updater instance registered with the given \a url + * shall try to open the downloaded file. + * + * If you want to implement your own way to handle the downloaded file, just + * bind to the \c downloadFinished() signal and disable the integrated + * downloader with the \c setUseCustomInstallProcedures() function. + * + * \note If an \c Updater instance registered with the given \a url is not + * found, that \c Updater instance will be initialized automatically + */ +bool QSimpleUpdater::usesCustomInstallProcedures (const QString& url) const +{ + return getUpdater (url)->useCustomInstallProcedures(); +} + +/** + * Returns the URL to open in a web browser of the \c Updater instance + * registered with the given \a url. + * + * \note If the module name is empty, then the \c Updater will use the + * application name as its module name. + * \note If an \c Updater instance registered with the given \a url is not + * found, that \c Updater instance will be initialized automatically + */ +QString QSimpleUpdater::getOpenUrl (const QString& url) const +{ + return getUpdater (url)->openUrl(); +} + +/** + * Returns the changelog of the \c Updater instance registered with the given + * \a url. + * + * \warning You should call \c checkForUpdates() before using this function + * \note If an \c Updater instance registered with the given \a url is not + * found, that \c Updater instance will be initialized automatically + */ +QString QSimpleUpdater::getChangelog (const QString& url) const +{ + return getUpdater (url)->changelog(); +} + +/** + * Returns the module name of the \c Updater instance registered with the given + * \a url. + * + * \note If the module name is empty, then the \c Updater will use the + * application name as its module name. + * \note If an \c Updater instance registered with the given \a url is not + * found, that \c Updater instance will be initialized automatically + */ +QString QSimpleUpdater::getModuleName (const QString& url) const +{ + return getUpdater (url)->moduleName(); +} + +/** + * Returns the download URL of the \c Updater instance registered with the given + * \a url. + * + * \warning You should call \c checkForUpdates() before using this function + * \note If an \c Updater instance registered with the given \a url is not + * found, that \c Updater instance will be initialized automatically + */ +QString QSimpleUpdater::getDownloadUrl (const QString& url) const +{ + return getUpdater (url)->downloadUrl(); +} + +/** + * Returns the platform key of the \c Updater registered with the given \a url. + * If you do not define a platform key, the system will assign the following + * platform key: + * - On iOS: \c ios + * - On Mac OSX: \c osx + * - On Android: \c android + * - On GNU/Linux: \c linux + * - On Microsoft Windows: \c windows + * + * \note If an \c Updater instance registered with the given \a url is not + * found, that \c Updater instance will be initialized automatically + */ +QString QSimpleUpdater::getPlatformKey (const QString& url) const +{ + return getUpdater (url)->platformKey(); +} + +/** + * Returns the remote module version of the \c Updater instance registered with + * the given \a url. + * + * \warning You should call \c checkForUpdates() before using this function + * \note If an \c Updater instance registered with the given \a url is not + * found, that \c Updater instance will be initialized automatically + */ +QString QSimpleUpdater::getLatestVersion (const QString& url) const +{ + return getUpdater (url)->latestVersion(); +} + +/** + * Returns the module version of the \c Updater instance registered with the + * given \a url. + * + * \note If the module version is empty, then the \c Updater will use the + * application version as its module version. + * \note If an \c Updater instance registered with the given \a url is not + * found, that \c Updater instance will be initialized automatically + */ +QString QSimpleUpdater::getModuleVersion (const QString& url) const +{ + return getUpdater (url)->moduleVersion(); +} + +/** + * Returns the user-agent string used by the updater to communicate with + * the remote HTTP(S) server. + * + * \note If an \c Updater instance registered with the given \a url is not + * found, that \c Updater instance will be initialized automatically + */ +QString QSimpleUpdater::getUserAgentString (const QString& url) const +{ + return getUpdater (url)->userAgentString(); +} + +/** + * Instructs the \c Updater instance with the registered \c url to download and + * interpret the update definitions file. + * + * \note If an \c Updater instance registered with the given \a url is not + * found, that \c Updater instance will be initialized automatically + */ +void QSimpleUpdater::checkForUpdates (const QString& url) +{ + getUpdater (url)->checkForUpdates(); +} + +/** + * Changes the module \a name of the \c Updater instance registered at the + * given \a url. + * + * \note If an \c Updater instance registered with the given \a url is not + * found, that \c Updater instance will be initialized automatically + * \note The module name is used on the user prompts. If the module name is + * empty, then the prompts will show the name of the application. + */ +void QSimpleUpdater::setModuleName (const QString& url, const QString& name) +{ + getUpdater (url)->setModuleName (name); +} + +/** + * If \a notify is set to \c true, then the \c Updater instance registered with + * the given \a url will notify the user when an update is available. + * + * \note If an \c Updater instance registered with the given \a url is not + * found, that \c Updater instance will be initialized automatically + */ +void QSimpleUpdater::setNotifyOnUpdate (const QString& url, + const bool notify) +{ + getUpdater (url)->setNotifyOnUpdate (notify); +} + +/** + * If \a notify is set to \c true, then the \c Updater instance registered with + * the given \a url will notify the user when it has finished interpreting the + * update definitions file. + * + * \note If an \c Updater instance registered with the given \a url is not + * found, that \c Updater instance will be initialized automatically + */ +void QSimpleUpdater::setNotifyOnFinish (const QString& url, + const bool notify) +{ + getUpdater (url)->setNotifyOnFinish (notify); +} + +/** + * Changes the platform key of the \c Updater isntance registered at the given + * \a url. + * + * If the platform key is empty, then the system will use the following keys: + * - On iOS: \c ios + * - On Mac OSX: \c osx + * - On Android: \c android + * - On GNU/Linux: \c linux + * - On Microsoft Windows: \c windows + * + * \note If an \c Updater instance registered with the given \a url is not + * found, that \c Updater instance will be initialized automatically + */ +void QSimpleUpdater::setPlatformKey (const QString& url, + const QString& platform) +{ + getUpdater (url)->setPlatformKey (platform); +} + +/** + * Changes the module \version of the \c Updater instance registered at the + * given \a url. + * + * \note The module version is used to compare it with the remove version. + * If the module name is empty, then the \c Updater instance will use the + * application version. + */ +void QSimpleUpdater::setModuleVersion (const QString& url, + const QString& version) +{ + getUpdater (url)->setModuleVersion (version); +} + +/** + * If the \a enabled parameter is set to \c true, the \c Updater instance + * registered with the given \a url will open the integrated downloader + * if the user agrees to install the update (if any). + * + * \note If an \c Updater instance registered with the given \a url is not + * found, that \c Updater instance will be initialized automatically + */ +void QSimpleUpdater::setDownloaderEnabled (const QString& url, + const bool enabled) +{ + getUpdater (url)->setDownloaderEnabled (enabled); +} + +/** + * Changes the user-agent string used by the updater to communicate + * with the remote server + * + * \note If an \c Updater instance registered with the given \a url is not + * found, that \c Updater instance will be initialized automatically + */ +void QSimpleUpdater::setUserAgentString (const QString& url, + const QString& agent) +{ + getUpdater (url)->setUserAgentString (agent); +} + +/** + * If the \a customAppcast parameter is set to \c true, then the \c Updater + * will not try to read the network reply from the server, instead, it will + * emit the \c appcastDownloaded() signal, which allows the application to + * read and interpret the appcast file by itself. + * + * \note If an \c Updater instance registered with the given \a url is not + * found, that \c Updater instance will be initialized automatically + */ +void QSimpleUpdater::setUseCustomAppcast (const QString& url, + const bool customAppcast) +{ + getUpdater (url)->setUseCustomAppcast (customAppcast); +} + +/** + * If the \a custom parameter is set to \c true, the \c Updater instance + * registered with the given \a url will not try to open the downloaded file. + * + * If you want to implement your own way to handle the downloaded file, just + * bind to the \c downloadFinished() signal and disable the integrated + * downloader with the \c setUseCustomInstallProcedures() function. + * + * \note If an \c Updater instance registered with the given \a url is not + * found, that \c Updater instance will be initialized automatically + */ +void QSimpleUpdater::setUseCustomInstallProcedures (const QString& url, + const bool custom) +{ + getUpdater (url)->setUseCustomInstallProcedures (custom); +} +void QSimpleUpdater::setNoNotifyDownload (const QString& url, + const bool custom) +{ + getUpdater (url)->setNoNotifyDownload (custom); +} +void QSimpleUpdater::setCompareBySameString (const QString& url, + const bool custom) +{ + getUpdater (url)->setCompareBySameString (custom); +} +void QSimpleUpdater::setMandatoryUpdate(const QString& url, + const bool mandatory_update) +{ + getUpdater (url)->setMandatoryUpdate(mandatory_update); +} + +/** + * Returns the \c Updater instance registered with the given \a url. + * + * If an \c Updater instance registered with teh given \a url does not exist, + * this function will create it and configure it automatically. + */ +Updater* QSimpleUpdater::getUpdater (const QString& url) const +{ + if (!URLS.contains (url)) { + Updater* updater = new Updater; + updater->setUrl (url); + + URLS.append (url); + UPDATERS.append (updater); + + connect (updater, SIGNAL (checkingFinished (QString)), + this, SIGNAL (checkingFinished (QString))); + connect (updater, SIGNAL (downloadFinished (QString, QString)), + this, SIGNAL (downloadFinished (QString, QString))); + connect (updater, SIGNAL (appcastDownloaded (QString, QByteArray)), + this, SIGNAL (appcastDownloaded (QString, QByteArray))); + } + + return UPDATERS.at (URLS.indexOf (url)); +} diff --git a/LedOK/QSimpleUpdater/src/Updater.cpp b/LedOK/QSimpleUpdater/src/Updater.cpp index ba7eb99..c315dd9 100644 --- a/LedOK/QSimpleUpdater/src/Updater.cpp +++ b/LedOK/QSimpleUpdater/src/Updater.cpp @@ -1,498 +1,498 @@ -/* - * Copyright (c) 2014-2016 Alex Spataru - * - * This file is part of the QSimpleUpdater library, which is released under - * the DBAD license, you can read a copy of it below: - * - * DON'T BE A DICK PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, - * DISTRIBUTION AND MODIFICATION: - * - * Do whatever you like with the original work, just don't be a dick. - * Being a dick includes - but is not limited to - the following instances: - * - * 1a. Outright copyright infringement - Don't just copy this and change the - * name. - * 1b. Selling the unmodified original with no work done what-so-ever, that's - * REALLY being a dick. - * 1c. Modifying the original work to contain hidden harmful content. - * That would make you a PROPER dick. - * - * If you become rich through modifications, related works/services, or - * supporting the original work, share the love. - * Only a dick would make loads off this work and not buy the original works - * creator(s) a pint. - * - * Code is provided with no warranty. Using somebody else's code and bitching - * when it goes wrong makes you a DONKEY dick. - * Fix the problem yourself. A non-dick would submit the fix back. - */ - -#include -#include -#include -#include -#include -#include - -#include "Updater.h" -#include "Downloader.h" -#include "cfg.h" -#include "qsettings.h" -Updater::Updater() { - m_url = ""; - m_openUrl = ""; - m_changelog = ""; - m_downloadUrl = ""; - m_latestVersion = ""; - m_customAppcast = false; - m_notifyOnUpdate = true; - m_notifyOnFinish = false; - m_updateAvailable = true; - m_sameVersion = false; - m_downloaderEnabled = true; - m_noTipDownload = false; - m_bSameStringCompare = false; - m_moduleName = qApp->applicationName(); - m_moduleVersion = qApp->applicationVersion(); - m_mandatoryUpdate = false; - - m_downloader = new Downloader(); - m_manager = new QNetworkAccessManager(); - QNetworkReply *pReply = m_manager->get(QNetworkRequest(QUrl(UpdVerUrl))); - QReplyTimeout *pTimeout = new QReplyTimeout(pReply, 10000); - // 超时进一步处理 - connect(pTimeout, &QReplyTimeout::timeout, [=]() { - qDebug() << "Timeout"; - }); -#if defined Q_OS_WIN - m_platform = "windows"; -#elif defined Q_OS_MAC - m_platform = "osx"; -#elif defined Q_OS_LINUX - m_platform = "linux"; -#elif defined Q_OS_ANDROID - m_platform = "android"; -#elif defined Q_OS_IOS - m_platform = "ios"; -#endif - setUserAgentString (QString ("%1/%2 (Qt; QSimpleUpdater)").arg(qApp->applicationName(), qApp->applicationVersion())); - connect (m_downloader, SIGNAL(downloadFinished(QString, QString)), this, SIGNAL (downloadFinished(QString, QString))); - connect (m_manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(onReply(QNetworkReply*))); -} - -Updater::~Updater() -{ - delete m_downloader; -} - -/** - * Returns the URL of the update definitions file - */ -QString Updater::url() const -{ - return m_url; -} - -/** - * Returns the URL that the update definitions file wants us to open in - * a web browser. - * - * \warning You should call \c checkForUpdates() before using this functio - */ -QString Updater::openUrl() const -{ - return m_openUrl; -} - -/** - * Returns the changelog defined by the update definitions file. - * \warning You should call \c checkForUpdates() before using this function - */ -QString Updater::changelog() const -{ - return m_changelog; -} - -/** - * Returns the name of the module (if defined) - */ -QString Updater::moduleName() const -{ - return m_moduleName; -} - -/** - * Returns the platform key (be it system-set or user-set). - * If you do not define a platform key, the system will assign the following - * platform key: - * - On iOS: \c ios - * - On Mac OSX: \c osx - * - On Android: \c android - * - On GNU/Linux: \c linux - * - On Microsoft Windows: \c windows - */ -QString Updater::platformKey() const -{ - return m_platform; -} - -/** - * Returns the download URL defined by the update definitions file. - * \warning You should call \c checkForUpdates() before using this function - */ -QString Updater::downloadUrl() const -{ - return m_downloadUrl; -} - -/** - * Returns the latest version defined by the update definitions file. - * \warning You should call \c checkForUpdates() before using this function - */ -QString Updater::latestVersion() const -{ - return m_latestVersion; -} - -/** - * Returns the user-agent header used by the client when communicating - * with the server through HTTP - */ -QString Updater::userAgentString() const -{ - return m_userAgentString; -} - -/** - * Returns the "local" version of the installed module - */ -QString Updater::moduleVersion() const -{ - return m_moduleVersion; -} - -/** - * Returns \c true if the updater should NOT interpret the downloaded appcast. - * This is useful if you need to store more variables (or information) in the - * JSON file or use another appcast format (e.g. XML) - */ -bool Updater::customAppcast() const -{ - return m_customAppcast; -} - -/** - * Returns \c true if the updater should notify the user when an update is - * available. - */ -bool Updater::notifyOnUpdate() const -{ - return m_notifyOnUpdate; -} - -/** - * Returns \c true if the updater should notify the user when it finishes - * checking for updates. - * - * \note If set to \c true, the \c Updater will notify the user even when there - * are no updates available (by congratulating him/her about being smart) - */ -bool Updater::notifyOnFinish() const -{ - return m_notifyOnFinish; -} - -/** - * Returns \c true if there the current update is mandatory. - * \warning You should call \c checkForUpdates() before using this function -*/ -bool Updater::mandatoryUpdate() const -{ - return m_mandatoryUpdate; -} - -/** - * Returns \c true if there is an update available. - * \warning You should call \c checkForUpdates() before using this function - */ -bool Updater::updateAvailable() const { - return m_updateAvailable; -} -bool Updater::updateSameVersionAvailable() const { - return m_sameVersion; -} - -/** - * Returns \c true if the integrated downloader is enabled. - * \note If set to \c true, the \c Updater will open the downloader dialog if - * the user agrees to download the update. - */ -bool Updater::downloaderEnabled() const -{ - return m_downloaderEnabled; -} - -/** - * Returns \c true if the updater shall not intervene when the download has - * finished (you can use the \c QSimpleUpdater signals to know when the - * download is completed). - */ -bool Updater::useCustomInstallProcedures() const -{ - return m_downloader->useCustomInstallProcedures(); -} - -/** - * Downloads and interpets the update definitions file referenced by the - * \c url() function. - */ -void Updater::checkForUpdates(){ - QNetworkRequest request (url()); - if(!userAgentString().isEmpty()) request.setRawHeader("User-Agent", userAgentString().toUtf8()); - m_manager->get(request); -} - -/** - * Changes the \c url in which the \c Updater can find the update definitions - * file. - */ -void Updater::setUrl (const QString& url) -{ - m_url = url; -} - -/** - * Changes the module \a name. - * \note The module name is used on the user prompts. If the module name is - * empty, then the prompts will show the name of the application. - */ -void Updater::setModuleName (const QString& name) -{ - m_moduleName = name; -} - -/** - * If \a notify is set to \c true, then the \c Updater will notify the user - * when an update is available. - */ -void Updater::setNotifyOnUpdate (const bool notify) -{ - m_notifyOnUpdate = notify; -} - -/** - * If \a notify is set to \c true, then the \c Updater will notify the user - * when it has finished interpreting the update definitions file. - */ -void Updater::setNotifyOnFinish (const bool notify) -{ - m_notifyOnFinish = notify; -} -void Updater::setNoNotifyDownload(const bool notify) -{ - m_noTipDownload = notify; -} -void Updater::setCompareBySameString(const bool notify) -{ - m_bSameStringCompare = notify; -} -/** - * Changes the user agent string used to identify the client application - * from the server in a HTTP session. - * - * By default, the user agent will co - */ -void Updater::setUserAgentString (const QString& agent) -{ - m_userAgentString = agent; - m_downloader->setUserAgentString (agent); -} - -/** - * Changes the module \a version - * \note The module version is used to compare the local and remote versions. - * If the \a version parameter is empty, then the \c Updater will use the - * application version (referenced by \c qApp) - */ -void Updater::setModuleVersion (const QString& version) -{ - m_moduleVersion = version; -} - -/** - * If the \a enabled parameter is set to \c true, the \c Updater will open the - * integrated downloader if the user agrees to install the update (if any) - */ -void Updater::setDownloaderEnabled (const bool enabled) -{ - m_downloaderEnabled = enabled; -} - -/** - * Changes the platform key. - * If the platform key is empty, then the system will use the following keys: - * - On iOS: \c ios - * - On Mac OSX: \c osx - * - On Android: \c android - * - On GNU/Linux: \c linux - * - On Microsoft Windows: \c windows - */ -void Updater::setPlatformKey (const QString& platformKey) -{ - m_platform = platformKey; -} - -/** - * If the \a customAppcast parameter is set to \c true, then the \c Updater - * will not try to read the network reply from the server, instead, it will - * emit the \c appcastDownloaded() signal, which allows the application to - * read and interpret the appcast file by itself - */ -void Updater::setUseCustomAppcast (const bool customAppcast) -{ - m_customAppcast = customAppcast; -} - -/** - * If the \a custom parameter is set to \c true, the \c Updater will not try - * to open the downloaded file. Use the signals fired by the \c QSimpleUpdater - * to install the update from the downloaded file by yourself. - */ -void Updater::setUseCustomInstallProcedures (const bool custom) -{ - m_downloader->setUseCustomInstallProcedures (custom); -} - -/** - * If the \a mandatory_update is set to \c true, the \c Updater has to download and install the - * update. If the user cancels or exits, the application will close - */ -void Updater::setMandatoryUpdate(const bool mandatory_update) -{ - m_mandatoryUpdate = mandatory_update; -} -/** - * Called when the download of the update definitions file is finished. - */ - -void Updater::onReply(QNetworkReply* reply) { - /* Check if we need to redirect */ - QUrl redirect = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); - if (!redirect.isEmpty()) { - setUrl (redirect.toString()); - checkForUpdates(); - return; - } - reply->ignoreSslErrors(); - /* There was a network error */ - int err = reply->error(); - if (err != QNetworkReply::NoError) { - qDebug()<<"Updater::onReply QNetworkReply::Error="<< err <url(); - setUpdateAvailable (false); - emit checkingFinished (url()); - return; - } - /* The application wants to interpret the appcast by itself */ - if (customAppcast()) { - emit appcastDownloaded (url(), reply->readAll()); - emit checkingFinished (url()); - return; - } - - /* Try to create a JSON document from downloaded data */ - QJsonDocument document = QJsonDocument::fromJson (reply->readAll()); - /* JSON is invalid */ - if(document.isNull()) { - qDebug()<<"Updater::onReply document.isNull()"; - setUpdateAvailable (false); - emit checkingFinished (url()); - return; - } - /* Get the platform information */ - QJsonObject updates = document.object().value ("updates").toObject(); - QJsonObject platform = updates.value(platformKey()).toObject(); - /* Get update information */ - m_openUrl = platform.value("open-url").toString(); - m_changelog = platform.value("changelog_zhCN").toString(); - m_downloadUrl = platform.value("download-url").toString(); - m_latestVersion = platform.value("latest-version").toString(); - if(platform.contains("mandatory-update")) m_mandatoryUpdate = platform.value ("mandatory-update").toBool(); - - /* Compare latest and current version */ - if(m_bSameStringCompare) { - m_sameVersion = false; - if(latestVersion()==moduleVersion()) m_sameVersion=true; - setUpdateAvailable(!m_sameVersion); - } else { - if(latestVersion()==moduleVersion()){ - setUpdateAvailable(false); - m_sameVersion = true; - } else { - setUpdateAvailable(compare(latestVersion(), moduleVersion())); - m_sameVersion = false; - } - } - emit checkingFinished(url()); -} - -/** - * Prompts the user based on the value of the \a available parameter and the - * settings of this instance of the \c Updater class. - */ -void Updater::setUpdateAvailable(const bool available) { - m_updateAvailable = available; - QMessageBox box; - box.setTextFormat (Qt::RichText); - box.setIcon (QMessageBox::Information); - if(updateAvailable() && (notifyOnUpdate() || notifyOnFinish())) { - QString text = tr("Would you like to download the update now?"); - if(m_mandatoryUpdate) text = tr ("Would you like to download the update now? This is a mandatory update, exiting now will close the application"); - if(m_noTipDownload) { - m_downloader->setUrlId (url()); - m_downloader->setFileName (downloadUrl().split ("/").last()); - m_downloader->setMandatoryUpdate(m_mandatoryUpdate); - m_downloader->startDownload (QUrl (downloadUrl())); - m_downloader->m_strVersion=latestVersion(); - } else { - if (!openUrl().isEmpty()) QDesktopServices::openUrl (QUrl (openUrl())); - else if (downloaderEnabled()) { - m_downloader->setUrlId (url()); - m_downloader->setFileName (downloadUrl().split ("/").last()); - m_downloader->setMandatoryUpdate(m_mandatoryUpdate); - m_downloader->startDownload (QUrl (downloadUrl())); - m_downloader->m_strVersion=latestVersion(); - } - else QDesktopServices::openUrl (QUrl (downloadUrl())); - } - } - - else if (notifyOnFinish()) { - box.setStandardButtons (QMessageBox::Close); - box.setInformativeText (tr ("No updates are available for the moment")); - box.setText ("

" - + tr ("Congratulations! You are running the " - "latest version of %1").arg (moduleName()) - + "

"); - - box.exec(); - } -} - -/** - * Compares the two version strings (\a x and \a y). - * - If \a x is greater than \y, this function returns \c true. - * - If \a y is greater than \x, this function returns \c false. - * - If both versions are the same, this function returns \c false. - */ -bool Updater::compare(const QString& x, const QString& y) { - QStringList versionsX = x.split("."); - QStringList versionsY = y.split("."); - int count = qMin(versionsX.count(), versionsY.count()); - for (int i = 0; i < count; ++i) { - int a = QString(versionsX.at (i)).toInt(); - int b = QString(versionsY.at (i)).toInt(); - if(a >= b) return true; - else if(b > a) return false; - } - return versionsY.count() < versionsX.count(); -} +/* + * Copyright (c) 2014-2016 Alex Spataru + * + * This file is part of the QSimpleUpdater library, which is released under + * the DBAD license, you can read a copy of it below: + * + * DON'T BE A DICK PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, + * DISTRIBUTION AND MODIFICATION: + * + * Do whatever you like with the original work, just don't be a dick. + * Being a dick includes - but is not limited to - the following instances: + * + * 1a. Outright copyright infringement - Don't just copy this and change the + * name. + * 1b. Selling the unmodified original with no work done what-so-ever, that's + * REALLY being a dick. + * 1c. Modifying the original work to contain hidden harmful content. + * That would make you a PROPER dick. + * + * If you become rich through modifications, related works/services, or + * supporting the original work, share the love. + * Only a dick would make loads off this work and not buy the original works + * creator(s) a pint. + * + * Code is provided with no warranty. Using somebody else's code and bitching + * when it goes wrong makes you a DONKEY dick. + * Fix the problem yourself. A non-dick would submit the fix back. + */ + +#include +#include +#include +#include +#include +#include + +#include "Updater.h" +#include "Downloader.h" +#include "cfg.h" +#include "qsettings.h" +Updater::Updater() { + m_url = ""; + m_openUrl = ""; + m_changelog = ""; + m_downloadUrl = ""; + m_latestVersion = ""; + m_customAppcast = false; + m_notifyOnUpdate = true; + m_notifyOnFinish = false; + m_updateAvailable = true; + m_sameVersion = false; + m_downloaderEnabled = true; + m_noTipDownload = false; + m_bSameStringCompare = false; + m_moduleName = qApp->applicationName(); + m_moduleVersion = qApp->applicationVersion(); + m_mandatoryUpdate = false; + + m_downloader = new Downloader(); + m_manager = new QNetworkAccessManager(); + QNetworkReply *pReply = m_manager->get(QNetworkRequest(QUrl(UpdVerUrl))); + QReplyTimeout *pTimeout = new QReplyTimeout(pReply, 10000); + // 超时进一步处理 + connect(pTimeout, &QReplyTimeout::timeout, [=]() { + qDebug() << "Timeout"; + }); +#if defined Q_OS_WIN + m_platform = "windows"; +#elif defined Q_OS_MAC + m_platform = "osx"; +#elif defined Q_OS_LINUX + m_platform = "linux"; +#elif defined Q_OS_ANDROID + m_platform = "android"; +#elif defined Q_OS_IOS + m_platform = "ios"; +#endif + setUserAgentString (QString ("%1/%2 (Qt; QSimpleUpdater)").arg(qApp->applicationName(), qApp->applicationVersion())); + connect (m_downloader, SIGNAL(downloadFinished(QString, QString)), this, SIGNAL (downloadFinished(QString, QString))); + connect (m_manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(onReply(QNetworkReply*))); +} + +Updater::~Updater() +{ + delete m_downloader; +} + +/** + * Returns the URL of the update definitions file + */ +QString Updater::url() const +{ + return m_url; +} + +/** + * Returns the URL that the update definitions file wants us to open in + * a web browser. + * + * \warning You should call \c checkForUpdates() before using this functio + */ +QString Updater::openUrl() const +{ + return m_openUrl; +} + +/** + * Returns the changelog defined by the update definitions file. + * \warning You should call \c checkForUpdates() before using this function + */ +QString Updater::changelog() const +{ + return m_changelog; +} + +/** + * Returns the name of the module (if defined) + */ +QString Updater::moduleName() const +{ + return m_moduleName; +} + +/** + * Returns the platform key (be it system-set or user-set). + * If you do not define a platform key, the system will assign the following + * platform key: + * - On iOS: \c ios + * - On Mac OSX: \c osx + * - On Android: \c android + * - On GNU/Linux: \c linux + * - On Microsoft Windows: \c windows + */ +QString Updater::platformKey() const +{ + return m_platform; +} + +/** + * Returns the download URL defined by the update definitions file. + * \warning You should call \c checkForUpdates() before using this function + */ +QString Updater::downloadUrl() const +{ + return m_downloadUrl; +} + +/** + * Returns the latest version defined by the update definitions file. + * \warning You should call \c checkForUpdates() before using this function + */ +QString Updater::latestVersion() const +{ + return m_latestVersion; +} + +/** + * Returns the user-agent header used by the client when communicating + * with the server through HTTP + */ +QString Updater::userAgentString() const +{ + return m_userAgentString; +} + +/** + * Returns the "local" version of the installed module + */ +QString Updater::moduleVersion() const +{ + return m_moduleVersion; +} + +/** + * Returns \c true if the updater should NOT interpret the downloaded appcast. + * This is useful if you need to store more variables (or information) in the + * JSON file or use another appcast format (e.g. XML) + */ +bool Updater::customAppcast() const +{ + return m_customAppcast; +} + +/** + * Returns \c true if the updater should notify the user when an update is + * available. + */ +bool Updater::notifyOnUpdate() const +{ + return m_notifyOnUpdate; +} + +/** + * Returns \c true if the updater should notify the user when it finishes + * checking for updates. + * + * \note If set to \c true, the \c Updater will notify the user even when there + * are no updates available (by congratulating him/her about being smart) + */ +bool Updater::notifyOnFinish() const +{ + return m_notifyOnFinish; +} + +/** + * Returns \c true if there the current update is mandatory. + * \warning You should call \c checkForUpdates() before using this function +*/ +bool Updater::mandatoryUpdate() const +{ + return m_mandatoryUpdate; +} + +/** + * Returns \c true if there is an update available. + * \warning You should call \c checkForUpdates() before using this function + */ +bool Updater::updateAvailable() const { + return m_updateAvailable; +} +bool Updater::updateSameVersionAvailable() const { + return m_sameVersion; +} + +/** + * Returns \c true if the integrated downloader is enabled. + * \note If set to \c true, the \c Updater will open the downloader dialog if + * the user agrees to download the update. + */ +bool Updater::downloaderEnabled() const +{ + return m_downloaderEnabled; +} + +/** + * Returns \c true if the updater shall not intervene when the download has + * finished (you can use the \c QSimpleUpdater signals to know when the + * download is completed). + */ +bool Updater::useCustomInstallProcedures() const +{ + return m_downloader->useCustomInstallProcedures(); +} + +/** + * Downloads and interpets the update definitions file referenced by the + * \c url() function. + */ +void Updater::checkForUpdates(){ + QNetworkRequest request (url()); + if(!userAgentString().isEmpty()) request.setRawHeader("User-Agent", userAgentString().toUtf8()); + m_manager->get(request); +} + +/** + * Changes the \c url in which the \c Updater can find the update definitions + * file. + */ +void Updater::setUrl (const QString& url) +{ + m_url = url; +} + +/** + * Changes the module \a name. + * \note The module name is used on the user prompts. If the module name is + * empty, then the prompts will show the name of the application. + */ +void Updater::setModuleName (const QString& name) +{ + m_moduleName = name; +} + +/** + * If \a notify is set to \c true, then the \c Updater will notify the user + * when an update is available. + */ +void Updater::setNotifyOnUpdate (const bool notify) +{ + m_notifyOnUpdate = notify; +} + +/** + * If \a notify is set to \c true, then the \c Updater will notify the user + * when it has finished interpreting the update definitions file. + */ +void Updater::setNotifyOnFinish (const bool notify) +{ + m_notifyOnFinish = notify; +} +void Updater::setNoNotifyDownload(const bool notify) +{ + m_noTipDownload = notify; +} +void Updater::setCompareBySameString(const bool notify) +{ + m_bSameStringCompare = notify; +} +/** + * Changes the user agent string used to identify the client application + * from the server in a HTTP session. + * + * By default, the user agent will co + */ +void Updater::setUserAgentString (const QString& agent) +{ + m_userAgentString = agent; + m_downloader->setUserAgentString (agent); +} + +/** + * Changes the module \a version + * \note The module version is used to compare the local and remote versions. + * If the \a version parameter is empty, then the \c Updater will use the + * application version (referenced by \c qApp) + */ +void Updater::setModuleVersion (const QString& version) +{ + m_moduleVersion = version; +} + +/** + * If the \a enabled parameter is set to \c true, the \c Updater will open the + * integrated downloader if the user agrees to install the update (if any) + */ +void Updater::setDownloaderEnabled (const bool enabled) +{ + m_downloaderEnabled = enabled; +} + +/** + * Changes the platform key. + * If the platform key is empty, then the system will use the following keys: + * - On iOS: \c ios + * - On Mac OSX: \c osx + * - On Android: \c android + * - On GNU/Linux: \c linux + * - On Microsoft Windows: \c windows + */ +void Updater::setPlatformKey (const QString& platformKey) +{ + m_platform = platformKey; +} + +/** + * If the \a customAppcast parameter is set to \c true, then the \c Updater + * will not try to read the network reply from the server, instead, it will + * emit the \c appcastDownloaded() signal, which allows the application to + * read and interpret the appcast file by itself + */ +void Updater::setUseCustomAppcast (const bool customAppcast) +{ + m_customAppcast = customAppcast; +} + +/** + * If the \a custom parameter is set to \c true, the \c Updater will not try + * to open the downloaded file. Use the signals fired by the \c QSimpleUpdater + * to install the update from the downloaded file by yourself. + */ +void Updater::setUseCustomInstallProcedures (const bool custom) +{ + m_downloader->setUseCustomInstallProcedures (custom); +} + +/** + * If the \a mandatory_update is set to \c true, the \c Updater has to download and install the + * update. If the user cancels or exits, the application will close + */ +void Updater::setMandatoryUpdate(const bool mandatory_update) +{ + m_mandatoryUpdate = mandatory_update; +} +/** + * Called when the download of the update definitions file is finished. + */ + +void Updater::onReply(QNetworkReply* reply) { + /* Check if we need to redirect */ + QUrl redirect = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); + if (!redirect.isEmpty()) { + setUrl (redirect.toString()); + checkForUpdates(); + return; + } + reply->ignoreSslErrors(); + /* There was a network error */ + int err = reply->error(); + if (err != QNetworkReply::NoError) { + qDebug()<<"Updater::onReply QNetworkReply::Error="<< err <url(); + setUpdateAvailable (false); + emit checkingFinished (url()); + return; + } + /* The application wants to interpret the appcast by itself */ + if (customAppcast()) { + emit appcastDownloaded (url(), reply->readAll()); + emit checkingFinished (url()); + return; + } + + /* Try to create a JSON document from downloaded data */ + QJsonDocument document = QJsonDocument::fromJson (reply->readAll()); + /* JSON is invalid */ + if(document.isNull()) { + qDebug()<<"Updater::onReply document.isNull()"; + setUpdateAvailable (false); + emit checkingFinished (url()); + return; + } + /* Get the platform information */ + QJsonObject updates = document.object().value ("updates").toObject(); + QJsonObject platform = updates.value(platformKey()).toObject(); + /* Get update information */ + m_openUrl = platform.value("open-url").toString(); + m_changelog = platform.value("changelog_zhCN").toString(); + m_downloadUrl = platform.value("download-url").toString(); + m_latestVersion = platform.value("latest-version").toString(); + if(platform.contains("mandatory-update")) m_mandatoryUpdate = platform.value ("mandatory-update").toBool(); + + /* Compare latest and current version */ + if(m_bSameStringCompare) { + m_sameVersion = false; + if(latestVersion()==moduleVersion()) m_sameVersion=true; + setUpdateAvailable(!m_sameVersion); + } else { + if(latestVersion()==moduleVersion()){ + setUpdateAvailable(false); + m_sameVersion = true; + } else { + setUpdateAvailable(compare(latestVersion(), moduleVersion())); + m_sameVersion = false; + } + } + emit checkingFinished(url()); +} + +/** + * Prompts the user based on the value of the \a available parameter and the + * settings of this instance of the \c Updater class. + */ +void Updater::setUpdateAvailable(const bool available) { + m_updateAvailable = available; + QMessageBox box; + box.setTextFormat (Qt::RichText); + box.setIcon (QMessageBox::Information); + if(updateAvailable() && (notifyOnUpdate() || notifyOnFinish())) { + QString text = tr("Would you like to download the update now?"); + if(m_mandatoryUpdate) text = tr ("Would you like to download the update now? This is a mandatory update, exiting now will close the application"); + if(m_noTipDownload) { + m_downloader->setUrlId (url()); + m_downloader->setFileName (downloadUrl().split ("/").last()); + m_downloader->setMandatoryUpdate(m_mandatoryUpdate); + m_downloader->startDownload (QUrl (downloadUrl())); + m_downloader->m_strVersion=latestVersion(); + } else { + if (!openUrl().isEmpty()) QDesktopServices::openUrl (QUrl (openUrl())); + else if (downloaderEnabled()) { + m_downloader->setUrlId (url()); + m_downloader->setFileName (downloadUrl().split ("/").last()); + m_downloader->setMandatoryUpdate(m_mandatoryUpdate); + m_downloader->startDownload (QUrl (downloadUrl())); + m_downloader->m_strVersion=latestVersion(); + } + else QDesktopServices::openUrl (QUrl (downloadUrl())); + } + } + + else if (notifyOnFinish()) { + box.setStandardButtons (QMessageBox::Close); + box.setInformativeText (tr ("No updates are available for the moment")); + box.setText ("

" + + tr ("Congratulations! You are running the " + "latest version of %1").arg (moduleName()) + + "

"); + + box.exec(); + } +} + +/** + * Compares the two version strings (\a x and \a y). + * - If \a x is greater than \y, this function returns \c true. + * - If \a y is greater than \x, this function returns \c false. + * - If both versions are the same, this function returns \c false. + */ +bool Updater::compare(const QString& x, const QString& y) { + QStringList versionsX = x.split("."); + QStringList versionsY = y.split("."); + int count = qMin(versionsX.count(), versionsY.count()); + for (int i = 0; i < count; ++i) { + int a = QString(versionsX.at (i)).toInt(); + int b = QString(versionsY.at (i)).toInt(); + if(a >= b) return true; + else if(b > a) return false; + } + return versionsY.count() < versionsX.count(); +} diff --git a/LedOK/QSimpleUpdater/src/Updater.h b/LedOK/QSimpleUpdater/src/Updater.h index 984d30d..9e9c064 100644 --- a/LedOK/QSimpleUpdater/src/Updater.h +++ b/LedOK/QSimpleUpdater/src/Updater.h @@ -1,156 +1,156 @@ -/* - * Copyright (c) 2014-2016 Alex Spataru - * - * This file is part of the QSimpleUpdater library, which is released under - * the DBAD license, you can read a copy of it below: - * - * DON'T BE A DICK PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, - * DISTRIBUTION AND MODIFICATION: - * - * Do whatever you like with the original work, just don't be a dick. - * Being a dick includes - but is not limited to - the following instances: - * - * 1a. Outright copyright infringement - Don't just copy this and change the - * name. - * 1b. Selling the unmodified original with no work done what-so-ever, that's - * REALLY being a dick. - * 1c. Modifying the original work to contain hidden harmful content. - * That would make you a PROPER dick. - * - * If you become rich through modifications, related works/services, or - * supporting the original work, share the love. - * Only a dick would make loads off this work and not buy the original works - * creator(s) a pint. - * - * Code is provided with no warranty. Using somebody else's code and bitching - * when it goes wrong makes you a DONKEY dick. - * Fix the problem yourself. A non-dick would submit the fix back. - */ - -#ifndef _QSIMPLEUPDATER_UPDATER_H -#define _QSIMPLEUPDATER_UPDATER_H - -#include -#include -#include -#include - -#include - -class Downloader; - -/** - * \brief Downloads and interprests the update definition file - */ -class QSU_DECL Updater : public QObject -{ - Q_OBJECT - -signals: - void checkingFinished (const QString& url); - void downloadFinished (const QString& url, const QString& filepath); - void appcastDownloaded (const QString& url, const QByteArray& data); - -public: - Updater(); - ~Updater(); - - QString url() const; - QString openUrl() const; - QString changelog() const; - QString moduleName() const; - QString downloadUrl() const; - QString platformKey() const; - QString moduleVersion() const; - QString latestVersion() const; - QString userAgentString() const; - bool mandatoryUpdate() const; - - bool customAppcast() const; - bool notifyOnUpdate() const; - bool notifyOnFinish() const; - bool updateAvailable() const; - bool updateSameVersionAvailable() const; - bool downloaderEnabled() const; - bool useCustomInstallProcedures() const; - -public slots: - void checkForUpdates(); - void setUrl (const QString& url); - void setModuleName (const QString& name); - void setNotifyOnUpdate (const bool notify); - void setNotifyOnFinish (const bool notify); - void setNoNotifyDownload(const bool notify); - void setCompareBySameString(const bool notify); - - void setUserAgentString (const QString& agent); - void setModuleVersion (const QString& version); - void setDownloaderEnabled (const bool enabled); - void setPlatformKey (const QString& platformKey); - void setUseCustomAppcast (const bool customAppcast); - void setUseCustomInstallProcedures (const bool custom); - void setMandatoryUpdate (const bool mandatory_update); - -private slots: - void onReply (QNetworkReply* reply); - void setUpdateAvailable (const bool available); - -private: - bool compare (const QString& x, const QString& y); - -private: - QString m_url; - QString m_userAgentString; - - bool m_customAppcast; - bool m_notifyOnUpdate; - bool m_notifyOnFinish; - bool m_updateAvailable; - bool m_sameVersion; - bool m_downloaderEnabled; - bool m_mandatoryUpdate; - bool m_noTipDownload; - bool m_bSameStringCompare; - - QString m_openUrl; - QString m_platform; - QString m_changelog; - QString m_moduleName; - QString m_downloadUrl; - QString m_moduleVersion; - QString m_latestVersion; - - - Downloader* m_downloader; - QNetworkAccessManager* m_manager; -}; -#include -#include -#include - -class QReplyTimeout : public QObject { - - Q_OBJECT - -public: - QReplyTimeout(QNetworkReply *reply, const int timeout) : QObject(reply) { - Q_ASSERT(reply); - if (reply && reply->isRunning()) { // 启动单次定时器 - QTimer::singleShot(timeout, this, SLOT(onTimeout())); - } - } - -signals: - void timeout(); // 超时信号 - 供进一步处理 - -private slots: - void onTimeout() { // 处理超时 - QNetworkReply *reply = static_cast(parent()); - if (reply->isRunning()) { - reply->abort(); - reply->deleteLater(); - emit timeout(); - } - } -}; -#endif +/* + * Copyright (c) 2014-2016 Alex Spataru + * + * This file is part of the QSimpleUpdater library, which is released under + * the DBAD license, you can read a copy of it below: + * + * DON'T BE A DICK PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, + * DISTRIBUTION AND MODIFICATION: + * + * Do whatever you like with the original work, just don't be a dick. + * Being a dick includes - but is not limited to - the following instances: + * + * 1a. Outright copyright infringement - Don't just copy this and change the + * name. + * 1b. Selling the unmodified original with no work done what-so-ever, that's + * REALLY being a dick. + * 1c. Modifying the original work to contain hidden harmful content. + * That would make you a PROPER dick. + * + * If you become rich through modifications, related works/services, or + * supporting the original work, share the love. + * Only a dick would make loads off this work and not buy the original works + * creator(s) a pint. + * + * Code is provided with no warranty. Using somebody else's code and bitching + * when it goes wrong makes you a DONKEY dick. + * Fix the problem yourself. A non-dick would submit the fix back. + */ + +#ifndef _QSIMPLEUPDATER_UPDATER_H +#define _QSIMPLEUPDATER_UPDATER_H + +#include +#include +#include +#include + +#include + +class Downloader; + +/** + * \brief Downloads and interprests the update definition file + */ +class QSU_DECL Updater : public QObject +{ + Q_OBJECT + +signals: + void checkingFinished (const QString& url); + void downloadFinished (const QString& url, const QString& filepath); + void appcastDownloaded (const QString& url, const QByteArray& data); + +public: + Updater(); + ~Updater(); + + QString url() const; + QString openUrl() const; + QString changelog() const; + QString moduleName() const; + QString downloadUrl() const; + QString platformKey() const; + QString moduleVersion() const; + QString latestVersion() const; + QString userAgentString() const; + bool mandatoryUpdate() const; + + bool customAppcast() const; + bool notifyOnUpdate() const; + bool notifyOnFinish() const; + bool updateAvailable() const; + bool updateSameVersionAvailable() const; + bool downloaderEnabled() const; + bool useCustomInstallProcedures() const; + +public slots: + void checkForUpdates(); + void setUrl (const QString& url); + void setModuleName (const QString& name); + void setNotifyOnUpdate (const bool notify); + void setNotifyOnFinish (const bool notify); + void setNoNotifyDownload(const bool notify); + void setCompareBySameString(const bool notify); + + void setUserAgentString (const QString& agent); + void setModuleVersion (const QString& version); + void setDownloaderEnabled (const bool enabled); + void setPlatformKey (const QString& platformKey); + void setUseCustomAppcast (const bool customAppcast); + void setUseCustomInstallProcedures (const bool custom); + void setMandatoryUpdate (const bool mandatory_update); + +private slots: + void onReply (QNetworkReply* reply); + void setUpdateAvailable (const bool available); + +private: + bool compare (const QString& x, const QString& y); + +private: + QString m_url; + QString m_userAgentString; + + bool m_customAppcast; + bool m_notifyOnUpdate; + bool m_notifyOnFinish; + bool m_updateAvailable; + bool m_sameVersion; + bool m_downloaderEnabled; + bool m_mandatoryUpdate; + bool m_noTipDownload; + bool m_bSameStringCompare; + + QString m_openUrl; + QString m_platform; + QString m_changelog; + QString m_moduleName; + QString m_downloadUrl; + QString m_moduleVersion; + QString m_latestVersion; + + + Downloader* m_downloader; + QNetworkAccessManager* m_manager; +}; +#include +#include +#include + +class QReplyTimeout : public QObject { + + Q_OBJECT + +public: + QReplyTimeout(QNetworkReply *reply, const int timeout) : QObject(reply) { + Q_ASSERT(reply); + if (reply && reply->isRunning()) { // 启动单次定时器 + QTimer::singleShot(timeout, this, SLOT(onTimeout())); + } + } + +signals: + void timeout(); // 超时信号 - 供进一步处理 + +private slots: + void onTimeout() { // 处理超时 + QNetworkReply *reply = static_cast(parent()); + if (reply->isRunning()) { + reply->abort(); + reply->deleteLater(); + emit timeout(); + } + } +}; +#endif diff --git a/LedOK/QSimpleUpdater/tests/Test_Downloader.h b/LedOK/QSimpleUpdater/tests/Test_Downloader.h index b0d0658..a8c4e9b 100644 --- a/LedOK/QSimpleUpdater/tests/Test_Downloader.h +++ b/LedOK/QSimpleUpdater/tests/Test_Downloader.h @@ -1,34 +1,34 @@ -/* - * Copyright (c) 2015-2016 Alex Spataru - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef TEST_DOWNLOADER_H -#define TEST_DOWNLOADER_H - -#include -#include - -class Test_Downloader : public QObject -{ - Q_OBJECT -}; - -#endif +/* + * Copyright (c) 2015-2016 Alex Spataru + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef TEST_DOWNLOADER_H +#define TEST_DOWNLOADER_H + +#include +#include + +class Test_Downloader : public QObject +{ + Q_OBJECT +}; + +#endif diff --git a/LedOK/QSimpleUpdater/tests/Test_QSimpleUpdater.h b/LedOK/QSimpleUpdater/tests/Test_QSimpleUpdater.h index 2fff5ee..0e78a3f 100644 --- a/LedOK/QSimpleUpdater/tests/Test_QSimpleUpdater.h +++ b/LedOK/QSimpleUpdater/tests/Test_QSimpleUpdater.h @@ -1,34 +1,34 @@ -/* - * Copyright (c) 2015-2016 Alex Spataru - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef TEST_QSIMPLEUPDATER_H -#define TEST_QSIMPLEUPDATER_H - -#include -#include - -class Test_QSimpleUpdater : public QObject -{ - Q_OBJECT -}; - -#endif +/* + * Copyright (c) 2015-2016 Alex Spataru + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef TEST_QSIMPLEUPDATER_H +#define TEST_QSIMPLEUPDATER_H + +#include +#include + +class Test_QSimpleUpdater : public QObject +{ + Q_OBJECT +}; + +#endif diff --git a/LedOK/QSimpleUpdater/tests/Test_Updater.h b/LedOK/QSimpleUpdater/tests/Test_Updater.h index 886eaba..cb354d8 100644 --- a/LedOK/QSimpleUpdater/tests/Test_Updater.h +++ b/LedOK/QSimpleUpdater/tests/Test_Updater.h @@ -1,34 +1,34 @@ -/* - * Copyright (c) 2015-2016 Alex Spataru - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef TEST_UPDATER_H -#define TEST_UPDATER_H - -#include -#include - -class Test_Updater : public QObject -{ - Q_OBJECT -}; - -#endif +/* + * Copyright (c) 2015-2016 Alex Spataru + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef TEST_UPDATER_H +#define TEST_UPDATER_H + +#include +#include + +class Test_Updater : public QObject +{ + Q_OBJECT +}; + +#endif diff --git a/LedOK/QSimpleUpdater/tests/main.cpp b/LedOK/QSimpleUpdater/tests/main.cpp index 60e7521..787818e 100644 --- a/LedOK/QSimpleUpdater/tests/main.cpp +++ b/LedOK/QSimpleUpdater/tests/main.cpp @@ -1,41 +1,41 @@ -/* - * Copyright (c) 2015-2016 Alex Spataru - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "Test_Updater.h" -#include "Test_Downloader.h" -#include "Test_QSimpleUpdater.h" - -int main (int argc, char* argv[]) -{ - QApplication app (argc, argv); - - app.setApplicationName ("QSimpleUpdater Tests"); - app.setOrganizationName ("The QSimpleUpdater Library"); - - QTest::qExec (new Test_Updater, argc, argv); - QTest::qExec (new Test_Downloader, argc, argv); - QTest::qExec (new Test_QSimpleUpdater, argc, argv); - - QTimer::singleShot (1000, Qt::PreciseTimer, qApp, SLOT (quit())); - - return app.exec(); -} +/* + * Copyright (c) 2015-2016 Alex Spataru + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "Test_Updater.h" +#include "Test_Downloader.h" +#include "Test_QSimpleUpdater.h" + +int main (int argc, char* argv[]) +{ + QApplication app (argc, argv); + + app.setApplicationName ("QSimpleUpdater Tests"); + app.setOrganizationName ("The QSimpleUpdater Library"); + + QTest::qExec (new Test_Updater, argc, argv); + QTest::qExec (new Test_Downloader, argc, argv); + QTest::qExec (new Test_QSimpleUpdater, argc, argv); + + QTimer::singleShot (1000, Qt::PreciseTimer, qApp, SLOT (quit())); + + return app.exec(); +} diff --git a/LedOK/QSimpleUpdater/tutorial/src/Window.cpp b/LedOK/QSimpleUpdater/tutorial/src/Window.cpp index 1b34273..5879e06 100644 --- a/LedOK/QSimpleUpdater/tutorial/src/Window.cpp +++ b/LedOK/QSimpleUpdater/tutorial/src/Window.cpp @@ -1,137 +1,137 @@ -/* - * Copyright (c) 2014-2016 Alex Spataru - * - * This work is free. You can redistribute it and/or modify it under the - * terms of the Do What The Fuck You Want To Public License, Version 2, - * as published by Sam Hocevar. See the COPYING file for more details. - */ - -#include "Window.h" -#include "ui_Window.h" - -#include -#include - -//============================================================================== -// Define the URL of the Update Definitions file -//============================================================================== - -static const QString DEFS_URL = "https://raw.githubusercontent.com/" - "alex-spataru/QSimpleUpdater/master/tutorial/" - "definitions/updates.json"; - -//============================================================================== -// Window::Window -//============================================================================== - -Window::Window (QWidget* parent) : QMainWindow (parent) -{ - m_ui = new Ui::Window; - m_ui->setupUi (this); - - setWindowTitle (qApp->applicationName()); - - /* QSimpleUpdater is single-instance */ - m_updater = QSimpleUpdater::getInstance(); - - /* Check for updates when the "Check For Updates" button is clicked */ - connect (m_updater, SIGNAL (checkingFinished (QString)), - this, SLOT (updateChangelog (QString))); - connect (m_updater, SIGNAL (appcastDownloaded (QString, QByteArray)), - this, SLOT (displayAppcast (QString, QByteArray))); - - /* React to button clicks */ - connect (m_ui->resetButton, SIGNAL (clicked()), - this, SLOT (resetFields())); - connect (m_ui->closeButton, SIGNAL (clicked()), - this, SLOT (close())); - connect (m_ui->checkButton, SIGNAL (clicked()), - this, SLOT (checkForUpdates())); - - /* Resize the dialog to fit */ - setMinimumSize (minimumSizeHint()); - resize (minimumSizeHint()); - - /* Reset the UI state */ - resetFields(); -} - -//============================================================================== -// Window::~Window -//============================================================================== - -Window::~Window() -{ - delete m_ui; -} - -//============================================================================== -// Window::checkForUpdates -//============================================================================== - -void Window::resetFields() -{ - m_ui->installedVersion->setText ("0.1"); - m_ui->customAppcast->setChecked (false); - m_ui->enableDownloader->setChecked (true); - m_ui->showAllNotifcations->setChecked (false); - m_ui->showUpdateNotifications->setChecked (true); - m_ui->mandatoryUpdate->setChecked (false); - -} - -//============================================================================== -// Window::checkForUpdates -//============================================================================== - -void Window::checkForUpdates() -{ - /* Get settings from the UI */ - QString version = m_ui->installedVersion->text(); - bool customAppcast = m_ui->customAppcast->isChecked(); - bool downloaderEnabled = m_ui->enableDownloader->isChecked(); - bool notifyOnFinish = m_ui->showAllNotifcations->isChecked(); - bool notifyOnUpdate = m_ui->showUpdateNotifications->isChecked(); - bool mandatoryUpdate = m_ui->mandatoryUpdate->isChecked(); - - /* Apply the settings */ - m_updater->setModuleVersion (DEFS_URL, version); - m_updater->setNotifyOnFinish (DEFS_URL, notifyOnFinish); - m_updater->setNotifyOnUpdate (DEFS_URL, notifyOnUpdate); - m_updater->setUseCustomAppcast (DEFS_URL, customAppcast); - m_updater->setDownloaderEnabled (DEFS_URL, downloaderEnabled); - m_updater->setMandatoryUpdate (DEFS_URL, mandatoryUpdate); - - /* Check for updates */ - m_updater->checkForUpdates (DEFS_URL); -} - -//============================================================================== -// Window::updateChangelog -//============================================================================== - -void Window::updateChangelog (const QString& url) -{ - if (url == DEFS_URL) - m_ui->changelogText->setText (m_updater->getChangelog (url)); -} - - -//============================================================================== -// Window::displayAppcast -//============================================================================== - -void Window::displayAppcast (const QString& url, const QByteArray& reply) -{ - if (url == DEFS_URL) { - QString text = "This is the downloaded appcast:

" +
-                       QString::fromUtf8 (reply) +
-                       "

If you need to store more information on the " - "appcast (or use another format), just use the " - "QSimpleUpdater::setCustomAppcast() function. " - "It allows your application to interpret the appcast " - "using your code and not QSU's code.

"; - - m_ui->changelogText->setText (text); - } -} +/* + * Copyright (c) 2014-2016 Alex Spataru + * + * This work is free. You can redistribute it and/or modify it under the + * terms of the Do What The Fuck You Want To Public License, Version 2, + * as published by Sam Hocevar. See the COPYING file for more details. + */ + +#include "Window.h" +#include "ui_Window.h" + +#include +#include + +//============================================================================== +// Define the URL of the Update Definitions file +//============================================================================== + +static const QString DEFS_URL = "https://raw.githubusercontent.com/" + "alex-spataru/QSimpleUpdater/master/tutorial/" + "definitions/updates.json"; + +//============================================================================== +// Window::Window +//============================================================================== + +Window::Window (QWidget* parent) : QMainWindow (parent) +{ + m_ui = new Ui::Window; + m_ui->setupUi (this); + + setWindowTitle (qApp->applicationName()); + + /* QSimpleUpdater is single-instance */ + m_updater = QSimpleUpdater::getInstance(); + + /* Check for updates when the "Check For Updates" button is clicked */ + connect (m_updater, SIGNAL (checkingFinished (QString)), + this, SLOT (updateChangelog (QString))); + connect (m_updater, SIGNAL (appcastDownloaded (QString, QByteArray)), + this, SLOT (displayAppcast (QString, QByteArray))); + + /* React to button clicks */ + connect (m_ui->resetButton, SIGNAL (clicked()), + this, SLOT (resetFields())); + connect (m_ui->closeButton, SIGNAL (clicked()), + this, SLOT (close())); + connect (m_ui->checkButton, SIGNAL (clicked()), + this, SLOT (checkForUpdates())); + + /* Resize the dialog to fit */ + setMinimumSize (minimumSizeHint()); + resize (minimumSizeHint()); + + /* Reset the UI state */ + resetFields(); +} + +//============================================================================== +// Window::~Window +//============================================================================== + +Window::~Window() +{ + delete m_ui; +} + +//============================================================================== +// Window::checkForUpdates +//============================================================================== + +void Window::resetFields() +{ + m_ui->installedVersion->setText ("0.1"); + m_ui->customAppcast->setChecked (false); + m_ui->enableDownloader->setChecked (true); + m_ui->showAllNotifcations->setChecked (false); + m_ui->showUpdateNotifications->setChecked (true); + m_ui->mandatoryUpdate->setChecked (false); + +} + +//============================================================================== +// Window::checkForUpdates +//============================================================================== + +void Window::checkForUpdates() +{ + /* Get settings from the UI */ + QString version = m_ui->installedVersion->text(); + bool customAppcast = m_ui->customAppcast->isChecked(); + bool downloaderEnabled = m_ui->enableDownloader->isChecked(); + bool notifyOnFinish = m_ui->showAllNotifcations->isChecked(); + bool notifyOnUpdate = m_ui->showUpdateNotifications->isChecked(); + bool mandatoryUpdate = m_ui->mandatoryUpdate->isChecked(); + + /* Apply the settings */ + m_updater->setModuleVersion (DEFS_URL, version); + m_updater->setNotifyOnFinish (DEFS_URL, notifyOnFinish); + m_updater->setNotifyOnUpdate (DEFS_URL, notifyOnUpdate); + m_updater->setUseCustomAppcast (DEFS_URL, customAppcast); + m_updater->setDownloaderEnabled (DEFS_URL, downloaderEnabled); + m_updater->setMandatoryUpdate (DEFS_URL, mandatoryUpdate); + + /* Check for updates */ + m_updater->checkForUpdates (DEFS_URL); +} + +//============================================================================== +// Window::updateChangelog +//============================================================================== + +void Window::updateChangelog (const QString& url) +{ + if (url == DEFS_URL) + m_ui->changelogText->setText (m_updater->getChangelog (url)); +} + + +//============================================================================== +// Window::displayAppcast +//============================================================================== + +void Window::displayAppcast (const QString& url, const QByteArray& reply) +{ + if (url == DEFS_URL) { + QString text = "This is the downloaded appcast:

" +
+                       QString::fromUtf8 (reply) +
+                       "

If you need to store more information on the " + "appcast (or use another format), just use the " + "QSimpleUpdater::setCustomAppcast() function. " + "It allows your application to interpret the appcast " + "using your code and not QSU's code.

"; + + m_ui->changelogText->setText (text); + } +} diff --git a/LedOK/QSimpleUpdater/tutorial/src/Window.h b/LedOK/QSimpleUpdater/tutorial/src/Window.h index ccd8da2..027508e 100644 --- a/LedOK/QSimpleUpdater/tutorial/src/Window.h +++ b/LedOK/QSimpleUpdater/tutorial/src/Window.h @@ -1,40 +1,40 @@ -/* - * Copyright (c) 2014-2016 Alex Spataru - * - * This work is free. You can redistribute it and/or modify it under the - * terms of the Do What The Fuck You Want To Public License, Version 2, - * as published by Sam Hocevar. See the COPYING file for more details. - */ - -#ifndef _WINDOW_H -#define _WINDOW_H - -#include -#include - -namespace Ui { -class Window; -} - -class QSimpleUpdater; - -class Window : public QMainWindow -{ - Q_OBJECT - -public: - explicit Window (QWidget* parent = 0); - ~Window(); - -public slots: - void resetFields(); - void checkForUpdates(); - void updateChangelog (const QString& url); - void displayAppcast (const QString& url, const QByteArray& reply); - -private: - Ui::Window* m_ui; - QSimpleUpdater* m_updater; -}; - -#endif +/* + * Copyright (c) 2014-2016 Alex Spataru + * + * This work is free. You can redistribute it and/or modify it under the + * terms of the Do What The Fuck You Want To Public License, Version 2, + * as published by Sam Hocevar. See the COPYING file for more details. + */ + +#ifndef _WINDOW_H +#define _WINDOW_H + +#include +#include + +namespace Ui { +class Window; +} + +class QSimpleUpdater; + +class Window : public QMainWindow +{ + Q_OBJECT + +public: + explicit Window (QWidget* parent = 0); + ~Window(); + +public slots: + void resetFields(); + void checkForUpdates(); + void updateChangelog (const QString& url); + void displayAppcast (const QString& url, const QByteArray& reply); + +private: + Ui::Window* m_ui; + QSimpleUpdater* m_updater; +}; + +#endif diff --git a/LedOK/QSimpleUpdater/tutorial/src/main.cpp b/LedOK/QSimpleUpdater/tutorial/src/main.cpp index a793d0d..85c31ba 100644 --- a/LedOK/QSimpleUpdater/tutorial/src/main.cpp +++ b/LedOK/QSimpleUpdater/tutorial/src/main.cpp @@ -1,21 +1,21 @@ -/* - * Copyright (c) 2014-2016 Alex Spataru - * - * This work is free. You can redistribute it and/or modify it under the - * terms of the Do What The Fuck You Want To Public License, Version 2, - * as published by Sam Hocevar. See the COPYING file for more details. - */ - -#include "Window.h" - -int main (int argc, char** argv) -{ - QApplication app (argc, argv); - app.setApplicationVersion ("1.0"); - app.setApplicationName ("Bob's Badass App"); - - Window window; - window.show(); - - return app.exec(); -} +/* + * Copyright (c) 2014-2016 Alex Spataru + * + * This work is free. You can redistribute it and/or modify it under the + * terms of the Do What The Fuck You Want To Public License, Version 2, + * as published by Sam Hocevar. See the COPYING file for more details. + */ + +#include "Window.h" + +int main (int argc, char** argv) +{ + QApplication app (argc, argv); + app.setApplicationVersion ("1.0"); + app.setApplicationName ("Bob's Badass App"); + + Window window; + window.show(); + + return app.exec(); +} diff --git a/LedOK/base/aboutdlg.cpp b/LedOK/base/aboutdlg.cpp index 92327ca..6361d3c 100644 --- a/LedOK/base/aboutdlg.cpp +++ b/LedOK/base/aboutdlg.cpp @@ -1,43 +1,43 @@ -#include "aboutdlg.h" -#include "globaldefine.h" -#include -#include -#include - -AboutDlg::AboutDlg(QWidget *parent) : QDialog(parent) { - setWindowFlag(Qt::WindowContextHelpButtonHint, false); - setWindowTitle(tr("About")); - - auto hBox = new QHBoxLayout(this); - hBox->setContentsMargins(24,24,24,24); - hBox->setSpacing(24); - auto label_4 = new QLabel(); - label_4->setPixmap(QPixmap(":/res/Logo.png")); - hBox->addWidget(label_4); - - auto vBox = new QVBoxLayout(); - auto label = new QLabel("LedOK Express"); - QFont font; - font.setPointSize(24); - label->setFont(font); - label->setTextFormat(Qt::AutoText); - label->setAlignment(Qt::AlignCenter); - vBox->addWidget(label); - - auto label_2 = new QLabel(APP_VERSION); - QFont font1; - font1.setPointSize(14); - label_2->setFont(font1); - label_2->setAlignment(Qt::AlignCenter); - vBox->addWidget(label_2); - - auto label_3 = new QLabel("www.ledok.cn"); - QFont font2; - font2.setPointSize(15); - label_3->setFont(font2); - label_3->setAlignment(Qt::AlignCenter); - label_3->setOpenExternalLinks(true); - vBox->addWidget(label_3); - - hBox->addLayout(vBox); -} +#include "aboutdlg.h" +#include "globaldefine.h" +#include +#include +#include + +AboutDlg::AboutDlg(QWidget *parent) : QDialog(parent) { + setWindowFlag(Qt::WindowContextHelpButtonHint, false); + setWindowTitle(tr("About")); + + auto hBox = new QHBoxLayout(this); + hBox->setContentsMargins(24,24,24,24); + hBox->setSpacing(24); + auto label_4 = new QLabel(); + label_4->setPixmap(QPixmap(":/res/Logo.png")); + hBox->addWidget(label_4); + + auto vBox = new QVBoxLayout(); + auto label = new QLabel("LedOK Express"); + QFont font; + font.setPointSize(24); + label->setFont(font); + label->setTextFormat(Qt::AutoText); + label->setAlignment(Qt::AlignCenter); + vBox->addWidget(label); + + auto label_2 = new QLabel(APP_VERSION); + QFont font1; + font1.setPointSize(14); + label_2->setFont(font1); + label_2->setAlignment(Qt::AlignCenter); + vBox->addWidget(label_2); + + auto label_3 = new QLabel("www.ledok.cn"); + QFont font2; + font2.setPointSize(15); + label_3->setFont(font2); + label_3->setAlignment(Qt::AlignCenter); + label_3->setOpenExternalLinks(true); + vBox->addWidget(label_3); + + hBox->addLayout(vBox); +} diff --git a/LedOK/base/aboutdlg.h b/LedOK/base/aboutdlg.h index b182f75..566056d 100644 --- a/LedOK/base/aboutdlg.h +++ b/LedOK/base/aboutdlg.h @@ -1,12 +1,12 @@ -#ifndef ABOUTDLG_H -#define ABOUTDLG_H - -#include - -class AboutDlg : public QDialog { - Q_OBJECT -public: - explicit AboutDlg(QWidget *parent = nullptr); -}; - -#endif // ABOUTDLG_H +#ifndef ABOUTDLG_H +#define ABOUTDLG_H + +#include + +class AboutDlg : public QDialog { + Q_OBJECT +public: + explicit AboutDlg(QWidget *parent = nullptr); +}; + +#endif // ABOUTDLG_H diff --git a/LedOK/base/changepasswordform.cpp b/LedOK/base/changepasswordform.cpp index 5d670f9..cadff25 100644 --- a/LedOK/base/changepasswordform.cpp +++ b/LedOK/base/changepasswordform.cpp @@ -1,84 +1,84 @@ -#include "changepasswordform.h" -#include -#include -#include -#include -#include -#include -#include "cfg.h" -#include "QTextCodec" -ChangePasswordForm::ChangePasswordForm(QWidget *parent) : BaseDlg(parent) { - resize(240, 160); - auto vBox = new QVBoxLayout(this); - auto hBox = new QHBoxLayout(); - auto label = new QLabel(tr("Old password")); - hBox->addWidget(label); - - fdOld = new QLineEdit(); - fdOld->setEchoMode(QLineEdit::Password); - fdOld->setMaxLength(16); - hBox->addWidget(fdOld); - vBox->addLayout(hBox); - - hBox = new QHBoxLayout(); - auto label_2 = new QLabel(tr("New password")); - hBox->addWidget(label_2); - - fdNew = new QLineEdit(); - fdNew->setEchoMode(QLineEdit::Password); - fdNew->setMaxLength(8); - hBox->addWidget(fdNew); - vBox->addLayout(hBox); - - hBox = new QHBoxLayout(); - auto label_3 = new QLabel(tr("Repeat again")); - hBox->addWidget(label_3); - - fdAgn = new QLineEdit(); - fdAgn->setEchoMode(QLineEdit::Password); - fdAgn->setMaxLength(8); - hBox->addWidget(fdAgn); - vBox->addLayout(hBox); - - hBox = new QHBoxLayout(); - auto pushButton_2 = new QPushButton(tr("OK")); - pushButton_2->setProperty("ssType", "progManageTool"); - hBox->addWidget(pushButton_2); - connect(pushButton_2, &QPushButton::clicked, this, [this]() { - QString pwdOld = fdOld->text(); - if(pwdOld.isEmpty()) { - QMessageBox::warning(this, tr("Tip"), tr("Please input old password")); - fdOld->setFocus(); - return; - } - QSettings settings; - QString pwdRaw = settings.value("advUiPs").toString(); - QString pwd = pwdRaw.isEmpty() ? "888" : QTextCodec::codecForName("GBK")->toUnicode(QByteArray::fromBase64(pwdRaw.toLocal8Bit())); - if(pwd != pwdOld) { - QMessageBox::critical(this, tr("Tip"), tr("Old password is wrong")); - fdOld->setFocus(); - return; - } - QString pwdNew = fdNew->text(); - if(pwdNew.length() < 6) { - QMessageBox::warning(this, tr("Tip"), tr("Please enter a password with more than 6 characters")); - fdNew->setFocus(); - return; - } - QString pwdAgn = fdAgn->text(); - if(pwdAgn != pwdNew) { - QMessageBox::warning(this, tr("Tip"), tr("The new password is not consistent in two times")); - fdAgn->setFocus(); - return; - } - settings.setValue("advUiPs", QString::fromLatin1(pwdNew.toLocal8Bit().toBase64())); - QMessageBox::information(this, tr("Tip"), tr("Password changed successfully")); - accept(); - }); - - auto pushButton = new QPushButton(tr("Cancel")); - pushButton->setProperty("ssType", "progManageTool"); - hBox->addWidget(pushButton); - connect(pushButton, &QPushButton::clicked, this, &ChangePasswordForm::reject); - vBox->addLayout(hBox); -} +#include "changepasswordform.h" +#include +#include +#include +#include +#include +#include +#include "cfg.h" +#include "QTextCodec" +ChangePasswordForm::ChangePasswordForm(QWidget *parent) : BaseDlg(parent) { + resize(240, 160); + auto vBox = new QVBoxLayout(this); + auto hBox = new QHBoxLayout(); + auto label = new QLabel(tr("Old password")); + hBox->addWidget(label); + + fdOld = new QLineEdit(); + fdOld->setEchoMode(QLineEdit::Password); + fdOld->setMaxLength(16); + hBox->addWidget(fdOld); + vBox->addLayout(hBox); + + hBox = new QHBoxLayout(); + auto label_2 = new QLabel(tr("New password")); + hBox->addWidget(label_2); + + fdNew = new QLineEdit(); + fdNew->setEchoMode(QLineEdit::Password); + fdNew->setMaxLength(8); + hBox->addWidget(fdNew); + vBox->addLayout(hBox); + + hBox = new QHBoxLayout(); + auto label_3 = new QLabel(tr("Repeat again")); + hBox->addWidget(label_3); + + fdAgn = new QLineEdit(); + fdAgn->setEchoMode(QLineEdit::Password); + fdAgn->setMaxLength(8); + hBox->addWidget(fdAgn); + vBox->addLayout(hBox); + + hBox = new QHBoxLayout(); + auto pushButton_2 = new QPushButton(tr("OK")); + pushButton_2->setProperty("ssType", "progManageTool"); + hBox->addWidget(pushButton_2); + connect(pushButton_2, &QPushButton::clicked, this, [this]() { + QString pwdOld = fdOld->text(); + if(pwdOld.isEmpty()) { + QMessageBox::warning(this, tr("Tip"), tr("Please input old password")); + fdOld->setFocus(); + return; + } + QSettings settings; + QString pwdRaw = settings.value("advUiPs").toString(); + QString pwd = pwdRaw.isEmpty() ? "888" : QTextCodec::codecForName("GBK")->toUnicode(QByteArray::fromBase64(pwdRaw.toLocal8Bit())); + if(pwd != pwdOld) { + QMessageBox::critical(this, tr("Tip"), tr("Old password is wrong")); + fdOld->setFocus(); + return; + } + QString pwdNew = fdNew->text(); + if(pwdNew.length() < 6) { + QMessageBox::warning(this, tr("Tip"), tr("Please enter a password with more than 6 characters")); + fdNew->setFocus(); + return; + } + QString pwdAgn = fdAgn->text(); + if(pwdAgn != pwdNew) { + QMessageBox::warning(this, tr("Tip"), tr("The new password is not consistent in two times")); + fdAgn->setFocus(); + return; + } + settings.setValue("advUiPs", QString::fromLatin1(pwdNew.toLocal8Bit().toBase64())); + QMessageBox::information(this, tr("Tip"), tr("Password changed successfully")); + accept(); + }); + + auto pushButton = new QPushButton(tr("Cancel")); + pushButton->setProperty("ssType", "progManageTool"); + hBox->addWidget(pushButton); + connect(pushButton, &QPushButton::clicked, this, &ChangePasswordForm::reject); + vBox->addLayout(hBox); +} diff --git a/LedOK/base/changepasswordform.h b/LedOK/base/changepasswordform.h index ad0b372..f1301f9 100644 --- a/LedOK/base/changepasswordform.h +++ b/LedOK/base/changepasswordform.h @@ -1,16 +1,16 @@ -#ifndef CHANGEPASSWORDFORM_H -#define CHANGEPASSWORDFORM_H - -#include "basedlg.h" -#include - -class ChangePasswordForm : public BaseDlg { - Q_OBJECT - -public: - explicit ChangePasswordForm(QWidget *parent = nullptr); - QLineEdit *fdOld, *fdNew, *fdAgn; - -}; - -#endif // CHANGEPASSWORDFORM_H +#ifndef CHANGEPASSWORDFORM_H +#define CHANGEPASSWORDFORM_H + +#include "basedlg.h" +#include + +class ChangePasswordForm : public BaseDlg { + Q_OBJECT + +public: + explicit ChangePasswordForm(QWidget *parent = nullptr); + QLineEdit *fdOld, *fdNew, *fdAgn; + +}; + +#endif // CHANGEPASSWORDFORM_H diff --git a/LedOK/base/customprogressindicator.cpp b/LedOK/base/customprogressindicator.cpp index cd7ecdb..743fcf1 100644 --- a/LedOK/base/customprogressindicator.cpp +++ b/LedOK/base/customprogressindicator.cpp @@ -1,137 +1,137 @@ -#include "customprogressindicator.h" -#include -#include - -CustomProgressIndicator::CustomProgressIndicator(QWidget* parent) - : QWidget(parent), - angle_(0), - timerId_(-1), - delay_(20), - displayedWhenStopped_(false), - color_(Qt::green) { - setAttribute(Qt::WA_DeleteOnClose); - setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - setFocusPolicy(Qt::NoFocus); - setWindowFlags(Qt::FramelessWindowHint);//无窗体 - setAttribute(Qt::WA_TranslucentBackground);//背景透明 -} - -bool CustomProgressIndicator::isAnimated () const { - return (timerId_ != -1); -} - -void CustomProgressIndicator::setDisplayedWhenStopped(bool state) { - displayedWhenStopped_ = state; - - update(); -} - -bool CustomProgressIndicator::isDisplayedWhenStopped() const { - return displayedWhenStopped_; -} -void CustomProgressIndicator::setDisplayModel(int iFlag) -{ - m_iLoopBackFlag=iFlag; -} -void CustomProgressIndicator::startAnimation() { - angle_ = 0; - - if (timerId_ == -1) { - timerId_ = startTimer(delay_); - } -} -void CustomProgressIndicator::setDisplayStringInfo(QString strTip,QString strTiping) { - m_strTip=strTip; - m_strTiping=strTiping; - update(); -} -void CustomProgressIndicator::stopAnimation() { - if (timerId_ != -1) { - killTimer(timerId_); - } - - timerId_ = -1; - - update(); -} - -void CustomProgressIndicator::setAnimationDelay(int delay) { - if (timerId_ != -1){ - killTimer(timerId_); - } - - delay_ = delay; - - if (timerId_ != -1){ - timerId_ = startTimer(delay_); - } -} - -void CustomProgressIndicator::setColor(const QColor & color) { - color_ = color; - - update(); -} - -QSize CustomProgressIndicator::sizeHint() const { - return QSize(80,80); -} - - -void CustomProgressIndicator::timerEvent(QTimerEvent *) { - angle_ = (angle_+30)%360; - - update(); -} - -void CustomProgressIndicator::paintEvent(QPaintEvent *) { - QPainter p(this); - drawJuHua(&p); -} -void CustomProgressIndicator::drawJuHua(QPainter *painter) -{ - painter->setRenderHint(QPainter::Antialiasing); - if (displayedWhenStopped_ && !isAnimated()) //如果displayedWhenStopped_==flash并且动画已经停止则不绘制 - { - painter->setPen(color_); - painter->drawPixmap(rect(),currentPix_); - painter->drawText(rect(), Qt::AlignCenter, m_strTip); - - return; - } - - int width = qMin(this->width(), this->height()); - - int outerRadius = (width-1) >> 1; - int innerRadius = int(((width-1) >> 1)*0.38); - - int capsuleHeight = outerRadius - innerRadius; - int capsuleWidth = (width > 32 ) ? (int)(capsuleHeight *0.23) : (int)(capsuleHeight *0.35); - int capsuleRadius = capsuleWidth >> 1; - if(m_iLoopBackFlag==1) - { - painter->setPen(color_); - painter->drawText(rect(), Qt::AlignCenter, m_strTiping); - } - else { - /* 撰写进度 */ - if (progress_ > 0 && progress_ < 100) { - painter->setPen(color_); - painter->drawText(rect(), Qt::AlignCenter, QString("%1%").arg(progress_)); - } - else if (progress_ == 100) { - stopAnimation(); - } - } - for (int i=0; i<12; ++i) { - QColor color = color_; - color.setAlphaF(1.0f - (i/12.0f)); - painter->setPen(Qt::NoPen); - painter->setBrush(color); - painter->save(); - painter->translate(rect().center()); - painter->rotate(angle_ - i*30.0f); - painter->drawRoundedRect(((-capsuleWidth) >> 1), -(innerRadius+capsuleHeight), capsuleWidth, capsuleHeight, capsuleRadius, capsuleRadius); - painter->restore(); - } -} +#include "customprogressindicator.h" +#include +#include + +CustomProgressIndicator::CustomProgressIndicator(QWidget* parent) + : QWidget(parent), + angle_(0), + timerId_(-1), + delay_(20), + displayedWhenStopped_(false), + color_(Qt::green) { + setAttribute(Qt::WA_DeleteOnClose); + setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + setFocusPolicy(Qt::NoFocus); + setWindowFlags(Qt::FramelessWindowHint);//无窗体 + setAttribute(Qt::WA_TranslucentBackground);//背景透明 +} + +bool CustomProgressIndicator::isAnimated () const { + return (timerId_ != -1); +} + +void CustomProgressIndicator::setDisplayedWhenStopped(bool state) { + displayedWhenStopped_ = state; + + update(); +} + +bool CustomProgressIndicator::isDisplayedWhenStopped() const { + return displayedWhenStopped_; +} +void CustomProgressIndicator::setDisplayModel(int iFlag) +{ + m_iLoopBackFlag=iFlag; +} +void CustomProgressIndicator::startAnimation() { + angle_ = 0; + + if (timerId_ == -1) { + timerId_ = startTimer(delay_); + } +} +void CustomProgressIndicator::setDisplayStringInfo(QString strTip,QString strTiping) { + m_strTip=strTip; + m_strTiping=strTiping; + update(); +} +void CustomProgressIndicator::stopAnimation() { + if (timerId_ != -1) { + killTimer(timerId_); + } + + timerId_ = -1; + + update(); +} + +void CustomProgressIndicator::setAnimationDelay(int delay) { + if (timerId_ != -1){ + killTimer(timerId_); + } + + delay_ = delay; + + if (timerId_ != -1){ + timerId_ = startTimer(delay_); + } +} + +void CustomProgressIndicator::setColor(const QColor & color) { + color_ = color; + + update(); +} + +QSize CustomProgressIndicator::sizeHint() const { + return QSize(80,80); +} + + +void CustomProgressIndicator::timerEvent(QTimerEvent *) { + angle_ = (angle_+30)%360; + + update(); +} + +void CustomProgressIndicator::paintEvent(QPaintEvent *) { + QPainter p(this); + drawJuHua(&p); +} +void CustomProgressIndicator::drawJuHua(QPainter *painter) +{ + painter->setRenderHint(QPainter::Antialiasing); + if (displayedWhenStopped_ && !isAnimated()) //如果displayedWhenStopped_==flash并且动画已经停止则不绘制 + { + painter->setPen(color_); + painter->drawPixmap(rect(),currentPix_); + painter->drawText(rect(), Qt::AlignCenter, m_strTip); + + return; + } + + int width = qMin(this->width(), this->height()); + + int outerRadius = (width-1) >> 1; + int innerRadius = int(((width-1) >> 1)*0.38); + + int capsuleHeight = outerRadius - innerRadius; + int capsuleWidth = (width > 32 ) ? (int)(capsuleHeight *0.23) : (int)(capsuleHeight *0.35); + int capsuleRadius = capsuleWidth >> 1; + if(m_iLoopBackFlag==1) + { + painter->setPen(color_); + painter->drawText(rect(), Qt::AlignCenter, m_strTiping); + } + else { + /* 撰写进度 */ + if (progress_ > 0 && progress_ < 100) { + painter->setPen(color_); + painter->drawText(rect(), Qt::AlignCenter, QString("%1%").arg(progress_)); + } + else if (progress_ == 100) { + stopAnimation(); + } + } + for (int i=0; i<12; ++i) { + QColor color = color_; + color.setAlphaF(1.0f - (i/12.0f)); + painter->setPen(Qt::NoPen); + painter->setBrush(color); + painter->save(); + painter->translate(rect().center()); + painter->rotate(angle_ - i*30.0f); + painter->drawRoundedRect(((-capsuleWidth) >> 1), -(innerRadius+capsuleHeight), capsuleWidth, capsuleHeight, capsuleRadius, capsuleRadius); + painter->restore(); + } +} diff --git a/LedOK/base/customprogressindicator.h b/LedOK/base/customprogressindicator.h index 571760d..3238a08 100644 --- a/LedOK/base/customprogressindicator.h +++ b/LedOK/base/customprogressindicator.h @@ -1,116 +1,116 @@ -#ifndef CUSTOMPROGRESSINDICATOR_H -#define CUSTOMPROGRESSINDICATOR_H - -#include -#include -#include -/* -* 菊花转 进度类,基于代码无需图片资源 -* 作者:陈鲁勇 -* 邮箱:727057301@qq.com -* 创建时间:2017年2月10日16:26:48 -* QT版本:5.0.2 -* CSDN:http://blog.csdn.net/csnd_ayo -* ************************************** -* 说明: -* 使用前请确保在QT.pro中加入 C++11 的支持 -* -* 示例代码: - - pIndicator = new CustomProgressIndicator(this); - pIndicator->setColor(Qt::red); - pIndicator->startAnimation(); -*/ - -class CustomProgressIndicator : public QWidget -{ - Q_OBJECT - Q_PROPERTY(int delay READ animationDelay WRITE setAnimationDelay) - Q_PROPERTY(bool displayedWhenStopped READ isDisplayedWhenStopped WRITE setDisplayedWhenStopped) - Q_PROPERTY(QColor color READ color WRITE setColor) -public: - CustomProgressIndicator(QWidget* parent = nullptr); - - int animationDelay() const { return delay_; } - - /* 动画是否正在进行中 */ - bool isAnimated () const; - - /* 动画完毕后,是否隐藏菊花转 */ - bool isDisplayedWhenStopped() const; - - /* 当前菊花转的颜色 */ - const QColor & color() const { return color_; } - - /* 虚函数:当前大小 */ - virtual QSize sizeHint() const; - - void setBackground(const QString& _icon) { - currentPix_ = QPixmap(_icon); - } -signals: - void Finished(void); -public slots: - - /* 开始动画 */ - void startAnimation(); - - /* 停止动画 */ - void stopAnimation(); - /* 设置停止菊花,显示圆圈加对号*/ - void setDisplayStringInfo(QString strTip,QString strTiping); - void setDisplayModel(int iFlag);//iFlag 0:表示进度统计,1:表示strTiping提示,结束后显示strTip - - /* 设置菊花转的转速 */ - void setAnimationDelay(int delay); - - /* 动画完毕后,是否隐藏菊花转 */ - void setDisplayedWhenStopped(bool state); - - /* 设置菊花转颜色 */ - void setColor(const QColor & color); - - /* - * 进度 - * 参数 _progress:当前进度 0 < _progress < 100 - */ - void onProgress(QString msg, int _progress, bool done) - { - Q_UNUSED(msg) - progress_ = _progress; - if(done) - { - progress_=100; - - } - } -protected: - /* 系统基类函数 */ - virtual void timerEvent(QTimerEvent * event); - virtual void paintEvent(QPaintEvent * event); - void drawJuHua(QPainter *painter); - -private: - /* 角度 */ - unsigned int angle_; - /* 定时器ID */ - int timerId_; - /* 转速 */ - int delay_; - /* 是否隐藏 */ - bool displayedWhenStopped_; - /* 菊花转颜色 */ - QColor color_; - /* 进度 */ - int progress_; - /* 背景图 */ - QPixmap currentPix_; - /*显示圆圈中的字符串内容*/ - QString m_strTip = ""; - QString m_strTiping = ""; - int m_iLoopBackFlag = 0; - -}; - - -#endif // CUSTOMPROGRESSINDICATOR_H +#ifndef CUSTOMPROGRESSINDICATOR_H +#define CUSTOMPROGRESSINDICATOR_H + +#include +#include +#include +/* +* 菊花转 进度类,基于代码无需图片资源 +* 作者:陈鲁勇 +* 邮箱:727057301@qq.com +* 创建时间:2017年2月10日16:26:48 +* QT版本:5.0.2 +* CSDN:http://blog.csdn.net/csnd_ayo +* ************************************** +* 说明: +* 使用前请确保在QT.pro中加入 C++11 的支持 +* +* 示例代码: + + pIndicator = new CustomProgressIndicator(this); + pIndicator->setColor(Qt::red); + pIndicator->startAnimation(); +*/ + +class CustomProgressIndicator : public QWidget +{ + Q_OBJECT + Q_PROPERTY(int delay READ animationDelay WRITE setAnimationDelay) + Q_PROPERTY(bool displayedWhenStopped READ isDisplayedWhenStopped WRITE setDisplayedWhenStopped) + Q_PROPERTY(QColor color READ color WRITE setColor) +public: + CustomProgressIndicator(QWidget* parent = nullptr); + + int animationDelay() const { return delay_; } + + /* 动画是否正在进行中 */ + bool isAnimated () const; + + /* 动画完毕后,是否隐藏菊花转 */ + bool isDisplayedWhenStopped() const; + + /* 当前菊花转的颜色 */ + const QColor & color() const { return color_; } + + /* 虚函数:当前大小 */ + virtual QSize sizeHint() const; + + void setBackground(const QString& _icon) { + currentPix_ = QPixmap(_icon); + } +signals: + void Finished(void); +public slots: + + /* 开始动画 */ + void startAnimation(); + + /* 停止动画 */ + void stopAnimation(); + /* 设置停止菊花,显示圆圈加对号*/ + void setDisplayStringInfo(QString strTip,QString strTiping); + void setDisplayModel(int iFlag);//iFlag 0:表示进度统计,1:表示strTiping提示,结束后显示strTip + + /* 设置菊花转的转速 */ + void setAnimationDelay(int delay); + + /* 动画完毕后,是否隐藏菊花转 */ + void setDisplayedWhenStopped(bool state); + + /* 设置菊花转颜色 */ + void setColor(const QColor & color); + + /* + * 进度 + * 参数 _progress:当前进度 0 < _progress < 100 + */ + void onProgress(QString msg, int _progress, bool done) + { + Q_UNUSED(msg) + progress_ = _progress; + if(done) + { + progress_=100; + + } + } +protected: + /* 系统基类函数 */ + virtual void timerEvent(QTimerEvent * event); + virtual void paintEvent(QPaintEvent * event); + void drawJuHua(QPainter *painter); + +private: + /* 角度 */ + unsigned int angle_; + /* 定时器ID */ + int timerId_; + /* 转速 */ + int delay_; + /* 是否隐藏 */ + bool displayedWhenStopped_; + /* 菊花转颜色 */ + QColor color_; + /* 进度 */ + int progress_; + /* 背景图 */ + QPixmap currentPix_; + /*显示圆圈中的字符串内容*/ + QString m_strTip = ""; + QString m_strTiping = ""; + int m_iLoopBackFlag = 0; + +}; + + +#endif // CUSTOMPROGRESSINDICATOR_H diff --git a/LedOK/base/extendedgroupbox.cpp b/LedOK/base/extendedgroupbox.cpp index 4b14434..206236d 100644 --- a/LedOK/base/extendedgroupbox.cpp +++ b/LedOK/base/extendedgroupbox.cpp @@ -1,62 +1,62 @@ -#include "extendedgroupbox.h" -ExtendedGroupBox::ExtendedGroupBox(QWidget *parent /*= nullptr*/, State state /*= STATE_NORMAL*/) - : QGroupBox(parent) -{ - setCheckable(true); - state_ = state; - if (state_ == STATE_NORMAL) - { - //隐藏垂直边框 - setFlat(true); - } - connect(this, SIGNAL(clicked(bool)), this, SLOT(onChecked(bool))); -} - -ExtendedGroupBox::ExtendedGroupBox(const QString &title, QWidget *parent /*= nullptr*/, State state /*= STATE_NORMAL*/) - : QGroupBox(title, parent) -{ - setCheckable(true); - state_ = state; - if (state_ == STATE_NORMAL) - { - //隐藏垂直边框 - setFlat(true); - } - // this->toggled(); - - connect(this, SIGNAL(toggled(bool)), this, SLOT(onChecked(bool))); -} - - -void ExtendedGroupBox::onChecked(bool checked) -{ - if (checked) - { - //显示垂直边框 - QList widgets = findChildren(); - for (auto iter = widgets.begin(); iter != widgets.end(); ++iter) - { - (*iter)->setVisible(true); - } - state_ = STATE_EXPAND; - } - else - { - //隐藏垂直边框 - QList widgets = findChildren(); - for (auto iter = widgets.begin(); iter != widgets.end(); ++iter) - (*iter)->setVisible(false); -// QList layouts = findChildren(); -// for (auto iter1 = layouts.begin(); iter1 != layouts.end(); ++iter1) -// (*iter1)->setVisible(false); - -// QLayout aa; -// a-> - state_ = STATE_NORMAL; - } -} - -ExtendedGroupBox::State ExtendedGroupBox::getState() const -{ - return state_; -} +#include "extendedgroupbox.h" +ExtendedGroupBox::ExtendedGroupBox(QWidget *parent /*= nullptr*/, State state /*= STATE_NORMAL*/) + : QGroupBox(parent) +{ + setCheckable(true); + state_ = state; + if (state_ == STATE_NORMAL) + { + //隐藏垂直边框 + setFlat(true); + } + connect(this, SIGNAL(clicked(bool)), this, SLOT(onChecked(bool))); +} + +ExtendedGroupBox::ExtendedGroupBox(const QString &title, QWidget *parent /*= nullptr*/, State state /*= STATE_NORMAL*/) + : QGroupBox(title, parent) +{ + setCheckable(true); + state_ = state; + if (state_ == STATE_NORMAL) + { + //隐藏垂直边框 + setFlat(true); + } + // this->toggled(); + + connect(this, SIGNAL(toggled(bool)), this, SLOT(onChecked(bool))); +} + + +void ExtendedGroupBox::onChecked(bool checked) +{ + if (checked) + { + //显示垂直边框 + QList widgets = findChildren(); + for (auto iter = widgets.begin(); iter != widgets.end(); ++iter) + { + (*iter)->setVisible(true); + } + state_ = STATE_EXPAND; + } + else + { + //隐藏垂直边框 + QList widgets = findChildren(); + for (auto iter = widgets.begin(); iter != widgets.end(); ++iter) + (*iter)->setVisible(false); +// QList layouts = findChildren(); +// for (auto iter1 = layouts.begin(); iter1 != layouts.end(); ++iter1) +// (*iter1)->setVisible(false); + +// QLayout aa; +// a-> + state_ = STATE_NORMAL; + } +} + +ExtendedGroupBox::State ExtendedGroupBox::getState() const +{ + return state_; +} diff --git a/LedOK/base/extendedgroupbox.h b/LedOK/base/extendedgroupbox.h index 960d675..2adc841 100644 --- a/LedOK/base/extendedgroupbox.h +++ b/LedOK/base/extendedgroupbox.h @@ -1,32 +1,32 @@ -#ifndef EXTENDEDGROUPBOX_H -#define EXTENDEDGROUPBOX_H -#include -#include - -class ExtendedGroupBox : public QGroupBox -{ - Q_OBJECT - -public: - enum State - { - STATE_NORMAL, - STATE_EXPAND - }; - -public: - ExtendedGroupBox(QWidget *parent = nullptr, State state = STATE_NORMAL); - ExtendedGroupBox(const QString &title, QWidget *parent = nullptr, State state = STATE_NORMAL); - -private Q_SLOTS: - void onChecked(bool checked); - -public: - void addWidget(QWidget *widget); - State getState() const; - -private: - State state_; -}; - -#endif // EXTENDEDGROUPBOX_H +#ifndef EXTENDEDGROUPBOX_H +#define EXTENDEDGROUPBOX_H +#include +#include + +class ExtendedGroupBox : public QGroupBox +{ + Q_OBJECT + +public: + enum State + { + STATE_NORMAL, + STATE_EXPAND + }; + +public: + ExtendedGroupBox(QWidget *parent = nullptr, State state = STATE_NORMAL); + ExtendedGroupBox(const QString &title, QWidget *parent = nullptr, State state = STATE_NORMAL); + +private Q_SLOTS: + void onChecked(bool checked); + +public: + void addWidget(QWidget *widget); + State getState() const; + +private: + State state_; +}; + +#endif // EXTENDEDGROUPBOX_H diff --git a/LedOK/base/ffutil.cpp b/LedOK/base/ffutil.cpp index 18a8188..fe03275 100644 --- a/LedOK/base/ffutil.cpp +++ b/LedOK/base/ffutil.cpp @@ -6,6 +6,10 @@ extern "C"{ #include } +static void imgCleanupHandler(void *info) { + delete [] (uchar*)info; +} + QString videoInfo(QByteArray url, QImage &img, int64_t *dur, AVCodecID *codec_id) { AVFormatContext *fmt_ctx = avformat_alloc_context(); QString err; @@ -44,9 +48,12 @@ QString videoInfo(QByteArray url, QImage &img, int64_t *dur, AVCodecID *codec_id avcodec_free_context(&vcCtx); goto free; } - auto sws_ctx = sws_getContext(vcCtx->width, vcCtx->height, vcCtx->pix_fmt, vcCtx->width, vcCtx->height, AV_PIX_FMT_RGB32, SWS_FAST_BILINEAR, nullptr, nullptr, nullptr); + auto sws_ctx = sws_getContext(vcCtx->width, vcCtx->height, vcCtx->pix_fmt, vcCtx->width, vcCtx->height, AV_PIX_FMT_RGB32, SWS_FAST_BILINEAR, 0, 0, 0); auto packet = av_packet_alloc(); auto frm = av_frame_alloc(); + int dstStride[4]{(vcCtx->width*4+63)/64*64}; + dstStride[3] = dstStride[0] * vcCtx->height; + uint8_t *dst[4]{0}; while(1) { if(av_read_frame(fmt_ctx, packet) < 0) break; if(packet->stream_index != vi_idx) continue; @@ -54,10 +61,9 @@ QString videoInfo(QByteArray url, QImage &img, int64_t *dur, AVCodecID *codec_id if(res < 0) break; while((res = avcodec_receive_frame(vcCtx, frm)) != AVERROR(EAGAIN)) { if(res < 0) goto free2; - img = QImage(vcCtx->width, vcCtx->height, QImage::Format_ARGB32); - uint8_t *dst[4]{img.bits()}; - int dstStride[4]{img.bytesPerLine()}; + dst[0] = new uchar[dstStride[3]]; sws_scale(sws_ctx, frm->data, frm->linesize, 0, vcCtx->height, dst, dstStride); + img = QImage(dst[0], vcCtx->width, vcCtx->height, dstStride[0], QImage::Format_ARGB32, imgCleanupHandler, dst[0]); goto free2; } } @@ -71,188 +77,6 @@ QString videoInfo(QByteArray url, QImage &img, int64_t *dur, AVCodecID *codec_id avformat_close_input(&fmt_ctx); return err; } -QString videoTrans(int sw, int sh, int dw, int dh, int cnt, QPointF pos, QByteArray file) { - AVFormatContext *in_fmt = avformat_alloc_context(), *out_fmt = 0; - AVCodecContext *de_ctx = 0, *en_ctx = 0; - QString err; - char buf[AV_ERROR_MAX_STRING_SIZE]; - int ret; - { - if((ret = avformat_open_input(&in_fmt, file.constData(), nullptr, nullptr)) < 0) { - err = QString("Couldn't open input stream. ")+av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); - goto free; - } - if((ret = avformat_find_stream_info(in_fmt, nullptr)) < 0) { - err = QString("Couldn't find stream information. ")+av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); - goto free; - } - auto outfile = file+"-square.mp4"; - if((ret = avformat_alloc_output_context2(&out_fmt, 0, "mp4", outfile.constData())) < 0) { - err = QString("avformat_alloc_output_context2 fail. ")+av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); - goto free; - } - int vi_idx = -1; - for(uint ss=0; ssnb_streams; ss++) { - AVStream *stream = in_fmt->streams[ss]; - AVStream *out_stream = avformat_new_stream(out_fmt, 0); - if((ret = avcodec_parameters_copy(out_stream->codecpar, stream->codecpar)) < 0) { - err = QString("avcodec_parameters_copy fail. ") + av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); - goto free; - } - out_stream->time_base = stream->time_base; - out_stream->start_time = stream->start_time; - out_stream->duration = stream->duration; - out_stream->avg_frame_rate = stream->avg_frame_rate; - out_stream->sample_aspect_ratio = {1,1}; - if(vi_idx == -1 && stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) vi_idx = ss; - } - if(vi_idx == -1) { - err = "Didn't find a Video Stream"; - goto free; - } - - auto codecpar = in_fmt->streams[vi_idx]->codecpar; - qDebug()<<"codec_id"<codec_id<codec_id); - - auto decoder = avcodec_find_decoder(codecpar->codec_id); - if(decoder==0) { - err = "Could not found Video Decoder"; - goto free; - } - de_ctx = avcodec_alloc_context3(decoder); - avcodec_parameters_to_context(de_ctx, codecpar); - if(avcodec_open2(de_ctx, decoder, 0) < 0) { - err = "Could not open Video decode Ctx"; - goto free; - } - - auto out_codecpar = out_fmt->streams[vi_idx]->codecpar; - out_codecpar->codec_id = AV_CODEC_ID_H264; - out_codecpar->format = AV_PIX_FMT_YUV420P; - out_codecpar->width = dw; - out_codecpar->height = dh; - out_codecpar->sample_aspect_ratio = {1,1}; - out_fmt->streams[vi_idx]->sample_aspect_ratio = {1,1}; - - auto encoder = avcodec_find_encoder(out_codecpar->codec_id); - if(encoder==0) { - fprintf(stderr, "Codec not found\n"); - goto free; - } - en_ctx = avcodec_alloc_context3(encoder); - avcodec_parameters_to_context(en_ctx, out_codecpar); - en_ctx->bit_rate = dw*dh*6; - en_ctx->gop_size = de_ctx->gop_size; - en_ctx->max_b_frames = 3; - en_ctx->framerate = de_ctx->framerate; - en_ctx->time_base = out_fmt->streams[vi_idx]->time_base; - - if((ret = avcodec_open2(en_ctx, encoder, 0)) < 0) { - err = QString("Open video encode ctx failed. ") + av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); - goto free; - } - - if(out_fmt->flags & AVFMT_NOFILE) qDebug()<<"AVFMT_NOFILE"; - else if((ret = avio_open(&out_fmt->pb, outfile.constData(), AVIO_FLAG_WRITE)) < 0) { - err = QString("avio_open fail. ")+av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); - goto free; - } - if((ret = avformat_write_header(out_fmt, 0)) < 0) { - err = QString("avformat_write_header fail. ")+av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); - goto free; - } - auto sws_ctx = sws_getContext(de_ctx->width, de_ctx->height, de_ctx->pix_fmt, sw, sh, AV_PIX_FMT_0RGB, SWS_FAST_BILINEAR, 0, 0, 0); - auto out_sws_ctx = sws_getContext(dw, dh, AV_PIX_FMT_0RGB, dw, dh, AV_PIX_FMT_YUV420P, SWS_FAST_BILINEAR, 0, 0, 0); - auto packet = av_packet_alloc(); - auto frm = av_frame_alloc(); - auto out_frm = av_frame_alloc(); - QImage img(sw, sh, QImage::Format_RGB32); - uint8_t *img_data[4]{img.bits(), 0, 0, 0}; - int img_linesize[4]{img.bytesPerLine(), 0, 0, 0}; - QImage out_img(dw, dh, QImage::Format_RGB32); - uint8_t *out_img_data[4]{out_img.bits(), 0, 0, 0}; - int out_img_linesize[4]{out_img.bytesPerLine(), 0, 0, 0}; - QPainter painter(&out_img); - while(1) { - if((ret = av_read_frame(in_fmt, packet)) < 0) { - if(ret!=AVERROR_EOF) { - err = QString("Read packet fail: ")+av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); - break; - } - ret = avcodec_send_packet(de_ctx, 0); - } else { - if(packet->stream_index != vi_idx) { - av_interleaved_write_frame(out_fmt, packet); - continue; - } - ret = avcodec_send_packet(de_ctx, packet); - } - if(ret < 0) { - err = QString("avcodec_send_packet fail. ")+av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); - break; - } - while((ret = avcodec_receive_frame(de_ctx, frm)) != AVERROR(EAGAIN)) { - if(ret < 0) { - if(ret!=AVERROR_EOF) { - err = QString("Receive frame fail: ")+av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); - goto free2; - } - ret = avcodec_send_frame(en_ctx, 0); - } else { - sws_scale(sws_ctx, frm->data, frm->linesize, 0, de_ctx->height, img_data, img_linesize); - painter.drawImage(pos, img); - auto apos = pos; - for(int i=1; iformat = AV_PIX_FMT_YUV420P; - out_frm->width = dw; - out_frm->height = dh; - out_frm->sample_aspect_ratio = {1,1}; - if((ret = av_frame_get_buffer(out_frm, 0)) < 0) { - err = QString("av_frame_get_buffer fail. ")+av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); - goto free2; - } - sws_scale(out_sws_ctx, out_img_data, out_img_linesize, 0, dh, out_frm->data, out_frm->linesize); - ret = avcodec_send_frame(en_ctx, out_frm); - } - if(ret < 0) { - err = QString("avcodec_send_frame fail. ")+av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); - goto free2; - } - while((ret = avcodec_receive_packet(en_ctx, packet)) != AVERROR(EAGAIN)) { - if(ret < 0) { - if(ret!=AVERROR_EOF) err = QString("Receive frame fail: ")+av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); - else { - av_interleaved_write_frame(out_fmt, 0); - av_write_trailer(out_fmt); - } - goto free2; - } else { - av_interleaved_write_frame(out_fmt, packet); - } - } - } - } - free2: - av_frame_free(&frm); - av_frame_free(&out_frm); - av_packet_free(&packet); - sws_freeContext(sws_ctx); - sws_freeContext(out_sws_ctx); - } - free: - avcodec_free_context(&de_ctx); - avcodec_free_context(&en_ctx); - avformat_close_input(&in_fmt); - avio_closep(&out_fmt->pb); - if(out_fmt) avformat_free_context(out_fmt); - return err; -} QString audioInfo(QByteArray url, int64_t *dur) { AVFormatContext *fmt_ctx = avformat_alloc_context(); QString err; diff --git a/LedOK/base/ffutil.h b/LedOK/base/ffutil.h index 2cda8cb..fff1b75 100644 --- a/LedOK/base/ffutil.h +++ b/LedOK/base/ffutil.h @@ -7,7 +7,6 @@ extern "C"{ } QString videoInfo(QByteArray url, QImage &, int64_t *dur, AVCodecID *); -QString videoTrans(int sw, int sh, int dw, int dh, int cnt, QPointF pos, QByteArray file); QString audioInfo(QByteArray url, int64_t *dur); #endif // FFUTIL_H diff --git a/LedOK/base/locolorselector.cpp b/LedOK/base/locolorselector.cpp index a07c69c..af69799 100644 --- a/LedOK/base/locolorselector.cpp +++ b/LedOK/base/locolorselector.cpp @@ -13,9 +13,12 @@ LoColorSelector::LoColorSelector(const QString &text, const QColor &color, QWidg } void LoColorSelector::init() { connect(this, &QPushButton::clicked, this, [this]{ - QColorDialog colorDlg(this->color, this); + QColorDialog colorDlg(this); colorDlg.setOption(QColorDialog::ShowAlphaChannel); colorDlg.setOption(QColorDialog::DontUseNativeDialog); + auto color = this->color; + color.setAlpha(255); + colorDlg.setCurrentColor(color); auto btn = new QPushButton(tr("Transparent")); connect(btn, &QPushButton::clicked, &colorDlg, [&colorDlg] { @@ -25,10 +28,8 @@ void LoColorSelector::init() { static_cast(colorDlg.layout()->itemAt(0)->layout()->itemAt(0)->layout())->insertWidget(2, btn); if(colorDlg.exec() != QColorDialog::Accepted) return; - QColor color = colorDlg.selectedColor(); - if(color == this->color) return; + color = colorDlg.selectedColor(); if(! color.isValid()) return; - if(color.alpha()==0 && this->color.alpha()==0) color.setAlpha(255); setColor(color); emit sColorChanged(color); }); diff --git a/LedOK/base/lodateselector.cpp b/LedOK/base/lodateselector.cpp index f306b50..66d4dbb 100644 --- a/LedOK/base/lodateselector.cpp +++ b/LedOK/base/lodateselector.cpp @@ -7,13 +7,13 @@ LoDateSelector::LoDateSelector(QWidget *parent) : QPushButton(parent) { setStyleSheet(R"rrr( LoDateSelector { background-color: transparent; - image: url(:/res/ProgramManager/EditProgram/DateSelect_enable.png); + image: url(:/res/program/DateSelect_enable.png); padding: 0; max-width: 32px; max-height: 32px; } LoDateSelector:!enabled{ - image: url(:/res/ProgramManager/EditProgram/DateSelect_e.png); + image: url(:/res/program/DateSelect_e.png); } LoDateSelector:pressed { margin-top: 1px; diff --git a/LedOK/base/loemptydialog.cpp b/LedOK/base/loemptydialog.cpp index 0ca4441..b24d64a 100644 --- a/LedOK/base/loemptydialog.cpp +++ b/LedOK/base/loemptydialog.cpp @@ -1,78 +1,78 @@ -#include "loemptydialog.h" -#include - -LoEmptyDialog::LoEmptyDialog(QWidget *parent) : BaseDlg(parent) { - setAttribute(Qt::WA_DeleteOnClose); - - auto pal = palette(); - pal.setBrush(QPalette::Window, QColor(0xdd, 0xdd, 0xdd, 0xdd)); - setPalette(pal); - - auto vBox = new QVBoxLayout(this); - vBox->addStretch(); - - mIndicator = new CustomProgressIndicator(this); - mIndicator->setDisplayModel(1); - mIndicator->setColor(QColor(0x0088dd)); - mIndicator->setDisplayedWhenStopped(true);//动画停止后任就显示,直到关闭窗口 - mIndicator->startAnimation(); - vBox->addWidget(mIndicator, 0, Qt::AlignCenter); - - vBox->addStretch(); - - label = new QLabel(); - label->setAlignment(Qt::AlignCenter); - label->setStyleSheet("font-size: 24px; font-weight: bold; color: #08d;"); - vBox->addWidget(label); - - vBox->addStretch(); -} - -void LoEmptyDialog::SetTipTextContent(QString strTip) { - label->setText(strTip); -} -void LoEmptyDialog::SetFailedTipString(QString strTip) { - mTimeroutTip = strTip; -} -bool LoEmptyDialog::getLockStatus() { - return iLockFlag; -} - -void LoEmptyDialog::lock(QString strTip, QString finishTip, QString timeroutTip) { - iLockFlag = true; - label->setText(strTip); - mFinishTip = finishTip; - mTimeroutTip = timeroutTip; -} - -void LoEmptyDialog::unlock() { - if(iClosedFlag==1) return; - label->setText(mFinishTip); - if(mIndicator != nullptr) { - mIndicator->setBackground(":/res/success.png"); - mIndicator->stopAnimation(); - CloseWndByDelaySec(600); - } - iClosedFlag=1; - iLockFlag = false; -} -void LoEmptyDialog::TimerOutUnlock() { - if(iClosedFlag==1) return; - label->setText(mTimeroutTip); - if(mIndicator != nullptr) { - mIndicator->setBackground(":/res/tip.png"); - mIndicator->stopAnimation(); - CloseWndByDelaySec(600); - } - iClosedFlag = 1; -} -void LoEmptyDialog::CloseWndByDelaySec(int iCloseWndDelaySec) { - auto timer = new QTimer(this); - timer->setSingleShot(true); - connect(timer, &QTimer::timeout, this, [this, timer] { - timer->stop(); - close(); - emit sigClose(); - }); - timer->start(iCloseWndDelaySec); -} +#include "loemptydialog.h" +#include + +LoEmptyDialog::LoEmptyDialog(QWidget *parent) : BaseDlg(parent) { + setAttribute(Qt::WA_DeleteOnClose); + + auto pal = palette(); + pal.setBrush(QPalette::Window, QColor(0xdd, 0xdd, 0xdd, 0xdd)); + setPalette(pal); + + auto vBox = new QVBoxLayout(this); + vBox->addStretch(); + + mIndicator = new CustomProgressIndicator(this); + mIndicator->setDisplayModel(1); + mIndicator->setColor(QColor(0x0088dd)); + mIndicator->setDisplayedWhenStopped(true);//动画停止后任就显示,直到关闭窗口 + mIndicator->startAnimation(); + vBox->addWidget(mIndicator, 0, Qt::AlignCenter); + + vBox->addStretch(); + + label = new QLabel(); + label->setAlignment(Qt::AlignCenter); + label->setStyleSheet("font-size: 24px; font-weight: bold; color: #08d;"); + vBox->addWidget(label); + + vBox->addStretch(); +} + +void LoEmptyDialog::SetTipTextContent(QString strTip) { + label->setText(strTip); +} +void LoEmptyDialog::SetFailedTipString(QString strTip) { + mTimeroutTip = strTip; +} +bool LoEmptyDialog::getLockStatus() { + return iLockFlag; +} + +void LoEmptyDialog::lock(QString strTip, QString finishTip, QString timeroutTip) { + iLockFlag = true; + label->setText(strTip); + mFinishTip = finishTip; + mTimeroutTip = timeroutTip; +} + +void LoEmptyDialog::unlock() { + if(iClosedFlag==1) return; + label->setText(mFinishTip); + if(mIndicator != nullptr) { + mIndicator->setBackground(":/res/success.png"); + mIndicator->stopAnimation(); + CloseWndByDelaySec(600); + } + iClosedFlag=1; + iLockFlag = false; +} +void LoEmptyDialog::TimerOutUnlock() { + if(iClosedFlag==1) return; + label->setText(mTimeroutTip); + if(mIndicator != nullptr) { + mIndicator->setBackground(":/res/tip.png"); + mIndicator->stopAnimation(); + CloseWndByDelaySec(600); + } + iClosedFlag = 1; +} +void LoEmptyDialog::CloseWndByDelaySec(int iCloseWndDelaySec) { + auto timer = new QTimer(this); + timer->setSingleShot(true); + connect(timer, &QTimer::timeout, this, [this, timer] { + timer->stop(); + close(); + emit sigClose(); + }); + timer->start(iCloseWndDelaySec); +} diff --git a/LedOK/base/loemptydialog.h b/LedOK/base/loemptydialog.h index 8bdbfe5..456ec1c 100644 --- a/LedOK/base/loemptydialog.h +++ b/LedOK/base/loemptydialog.h @@ -1,37 +1,37 @@ -#ifndef LOEMPTYDIALOG_H -#define LOEMPTYDIALOG_H - -#include -#include -#include - -class LoEmptyDialog : public BaseDlg { - Q_OBJECT -public: - explicit LoEmptyDialog(QWidget *parent = nullptr); - int exec() override { - emit startUp(); - return BaseDlg::exec(); - } - CustomProgressIndicator *mIndicator{0}; -signals: - void startUp(); - void sigClose(); -public slots: - void lock(QString strTip,QString strUnLockTip,QString strTimerOutUnLockTip); - void unlock(); - void TimerOutUnlock(); - bool getLockStatus(); - void SetFailedTipString(QString strTip); - void SetTipTextContent(QString strTip); -private: - QLabel *label; - int iClosedFlag=0; - bool iLockFlag = false; - QString mFinishTip; - QString mTimeroutTip; - LoEmptyDialog *m_pSelf=nullptr; - void CloseWndByDelaySec(int iCloseWndDelaySec); -}; - -#endif // LOEMPTYDIALOG_H +#ifndef LOEMPTYDIALOG_H +#define LOEMPTYDIALOG_H + +#include +#include +#include + +class LoEmptyDialog : public BaseDlg { + Q_OBJECT +public: + explicit LoEmptyDialog(QWidget *parent = nullptr); + int exec() override { + emit startUp(); + return BaseDlg::exec(); + } + CustomProgressIndicator *mIndicator{0}; +signals: + void startUp(); + void sigClose(); +public slots: + void lock(QString strTip,QString strUnLockTip,QString strTimerOutUnLockTip); + void unlock(); + void TimerOutUnlock(); + bool getLockStatus(); + void SetFailedTipString(QString strTip); + void SetTipTextContent(QString strTip); +private: + QLabel *label; + int iClosedFlag=0; + bool iLockFlag = false; + QString mFinishTip; + QString mTimeroutTip; + LoEmptyDialog *m_pSelf=nullptr; + void CloseWndByDelaySec(int iCloseWndDelaySec); +}; + +#endif // LOEMPTYDIALOG_H diff --git a/LedOK/base/loqtreewidget.cpp b/LedOK/base/loqtreewidget.cpp index faf4fc5..611d63e 100644 --- a/LedOK/base/loqtreewidget.cpp +++ b/LedOK/base/loqtreewidget.cpp @@ -19,13 +19,7 @@ void CheckableHeader::paintSection(QPainter *painter, const QRect &rect, int log LoQTreeWidget::LoQTreeWidget(QWidget *parent) : QTreeWidget(parent), m_checkState(CheckNone) { fdIsSelAll = new QCheckBox(); - fdIsSelAll->setStyleSheet(R"rrr( -QCheckBox::indicator { - width: 24px; - height: 24px; - margin-left: 10px; -} -)rrr"); + fdIsSelAll->setStyleSheet("QCheckBox{margin-left: 5px;}"); m_header = new CheckableHeader(Qt::Horizontal, fdIsSelAll); setHeader(m_header); setProperty("ssType", "topList"); diff --git a/LedOK/base/pixbmpshowdialog.cpp b/LedOK/base/pixbmpshowdialog.cpp index 5920617..6ad57d6 100644 --- a/LedOK/base/pixbmpshowdialog.cpp +++ b/LedOK/base/pixbmpshowdialog.cpp @@ -1,41 +1,41 @@ -#include "pixbmpshowdialog.h" -#include "ui_pixbmpshowdialog.h" -#include -PixbmpShowDialog::PixbmpShowDialog(QWidget *parent) : - BaseDlg(parent), - ui(new Ui::PixbmpShowDialog) -{ - setAttribute(Qt::WA_DeleteOnClose); - ui->setupUi(this); - -} - -PixbmpShowDialog::~PixbmpShowDialog() -{ - delete ui; -} -void PixbmpShowDialog::ResizeByPixmap(int w,int h) -{ - m_iWidth=w; - m_iHeight=h; - int iWidth=w; - int iHeight=h; - if(iWidthresize(iWidth,iHeight); - else { - if(iWidth>iHeight) - this->resize(rect().height()*iWidth/iHeight,rect().height()); - else - this->resize(rect().width(),rect().width()*iHeight/iWidth); - } -} -void PixbmpShowDialog::paintEvent(QPaintEvent * event) -{ - Q_UNUSED(event); - QPainter painter(this); - //painter.eraseRect(rect()); - // painter.scale(m_PixMap.width(), m_PixMap.height()); - QRectF sourceRt(0,0,m_iWidth,m_iHeight); - painter.drawPixmap(rect(), m_PixMap,sourceRt); - -} +#include "pixbmpshowdialog.h" +#include "ui_pixbmpshowdialog.h" +#include +PixbmpShowDialog::PixbmpShowDialog(QWidget *parent) : + BaseDlg(parent), + ui(new Ui::PixbmpShowDialog) +{ + setAttribute(Qt::WA_DeleteOnClose); + ui->setupUi(this); + +} + +PixbmpShowDialog::~PixbmpShowDialog() +{ + delete ui; +} +void PixbmpShowDialog::ResizeByPixmap(int w,int h) +{ + m_iWidth=w; + m_iHeight=h; + int iWidth=w; + int iHeight=h; + if(iWidthresize(iWidth,iHeight); + else { + if(iWidth>iHeight) + this->resize(rect().height()*iWidth/iHeight,rect().height()); + else + this->resize(rect().width(),rect().width()*iHeight/iWidth); + } +} +void PixbmpShowDialog::paintEvent(QPaintEvent * event) +{ + Q_UNUSED(event); + QPainter painter(this); + //painter.eraseRect(rect()); + // painter.scale(m_PixMap.width(), m_PixMap.height()); + QRectF sourceRt(0,0,m_iWidth,m_iHeight); + painter.drawPixmap(rect(), m_PixMap,sourceRt); + +} diff --git a/LedOK/base/pixbmpshowdialog.h b/LedOK/base/pixbmpshowdialog.h index db4b49c..005b545 100644 --- a/LedOK/base/pixbmpshowdialog.h +++ b/LedOK/base/pixbmpshowdialog.h @@ -1,30 +1,30 @@ -#ifndef PIXBMPSHOWDIALOG_H -#define PIXBMPSHOWDIALOG_H - -#include - -namespace Ui { -class PixbmpShowDialog; -} - -class PixbmpShowDialog : public BaseDlg -{ - Q_OBJECT - -public: - explicit PixbmpShowDialog(QWidget *parent = nullptr); - ~PixbmpShowDialog(); - QPixmap m_PixMap; - void ResizeByPixmap(int w,int h); - int m_iWidth; - int m_iHeight; - -public: - virtual void paintEvent(QPaintEvent *); - -private: - Ui::PixbmpShowDialog *ui; - -}; - -#endif // PIXBMPSHOWDIALOG_H +#ifndef PIXBMPSHOWDIALOG_H +#define PIXBMPSHOWDIALOG_H + +#include + +namespace Ui { +class PixbmpShowDialog; +} + +class PixbmpShowDialog : public BaseDlg +{ + Q_OBJECT + +public: + explicit PixbmpShowDialog(QWidget *parent = nullptr); + ~PixbmpShowDialog(); + QPixmap m_PixMap; + void ResizeByPixmap(int w,int h); + int m_iWidth; + int m_iHeight; + +public: + virtual void paintEvent(QPaintEvent *); + +private: + Ui::PixbmpShowDialog *ui; + +}; + +#endif // PIXBMPSHOWDIALOG_H diff --git a/LedOK/base/pixbmpshowdialog.ui b/LedOK/base/pixbmpshowdialog.ui index 8724de0..4e92161 100644 --- a/LedOK/base/pixbmpshowdialog.ui +++ b/LedOK/base/pixbmpshowdialog.ui @@ -1,88 +1,88 @@ - - - PixbmpShowDialog - - - - 0 - 0 - 800 - 600 - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 30 - 20 - - - - - 40 - 30 - - - - X - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - pushButton - clicked() - PixbmpShowDialog - close() - - - 199 - 20 - - - 199 - 149 - - - - - + + + PixbmpShowDialog + + + + 0 + 0 + 800 + 600 + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 30 + 20 + + + + + 40 + 30 + + + + X + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + pushButton + clicked() + PixbmpShowDialog + close() + + + 199 + 20 + + + 199 + 149 + + + + + diff --git a/LedOK/base/qexcel.cpp b/LedOK/base/qexcel.cpp index d90b7ed..5203db5 100644 --- a/LedOK/base/qexcel.cpp +++ b/LedOK/base/qexcel.cpp @@ -1,335 +1,335 @@ -#include -#include -#include -#include - -#include "qexcel.h" -#include "QMessageBox" -#include - -QExcel::QExcel(QString xlsFilePath, QObject *parent) -{ - excel = nullptr; - workBooks = nullptr; - workBook = nullptr; - sheets = nullptr; - sheet = nullptr; - CoInitializeEx(NULL, COINIT_MULTITHREADED); - - excel = new QAxObject("Excel.Application"); - excel->setProperty("Visible", false); - workBooks = excel->querySubObject("Workbooks"); - if(workBooks!=nullptr) - { - QFile file(xlsFilePath); - if (file.exists()) - { - workBooks->dynamicCall("Open(const QString&)", xlsFilePath); - workBook = excel->querySubObject("ActiveWorkBook"); - sheets = workBook->querySubObject("WorkSheets"); - } - m_bSupportExcel=true; - } - else { - QMessageBox::information(nullptr, "Title", tr("no support QExcel"), - QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); - m_bSupportExcel=false; - } - -} - -QExcel::~QExcel() -{ - if(excel!=nullptr) - close(); -} - -void QExcel::close() -{ - excel->dynamicCall("Quit()"); - delete sheet; - delete sheets; - delete workBook; - delete workBooks; - delete excel; - - excel = nullptr; - workBooks = nullptr; - workBook = nullptr; - sheets = nullptr; - sheet = nullptr; -} - -QAxObject *QExcel::getWorkBooks() -{ - return workBooks; -} - -QAxObject *QExcel::getWorkBook() -{ - return workBook; -} - -QAxObject *QExcel::getWorkSheets() -{ - return sheets; -} - -QAxObject *QExcel::getWorkSheet() -{ - return sheet; -} - -void QExcel::selectSheet(const QString& sheetName) -{ - sheet = sheets->querySubObject("Item(const QString&)", sheetName); -} - -void QExcel::deleteSheet(const QString& sheetName) -{ - QAxObject * a = sheets->querySubObject("Item(const QString&)", sheetName); - a->dynamicCall("delete"); -} - -void QExcel::deleteSheet(int sheetIndex) -{ - QAxObject * a = sheets->querySubObject("Item(int)", sheetIndex); - a->dynamicCall("delete"); -} - -void QExcel::selectSheet(int sheetIndex) -{ - sheet = sheets->querySubObject("Item(int)", sheetIndex); -} - -void QExcel::setCellString(int row, int column, const QString& value) -{ - QAxObject *range = sheet->querySubObject("Cells(int,int)", row, column); - range->dynamicCall("SetValue(const QString&)", value); -} - -void QExcel::setCellFontBold(int row, int column, bool isBold) -{ - QString cell; - cell.append(QChar(column - 1 + 'A')); - cell.append(QString::number(row)); - - QAxObject *range = sheet->querySubObject("Range(const QString&)", cell); - range = range->querySubObject("Font"); - range->setProperty("Bold", isBold); -} - -void QExcel::setCellFontSize(int row, int column, int size) -{ - QString cell; - cell.append(QChar(column - 1 + 'A')); - cell.append(QString::number(row)); - - QAxObject *range = sheet->querySubObject("Range(const QString&)", cell); - range = range->querySubObject("Font"); - range->setProperty("Size", size); -} - -void QExcel::mergeCells(const QString& cell) -{ - QAxObject *range = sheet->querySubObject("Range(const QString&)", cell); - range->setProperty("VerticalAlignment", -4108);//xlCenter - range->setProperty("WrapText", true); - range->setProperty("MergeCells", true); -} - -void QExcel::mergeCells(int topLeftRow, int topLeftColumn, int bottomRightRow, int bottomRightColumn) -{ - QString cell; - cell.append(QChar(topLeftColumn - 1 + 'A')); - cell.append(QString::number(topLeftRow)); - cell.append(":"); - cell.append(QChar(bottomRightColumn - 1 + 'A')); - cell.append(QString::number(bottomRightRow)); - - QAxObject *range = sheet->querySubObject("Range(const QString&)", cell); - range->setProperty("VerticalAlignment", -4108);//xlCenter - range->setProperty("WrapText", true); - range->setProperty("MergeCells", true); -} - -QVariant QExcel::getCellValue(int row, int column) -{ - QAxObject *range = sheet->querySubObject("Cells(int,int)", row, column); - return range->property("Value"); -} - -void QExcel::save() -{ - workBook->dynamicCall("Save()"); -} - -int QExcel::getSheetsCount() -{ - return sheets->property("Count").toInt(); -} - -QString QExcel::getSheetName() -{ - return sheet->property("Name").toString(); -} - -QString QExcel::getSheetName(int sheetIndex) -{ - QAxObject * a = sheets->querySubObject("Item(int)", sheetIndex); - return a->property("Name").toString(); -} - -void QExcel::getUsedRange(int *topLeftRow, int *topLeftColumn, int *bottomRightRow, int *bottomRightColumn) -{ - QAxObject *usedRange = sheet->querySubObject("UsedRange"); - *topLeftRow = usedRange->property("Row").toInt(); - *topLeftColumn = usedRange->property("Column").toInt(); - - QAxObject *rows = usedRange->querySubObject("Rows"); - *bottomRightRow = *topLeftRow + rows->property("Count").toInt() - 1; - - QAxObject *columns = usedRange->querySubObject("Columns"); - *bottomRightColumn = *topLeftColumn + columns->property("Count").toInt() - 1; -} - -void QExcel::setColumnWidth(int column, int width) -{ - QString columnName; - columnName.append(QChar(column - 1 + 'A')); - columnName.append(":"); - columnName.append(QChar(column - 1 + 'A')); - - QAxObject * col = sheet->querySubObject("Columns(const QString&)", columnName); - col->setProperty("ColumnWidth", width); -} - -void QExcel::setCellTextCenter(int row, int column) -{ - QString cell; - cell.append(QChar(column - 1 + 'A')); - cell.append(QString::number(row)); - - QAxObject *range = sheet->querySubObject("Range(const QString&)", cell); - range->setProperty("HorizontalAlignment", -4108);//xlCenter -} - -void QExcel::setCellTextWrap(int row, int column, bool isWrap) -{ - QString cell; - cell.append(QChar(column - 1 + 'A')); - cell.append(QString::number(row)); - - QAxObject *range = sheet->querySubObject("Range(const QString&)", cell); - range->setProperty("WrapText", isWrap); -} - -void QExcel::setAutoFitRow(int row) -{ - QString rowsName; - rowsName.append(QString::number(row)); - rowsName.append(":"); - rowsName.append(QString::number(row)); - - QAxObject * rows = sheet->querySubObject("Rows(const QString &)", rowsName); - rows->dynamicCall("AutoFit()"); -} - -void QExcel::insertSheet(QString sheetName) -{ - sheets->querySubObject("Add()"); - QAxObject * a = sheets->querySubObject("Item(int)", 1); - a->setProperty("Name", sheetName); -} - -void QExcel::mergeSerialSameCellsInAColumn(int column, int topRow) -{ - int a,b,c,rowsCount; - getUsedRange(&a, &b, &rowsCount, &c); - - int aMergeStart = topRow, aMergeEnd = topRow + 1; - - QString value; - while(aMergeEnd <= rowsCount) - { - value = getCellValue(aMergeStart, column).toString(); - while(value == getCellValue(aMergeEnd, column).toString()) - { - clearCell(aMergeEnd, column); - aMergeEnd++; - } - aMergeEnd--; - mergeCells(aMergeStart, column, aMergeEnd, column); - - aMergeStart = aMergeEnd + 1; - aMergeEnd = aMergeStart + 1; - } -} - -void QExcel::clearCell(int row, int column) -{ - QString cell; - cell.append(QChar(column - 1 + 'A')); - cell.append(QString::number(row)); - - QAxObject *range = sheet->querySubObject("Range(const QString&)", cell); - range->dynamicCall("ClearContents()"); -} - -void QExcel::clearCell(const QString& cell) -{ - QAxObject *range = sheet->querySubObject("Range(const QString&)", cell); - range->dynamicCall("ClearContents()"); -} - -int QExcel::getUsedRowsCount() -{ - QAxObject *usedRange = sheet->querySubObject("UsedRange"); - int topRow = usedRange->property("Row").toInt(); - QAxObject *rows = usedRange->querySubObject("Rows"); - int bottomRow = topRow + rows->property("Count").toInt() - 1; - return bottomRow; -} - -void QExcel::setCellString(const QString& cell, const QString& value) -{ - QAxObject *range = sheet->querySubObject("Range(const QString&)", cell); - range->dynamicCall("SetValue(const QString&)", value); -} - -void QExcel::setCellFontSize(const QString &cell, int size) -{ - QAxObject *range = sheet->querySubObject("Range(const QString&)", cell); - range = range->querySubObject("Font"); - range->setProperty("Size", size); -} - -void QExcel::setCellTextCenter(const QString &cell) -{ - QAxObject *range = sheet->querySubObject("Range(const QString&)", cell); - range->setProperty("HorizontalAlignment", -4108);//xlCenter -} - -void QExcel::setCellFontBold(const QString &cell, bool isBold) -{ - QAxObject *range = sheet->querySubObject("Range(const QString&)", cell); - range = range->querySubObject("Font"); - range->setProperty("Bold", isBold); -} - -void QExcel::setCellTextWrap(const QString &cell, bool isWrap) -{ - QAxObject *range = sheet->querySubObject("Range(const QString&)", cell); - range->setProperty("WrapText", isWrap); -} - -void QExcel::setRowHeight(int row, int height) -{ - QString rowsName; - rowsName.append(QString::number(row)); - rowsName.append(":"); - rowsName.append(QString::number(row)); - - QAxObject * r = sheet->querySubObject("Rows(const QString &)", rowsName); - r->setProperty("RowHeight", height); -} +#include +#include +#include +#include + +#include "qexcel.h" +#include "QMessageBox" +#include + +QExcel::QExcel(QString xlsFilePath, QObject *parent) +{ + excel = nullptr; + workBooks = nullptr; + workBook = nullptr; + sheets = nullptr; + sheet = nullptr; + CoInitializeEx(NULL, COINIT_MULTITHREADED); + + excel = new QAxObject("Excel.Application"); + excel->setProperty("Visible", false); + workBooks = excel->querySubObject("Workbooks"); + if(workBooks!=nullptr) + { + QFile file(xlsFilePath); + if (file.exists()) + { + workBooks->dynamicCall("Open(const QString&)", xlsFilePath); + workBook = excel->querySubObject("ActiveWorkBook"); + sheets = workBook->querySubObject("WorkSheets"); + } + m_bSupportExcel=true; + } + else { + QMessageBox::information(nullptr, "Title", tr("no support QExcel"), + QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); + m_bSupportExcel=false; + } + +} + +QExcel::~QExcel() +{ + if(excel!=nullptr) + close(); +} + +void QExcel::close() +{ + excel->dynamicCall("Quit()"); + delete sheet; + delete sheets; + delete workBook; + delete workBooks; + delete excel; + + excel = nullptr; + workBooks = nullptr; + workBook = nullptr; + sheets = nullptr; + sheet = nullptr; +} + +QAxObject *QExcel::getWorkBooks() +{ + return workBooks; +} + +QAxObject *QExcel::getWorkBook() +{ + return workBook; +} + +QAxObject *QExcel::getWorkSheets() +{ + return sheets; +} + +QAxObject *QExcel::getWorkSheet() +{ + return sheet; +} + +void QExcel::selectSheet(const QString& sheetName) +{ + sheet = sheets->querySubObject("Item(const QString&)", sheetName); +} + +void QExcel::deleteSheet(const QString& sheetName) +{ + QAxObject * a = sheets->querySubObject("Item(const QString&)", sheetName); + a->dynamicCall("delete"); +} + +void QExcel::deleteSheet(int sheetIndex) +{ + QAxObject * a = sheets->querySubObject("Item(int)", sheetIndex); + a->dynamicCall("delete"); +} + +void QExcel::selectSheet(int sheetIndex) +{ + sheet = sheets->querySubObject("Item(int)", sheetIndex); +} + +void QExcel::setCellString(int row, int column, const QString& value) +{ + QAxObject *range = sheet->querySubObject("Cells(int,int)", row, column); + range->dynamicCall("SetValue(const QString&)", value); +} + +void QExcel::setCellFontBold(int row, int column, bool isBold) +{ + QString cell; + cell.append(QChar(column - 1 + 'A')); + cell.append(QString::number(row)); + + QAxObject *range = sheet->querySubObject("Range(const QString&)", cell); + range = range->querySubObject("Font"); + range->setProperty("Bold", isBold); +} + +void QExcel::setCellFontSize(int row, int column, int size) +{ + QString cell; + cell.append(QChar(column - 1 + 'A')); + cell.append(QString::number(row)); + + QAxObject *range = sheet->querySubObject("Range(const QString&)", cell); + range = range->querySubObject("Font"); + range->setProperty("Size", size); +} + +void QExcel::mergeCells(const QString& cell) +{ + QAxObject *range = sheet->querySubObject("Range(const QString&)", cell); + range->setProperty("VerticalAlignment", -4108);//xlCenter + range->setProperty("WrapText", true); + range->setProperty("MergeCells", true); +} + +void QExcel::mergeCells(int topLeftRow, int topLeftColumn, int bottomRightRow, int bottomRightColumn) +{ + QString cell; + cell.append(QChar(topLeftColumn - 1 + 'A')); + cell.append(QString::number(topLeftRow)); + cell.append(":"); + cell.append(QChar(bottomRightColumn - 1 + 'A')); + cell.append(QString::number(bottomRightRow)); + + QAxObject *range = sheet->querySubObject("Range(const QString&)", cell); + range->setProperty("VerticalAlignment", -4108);//xlCenter + range->setProperty("WrapText", true); + range->setProperty("MergeCells", true); +} + +QVariant QExcel::getCellValue(int row, int column) +{ + QAxObject *range = sheet->querySubObject("Cells(int,int)", row, column); + return range->property("Value"); +} + +void QExcel::save() +{ + workBook->dynamicCall("Save()"); +} + +int QExcel::getSheetsCount() +{ + return sheets->property("Count").toInt(); +} + +QString QExcel::getSheetName() +{ + return sheet->property("Name").toString(); +} + +QString QExcel::getSheetName(int sheetIndex) +{ + QAxObject * a = sheets->querySubObject("Item(int)", sheetIndex); + return a->property("Name").toString(); +} + +void QExcel::getUsedRange(int *topLeftRow, int *topLeftColumn, int *bottomRightRow, int *bottomRightColumn) +{ + QAxObject *usedRange = sheet->querySubObject("UsedRange"); + *topLeftRow = usedRange->property("Row").toInt(); + *topLeftColumn = usedRange->property("Column").toInt(); + + QAxObject *rows = usedRange->querySubObject("Rows"); + *bottomRightRow = *topLeftRow + rows->property("Count").toInt() - 1; + + QAxObject *columns = usedRange->querySubObject("Columns"); + *bottomRightColumn = *topLeftColumn + columns->property("Count").toInt() - 1; +} + +void QExcel::setColumnWidth(int column, int width) +{ + QString columnName; + columnName.append(QChar(column - 1 + 'A')); + columnName.append(":"); + columnName.append(QChar(column - 1 + 'A')); + + QAxObject * col = sheet->querySubObject("Columns(const QString&)", columnName); + col->setProperty("ColumnWidth", width); +} + +void QExcel::setCellTextCenter(int row, int column) +{ + QString cell; + cell.append(QChar(column - 1 + 'A')); + cell.append(QString::number(row)); + + QAxObject *range = sheet->querySubObject("Range(const QString&)", cell); + range->setProperty("HorizontalAlignment", -4108);//xlCenter +} + +void QExcel::setCellTextWrap(int row, int column, bool isWrap) +{ + QString cell; + cell.append(QChar(column - 1 + 'A')); + cell.append(QString::number(row)); + + QAxObject *range = sheet->querySubObject("Range(const QString&)", cell); + range->setProperty("WrapText", isWrap); +} + +void QExcel::setAutoFitRow(int row) +{ + QString rowsName; + rowsName.append(QString::number(row)); + rowsName.append(":"); + rowsName.append(QString::number(row)); + + QAxObject * rows = sheet->querySubObject("Rows(const QString &)", rowsName); + rows->dynamicCall("AutoFit()"); +} + +void QExcel::insertSheet(QString sheetName) +{ + sheets->querySubObject("Add()"); + QAxObject * a = sheets->querySubObject("Item(int)", 1); + a->setProperty("Name", sheetName); +} + +void QExcel::mergeSerialSameCellsInAColumn(int column, int topRow) +{ + int a,b,c,rowsCount; + getUsedRange(&a, &b, &rowsCount, &c); + + int aMergeStart = topRow, aMergeEnd = topRow + 1; + + QString value; + while(aMergeEnd <= rowsCount) + { + value = getCellValue(aMergeStart, column).toString(); + while(value == getCellValue(aMergeEnd, column).toString()) + { + clearCell(aMergeEnd, column); + aMergeEnd++; + } + aMergeEnd--; + mergeCells(aMergeStart, column, aMergeEnd, column); + + aMergeStart = aMergeEnd + 1; + aMergeEnd = aMergeStart + 1; + } +} + +void QExcel::clearCell(int row, int column) +{ + QString cell; + cell.append(QChar(column - 1 + 'A')); + cell.append(QString::number(row)); + + QAxObject *range = sheet->querySubObject("Range(const QString&)", cell); + range->dynamicCall("ClearContents()"); +} + +void QExcel::clearCell(const QString& cell) +{ + QAxObject *range = sheet->querySubObject("Range(const QString&)", cell); + range->dynamicCall("ClearContents()"); +} + +int QExcel::getUsedRowsCount() +{ + QAxObject *usedRange = sheet->querySubObject("UsedRange"); + int topRow = usedRange->property("Row").toInt(); + QAxObject *rows = usedRange->querySubObject("Rows"); + int bottomRow = topRow + rows->property("Count").toInt() - 1; + return bottomRow; +} + +void QExcel::setCellString(const QString& cell, const QString& value) +{ + QAxObject *range = sheet->querySubObject("Range(const QString&)", cell); + range->dynamicCall("SetValue(const QString&)", value); +} + +void QExcel::setCellFontSize(const QString &cell, int size) +{ + QAxObject *range = sheet->querySubObject("Range(const QString&)", cell); + range = range->querySubObject("Font"); + range->setProperty("Size", size); +} + +void QExcel::setCellTextCenter(const QString &cell) +{ + QAxObject *range = sheet->querySubObject("Range(const QString&)", cell); + range->setProperty("HorizontalAlignment", -4108);//xlCenter +} + +void QExcel::setCellFontBold(const QString &cell, bool isBold) +{ + QAxObject *range = sheet->querySubObject("Range(const QString&)", cell); + range = range->querySubObject("Font"); + range->setProperty("Bold", isBold); +} + +void QExcel::setCellTextWrap(const QString &cell, bool isWrap) +{ + QAxObject *range = sheet->querySubObject("Range(const QString&)", cell); + range->setProperty("WrapText", isWrap); +} + +void QExcel::setRowHeight(int row, int height) +{ + QString rowsName; + rowsName.append(QString::number(row)); + rowsName.append(":"); + rowsName.append(QString::number(row)); + + QAxObject * r = sheet->querySubObject("Rows(const QString &)", rowsName); + r->setProperty("RowHeight", height); +} diff --git a/LedOK/base/qexcel.h b/LedOK/base/qexcel.h index 02b5551..df8df12 100644 --- a/LedOK/base/qexcel.h +++ b/LedOK/base/qexcel.h @@ -1,82 +1,82 @@ -#ifndef QEXCEL_H -#define QEXCEL_H - -#include -#include - -class QAxObject; - -class QExcel : public QObject -{ -public: - QExcel(QString xlsFilePath, QObject *parent = 0); - ~QExcel(); - -public: - QAxObject * getWorkBooks(); - QAxObject * getWorkBook(); - QAxObject * getWorkSheets(); - QAxObject * getWorkSheet(); - int m_bSupportExcel=false; - -public: - /**************************************************************************/ - /* 工作表 */ - /**************************************************************************/ - void selectSheet(const QString& sheetName); - //sheetIndex 起始于 1 - void selectSheet(int sheetIndex); - void deleteSheet(const QString& sheetName); - void deleteSheet(int sheetIndex); - void insertSheet(QString sheetName); - int getSheetsCount(); - //在 selectSheet() 之后才可调用 - QString getSheetName(); - QString getSheetName(int sheetIndex); - - /**************************************************************************/ - /* 单元格 */ - /**************************************************************************/ - void setCellString(int row, int column, const QString& value); - //cell 例如 "A7" - void setCellString(const QString& cell, const QString& value); - //range 例如 "A5:C7" - void mergeCells(const QString& range); - void mergeCells(int topLeftRow, int topLeftColumn, int bottomRightRow, int bottomRightColumn); - QVariant getCellValue(int row, int column); - void clearCell(int row, int column); - void clearCell(const QString& cell); - - /**************************************************************************/ - /* 布局格式 */ - /**************************************************************************/ - void getUsedRange(int *topLeftRow, int *topLeftColumn, int *bottomRightRow, int *bottomRightColumn); - void setColumnWidth(int column, int width); - void setRowHeight(int row, int height); - void setCellTextCenter(int row, int column); - void setCellTextCenter(const QString& cell); - void setCellTextWrap(int row, int column, bool isWrap); - void setCellTextWrap(const QString& cell, bool isWrap); - void setAutoFitRow(int row); - void mergeSerialSameCellsInAColumn(int column, int topRow); - int getUsedRowsCount(); - void setCellFontBold(int row, int column, bool isBold); - void setCellFontBold(const QString& cell, bool isBold); - void setCellFontSize(int row, int column, int size); - void setCellFontSize(const QString& cell, int size); - - /**************************************************************************/ - /* 文件 */ - /**************************************************************************/ - void save(); - void close(); - -private: - QAxObject * excel; - QAxObject * workBooks; - QAxObject * workBook; - QAxObject * sheets; - QAxObject * sheet; -}; - -#endif +#ifndef QEXCEL_H +#define QEXCEL_H + +#include +#include + +class QAxObject; + +class QExcel : public QObject +{ +public: + QExcel(QString xlsFilePath, QObject *parent = 0); + ~QExcel(); + +public: + QAxObject * getWorkBooks(); + QAxObject * getWorkBook(); + QAxObject * getWorkSheets(); + QAxObject * getWorkSheet(); + int m_bSupportExcel=false; + +public: + /**************************************************************************/ + /* 工作表 */ + /**************************************************************************/ + void selectSheet(const QString& sheetName); + //sheetIndex 起始于 1 + void selectSheet(int sheetIndex); + void deleteSheet(const QString& sheetName); + void deleteSheet(int sheetIndex); + void insertSheet(QString sheetName); + int getSheetsCount(); + //在 selectSheet() 之后才可调用 + QString getSheetName(); + QString getSheetName(int sheetIndex); + + /**************************************************************************/ + /* 单元格 */ + /**************************************************************************/ + void setCellString(int row, int column, const QString& value); + //cell 例如 "A7" + void setCellString(const QString& cell, const QString& value); + //range 例如 "A5:C7" + void mergeCells(const QString& range); + void mergeCells(int topLeftRow, int topLeftColumn, int bottomRightRow, int bottomRightColumn); + QVariant getCellValue(int row, int column); + void clearCell(int row, int column); + void clearCell(const QString& cell); + + /**************************************************************************/ + /* 布局格式 */ + /**************************************************************************/ + void getUsedRange(int *topLeftRow, int *topLeftColumn, int *bottomRightRow, int *bottomRightColumn); + void setColumnWidth(int column, int width); + void setRowHeight(int row, int height); + void setCellTextCenter(int row, int column); + void setCellTextCenter(const QString& cell); + void setCellTextWrap(int row, int column, bool isWrap); + void setCellTextWrap(const QString& cell, bool isWrap); + void setAutoFitRow(int row); + void mergeSerialSameCellsInAColumn(int column, int topRow); + int getUsedRowsCount(); + void setCellFontBold(int row, int column, bool isBold); + void setCellFontBold(const QString& cell, bool isBold); + void setCellFontSize(int row, int column, int size); + void setCellFontSize(const QString& cell, int size); + + /**************************************************************************/ + /* 文件 */ + /**************************************************************************/ + void save(); + void close(); + +private: + QAxObject * excel; + QAxObject * workBooks; + QAxObject * workBook; + QAxObject * sheets; + QAxObject * sheet; +}; + +#endif diff --git a/LedOK/base/qiplineedit.cpp b/LedOK/base/qiplineedit.cpp index 7b28763..ad0c89c 100644 --- a/LedOK/base/qiplineedit.cpp +++ b/LedOK/base/qiplineedit.cpp @@ -1,285 +1,285 @@ -/* - * 此类的封装参考了:博客网址:http://blog.csdn.net/u011417605,并在此基础上进行修改 - * 1.连续输入 - * 2.连续删除 - * 3.任意位置插入 - * 4.自适应大小变化 - * 5.正则匹配,每个值不大于255.设置IP值时,有正则验证是否是IP格式 - * 实现方法:使用一个大的QLineEdit嵌套四个小的QLineEdit,中间的点是使用paintEvent画出来的。操作是使用eventFilter来进行分发实现的 - * 修改: - * 用QWidget替换原先的__super - * 修改构造函数中的正则匹配 - * 修改小圆点位置和大小 - * 两个QLineEdit之间的空隙,在绘制小圆点之前,把空气用白色背景填充 - * 修改样式表加边框 - * 当输入类似192时,焦点自动跳转到下一个QLineEdit出 - * 修改text()的输出,使输出由原来的1921680127变为192.168.0.127 - **/ - -#include "qiplineedit.h" -#include -#include -#include -#include -#define SPACE 5 - -QIPLineEdit::QIPLineEdit(QWidget *parent) : QLineEdit(parent) { - QRegExp rx("((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)"); - pHBox = new QHBoxLayout(this); - pHBox->setSpacing(SPACE); - pHBox->setContentsMargins(0, 0, 0, 0); - for(int i = 0; i < 4; i++) { - m_lineEidt[i] = new QLineEdit(this); - m_lineEidt[i]->setFrame(false); - m_lineEidt[i]->setMaxLength(3); - m_lineEidt[i]->setAlignment(Qt::AlignCenter); - m_lineEidt[i]->installEventFilter(this); - m_lineEidt[i]->setValidator(new QRegExpValidator(rx, this)); - m_lineEidt[i]->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); - switch (i) - { - case 0: - m_lineEidt[i]->setStyleSheet(QLatin1String( "border:1px solid #536874;\n" "border-left-color: rgb(0, 0, 0);\n" - "border-top-color: rgb(0, 0, 0);\n" "border-bottom-color: rgb(0, 0, 0);\n" "border-right: 0px;\n" - "border-right-color: rgbl(255, 255, 255,0);" "border-radius:0px")); - break; - case 1: - m_lineEidt[i]->setStyleSheet(QLatin1String( "border:1px solid #536874;\n" "border-left-color: rgb(255, 255, 255);\n" - "border-top-color: rgb(0, 0, 0);\n" "border-bottom-color: rgb(0, 0, 0);\n" "border-right: 0px;\n" "border-left: 0px;\n" - "border-right-color: rgb(255, 255, 255);" "border-radius:0px")); - break; - case 2: - m_lineEidt[i]->setStyleSheet(QLatin1String( "border:1px solid #536874;\n" "border-left-color: rgb(255, 255, 255);\n" - "border-top-color: rgb(0, 0, 0);\n" "border-bottom-color: rgb(0, 0, 0);\n" "border-right: 0px;\n" "border-left: 0px;\n" - "border-right-color: rgb(255, 255, 255);" "border-radius:0px")); - break; - case 3: - m_lineEidt[i]->setStyleSheet(QLatin1String( "border:1px solid #536874;\n" "border-left-color: rgb(255, 255, 255);\n" - "border-top-color: rgb(0, 0, 0);\n" "border-bottom-color: rgb(0, 0, 0);\n" "border-left: 0px;\n" - "border-right-color: rgb(0, 0, 0);" "border-radius:0px")); - break; - default: - break; - } - pHBox->addWidget(m_lineEidt[i]); - } - this->setReadOnly(true); - m_Color=Qt::white; - connect(m_lineEidt[0],SIGNAL(textChanged(const QString &)),this,SLOT(OnLineEdit1TextChanged(const QString &))); - connect(m_lineEidt[1],SIGNAL(textChanged(const QString &)),this,SLOT(OnLineEdit2TextChanged(const QString &))); - connect(m_lineEidt[2],SIGNAL(textChanged(const QString &)),this,SLOT(OnLineEdit3TextChanged(const QString &))); - connect(m_lineEidt[3],SIGNAL(textChanged(const QString &)),this,SLOT(OnLineEdit4TextChanged(const QString &))); -} - -QIPLineEdit::~QIPLineEdit() { - m_lineEidt[0]->deleteLater(); - m_lineEidt[1]->deleteLater(); - m_lineEidt[2]->deleteLater(); - m_lineEidt[3]->deleteLater(); - pHBox->deleteLater(); -} -void QIPLineEdit::MySetColor(QColor cr) -{ - m_Color=cr; -} -void QIPLineEdit::OnLineEdit1TextChanged(const QString & strtemp) -{ - if(strtemp.right(1)=="."||strtemp.right(1)=="。") - { - m_lineEidt[0]->setText(strtemp.left(strtemp.length()-1)); - m_lineEidt[0 + 1]->setFocus(); - m_lineEidt[0 + 1]->setCursorPosition(0); - } -} -void QIPLineEdit::OnLineEdit2TextChanged(const QString & strtemp) -{ - if(strtemp.right(1)=="."||strtemp.right(1)=="。") - { - m_lineEidt[1]->setText(strtemp.left(strtemp.length()-1)); - m_lineEidt[1 + 1]->setFocus(); - m_lineEidt[1 + 1]->setCursorPosition(0); - } -} -void QIPLineEdit::OnLineEdit3TextChanged(const QString & strtemp) -{ - if(strtemp.right(1)=="."||strtemp.right(1)=="。") - { - m_lineEidt[2]->setText(strtemp.left(strtemp.length()-1)); - m_lineEidt[2 + 1]->setFocus(); - m_lineEidt[2 + 1]->setCursorPosition(0); - } -} -void QIPLineEdit::OnLineEdit4TextChanged(const QString & strtemp) -{ - if(strtemp.right(1)=="."||strtemp.right(1)=="。") - { - m_lineEidt[3]->setText(strtemp.left(strtemp.length()-1)); - } -} -void QIPLineEdit::paintEvent(QPaintEvent *event) { - QWidget::paintEvent(event); - QPainter painter(this); - QBrush brush; - int width = 0; - for(int i = 0; i < 3; i++) { - brush.setStyle(Qt::BrushStyle::SolidPattern); - //将两个lineEdit之间的空隙绘制成白色 - brush.setColor(m_Color); - painter.setPen(m_Color); - painter.setBrush(brush); - painter.drawRect(m_lineEidt[i]->x() + m_lineEidt[i]->width(), m_lineEidt[i]->y(), SPACE, height()); - //绘制空隙的边框 - painter.setPen(Qt::black); - painter.drawLine(0, 0, this->width(), 0); - painter.drawLine(0, this->height() - 1, this->width(), this->height() - 1); - //绘制小黑点 - brush.setColor(Qt::black); - painter.setPen(QPen()); - painter.setBrush(brush); - width += m_lineEidt[i]->width() + (i == 0 ? 2 : SPACE);//布局的间隔 - painter.drawEllipse(width, height() / 2 + 4, 1, 1); - } -} - -int QIPLineEdit::getIndex(QLineEdit *pEdit){ - int index = -1; - for(int i = 0; i < 4; i++) if(pEdit == m_lineEidt[i]) index = i; - return index; -} - -bool QIPLineEdit::eventFilter(QObject *obj, QEvent *ev) { - if(children().contains(obj) && QEvent::KeyPress == ev->type()) { - QKeyEvent *keyEvent = dynamic_cast(ev); - QLineEdit *pEdit = qobject_cast(obj); - switch (keyEvent->key()) { - case Qt::Key_0: - case Qt::Key_1: - case Qt::Key_2: - case Qt::Key_3: - case Qt::Key_4: - case Qt::Key_5: - case Qt::Key_6: - case Qt::Key_7: - case Qt::Key_8: - case Qt::Key_9: - { - QString strText = pEdit->text(); - if (pEdit->selectedText().length()) - { - pEdit->text().replace(pEdit->selectedText(), QChar(keyEvent->key())); - } - else if (strText.length() == 2 || (strText.length() < 2 && strText.toInt() * 10 > 255)) - { - int index = getIndex(pEdit); - if (index != -1 && index != 3) - { - m_lineEidt[index + 1]->setFocus(); - m_lineEidt[index + 1]->selectAll(); - } - } - else if (strText.length() == 2 && strText.toInt() * 10 < 255) - { - if (Qt::Key_0 == keyEvent->key() && strText.toInt()) - { - pEdit->setText(strText.insert(pEdit->cursorPosition(), QChar(Qt::Key_0))); - } - } - return QWidget::eventFilter(obj, ev); - } - break; - case Qt::Key_Backspace: - { - QString strText = pEdit->text(); - if (!strText.length() || (strText.length() && !pEdit->cursorPosition())) - { - int index = getIndex(pEdit); - if (index != -1 && index != 0) - { - m_lineEidt[index - 1]->setFocus(); - int length = m_lineEidt[index - 1]->text().length(); - m_lineEidt[index - 1]->setCursorPosition(length ? length : 0); - } - } - return QWidget::eventFilter(obj, ev); - } - break; - case Qt::Key_Left: - { - if (!pEdit->cursorPosition()) - { - int index = getIndex(pEdit); - if (index != -1 && index != 0) - { - m_lineEidt[index - 1]->setFocus(); - int length = m_lineEidt[index - 1]->text().length(); - m_lineEidt[index - 1]->setCursorPosition(length ? length : 0); - } - } - return QWidget::eventFilter(obj, ev); - } - break; - case Qt::Key_Right: - { - if (pEdit->cursorPosition() == pEdit->text().length()) - { - int index = getIndex(pEdit); - if (index != -1 && index != 3) - { - m_lineEidt[index + 1]->setFocus(); - m_lineEidt[index + 1]->setCursorPosition(0); - } - } - return QWidget::eventFilter(obj, ev); - } - break; - default: - break; - } - } - return false; -} - -void QIPLineEdit::setText(const QString &strIP) -{ - if (!isTextValid(strIP)) - { - QMessageBox::warning(this, "Attention", "Your IP Address is Invalid!["+strIP+"]", QMessageBox::StandardButton::Ok); - return; - } - else - { - int i = 0; - QStringList ipList = strIP.split("."); - foreach (QString ip, ipList) - { - m_lineEidt[i]->setText(ip); - i++; - } - } -} - -bool QIPLineEdit::isTextValid(const QString &strIP) { - QRegExp rx2("\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b"); - return rx2.exactMatch(strIP); -} - -QString QIPLineEdit::text() const -{ - QString strIP; - for (int i = 0; i < 4; i++) - { - strIP.append(m_lineEidt[i]->text()); - if (i < 3) - { - strIP.append("."); - } - } - return strIP; -} -void QIPLineEdit::MyClear() -{ - m_lineEidt[0]->clear(); - m_lineEidt[1]->clear(); - m_lineEidt[2]->clear(); - m_lineEidt[3]->clear(); -} +/* + * 此类的封装参考了:博客网址:http://blog.csdn.net/u011417605,并在此基础上进行修改 + * 1.连续输入 + * 2.连续删除 + * 3.任意位置插入 + * 4.自适应大小变化 + * 5.正则匹配,每个值不大于255.设置IP值时,有正则验证是否是IP格式 + * 实现方法:使用一个大的QLineEdit嵌套四个小的QLineEdit,中间的点是使用paintEvent画出来的。操作是使用eventFilter来进行分发实现的 + * 修改: + * 用QWidget替换原先的__super + * 修改构造函数中的正则匹配 + * 修改小圆点位置和大小 + * 两个QLineEdit之间的空隙,在绘制小圆点之前,把空气用白色背景填充 + * 修改样式表加边框 + * 当输入类似192时,焦点自动跳转到下一个QLineEdit出 + * 修改text()的输出,使输出由原来的1921680127变为192.168.0.127 + **/ + +#include "qiplineedit.h" +#include +#include +#include +#include +#define SPACE 5 + +QIPLineEdit::QIPLineEdit(QWidget *parent) : QLineEdit(parent) { + QRegExp rx("((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)"); + pHBox = new QHBoxLayout(this); + pHBox->setSpacing(SPACE); + pHBox->setContentsMargins(0, 0, 0, 0); + for(int i = 0; i < 4; i++) { + m_lineEidt[i] = new QLineEdit(this); + m_lineEidt[i]->setFrame(false); + m_lineEidt[i]->setMaxLength(3); + m_lineEidt[i]->setAlignment(Qt::AlignCenter); + m_lineEidt[i]->installEventFilter(this); + m_lineEidt[i]->setValidator(new QRegExpValidator(rx, this)); + m_lineEidt[i]->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + switch (i) + { + case 0: + m_lineEidt[i]->setStyleSheet(QLatin1String( "border:1px solid #536874;\n" "border-left-color: rgb(0, 0, 0);\n" + "border-top-color: rgb(0, 0, 0);\n" "border-bottom-color: rgb(0, 0, 0);\n" "border-right: 0px;\n" + "border-right-color: rgbl(255, 255, 255,0);" "border-radius:0px")); + break; + case 1: + m_lineEidt[i]->setStyleSheet(QLatin1String( "border:1px solid #536874;\n" "border-left-color: rgb(255, 255, 255);\n" + "border-top-color: rgb(0, 0, 0);\n" "border-bottom-color: rgb(0, 0, 0);\n" "border-right: 0px;\n" "border-left: 0px;\n" + "border-right-color: rgb(255, 255, 255);" "border-radius:0px")); + break; + case 2: + m_lineEidt[i]->setStyleSheet(QLatin1String( "border:1px solid #536874;\n" "border-left-color: rgb(255, 255, 255);\n" + "border-top-color: rgb(0, 0, 0);\n" "border-bottom-color: rgb(0, 0, 0);\n" "border-right: 0px;\n" "border-left: 0px;\n" + "border-right-color: rgb(255, 255, 255);" "border-radius:0px")); + break; + case 3: + m_lineEidt[i]->setStyleSheet(QLatin1String( "border:1px solid #536874;\n" "border-left-color: rgb(255, 255, 255);\n" + "border-top-color: rgb(0, 0, 0);\n" "border-bottom-color: rgb(0, 0, 0);\n" "border-left: 0px;\n" + "border-right-color: rgb(0, 0, 0);" "border-radius:0px")); + break; + default: + break; + } + pHBox->addWidget(m_lineEidt[i]); + } + this->setReadOnly(true); + m_Color=Qt::white; + connect(m_lineEidt[0],SIGNAL(textChanged(const QString &)),this,SLOT(OnLineEdit1TextChanged(const QString &))); + connect(m_lineEidt[1],SIGNAL(textChanged(const QString &)),this,SLOT(OnLineEdit2TextChanged(const QString &))); + connect(m_lineEidt[2],SIGNAL(textChanged(const QString &)),this,SLOT(OnLineEdit3TextChanged(const QString &))); + connect(m_lineEidt[3],SIGNAL(textChanged(const QString &)),this,SLOT(OnLineEdit4TextChanged(const QString &))); +} + +QIPLineEdit::~QIPLineEdit() { + m_lineEidt[0]->deleteLater(); + m_lineEidt[1]->deleteLater(); + m_lineEidt[2]->deleteLater(); + m_lineEidt[3]->deleteLater(); + pHBox->deleteLater(); +} +void QIPLineEdit::MySetColor(QColor cr) +{ + m_Color=cr; +} +void QIPLineEdit::OnLineEdit1TextChanged(const QString & strtemp) +{ + if(strtemp.right(1)=="."||strtemp.right(1)=="。") + { + m_lineEidt[0]->setText(strtemp.left(strtemp.length()-1)); + m_lineEidt[0 + 1]->setFocus(); + m_lineEidt[0 + 1]->setCursorPosition(0); + } +} +void QIPLineEdit::OnLineEdit2TextChanged(const QString & strtemp) +{ + if(strtemp.right(1)=="."||strtemp.right(1)=="。") + { + m_lineEidt[1]->setText(strtemp.left(strtemp.length()-1)); + m_lineEidt[1 + 1]->setFocus(); + m_lineEidt[1 + 1]->setCursorPosition(0); + } +} +void QIPLineEdit::OnLineEdit3TextChanged(const QString & strtemp) +{ + if(strtemp.right(1)=="."||strtemp.right(1)=="。") + { + m_lineEidt[2]->setText(strtemp.left(strtemp.length()-1)); + m_lineEidt[2 + 1]->setFocus(); + m_lineEidt[2 + 1]->setCursorPosition(0); + } +} +void QIPLineEdit::OnLineEdit4TextChanged(const QString & strtemp) +{ + if(strtemp.right(1)=="."||strtemp.right(1)=="。") + { + m_lineEidt[3]->setText(strtemp.left(strtemp.length()-1)); + } +} +void QIPLineEdit::paintEvent(QPaintEvent *event) { + QWidget::paintEvent(event); + QPainter painter(this); + QBrush brush; + int width = 0; + for(int i = 0; i < 3; i++) { + brush.setStyle(Qt::BrushStyle::SolidPattern); + //将两个lineEdit之间的空隙绘制成白色 + brush.setColor(m_Color); + painter.setPen(m_Color); + painter.setBrush(brush); + painter.drawRect(m_lineEidt[i]->x() + m_lineEidt[i]->width(), m_lineEidt[i]->y(), SPACE, height()); + //绘制空隙的边框 + painter.setPen(Qt::black); + painter.drawLine(0, 0, this->width(), 0); + painter.drawLine(0, this->height() - 1, this->width(), this->height() - 1); + //绘制小黑点 + brush.setColor(Qt::black); + painter.setPen(QPen()); + painter.setBrush(brush); + width += m_lineEidt[i]->width() + (i == 0 ? 2 : SPACE);//布局的间隔 + painter.drawEllipse(width, height() / 2 + 4, 1, 1); + } +} + +int QIPLineEdit::getIndex(QLineEdit *pEdit){ + int index = -1; + for(int i = 0; i < 4; i++) if(pEdit == m_lineEidt[i]) index = i; + return index; +} + +bool QIPLineEdit::eventFilter(QObject *obj, QEvent *ev) { + if(children().contains(obj) && QEvent::KeyPress == ev->type()) { + QKeyEvent *keyEvent = dynamic_cast(ev); + QLineEdit *pEdit = qobject_cast(obj); + switch (keyEvent->key()) { + case Qt::Key_0: + case Qt::Key_1: + case Qt::Key_2: + case Qt::Key_3: + case Qt::Key_4: + case Qt::Key_5: + case Qt::Key_6: + case Qt::Key_7: + case Qt::Key_8: + case Qt::Key_9: + { + QString strText = pEdit->text(); + if (pEdit->selectedText().length()) + { + pEdit->text().replace(pEdit->selectedText(), QChar(keyEvent->key())); + } + else if (strText.length() == 2 || (strText.length() < 2 && strText.toInt() * 10 > 255)) + { + int index = getIndex(pEdit); + if (index != -1 && index != 3) + { + m_lineEidt[index + 1]->setFocus(); + m_lineEidt[index + 1]->selectAll(); + } + } + else if (strText.length() == 2 && strText.toInt() * 10 < 255) + { + if (Qt::Key_0 == keyEvent->key() && strText.toInt()) + { + pEdit->setText(strText.insert(pEdit->cursorPosition(), QChar(Qt::Key_0))); + } + } + return QWidget::eventFilter(obj, ev); + } + break; + case Qt::Key_Backspace: + { + QString strText = pEdit->text(); + if (!strText.length() || (strText.length() && !pEdit->cursorPosition())) + { + int index = getIndex(pEdit); + if (index != -1 && index != 0) + { + m_lineEidt[index - 1]->setFocus(); + int length = m_lineEidt[index - 1]->text().length(); + m_lineEidt[index - 1]->setCursorPosition(length ? length : 0); + } + } + return QWidget::eventFilter(obj, ev); + } + break; + case Qt::Key_Left: + { + if (!pEdit->cursorPosition()) + { + int index = getIndex(pEdit); + if (index != -1 && index != 0) + { + m_lineEidt[index - 1]->setFocus(); + int length = m_lineEidt[index - 1]->text().length(); + m_lineEidt[index - 1]->setCursorPosition(length ? length : 0); + } + } + return QWidget::eventFilter(obj, ev); + } + break; + case Qt::Key_Right: + { + if (pEdit->cursorPosition() == pEdit->text().length()) + { + int index = getIndex(pEdit); + if (index != -1 && index != 3) + { + m_lineEidt[index + 1]->setFocus(); + m_lineEidt[index + 1]->setCursorPosition(0); + } + } + return QWidget::eventFilter(obj, ev); + } + break; + default: + break; + } + } + return false; +} + +void QIPLineEdit::setText(const QString &strIP) +{ + if (!isTextValid(strIP)) + { + QMessageBox::warning(this, "Attention", "Your IP Address is Invalid!["+strIP+"]", QMessageBox::StandardButton::Ok); + return; + } + else + { + int i = 0; + QStringList ipList = strIP.split("."); + foreach (QString ip, ipList) + { + m_lineEidt[i]->setText(ip); + i++; + } + } +} + +bool QIPLineEdit::isTextValid(const QString &strIP) { + QRegExp rx2("\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b"); + return rx2.exactMatch(strIP); +} + +QString QIPLineEdit::text() const +{ + QString strIP; + for (int i = 0; i < 4; i++) + { + strIP.append(m_lineEidt[i]->text()); + if (i < 3) + { + strIP.append("."); + } + } + return strIP; +} +void QIPLineEdit::MyClear() +{ + m_lineEidt[0]->clear(); + m_lineEidt[1]->clear(); + m_lineEidt[2]->clear(); + m_lineEidt[3]->clear(); +} diff --git a/LedOK/base/qiplineedit.h b/LedOK/base/qiplineedit.h index d53eaa6..083eeb5 100644 --- a/LedOK/base/qiplineedit.h +++ b/LedOK/base/qiplineedit.h @@ -1,37 +1,37 @@ -#ifndef QIPLINEEDIT_H -#define QIPLINEEDIT_H - -#include -#include -#include - -class QIPLineEdit : public QLineEdit { - Q_OBJECT -public: - QIPLineEdit(QWidget *parent = nullptr); - ~QIPLineEdit(); - - void setText(const QString &strIP); - QString text() const; - void MyClear(); - void MySetColor(QColor cr); - -protected: - void paintEvent(QPaintEvent *event); - bool eventFilter(QObject *obj, QEvent *ev); - - int getIndex(QLineEdit *pEdit); - bool isTextValid(const QString &strIP); -protected slots: - void OnLineEdit1TextChanged(const QString & strtemp); - void OnLineEdit2TextChanged(const QString & strtemp); - void OnLineEdit3TextChanged(const QString & strtemp); - void OnLineEdit4TextChanged(const QString & strtemp); - -private: - QLineEdit *m_lineEidt[4]; - QHBoxLayout *pHBox; - QColor m_Color; -}; - -#endif // QIPLINEEDIT_H +#ifndef QIPLINEEDIT_H +#define QIPLINEEDIT_H + +#include +#include +#include + +class QIPLineEdit : public QLineEdit { + Q_OBJECT +public: + QIPLineEdit(QWidget *parent = nullptr); + ~QIPLineEdit(); + + void setText(const QString &strIP); + QString text() const; + void MyClear(); + void MySetColor(QColor cr); + +protected: + void paintEvent(QPaintEvent *event); + bool eventFilter(QObject *obj, QEvent *ev); + + int getIndex(QLineEdit *pEdit); + bool isTextValid(const QString &strIP); +protected slots: + void OnLineEdit1TextChanged(const QString & strtemp); + void OnLineEdit2TextChanged(const QString & strtemp); + void OnLineEdit3TextChanged(const QString & strtemp); + void OnLineEdit4TextChanged(const QString & strtemp); + +private: + QLineEdit *m_lineEidt[4]; + QHBoxLayout *pHBox; + QColor m_Color; +}; + +#endif // QIPLINEEDIT_H diff --git a/LedOK/base/readexcel.cpp b/LedOK/base/readexcel.cpp index 302f608..bfd8fe8 100644 --- a/LedOK/base/readexcel.cpp +++ b/LedOK/base/readexcel.cpp @@ -1,169 +1,169 @@ -#include "readexcel.h" -#include -#include - -ReadExcel::ReadExcel() - :m_row(0), m_col(0), m_filename("") -{ - m_excel = new QAxObject("Excel.Application"); -} - -ReadExcel::~ReadExcel() -{ - if (!m_mapdata.empty()) { - m_mapdata.clear(); - } - delete m_excel; -} - -// -bool ReadExcel::openExcel(const QString &filename) -{ - if (filename.isEmpty()) { - m_row = 0; - m_col = 0; - return false; - } - QFile file(filename); - if (!file.exists()){ - m_row = 0; - m_col = 0; - return false; - }; - if (!m_mapdata.empty()) { - m_mapdata.clear(); - } - m_filename = filename; - try { - getALLfromExcel(); - - } catch (...) { - return false; - } - - return true; -} -void ReadExcel::getALLfromDirNormalExcel(QString strFileName) -{ - openExcelForWrite(strFileName); -} -bool ReadExcel::openExcelForWrite(const QString &filename) -{ - if (filename.isEmpty()) { - m_row = 0; - m_col = 0; - return false; - } - QFile file(filename); - if (!file.exists()){ - m_row = 0; - m_col = 0; - return false; - }; - if (!m_mapdata.empty()) { - m_mapdata.clear(); - } - m_filename = filename; - try { - WriteALLfromExcel(); - } catch (...) { - return false; - } - - return true; -} - -void ReadExcel::getInfo(int &row, int &col) const -{ - row = m_row; - col = m_col; -} - -std::string ReadExcel::getCellData(const int &row, const int &col) -{ - if (row >= 1 && row <= m_row && col >= 1 && col <= m_col) { - p.m_row = row; - p.m_col = col; - return m_mapdata[p]; - } else { - return nullptr; - } -} -int ReadExcel::WriteCellData(const int &row, const int &col,std::string strValue ) -{ - p.m_row = row; - p.m_col = col; - - m_mapdata[p]=strValue; - return 0; -} - -void ReadExcel::getALLfromExcel() -{ - m_excel->setProperty("Visible", 0); - QAxObject* workbooks = m_excel->querySubObject("WorkBooks"); - workbooks->dynamicCall("Open (const QString&)", m_filename); - QAxObject* workbook = m_excel->querySubObject("ActiveWorkBook"); - QAxObject* worksheets = workbook->querySubObject("WorkSheets"); - Q_UNUSED(worksheets) - QAxObject* worksheet = workbook->querySubObject("Worksheets(int)", 1); //worksheet number - QAxObject* usedrange = worksheet->querySubObject("UsedRange"); - QAxObject* rows = usedrange->querySubObject("Rows"); - QAxObject* columns = usedrange->querySubObject("Columns"); - int intRowStart = usedrange->property("Row").toInt(); - int intColStart = usedrange->property("Column").toInt(); - int intCols = columns->property("Count").toInt(); - int intRows = rows->property("Count").toInt(); - m_row = intRows; - m_col = intCols; - QAxObject * cell; - for (int i = intRowStart; i < intRowStart + intRows; i++) - { - for (int j = intColStart; j < intColStart + intCols; j++) - { - Position pos(i, j); - cell = m_excel->querySubObject("Cells(Int, Int)", i, j ); - QVariant cellValue = cell->dynamicCall("value"); - m_mapdata.insert(std::pair(pos, cellValue.toString().toStdString())); - } - } - m_excel->setProperty("DisplayAlerts", 0); - workbook->dynamicCall("Save(void)"); - workbook->dynamicCall("Close (Boolean)", false); - m_excel->setProperty("DisplayAlerts",1); -} -void ReadExcel::WriteALLfromExcel() -{ - m_excel->setProperty("Visible", 0); - QAxObject* workbooks = m_excel->querySubObject("WorkBooks"); - workbooks->dynamicCall("Open (const QString&)", m_filename); - QAxObject* workbook = m_excel->querySubObject("ActiveWorkBook"); - QAxObject* worksheets = workbook->querySubObject("WorkSheets"); - Q_UNUSED(worksheets) - QAxObject* worksheet = workbook->querySubObject("Worksheets(int)", 1); //worksheet number - QAxObject* usedrange = worksheet->querySubObject("UsedRange"); - QAxObject* rows = usedrange->querySubObject("Rows"); - QAxObject* columns = usedrange->querySubObject("Columns"); - int intRowStart = usedrange->property("Row").toInt(); - int intColStart = usedrange->property("Column").toInt(); - int intCols = columns->property("Count").toInt(); - int intRows = rows->property("Count").toInt(); - m_row = intRows; - m_col = intCols; - QAxObject * cell; - for (int i = intRowStart; i < intRowStart + intRows; i++) - { - for (int j = intColStart; j < intColStart + intCols; j++) - { - Position pos(i, j); - cell = m_excel->querySubObject("Cells(Int, Int)", i, j ); - QVariant cellValue = cell->dynamicCall("value"); - m_mapdata.insert(std::pair(pos, cellValue.toString().toStdString())); - } - } - - m_excel->setProperty("DisplayAlerts", 0); - workbook->dynamicCall("Save(void)"); - workbook->dynamicCall("Close (Boolean)", false); - m_excel->setProperty("DisplayAlerts",1); -} +#include "readexcel.h" +#include +#include + +ReadExcel::ReadExcel() + :m_row(0), m_col(0), m_filename("") +{ + m_excel = new QAxObject("Excel.Application"); +} + +ReadExcel::~ReadExcel() +{ + if (!m_mapdata.empty()) { + m_mapdata.clear(); + } + delete m_excel; +} + +// +bool ReadExcel::openExcel(const QString &filename) +{ + if (filename.isEmpty()) { + m_row = 0; + m_col = 0; + return false; + } + QFile file(filename); + if (!file.exists()){ + m_row = 0; + m_col = 0; + return false; + }; + if (!m_mapdata.empty()) { + m_mapdata.clear(); + } + m_filename = filename; + try { + getALLfromExcel(); + + } catch (...) { + return false; + } + + return true; +} +void ReadExcel::getALLfromDirNormalExcel(QString strFileName) +{ + openExcelForWrite(strFileName); +} +bool ReadExcel::openExcelForWrite(const QString &filename) +{ + if (filename.isEmpty()) { + m_row = 0; + m_col = 0; + return false; + } + QFile file(filename); + if (!file.exists()){ + m_row = 0; + m_col = 0; + return false; + }; + if (!m_mapdata.empty()) { + m_mapdata.clear(); + } + m_filename = filename; + try { + WriteALLfromExcel(); + } catch (...) { + return false; + } + + return true; +} + +void ReadExcel::getInfo(int &row, int &col) const +{ + row = m_row; + col = m_col; +} + +std::string ReadExcel::getCellData(const int &row, const int &col) +{ + if (row >= 1 && row <= m_row && col >= 1 && col <= m_col) { + p.m_row = row; + p.m_col = col; + return m_mapdata[p]; + } else { + return nullptr; + } +} +int ReadExcel::WriteCellData(const int &row, const int &col,std::string strValue ) +{ + p.m_row = row; + p.m_col = col; + + m_mapdata[p]=strValue; + return 0; +} + +void ReadExcel::getALLfromExcel() +{ + m_excel->setProperty("Visible", 0); + QAxObject* workbooks = m_excel->querySubObject("WorkBooks"); + workbooks->dynamicCall("Open (const QString&)", m_filename); + QAxObject* workbook = m_excel->querySubObject("ActiveWorkBook"); + QAxObject* worksheets = workbook->querySubObject("WorkSheets"); + Q_UNUSED(worksheets) + QAxObject* worksheet = workbook->querySubObject("Worksheets(int)", 1); //worksheet number + QAxObject* usedrange = worksheet->querySubObject("UsedRange"); + QAxObject* rows = usedrange->querySubObject("Rows"); + QAxObject* columns = usedrange->querySubObject("Columns"); + int intRowStart = usedrange->property("Row").toInt(); + int intColStart = usedrange->property("Column").toInt(); + int intCols = columns->property("Count").toInt(); + int intRows = rows->property("Count").toInt(); + m_row = intRows; + m_col = intCols; + QAxObject * cell; + for (int i = intRowStart; i < intRowStart + intRows; i++) + { + for (int j = intColStart; j < intColStart + intCols; j++) + { + Position pos(i, j); + cell = m_excel->querySubObject("Cells(Int, Int)", i, j ); + QVariant cellValue = cell->dynamicCall("value"); + m_mapdata.insert(std::pair(pos, cellValue.toString().toStdString())); + } + } + m_excel->setProperty("DisplayAlerts", 0); + workbook->dynamicCall("Save(void)"); + workbook->dynamicCall("Close (Boolean)", false); + m_excel->setProperty("DisplayAlerts",1); +} +void ReadExcel::WriteALLfromExcel() +{ + m_excel->setProperty("Visible", 0); + QAxObject* workbooks = m_excel->querySubObject("WorkBooks"); + workbooks->dynamicCall("Open (const QString&)", m_filename); + QAxObject* workbook = m_excel->querySubObject("ActiveWorkBook"); + QAxObject* worksheets = workbook->querySubObject("WorkSheets"); + Q_UNUSED(worksheets) + QAxObject* worksheet = workbook->querySubObject("Worksheets(int)", 1); //worksheet number + QAxObject* usedrange = worksheet->querySubObject("UsedRange"); + QAxObject* rows = usedrange->querySubObject("Rows"); + QAxObject* columns = usedrange->querySubObject("Columns"); + int intRowStart = usedrange->property("Row").toInt(); + int intColStart = usedrange->property("Column").toInt(); + int intCols = columns->property("Count").toInt(); + int intRows = rows->property("Count").toInt(); + m_row = intRows; + m_col = intCols; + QAxObject * cell; + for (int i = intRowStart; i < intRowStart + intRows; i++) + { + for (int j = intColStart; j < intColStart + intCols; j++) + { + Position pos(i, j); + cell = m_excel->querySubObject("Cells(Int, Int)", i, j ); + QVariant cellValue = cell->dynamicCall("value"); + m_mapdata.insert(std::pair(pos, cellValue.toString().toStdString())); + } + } + + m_excel->setProperty("DisplayAlerts", 0); + workbook->dynamicCall("Save(void)"); + workbook->dynamicCall("Close (Boolean)", false); + m_excel->setProperty("DisplayAlerts",1); +} diff --git a/LedOK/base/readexcel.h b/LedOK/base/readexcel.h index 2300d60..68bc5af 100644 --- a/LedOK/base/readexcel.h +++ b/LedOK/base/readexcel.h @@ -1,78 +1,78 @@ -#ifndef READEXCEL_H -#define READEXCEL_H - -#include -#include -#include -#include -#include -#include -#include - - -class Position -{ -public: - Position() { - m_row = 0; - m_col = 0; - } - - Position(int row, int col) { - m_row = row; - m_col = col; - } -public: - int m_row; - int m_col; - -public: - bool operator<(const Position & ct) const // 两个const是必需的。 - { - if (m_row < ct.m_row) { - return true; - } else if (m_row == ct.m_row) { - if ( m_col < ct.m_col ) { - return true; - } - } - return false; - } -}; - -class ReadExcel -{ -public: - ReadExcel(); - ~ReadExcel(); - -public: - //打开excel文件 - bool openExcel(const QString& filename); - void getALLfromDirNormalExcel(QString strFileName); - bool openExcelForWrite(const QString &filename); - //获取 指定单元格的数据 - std::string getCellData(const int& row, const int& col); - int WriteCellData(const int& row, const int& col,std::string strValue ); - //获取 行数,列数 - void getInfo(int& row, int& col) const; - -private: - void getALLfromExcel(); - void WriteALLfromExcel(); - -private: - int m_row; //行 - int m_col; //列 - QString m_filename; - QAxObject* m_excel; - int m_rowWrite; //行 - int m_colWrite; //列 - QAxObject* m_excelWrite; - - std::map m_mapdata; - std::map m_mapdataWrite; - Position p; -}; - -#endif // READEXCEL_H +#ifndef READEXCEL_H +#define READEXCEL_H + +#include +#include +#include +#include +#include +#include +#include + + +class Position +{ +public: + Position() { + m_row = 0; + m_col = 0; + } + + Position(int row, int col) { + m_row = row; + m_col = col; + } +public: + int m_row; + int m_col; + +public: + bool operator<(const Position & ct) const // 两个const是必需的。 + { + if (m_row < ct.m_row) { + return true; + } else if (m_row == ct.m_row) { + if ( m_col < ct.m_col ) { + return true; + } + } + return false; + } +}; + +class ReadExcel +{ +public: + ReadExcel(); + ~ReadExcel(); + +public: + //打开excel文件 + bool openExcel(const QString& filename); + void getALLfromDirNormalExcel(QString strFileName); + bool openExcelForWrite(const QString &filename); + //获取 指定单元格的数据 + std::string getCellData(const int& row, const int& col); + int WriteCellData(const int& row, const int& col,std::string strValue ); + //获取 行数,列数 + void getInfo(int& row, int& col) const; + +private: + void getALLfromExcel(); + void WriteALLfromExcel(); + +private: + int m_row; //行 + int m_col; //列 + QString m_filename; + QAxObject* m_excel; + int m_rowWrite; //行 + int m_colWrite; //列 + QAxObject* m_excelWrite; + + std::map m_mapdata; + std::map m_mapdataWrite; + Position p; +}; + +#endif // READEXCEL_H diff --git a/LedOK/base/softconfigdialog.cpp b/LedOK/base/softconfigdialog.cpp index 51a70c4..fb9d5e4 100644 --- a/LedOK/base/softconfigdialog.cpp +++ b/LedOK/base/softconfigdialog.cpp @@ -1,58 +1,58 @@ -#include "softconfigdialog.h" -#include "cfg.h" -#include "globaldefine.h" -#include -#include -#include -#include - -SoftConfigDialog::SoftConfigDialog(QWidget *parent) : BaseDlg(parent) { - resize(400, 300); - setWindowTitle(tr("Software Configuration")); - auto vbox = new QVBoxLayout(this); - - auto pushButton = new QPushButton("X"); - pushButton->setMinimumSize(30, 24); - connect(pushButton, &QPushButton::clicked, this, &QWidget::close); - vbox->addWidget(pushButton, 0, Qt::AlignRight); - - press_fd = new QCheckBox(tr("Video compress to")+" 720p"); - press_fd->setChecked(gVideoCompress); - vbox->addWidget(press_fd); - - trans_fd = new QCheckBox(tr("Video transcoding to")+" h264"); - trans_fd->setChecked(gVideoTranscoding); - vbox->addWidget(trans_fd); - - auto hbox = new QHBoxLayout(); - hbox->setContentsMargins(-1, 0, -1, -1); - anti_fd = new QCheckBox(tr("Text antialiasing")); - anti_fd->setChecked(gTextAntialiasing); - hbox->addWidget(anti_fd, 0, Qt::AlignTop); - - auto anti_tip = new QLabel(tr("TextAntilaTip")); - anti_tip->setStyleSheet("color:#FF0000;"); - anti_tip->setWordWrap(true); - hbox->addWidget(anti_tip); - - vbox->addLayout(hbox); - - vbox->addWidget(guangying_fd = new QCheckBox(tr("GuangYinPin"))); - guangying_fd->setChecked(gShowLoraScreen); - - vbox->addWidget(fdWidthSplit = new QCheckBox(tr("Width Split"))); - fdWidthSplit->setChecked(gWidthSplit); - - - auto ok_btn = new QPushButton(tr("OK")); - vbox->addWidget(ok_btn, 0, Qt::AlignCenter); - connect(ok_btn, &QPushButton::clicked, this, [this]() { - QSettings settings; - settings.setValue("VideoCompress", gVideoCompress = press_fd->isChecked()); - settings.setValue("VideoTranscoding", gVideoTranscoding = trans_fd->isChecked()); - settings.setValue("TextAntialiasing", gTextAntialiasing = anti_fd->isChecked()); - settings.setValue("GuangYingPin",gShowLoraScreen = guangying_fd->isChecked()); - settings.setValue("WidthSplit", gWidthSplit = fdWidthSplit->isChecked()); - accept(); - }); -} +#include "softconfigdialog.h" +#include "cfg.h" +#include "globaldefine.h" +#include +#include +#include +#include + +SoftConfigDialog::SoftConfigDialog(QWidget *parent) : BaseDlg(parent) { + resize(400, 300); + setWindowTitle(tr("Software Config")); + auto vbox = new QVBoxLayout(this); + + auto pushButton = new QPushButton("X"); + pushButton->setMinimumSize(30, 24); + connect(pushButton, &QPushButton::clicked, this, &QWidget::close); + vbox->addWidget(pushButton, 0, Qt::AlignRight); + + press_fd = new QCheckBox(tr("Video compress to")+" 720p"); + press_fd->setChecked(gVideoCompress); + vbox->addWidget(press_fd); + + trans_fd = new QCheckBox(tr("Video transcoding to")+" h264"); + trans_fd->setChecked(gVideoTranscoding); + vbox->addWidget(trans_fd); + + auto hbox = new QHBoxLayout(); + hbox->setContentsMargins(-1, 0, -1, -1); + anti_fd = new QCheckBox(tr("Text antialiasing")); + anti_fd->setChecked(gTextAntialiasing); + hbox->addWidget(anti_fd, 0, Qt::AlignTop); + + auto anti_tip = new QLabel(tr("TextAntilaTip")); + anti_tip->setStyleSheet("color:#FF0000;"); + anti_tip->setWordWrap(true); + hbox->addWidget(anti_tip); + + vbox->addLayout(hbox); + + vbox->addWidget(guangying_fd = new QCheckBox(tr("GuangYinPin"))); + guangying_fd->setChecked(gShowLoraScreen); + + vbox->addWidget(fdWidthSplit = new QCheckBox(tr("Width Split"))); + fdWidthSplit->setChecked(gWidthSplit); + + + auto ok_btn = new QPushButton(tr("OK")); + vbox->addWidget(ok_btn, 0, Qt::AlignCenter); + connect(ok_btn, &QPushButton::clicked, this, [this]() { + QSettings settings; + settings.setValue("VideoCompress", gVideoCompress = press_fd->isChecked()); + settings.setValue("VideoTranscoding", gVideoTranscoding = trans_fd->isChecked()); + settings.setValue("TextAntialiasing", gTextAntialiasing = anti_fd->isChecked()); + settings.setValue("GuangYingPin",gShowLoraScreen = guangying_fd->isChecked()); + settings.setValue("WidthSplit", gWidthSplit = fdWidthSplit->isChecked()); + accept(); + }); +} diff --git a/LedOK/base/softconfigdialog.h b/LedOK/base/softconfigdialog.h index ae7d2fa..c1f4f13 100644 --- a/LedOK/base/softconfigdialog.h +++ b/LedOK/base/softconfigdialog.h @@ -1,15 +1,15 @@ -#ifndef SOFTCONFIGDIALOG_H -#define SOFTCONFIGDIALOG_H - -#include "basedlg.h" -#include - -class SoftConfigDialog : public BaseDlg { - Q_OBJECT -public: - explicit SoftConfigDialog(QWidget *parent = nullptr); - - QCheckBox *press_fd, *trans_fd, *anti_fd, *guangying_fd, *fdWidthSplit; -}; - -#endif // SOFTCONFIGDIALOG_H +#ifndef SOFTCONFIGDIALOG_H +#define SOFTCONFIGDIALOG_H + +#include "basedlg.h" +#include + +class SoftConfigDialog : public BaseDlg { + Q_OBJECT +public: + explicit SoftConfigDialog(QWidget *parent = nullptr); + + QCheckBox *press_fd, *trans_fd, *anti_fd, *guangying_fd, *fdWidthSplit; +}; + +#endif // SOFTCONFIGDIALOG_H diff --git a/LedOK/base/switchcontrol.cpp b/LedOK/base/switchcontrol.cpp index d5784a9..a7f9fa3 100644 --- a/LedOK/base/switchcontrol.cpp +++ b/LedOK/base/switchcontrol.cpp @@ -1,484 +1,484 @@ -#include "switchcontrol.h" -#include "qpainter.h" -#include -#include "qevent.h" -#include "qtimer.h" -#include "qdebug.h" - -SwitchControl::SwitchControl(QWidget *parent): QWidget(parent) -{ - checked = false; - buttonStyle = ButtonStyle_Rect; - - bgColorOff = QColor(225, 225, 225); - bgColorOn = QColor(250, 250, 250); - - sliderColorOff = QColor(100, 100, 100); - sliderColorOn = QColor(100, 184, 255); - - textColorOff = QColor(255, 255, 255); - textColorOn = QColor(10, 10, 10); - - textOff = ""; - textOn = ""; - - imageOff = ":/image/btncheckoff1.png"; - imageOn = ":/image/btncheckon1.png"; - - space = 2; - rectRadius = 5; - - step = width() / 50; - startX = 0; - endX = 0; - - timer = new QTimer(this); - timer->setInterval(5); - connect(timer, SIGNAL(timeout()), this, SLOT(updateValue())); - - setFont(QFont("Microsoft Yahei", 10)); -} - -SwitchControl::~SwitchControl() -{ - -} - -void SwitchControl::mousePressEvent(QMouseEvent *) -{ - checked = !checked; - - //每次移动的步长为宽度的 50分之一 - step = width() / 50; - - //状态切换改变后自动计算终点坐标 - if (checked) { - if (buttonStyle == ButtonStyle_Rect) { - endX = width() - width() / 2; - } else if (buttonStyle == ButtonStyle_CircleIn) { - endX = width() - height(); - } else if (buttonStyle == ButtonStyle_CircleOut) { - endX = width() - height() + space; - } - } else { - endX = 0; - } - - timer->start(); - emit checkedChanged(checked); -} - -void SwitchControl::resizeEvent(QResizeEvent *) -{ - //每次移动的步长为宽度的 50分之一 - step = width() / 50; - - //尺寸大小改变后自动设置起点坐标为终点 - if (checked) { - if (buttonStyle == ButtonStyle_Rect) { - startX = width() - width() / 2; - } else if (buttonStyle == ButtonStyle_CircleIn) { - startX = width() - height(); - } else if (buttonStyle == ButtonStyle_CircleOut) { - startX = width() - height() + space; - } - } else { - startX = 0; - } - - update(); -} - -void SwitchControl::paintEvent(QPaintEvent *) -{ - //绘制准备工作,启用反锯齿 - QPainter painter(this); - painter.setRenderHint(QPainter::Antialiasing); - - if (buttonStyle == ButtonStyle_Image) { - //绘制图片 - drawImage(&painter); - } else { - //绘制背景 - drawBg(&painter); - //绘制滑块 - drawSlider(&painter); - //绘制文字 - drawText(&painter); - } -} - -void SwitchControl::drawBg(QPainter *painter) -{ - painter->save(); - painter->setPen(Qt::NoPen); - - if (!checked) { - painter->setBrush(bgColorOff); - } else { - painter->setBrush(bgColorOn); - } - - if (buttonStyle == ButtonStyle_Rect) { - painter->drawRoundedRect(rect(), rectRadius, rectRadius); - } else if (buttonStyle == ButtonStyle_CircleIn) { - QRect rect(0, 0, width(), height()); - //半径为高度的一半 - int radius = rect.height() / 2; - //圆的宽度为高度 - int circleWidth = rect.height(); - - QPainterPath path; - path.moveTo(radius, rect.left()); - path.arcTo(QRectF(rect.left(), rect.top(), circleWidth, circleWidth), 90, 180); - path.lineTo(rect.width() - radius, rect.height()); - path.arcTo(QRectF(rect.width() - rect.height(), rect.top(), circleWidth, circleWidth), 270, 180); - path.lineTo(radius, rect.top()); - - painter->drawPath(path); - } else if (buttonStyle == ButtonStyle_CircleOut) { - QRect rect(space, space, width() - space * 2, height() - space * 2); - painter->drawRoundedRect(rect, rectRadius, rectRadius); - } - - painter->restore(); -} - -void SwitchControl::drawSlider(QPainter *painter) -{ - painter->save(); - painter->setPen(Qt::NoPen); - - if (!checked) { - painter->setBrush(sliderColorOff); - } else { - painter->setBrush(sliderColorOn); - } - - if (buttonStyle == ButtonStyle_Rect) { - int sliderWidth = width() / 2 - space * 2; - int sliderHeight = height() - space * 2; - QRect sliderRect(startX + space, space, sliderWidth , sliderHeight); - painter->drawRoundedRect(sliderRect, rectRadius, rectRadius); - } else if (buttonStyle == ButtonStyle_CircleIn) { - QRect rect(0, 0, width(), height()); - int sliderWidth = rect.height() - space * 2; - QRect sliderRect(startX + space, space, sliderWidth, sliderWidth); - painter->drawEllipse(sliderRect); - } else if (buttonStyle == ButtonStyle_CircleOut) { - QRect rect(0, 0, width() - space, height() - space); - int sliderWidth = rect.height(); - QRect sliderRect(startX, space / 2, sliderWidth, sliderWidth); - painter->drawEllipse(sliderRect); - } - - painter->restore(); -} - -void SwitchControl::drawText(QPainter *painter) -{ - painter->save(); - - if (!checked) { - painter->setPen(textColorOff); - painter->drawText(width() / 2, 0, width() / 2 - space, height(), Qt::AlignCenter, textOff); - } else { - painter->setPen(textColorOn); - painter->drawText(0, 0, width() / 2 + space * 2, height(), Qt::AlignCenter, textOn); - } - - painter->restore(); -} - -void SwitchControl::drawImage(QPainter *painter) -{ - painter->save(); - - QPixmap pix; - - if (!checked) { - pix = QPixmap(imageOff); - } else { - pix = QPixmap(imageOn); - } - - //自动等比例平滑缩放居中显示 - int targetWidth = pix.width(); - int targetHeight = pix.height(); - pix = pix.scaled(targetWidth, targetHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation); - - int pixX = rect().center().x() - targetWidth / 2; - int pixY = rect().center().y() - targetHeight / 2; - QPoint point(pixX, pixY); - painter->drawPixmap(point, pix); - - painter->restore(); -} - -void SwitchControl::updateValue() -{ - if (checked) { - if (startX < endX) { - startX = startX + step; - } else { - startX = endX; - timer->stop(); - } - } else { - if (startX > endX) { - startX = startX - step; - } else { - startX = endX; - timer->stop(); - } - } - - update(); -} - -void SwitchControl::setChecked(bool checked) -{ - if (this->checked != checked) { - this->checked = checked; - emit checkedChanged(checked); - update(); - } -} -void SwitchControl::setCheckedStatus(bool checked) -{ - if (this->checked != checked) { - this->checked = checked; - - } - update(); - step = width() / 50; - //状态切换改变后自动计算终点坐标 - if (checked) { - if (buttonStyle == ButtonStyle_Rect) { - endX = width() - width() / 2; - } else if (buttonStyle == ButtonStyle_CircleIn) { - endX = width() - height(); - } else if (buttonStyle == ButtonStyle_CircleOut) { - endX = width() - height() + space; - } - } else { - endX = 0; - } - - timer->start(); - -} -void SwitchControl::setButtonStyle(SwitchControl::ButtonStyle buttonStyle) -{ - this->buttonStyle = buttonStyle; - update(); -} - -void SwitchControl::setBgColor(QColor bgColorOff, QColor bgColorOn) -{ - this->bgColorOff = bgColorOff; - this->bgColorOn = bgColorOn; - update(); -} - -void SwitchControl::setSliderColor(QColor sliderColorOff, QColor sliderColorOn) -{ - this->sliderColorOff = sliderColorOff; - this->sliderColorOn = sliderColorOn; - update(); -} - -void SwitchControl::setTextColor(QColor textColorOff, QColor textColorOn) -{ - this->textColorOff = textColorOff; - this->textColorOn = textColorOn; - update(); -} - -void SwitchControl::setText(QString textOff, QString textOn) -{ - this->textOff = textOff; - this->textOn = textOn; - update(); -} - -void SwitchControl::setImage(QString imageOff, QString imageOn) -{ - this->imageOff = imageOff; - this->imageOn = imageOn; - update(); -} - -void SwitchControl::setSpace(int space) -{ - this->space = space; - update(); -} - -void SwitchControl::setRectRadius(int rectRadius) -{ - this->rectRadius = rectRadius; - update(); -} -/*#include -#include - - -SwitchControl::SwitchControl(QWidget *parent) - : QWidget(parent) -{ - m_nHeight=16; - m_bChecked=false; - m_radius=8.0; - m_nMargin=5; - m_checkedColor=QColor(0, 150, 136); - m_thumbColor=Qt::white; - m_disabledColor=QColor(190, 190, 190); - m_background=Qt::black; - setAttribute(Qt::WA_DeleteOnClose); - // 鼠标滑过光标形状 - 手型 - setCursor(Qt::PointingHandCursor); - - // 连接信号槽 - connect(&m_timer, SIGNAL(timeout()), this, SLOT(onTimeout())); -} - -// 绘制开关 -void SwitchControl::paintEvent(QPaintEvent *event) -{ - Q_UNUSED(event); - - QPainter painter(this); - painter.setPen(Qt::NoPen); - painter.setRenderHint(QPainter::Antialiasing); - - QPainterPath path; - QColor background; - QColor thumbColor; - qreal dOpacity; - if (isEnabled()) { // 可用状态 - if (m_bChecked) { // 打开状态 - background = m_checkedColor; - thumbColor = m_checkedColor; - dOpacity = 0.600; - } else { //关闭状态 - background = m_background; - thumbColor = m_thumbColor; - dOpacity = 0.800; - } - } else { // 不可用状态 - background = m_background; - dOpacity = 0.260; - thumbColor = m_disabledColor; - } - // 绘制大椭圆 - painter.setBrush(background); - painter.setOpacity(dOpacity); - path.addRoundedRect(QRectF(m_nMargin, m_nMargin, width() - 2 * m_nMargin-(m_nHeight / 2), height() - 2 * m_nMargin), m_radius, m_radius); - painter.drawPath(path.simplified()); - - // 绘制小椭圆 - painter.setBrush(thumbColor); - painter.setOpacity(1.0); - painter.drawEllipse(QRectF(m_nX - (m_nHeight / 2), m_nY - (m_nHeight / 2), height(), height())); -} - -// 鼠标按下事件 -void SwitchControl::mousePressEvent(QMouseEvent *event) -{ - if (isEnabled()) { - if (event->buttons() & Qt::LeftButton) { - event->accept(); - } else { - event->ignore(); - } - } -} - -// 鼠标释放事件 - 切换开关状态、发射toggled()信号 -void SwitchControl::mouseReleaseEvent(QMouseEvent *event) -{ - if (isEnabled()) { - if ((event->type() == QMouseEvent::MouseButtonRelease) && (event->button() == Qt::LeftButton)) { - event->accept(); - m_bChecked = !m_bChecked; - emit toggled(m_bChecked); - m_timer.start(10); - } else { - event->ignore(); - } - } -} - -// 大小改变事件 -void SwitchControl::resizeEvent(QResizeEvent *event) -{ - m_nX = m_nHeight / 2; - m_nY = m_nHeight / 2; - QWidget::resizeEvent(event); -} - -// 默认大小 -QSize SwitchControl::sizeHint() const -{ - return minimumSizeHint(); -} - -// 最小大小 -QSize SwitchControl::minimumSizeHint() const -{ - return QSize(2 * (m_nHeight + m_nMargin), m_nHeight + 2 * m_nMargin); -} - -// 切换状态 - 滑动 -void SwitchControl::onTimeout() -{ - if (m_bChecked) { - m_nX += 1; - if (m_nX >= width() - m_nHeight*2) - m_timer.stop(); - } else { - m_nX -= 1; - if (m_nX <= m_nHeight / 2) - m_timer.stop(); - } - update(); -} - -// 返回开关状态 - 打开:true 关闭:false -bool SwitchControl::isToggled() const -{ - return m_bChecked; -} - -// 设置开关状态 -void SwitchControl::setToggle(bool checked) -{ - m_bChecked = checked; - m_timer.start(10); -} - -// 设置背景颜色 -void SwitchControl::setBackgroundColor(QColor color) -{ - m_background = color; -} -// 设置拇指颜色 -void SwitchControl::setthumbColor(QColor color) -{ - //拇指颜色 - m_thumbColor = color; -} - -// 设置选中颜色 -void SwitchControl::setCheckedColor(QColor color) -{ - m_checkedColor = color; -} - -// 设置不可用颜色 -void SwitchControl::setDisbaledColor(QColor color) -{ - m_disabledColor = color; -} -*/ +#include "switchcontrol.h" +#include "qpainter.h" +#include +#include "qevent.h" +#include "qtimer.h" +#include "qdebug.h" + +SwitchControl::SwitchControl(QWidget *parent): QWidget(parent) +{ + checked = false; + buttonStyle = ButtonStyle_Rect; + + bgColorOff = QColor(225, 225, 225); + bgColorOn = QColor(250, 250, 250); + + sliderColorOff = QColor(100, 100, 100); + sliderColorOn = QColor(100, 184, 255); + + textColorOff = QColor(255, 255, 255); + textColorOn = QColor(10, 10, 10); + + textOff = ""; + textOn = ""; + + imageOff = ":/image/btncheckoff1.png"; + imageOn = ":/image/btncheckon1.png"; + + space = 2; + rectRadius = 5; + + step = width() / 50; + startX = 0; + endX = 0; + + timer = new QTimer(this); + timer->setInterval(5); + connect(timer, SIGNAL(timeout()), this, SLOT(updateValue())); + + setFont(QFont("Microsoft Yahei", 10)); +} + +SwitchControl::~SwitchControl() +{ + +} + +void SwitchControl::mousePressEvent(QMouseEvent *) +{ + checked = !checked; + + //每次移动的步长为宽度的 50分之一 + step = width() / 50; + + //状态切换改变后自动计算终点坐标 + if (checked) { + if (buttonStyle == ButtonStyle_Rect) { + endX = width() - width() / 2; + } else if (buttonStyle == ButtonStyle_CircleIn) { + endX = width() - height(); + } else if (buttonStyle == ButtonStyle_CircleOut) { + endX = width() - height() + space; + } + } else { + endX = 0; + } + + timer->start(); + emit checkedChanged(checked); +} + +void SwitchControl::resizeEvent(QResizeEvent *) +{ + //每次移动的步长为宽度的 50分之一 + step = width() / 50; + + //尺寸大小改变后自动设置起点坐标为终点 + if (checked) { + if (buttonStyle == ButtonStyle_Rect) { + startX = width() - width() / 2; + } else if (buttonStyle == ButtonStyle_CircleIn) { + startX = width() - height(); + } else if (buttonStyle == ButtonStyle_CircleOut) { + startX = width() - height() + space; + } + } else { + startX = 0; + } + + update(); +} + +void SwitchControl::paintEvent(QPaintEvent *) +{ + //绘制准备工作,启用反锯齿 + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing); + + if (buttonStyle == ButtonStyle_Image) { + //绘制图片 + drawImage(&painter); + } else { + //绘制背景 + drawBg(&painter); + //绘制滑块 + drawSlider(&painter); + //绘制文字 + drawText(&painter); + } +} + +void SwitchControl::drawBg(QPainter *painter) +{ + painter->save(); + painter->setPen(Qt::NoPen); + + if (!checked) { + painter->setBrush(bgColorOff); + } else { + painter->setBrush(bgColorOn); + } + + if (buttonStyle == ButtonStyle_Rect) { + painter->drawRoundedRect(rect(), rectRadius, rectRadius); + } else if (buttonStyle == ButtonStyle_CircleIn) { + QRect rect(0, 0, width(), height()); + //半径为高度的一半 + int radius = rect.height() / 2; + //圆的宽度为高度 + int circleWidth = rect.height(); + + QPainterPath path; + path.moveTo(radius, rect.left()); + path.arcTo(QRectF(rect.left(), rect.top(), circleWidth, circleWidth), 90, 180); + path.lineTo(rect.width() - radius, rect.height()); + path.arcTo(QRectF(rect.width() - rect.height(), rect.top(), circleWidth, circleWidth), 270, 180); + path.lineTo(radius, rect.top()); + + painter->drawPath(path); + } else if (buttonStyle == ButtonStyle_CircleOut) { + QRect rect(space, space, width() - space * 2, height() - space * 2); + painter->drawRoundedRect(rect, rectRadius, rectRadius); + } + + painter->restore(); +} + +void SwitchControl::drawSlider(QPainter *painter) +{ + painter->save(); + painter->setPen(Qt::NoPen); + + if (!checked) { + painter->setBrush(sliderColorOff); + } else { + painter->setBrush(sliderColorOn); + } + + if (buttonStyle == ButtonStyle_Rect) { + int sliderWidth = width() / 2 - space * 2; + int sliderHeight = height() - space * 2; + QRect sliderRect(startX + space, space, sliderWidth , sliderHeight); + painter->drawRoundedRect(sliderRect, rectRadius, rectRadius); + } else if (buttonStyle == ButtonStyle_CircleIn) { + QRect rect(0, 0, width(), height()); + int sliderWidth = rect.height() - space * 2; + QRect sliderRect(startX + space, space, sliderWidth, sliderWidth); + painter->drawEllipse(sliderRect); + } else if (buttonStyle == ButtonStyle_CircleOut) { + QRect rect(0, 0, width() - space, height() - space); + int sliderWidth = rect.height(); + QRect sliderRect(startX, space / 2, sliderWidth, sliderWidth); + painter->drawEllipse(sliderRect); + } + + painter->restore(); +} + +void SwitchControl::drawText(QPainter *painter) +{ + painter->save(); + + if (!checked) { + painter->setPen(textColorOff); + painter->drawText(width() / 2, 0, width() / 2 - space, height(), Qt::AlignCenter, textOff); + } else { + painter->setPen(textColorOn); + painter->drawText(0, 0, width() / 2 + space * 2, height(), Qt::AlignCenter, textOn); + } + + painter->restore(); +} + +void SwitchControl::drawImage(QPainter *painter) +{ + painter->save(); + + QPixmap pix; + + if (!checked) { + pix = QPixmap(imageOff); + } else { + pix = QPixmap(imageOn); + } + + //自动等比例平滑缩放居中显示 + int targetWidth = pix.width(); + int targetHeight = pix.height(); + pix = pix.scaled(targetWidth, targetHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation); + + int pixX = rect().center().x() - targetWidth / 2; + int pixY = rect().center().y() - targetHeight / 2; + QPoint point(pixX, pixY); + painter->drawPixmap(point, pix); + + painter->restore(); +} + +void SwitchControl::updateValue() +{ + if (checked) { + if (startX < endX) { + startX = startX + step; + } else { + startX = endX; + timer->stop(); + } + } else { + if (startX > endX) { + startX = startX - step; + } else { + startX = endX; + timer->stop(); + } + } + + update(); +} + +void SwitchControl::setChecked(bool checked) +{ + if (this->checked != checked) { + this->checked = checked; + emit checkedChanged(checked); + update(); + } +} +void SwitchControl::setCheckedStatus(bool checked) +{ + if (this->checked != checked) { + this->checked = checked; + + } + update(); + step = width() / 50; + //状态切换改变后自动计算终点坐标 + if (checked) { + if (buttonStyle == ButtonStyle_Rect) { + endX = width() - width() / 2; + } else if (buttonStyle == ButtonStyle_CircleIn) { + endX = width() - height(); + } else if (buttonStyle == ButtonStyle_CircleOut) { + endX = width() - height() + space; + } + } else { + endX = 0; + } + + timer->start(); + +} +void SwitchControl::setButtonStyle(SwitchControl::ButtonStyle buttonStyle) +{ + this->buttonStyle = buttonStyle; + update(); +} + +void SwitchControl::setBgColor(QColor bgColorOff, QColor bgColorOn) +{ + this->bgColorOff = bgColorOff; + this->bgColorOn = bgColorOn; + update(); +} + +void SwitchControl::setSliderColor(QColor sliderColorOff, QColor sliderColorOn) +{ + this->sliderColorOff = sliderColorOff; + this->sliderColorOn = sliderColorOn; + update(); +} + +void SwitchControl::setTextColor(QColor textColorOff, QColor textColorOn) +{ + this->textColorOff = textColorOff; + this->textColorOn = textColorOn; + update(); +} + +void SwitchControl::setText(QString textOff, QString textOn) +{ + this->textOff = textOff; + this->textOn = textOn; + update(); +} + +void SwitchControl::setImage(QString imageOff, QString imageOn) +{ + this->imageOff = imageOff; + this->imageOn = imageOn; + update(); +} + +void SwitchControl::setSpace(int space) +{ + this->space = space; + update(); +} + +void SwitchControl::setRectRadius(int rectRadius) +{ + this->rectRadius = rectRadius; + update(); +} +/*#include +#include + + +SwitchControl::SwitchControl(QWidget *parent) + : QWidget(parent) +{ + m_nHeight=16; + m_bChecked=false; + m_radius=8.0; + m_nMargin=5; + m_checkedColor=QColor(0, 150, 136); + m_thumbColor=Qt::white; + m_disabledColor=QColor(190, 190, 190); + m_background=Qt::black; + setAttribute(Qt::WA_DeleteOnClose); + // 鼠标滑过光标形状 - 手型 + setCursor(Qt::PointingHandCursor); + + // 连接信号槽 + connect(&m_timer, SIGNAL(timeout()), this, SLOT(onTimeout())); +} + +// 绘制开关 +void SwitchControl::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event); + + QPainter painter(this); + painter.setPen(Qt::NoPen); + painter.setRenderHint(QPainter::Antialiasing); + + QPainterPath path; + QColor background; + QColor thumbColor; + qreal dOpacity; + if (isEnabled()) { // 可用状态 + if (m_bChecked) { // 打开状态 + background = m_checkedColor; + thumbColor = m_checkedColor; + dOpacity = 0.600; + } else { //关闭状态 + background = m_background; + thumbColor = m_thumbColor; + dOpacity = 0.800; + } + } else { // 不可用状态 + background = m_background; + dOpacity = 0.260; + thumbColor = m_disabledColor; + } + // 绘制大椭圆 + painter.setBrush(background); + painter.setOpacity(dOpacity); + path.addRoundedRect(QRectF(m_nMargin, m_nMargin, width() - 2 * m_nMargin-(m_nHeight / 2), height() - 2 * m_nMargin), m_radius, m_radius); + painter.drawPath(path.simplified()); + + // 绘制小椭圆 + painter.setBrush(thumbColor); + painter.setOpacity(1.0); + painter.drawEllipse(QRectF(m_nX - (m_nHeight / 2), m_nY - (m_nHeight / 2), height(), height())); +} + +// 鼠标按下事件 +void SwitchControl::mousePressEvent(QMouseEvent *event) +{ + if (isEnabled()) { + if (event->buttons() & Qt::LeftButton) { + event->accept(); + } else { + event->ignore(); + } + } +} + +// 鼠标释放事件 - 切换开关状态、发射toggled()信号 +void SwitchControl::mouseReleaseEvent(QMouseEvent *event) +{ + if (isEnabled()) { + if ((event->type() == QMouseEvent::MouseButtonRelease) && (event->button() == Qt::LeftButton)) { + event->accept(); + m_bChecked = !m_bChecked; + emit toggled(m_bChecked); + m_timer.start(10); + } else { + event->ignore(); + } + } +} + +// 大小改变事件 +void SwitchControl::resizeEvent(QResizeEvent *event) +{ + m_nX = m_nHeight / 2; + m_nY = m_nHeight / 2; + QWidget::resizeEvent(event); +} + +// 默认大小 +QSize SwitchControl::sizeHint() const +{ + return minimumSizeHint(); +} + +// 最小大小 +QSize SwitchControl::minimumSizeHint() const +{ + return QSize(2 * (m_nHeight + m_nMargin), m_nHeight + 2 * m_nMargin); +} + +// 切换状态 - 滑动 +void SwitchControl::onTimeout() +{ + if (m_bChecked) { + m_nX += 1; + if (m_nX >= width() - m_nHeight*2) + m_timer.stop(); + } else { + m_nX -= 1; + if (m_nX <= m_nHeight / 2) + m_timer.stop(); + } + update(); +} + +// 返回开关状态 - 打开:true 关闭:false +bool SwitchControl::isToggled() const +{ + return m_bChecked; +} + +// 设置开关状态 +void SwitchControl::setToggle(bool checked) +{ + m_bChecked = checked; + m_timer.start(10); +} + +// 设置背景颜色 +void SwitchControl::setBackgroundColor(QColor color) +{ + m_background = color; +} +// 设置拇指颜色 +void SwitchControl::setthumbColor(QColor color) +{ + //拇指颜色 + m_thumbColor = color; +} + +// 设置选中颜色 +void SwitchControl::setCheckedColor(QColor color) +{ + m_checkedColor = color; +} + +// 设置不可用颜色 +void SwitchControl::setDisbaledColor(QColor color) +{ + m_disabledColor = color; +} +*/ diff --git a/LedOK/base/switchcontrol.h b/LedOK/base/switchcontrol.h index e65a198..88dd274 100644 --- a/LedOK/base/switchcontrol.h +++ b/LedOK/base/switchcontrol.h @@ -1,230 +1,230 @@ -#ifndef SWITCHCONTROL_H -#define SWITCHCONTROL_H -/** - * 作者:feiyangqingyun(QQ:517216493) 2016-11-6 - * 1:可设置开关按钮的样式 圆角矩形/内圆形/外圆形/图片 - * 2:可设置选中和未选中时的背景颜色 - * 3:可设置选中和未选中时的滑块颜色 - * 4:可设置显示的文本 - * 5:可设置滑块离背景的间隔 - * 6:可设置圆角角度 - */ - -#include - -class QTimer; - -class SwitchControl: public QWidget -{ - Q_OBJECT -public: - enum ButtonStyle { - ButtonStyle_Rect = 0, //圆角矩形 - ButtonStyle_CircleIn = 1, //内圆形 - ButtonStyle_CircleOut = 2,//外圆形 - ButtonStyle_Image = 3 //图片 - }; - - SwitchControl(QWidget *parent = 0); - ~SwitchControl(); - -protected: - void mousePressEvent(QMouseEvent *); - void resizeEvent(QResizeEvent *); - void paintEvent(QPaintEvent *); - void drawBg(QPainter *painter); - void drawSlider(QPainter *painter); - void drawText(QPainter *painter); - void drawImage(QPainter *painter); - -private: - bool checked; //是否选中 - ButtonStyle buttonStyle; //开关按钮样式 - - QColor bgColorOff; //关闭时背景颜色 - QColor bgColorOn; //打开时背景颜色 - - QColor sliderColorOff; //关闭时滑块颜色 - QColor sliderColorOn; //打开时滑块颜色 - - QColor textColorOff; //关闭时文本颜色 - QColor textColorOn; //打开时文本颜色 - - QString textOff; //关闭时显示的文字 - QString textOn; //打开时显示的文字 - - QString imageOff; //关闭时显示的图片 - QString imageOn; //打开时显示的图片 - - int space; //滑块离背景间隔 - int rectRadius; //圆角角度 - - int step; //每次移动的步长 - int startX; //滑块开始X轴坐标 - int endX; //滑块结束X轴坐标 - QTimer *timer; //定时器绘制 - -private slots: - void updateValue(); - -public: - bool getChecked()const - { - return checked; - } - ButtonStyle getButtonStyle()const - { - return buttonStyle; - } - - QColor getBgColorOff()const - { - return bgColorOff; - } - QColor getBgColorOn()const - { - return bgColorOn; - } - - QColor getSliderColorOff()const - { - return sliderColorOff; - } - QColor getSliderColorOn()const - { - return sliderColorOn; - } - - QColor getTextColorOff()const - { - return textColorOff; - } - QColor getTextColorOn()const - { - return textColorOn; - } - - QString getTextOff()const - { - return textOff; - } - QString getTextOn()const - { - return textOn; - } - - QString getImageOff()const - { - return imageOff; - } - QString getImageOn()const - { - return imageOn; - } - - int getSpace()const - { - return space; - } - int getRectRadius()const - { - return rectRadius; - } - -public slots: - //设置是否选中 - void setChecked(bool checked); - void setCheckedStatus(bool checked); - //设置风格样式 - void setButtonStyle(ButtonStyle buttonStyle); - - //设置背景颜色 - void setBgColor(QColor bgColorOff, QColor bgColorOn); - //设置滑块颜色 - void setSliderColor(QColor sliderColorOff, QColor sliderColorOn); - //设置文本颜色 - void setTextColor(QColor textColorOff, QColor textColorOn); - - //设置文本 - void setText(QString textOff, QString textOn); - - //设置背景图片 - void setImage(QString imageOff, QString imageOn); - - //设置间隔 - void setSpace(int space); - //设置圆角角度 - void setRectRadius(int rectRadius); - -signals: - void checkedChanged(bool checked); -}; - -/* -#include -#include - -class SwitchControl : public QWidget -{ - Q_OBJECT - -public: - explicit SwitchControl(QWidget *parent = nullptr); - - // 返回开关状态 - 打开:true 关闭:false - bool isToggled() const; - - // 设置开关状态 - void setToggle(bool checked); - - // 设置背景颜色 - void setBackgroundColor(QColor color); - - // 设置选中颜色 - void setCheckedColor(QColor color); - - // 设置不可用颜色 - void setDisbaledColor(QColor color); - // 设置拇指颜色 - void setthumbColor(QColor color); -protected: - // 绘制开关 - void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; - - // 鼠标按下事件 - void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE; - - // 鼠标释放事件 - 切换开关状态、发射toggled()信号 - void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE; - - // 大小改变事件 - void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE; - - // 缺省大小 - QSize sizeHint() const Q_DECL_OVERRIDE; - QSize minimumSizeHint() const Q_DECL_OVERRIDE; - -signals: - // 状态改变时,发射信号 - void toggled(bool checked); - -private slots: - // 状态切换时,用于产生滑动效果 - void onTimeout(); - -private: - bool m_bChecked=false; //是否选中 - QColor m_background; //背景颜色 - QColor m_checkedColor; //选中颜色 - QColor m_disabledColor; //不可用颜色 - QColor m_thumbColor; //拇指颜色 - qreal m_radius; //圆角 - qreal m_nX; //x点坐标 - qreal m_nY; //y点坐标 - qint16 m_nHeight=20; //高度 - qint16 m_nMargin=5; //外边距 - QTimer m_timer; //定时器 - -};*/ - -#endif // SWITCHCONTROL_H +#ifndef SWITCHCONTROL_H +#define SWITCHCONTROL_H +/** + * 作者:feiyangqingyun(QQ:517216493) 2016-11-6 + * 1:可设置开关按钮的样式 圆角矩形/内圆形/外圆形/图片 + * 2:可设置选中和未选中时的背景颜色 + * 3:可设置选中和未选中时的滑块颜色 + * 4:可设置显示的文本 + * 5:可设置滑块离背景的间隔 + * 6:可设置圆角角度 + */ + +#include + +class QTimer; + +class SwitchControl: public QWidget +{ + Q_OBJECT +public: + enum ButtonStyle { + ButtonStyle_Rect = 0, //圆角矩形 + ButtonStyle_CircleIn = 1, //内圆形 + ButtonStyle_CircleOut = 2,//外圆形 + ButtonStyle_Image = 3 //图片 + }; + + SwitchControl(QWidget *parent = 0); + ~SwitchControl(); + +protected: + void mousePressEvent(QMouseEvent *); + void resizeEvent(QResizeEvent *); + void paintEvent(QPaintEvent *); + void drawBg(QPainter *painter); + void drawSlider(QPainter *painter); + void drawText(QPainter *painter); + void drawImage(QPainter *painter); + +private: + bool checked; //是否选中 + ButtonStyle buttonStyle; //开关按钮样式 + + QColor bgColorOff; //关闭时背景颜色 + QColor bgColorOn; //打开时背景颜色 + + QColor sliderColorOff; //关闭时滑块颜色 + QColor sliderColorOn; //打开时滑块颜色 + + QColor textColorOff; //关闭时文本颜色 + QColor textColorOn; //打开时文本颜色 + + QString textOff; //关闭时显示的文字 + QString textOn; //打开时显示的文字 + + QString imageOff; //关闭时显示的图片 + QString imageOn; //打开时显示的图片 + + int space; //滑块离背景间隔 + int rectRadius; //圆角角度 + + int step; //每次移动的步长 + int startX; //滑块开始X轴坐标 + int endX; //滑块结束X轴坐标 + QTimer *timer; //定时器绘制 + +private slots: + void updateValue(); + +public: + bool getChecked()const + { + return checked; + } + ButtonStyle getButtonStyle()const + { + return buttonStyle; + } + + QColor getBgColorOff()const + { + return bgColorOff; + } + QColor getBgColorOn()const + { + return bgColorOn; + } + + QColor getSliderColorOff()const + { + return sliderColorOff; + } + QColor getSliderColorOn()const + { + return sliderColorOn; + } + + QColor getTextColorOff()const + { + return textColorOff; + } + QColor getTextColorOn()const + { + return textColorOn; + } + + QString getTextOff()const + { + return textOff; + } + QString getTextOn()const + { + return textOn; + } + + QString getImageOff()const + { + return imageOff; + } + QString getImageOn()const + { + return imageOn; + } + + int getSpace()const + { + return space; + } + int getRectRadius()const + { + return rectRadius; + } + +public slots: + //设置是否选中 + void setChecked(bool checked); + void setCheckedStatus(bool checked); + //设置风格样式 + void setButtonStyle(ButtonStyle buttonStyle); + + //设置背景颜色 + void setBgColor(QColor bgColorOff, QColor bgColorOn); + //设置滑块颜色 + void setSliderColor(QColor sliderColorOff, QColor sliderColorOn); + //设置文本颜色 + void setTextColor(QColor textColorOff, QColor textColorOn); + + //设置文本 + void setText(QString textOff, QString textOn); + + //设置背景图片 + void setImage(QString imageOff, QString imageOn); + + //设置间隔 + void setSpace(int space); + //设置圆角角度 + void setRectRadius(int rectRadius); + +signals: + void checkedChanged(bool checked); +}; + +/* +#include +#include + +class SwitchControl : public QWidget +{ + Q_OBJECT + +public: + explicit SwitchControl(QWidget *parent = nullptr); + + // 返回开关状态 - 打开:true 关闭:false + bool isToggled() const; + + // 设置开关状态 + void setToggle(bool checked); + + // 设置背景颜色 + void setBackgroundColor(QColor color); + + // 设置选中颜色 + void setCheckedColor(QColor color); + + // 设置不可用颜色 + void setDisbaledColor(QColor color); + // 设置拇指颜色 + void setthumbColor(QColor color); +protected: + // 绘制开关 + void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; + + // 鼠标按下事件 + void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE; + + // 鼠标释放事件 - 切换开关状态、发射toggled()信号 + void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE; + + // 大小改变事件 + void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE; + + // 缺省大小 + QSize sizeHint() const Q_DECL_OVERRIDE; + QSize minimumSizeHint() const Q_DECL_OVERRIDE; + +signals: + // 状态改变时,发射信号 + void toggled(bool checked); + +private slots: + // 状态切换时,用于产生滑动效果 + void onTimeout(); + +private: + bool m_bChecked=false; //是否选中 + QColor m_background; //背景颜色 + QColor m_checkedColor; //选中颜色 + QColor m_disabledColor; //不可用颜色 + QColor m_thumbColor; //拇指颜色 + qreal m_radius; //圆角 + qreal m_nX; //x点坐标 + qreal m_nY; //y点坐标 + qint16 m_nHeight=20; //高度 + qint16 m_nMargin=5; //外边距 + QTimer m_timer; //定时器 + +};*/ + +#endif // SWITCHCONTROL_H diff --git a/LedOK/base/table.cpp b/LedOK/base/table.cpp deleted file mode 100644 index d2392db..0000000 --- a/LedOK/base/table.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "table.h" - -int Table::sizeHintForColumn(int column) const { - auto item = horizontalHeaderItem(column); - if(!item) return QTableWidget::sizeHintForColumn(column); - int width = item->data(0x99).toInt(); - if(!width) return QTableWidget::sizeHintForColumn(column); - auto header = horizontalHeader(); - if(header->sectionResizeMode(column)!=QHeaderView::ResizeToContents) return QTableWidget::sizeHintForColumn(column); - int colCnt = columnCount(); - int remainWidth = header->width(), stretchWidth = width; - for(int cc=0; ccsectionResizeMode(cc)==QHeaderView::ResizeToContents) stretchWidth += item->data(0x99).toInt(); - else remainWidth -= item->data(0x99).toInt(); - } - if(remainWidth<=0) return QTableWidget::sizeHintForColumn(column); - return width * remainWidth / stretchWidth; -} diff --git a/LedOK/base/table.h b/LedOK/base/table.h deleted file mode 100644 index dce2383..0000000 --- a/LedOK/base/table.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef TABLE_H -#define TABLE_H - -#include -#include - -struct ColAttr { - QString field; - QString text; - int width{0}; -}; -class Table : public QTableWidget { - Q_OBJECT -public: - explicit Table(QWidget *parent = nullptr) : QTableWidget{parent} {} - Table(std::initializer_list colAttrs, QWidget *parent = nullptr) : QTableWidget{0, (int)colAttrs.size(), parent} { - int i = 0; - for(typename std::initializer_list::const_iterator it = colAttrs.begin(); it != colAttrs.end(); ++it) { - auto item = horizontalHeaderItem(i); - if(!item) { - item = new QTableWidgetItem(); - item->setData(0x99, it->width); - setHorizontalHeaderItem(i, item); - } - item->setText(it->text); - if(it->width>0) horizontalHeader()->resizeSection(i, it->width); - mFieldMap.insert(it->field, i++); - } - } - - Table *setDefs() { - setSelectionBehavior(QTableWidget::SelectRows); - setEditTriggers(QAbstractItemView::NoEditTriggers); - setAlternatingRowColors(true); - horizontalHeader()->setBackgroundRole(QPalette::Window); - return this; - } - - auto item(int row, QString column) { - auto col = mFieldMap[column]; - return QTableWidget::item(row, col); - } - void setItem(int row, QString column, QTableWidgetItem *item) { - auto col = mFieldMap[column]; - QTableWidget::setItem(row, col, item); - } - void setValue(int row, QString column, const QString &text) { - auto col = mFieldMap[column]; - QTableWidget::setItem(row, col, new QTableWidgetItem(text)); - } - - auto cellWidget(int row, QString column) { - auto col = mFieldMap[column]; - return QTableWidget::cellWidget(row, col); - } - void setCellWidget(int row, QString column, QWidget *widget) { - auto col = mFieldMap[column]; - QTableWidget::setCellWidget(row, col, widget); - } - - QMap mFieldMap; - -protected: - int sizeHintForColumn(int column) const override; -}; - -#endif // TABLE_H diff --git a/LedOK/base/taesclass.cpp b/LedOK/base/taesclass.cpp index 8bf19c6..74e385e 100644 --- a/LedOK/base/taesclass.cpp +++ b/LedOK/base/taesclass.cpp @@ -1,472 +1,472 @@ -#include "taesclass.h" - -Aes::~Aes() -{ - -} -Aes::Aes() -{ - -} -//////////////////////////////////////////////////////////////////////////////////////////////// -//构造函数 -Aes::Aes(int keysize,unsigned char* keyBytes) -{ - SetNbNkNr(keysize); //设置密钥块数,轮数 - memcpy(key,keyBytes,keysize); //字符串拷贝函数,把keyBytes的keysize个字符复制到key中 - KeyExpansion(); //密钥扩展,必须提前做的初始化 -} -//////////////////////////////////////////////////////////////////////////////////////////////// -void Aes::SetNbNkNr(int keySize) -{ - Nb=4; - if(keySize==Bits128) - { - Nk=4; //4*4字节,128位密钥,10轮加密 - Nr=10; - } - else if(keySize==Bits192) - { - Nk=6; //6*4字节,192位密钥,12轮加密 - Nr=12; - } - else if(keySize==Bits256) - { - Nk=8; //8*4字节,256位密钥,14轮加密 - Nr=14; - } -} -//////////////////////////////////////////////////////////////////////////////////////////////// -void Aes::KeyExpansion() -{ - - memset(w,0,16*15); - for(int row=0;row 6 && (row % Nk == 4) ) //这个还没有搞清楚 - { - temp = SubWord(temp); - } - - // w[row] = w[row-Nk] xor temp - w[4*row+0] = (byte) ( (int) w[4*(row-Nk)+0] ^ (int)temp[0] ); - w[4*row+1] = (byte) ( (int) w[4*(row-Nk)+1] ^ (int)temp[1] ); - w[4*row+2] = (byte) ( (int) w[4*(row-Nk)+2] ^ (int)temp[2] ); - w[4*row+3] = (byte) ( (int) w[4*(row-Nk)+3] ^ (int)temp[3] ); - } // for loop - -} -//////////////////////////////////////////////////////////////////////////////////////////////// -//密钥移位函数 -unsigned char* Aes::RotWord(unsigned char* word) -{ - byte* temp = new byte[4]; - temp[0] = word[1]; - temp[1] = word[2]; - temp[2] = word[3]; - temp[3] = word[0]; - return temp; -} -//////////////////////////////////////////////////////////////////////////////////////////////// -//密钥字代换函数 -unsigned char* Aes::SubWord(unsigned char* word) -{ - byte* temp = new byte[4]; - for(int j=0;j<4;j++) - { - temp[j] = AesSbox[16*(word[j] >> 4)+(word[j] & 0x0f)]; //实际上也可以写成AesSbox[[j]];因为两者相等 - } - return temp; - -} -//////////////////////////////////////////////////////////////////////////////////////////////// -//Aes加密函数 -void Aes::Cipher(unsigned char* input, unsigned char* output) -{ - memset(&State[0][0],0,16); - for(int i=0;i<4*Nb;i++) //这里是先写列后写行的,即输入是一列一列的进来的 - { - State[i%4][i/4]=input[i]; //换成先写行后写列也是可以的,只要在输出时也是这样就可以了 - } - AddRoundKey(0); //轮密钥加 - - for (int round = 1; round <= (Nr - 1); round++) // main round loop - { - SubBytes(); //字节代换 - ShiftRows(); //行移位 - MixColumns(); //列混淆 - AddRoundKey(round); //轮密钥加 - } // main round loop - - SubBytes(); //字节代换 - ShiftRows(); //行移位 - AddRoundKey(Nr); //轮密钥加 - - // output = state - for (int i = 0; i < (4 * Nb); i++) - { - output[i] = State[i % 4][ i / 4]; - } - -} -//////////////////////////////////////////////////////////////////////////////////////////////// -//Aes解密函数 -void Aes::InvCipher(unsigned char* input,unsigned char* output) -{ - memset(&State[0][0],0,16); - for (int i = 0; i < (4 * Nb); i++) - { - State[i % 4][ i / 4] = input[i]; - } - - AddRoundKey(Nr); - - for (int round = Nr-1; round >= 1; round--) // main round loop - { - InvShiftRows(); - InvSubBytes(); - AddRoundKey(round); - InvMixColumns(); - } // end main round loop for InvCipher - - InvShiftRows(); - InvSubBytes(); - AddRoundKey(0); - - // output = state - for (int i = 0; i < (4 * Nb); i++) - { - output[i] = State[i % 4][ i / 4]; - } -} -//////////////////////////////////////////////////////////////////////////////////////////////// -//轮密钥加 -void Aes::AddRoundKey(int round) -{ - int i,j; //i行 j列 //因为密钥w是一列一列排列的,即 k0 k4 k8 k12 - for(j=0;j<4;j++) // k1 k5 k9 k13 - { // k2 k6 k10k14 - for(i=0;i<4;i++) // k3 k7 k11k15 - { // 所以i行j列的下标是4*((round*4)+j)+i即16*round+4*j+i - State[i][j]=(unsigned char)((int)State[i][j]^(int)w[4*((round*4)+j)+i]); - } - } -} -//////////////////////////////////////////////////////////////////////////////////////////////// -//字节代换函数 -void Aes::SubBytes() //Page 103 -{ - int i,j; - for(j=0;j<4;j++) - { - for(i=0;i<4;i++) - { - State[i][j]=AesSbox[State[i][j]]; - //因为 16*(State[i][j]>>4)+State[i][j]&0x0f=State[i][j] - - - } - } -} - -void Aes::InvSubBytes() -{ - int i,j; - for(j=0;j<4;j++) - { - for(i=0;i<4;i++) - { - State[i][j]=AesiSbox[State[i][j]]; //因为 16*(State[i][j]>>4)+State[i][j]&0x0f=State[i][j] - } - } - -} -//////////////////////////////////////////////////////////////////////////////////////////////// -void Aes::ShiftRows() -{ - unsigned char temp[4*4]; //Page105 - int i,j; - for(j=0;j<4;j++) - { - for(i=0;i<4;i++) - { - temp[4*i+j]=State[i][j]; - } - } - for(i=1;i<4;i++) - { - for(j=0;j<4;j++) - { - if(i==1)State[i][j]=temp[4*i+(j+1)%4]; //第一行左移1位 - else if(i==2)State[i][j]=temp[4*i+(j+2)%4]; //第二行左移2位 - else if(i==3)State[i][j]=temp[4*i+(j+3)%4]; //第三行左移3位 - } - } - -} -void Aes::InvShiftRows() -{ - unsigned char temp[4*4]; - int i,j; - for(j=0;j<4;j++) - { - for(i=0;i<4;i++) - { - temp[4*i+j]=State[i][j]; - } - } - for(i=1;i<4;i++) - { - for(j=0;j<4;j++) - { - //if(i==1)State[i][j]=temp[4*i+(j-1)%4]; 在此犯了一个错误 -1%4=-1 而不是3,所以采用了下面再加一个4的做法 - if(i==1)State[i][j]=temp[4*i+(j+3)%4]; //第一行右移1位 j-1+4=j+3 - else if(i==2)State[i][j]=temp[4*i+(j+2)%4]; //第二行右移2位 j-2+4=j+2 - else if(i==3)State[i][j]=temp[4*i+(j+1)%4]; //第三行右移3位 j-3+4=j+2 - } - } - -} -//////////////////////////////////////////////////////////////////////////////////////////////// -void Aes::MixColumns() -{ - unsigned char temp[4*4]; - int i,j; - for(j=0;j<4;j++) //2 3 1 1 列混淆矩阵 Page107 - { //1 2 3 1 - for(i=0;i<4;i++) //1 1 2 3 - { //3 1 1 2 - temp[4*i+j]=State[i][j]; - } - } - for(j=0;j<4;j++) - { - State[0][j] = (unsigned char) ( (int)gfmultby02(temp[0+j]) ^ (int)gfmultby03(temp[4*1+j]) ^ - (int)gfmultby01(temp[4*2+j]) ^ (int)gfmultby01(temp[4*3+j]) ); - State[1][j] = (unsigned char) ( (int)gfmultby01(temp[0+j]) ^ (int)gfmultby02(temp[4*1+j]) ^ - (int)gfmultby03(temp[4*2+j]) ^ (int)gfmultby01(temp[4*3+j]) ); - State[2][j] = (unsigned char) ( (int)gfmultby01(temp[0+j]) ^ (int)gfmultby01(temp[4*1+j]) ^ - (int)gfmultby02(temp[4*2+j]) ^ (int)gfmultby03(temp[4*3+j]) ); - State[3][j] = (unsigned char) ( (int)gfmultby03(temp[0+j]) ^ (int)gfmultby01(temp[4*1+j]) ^ - (int)gfmultby01(temp[4*2+j]) ^ (int)gfmultby02(temp[4*3+j]) ); - } - -} -void Aes::InvMixColumns() -{ - unsigned char temp[4*4]; - int i,j; - for (i = 0; i < 4; i++) // copy State into temp[] - { - for (j = 0; j < 4; j++) //0e 0b 0d 09 逆变换矩阵 Page108 - { //09 0e 0b 0d - temp[4*i+j] = State[i][j]; //0d 09 0e 0b - } //0b 0d 09 0e - } - - for (j = 0; j < 4; j++) - { - State[0][j] = (unsigned char) ( (int)gfmultby0e(temp[j]) ^ (int)gfmultby0b(temp[4+j]) ^ - (int)gfmultby0d(temp[4*2+j]) ^ (int)gfmultby09(temp[4*3+j]) ); - State[1][j] = (unsigned char) ( (int)gfmultby09(temp[j]) ^ (int)gfmultby0e(temp[4+j]) ^ - (int)gfmultby0b(temp[4*2+j]) ^ (int)gfmultby0d(temp[4*3+j]) ); - State[2][j] = (unsigned char) ( (int)gfmultby0d(temp[j]) ^ (int)gfmultby09(temp[4+j]) ^ - (int)gfmultby0e(temp[4*2+j]) ^ (int)gfmultby0b(temp[4*3+j]) ); - State[3][j] = (unsigned char) ( (int)gfmultby0b(temp[j]) ^ (int)gfmultby0d(temp[4+j]) ^ - (int)gfmultby09(temp[4*2+j]) ^ (int)gfmultby0e(temp[4*3+j]) ); - } -} -//////////////////////////////////////////////////////////////////////////////////////////////// -unsigned char Aes::gfmultby01(unsigned char b) -{ - return b; -} -unsigned char Aes::gfmultby02(unsigned char b) -{ - if (b < 0x80) - return (unsigned char)(int)(b <<1); - else - return (unsigned char)( (int)(b << 1) ^ (int)(0x1b) ); -} - -unsigned char Aes::gfmultby03(unsigned char b) -{ - return (unsigned char) ( (int)gfmultby02(b) ^ (int)b ); -} - -unsigned char Aes::gfmultby09(unsigned char b) -{ - return (unsigned char)( (int)gfmultby02(gfmultby02(gfmultby02(b))) ^ (int)b ); -} - -unsigned char Aes::gfmultby0b(unsigned char b) -{ - return (unsigned char)( (int)gfmultby02(gfmultby02(gfmultby02(b))) ^ - (int)gfmultby02(b) ^ (int)b ); -} - -unsigned char Aes::gfmultby0d(unsigned char b) -{ - return (unsigned char)( (int)gfmultby02(gfmultby02(gfmultby02(b))) ^ - (int)gfmultby02(gfmultby02(b)) ^ (int)(b) ); -} - -unsigned char Aes::gfmultby0e(unsigned char b) -{ - return (unsigned char)( (int)gfmultby02(gfmultby02(gfmultby02(b))) ^ - (int)gfmultby02(gfmultby02(b)) ^(int)gfmultby02(b) ); -} - -TAesClass::TAesClass() -{ - m_lpAes=NULL; - InitializePrivateKey(16,(unsigned char*)"\x79\x76\x68\x6B\x77\x66\x6E\x68\x72\x65\x73\x63\x6C\x6B\x70\x6E"); -} - -TAesClass::~TAesClass() -{ - if (m_lpAes!=NULL) - { - delete m_lpAes; - } -} -//------------------------------------------------------------------------------------------------------------ -// 编写人员:wfnhddd -// -// 函数名称:InitializeAes -// -// 函数描述:初始化AES 密钥,密钥用于加密解密 -// -// 调用参数:详细说明参考 MSDN 中的相关描述或相关的开发文档 -// -// 返回数值:无 -// -// 最近修改:2009 年 08 月 07 日 -//------------------------------------------------------------------------------------------------------------ - - -VOID TAesClass::InitializePrivateKey(DWORD KeySize,UCHAR *KeyBytes) -{ - if (m_lpAes) - { - delete m_lpAes; - m_lpAes=NULL; - } - m_lpAes=new Aes(KeySize,KeyBytes); - -} - -//------------------------------------------------------------------------------------------------------------ -// 编写人员:wfnhddd -// -// 函数名称:OnAesEncrypt -// -// 函数描述:用AES加密算法加密数据 -// -// 调用参数:详细说明参考 MSDN 中的相关描述或相关的开发文档 -// -// 返回数值:加密后的数据大小 ,错误返回值 0 -// -// 最近修改:2009 年 08 月 07 日 -//------------------------------------------------------------------------------------------------------------ - -DWORD TAesClass::OnAesEncrypt(LPVOID InBuffer,DWORD InLength,LPVOID OutBuffer) -{ - DWORD OutLength=0; - if (m_lpAes==NULL||OutBuffer==NULL) - { - return 0; - } - - UCHAR *lpCurInBuff=(UCHAR *)InBuffer; - UCHAR *lpCurOutBuff=(UCHAR *)OutBuffer; - long blocknum=InLength/16; - long leftnum=InLength%16; - for(long i=0;iCipher(lpCurInBuff,lpCurOutBuff); - lpCurInBuff+=16; - lpCurOutBuff+=16; - OutLength+=16; - } - if(leftnum) //多余出leftnum 字节 则加密时 多出16-leftnum 个字节 - { - UCHAR inbuff[16]; - memset(inbuff,0,16); - memcpy(inbuff,lpCurInBuff,leftnum); - m_lpAes->Cipher(inbuff,lpCurOutBuff); - lpCurOutBuff+=16; - OutLength+=16; - } - //新增16个字节,用以确定增加的字节数 - UCHAR extrabuff[16]; - memset(extrabuff,0,16); - *((LPDWORD)extrabuff)=16+(16-leftnum)%16; //多出16+(16-leftnum)%16个字节 - m_lpAes->Cipher(extrabuff,lpCurOutBuff); - OutLength+=16; - return OutLength; - -} - - -//------------------------------------------------------------------------------------------------------------ -// 编写人员:wfnhddd -// -// 函数名称:OnAesUncrypt -// -// 函数描述:用AES加密算法解密数据 -// -// 调用参数:详细说明参考 MSDN 中的相关描述或相关的开发文档 -// -// 返回数值:解密后的数据大小 ,错误返回值 0 -// -// 最近修改:2009 年 08 月 07 日 -//------------------------------------------------------------------------------------------------------------ -DWORD TAesClass::OnAesUncrypt(LPVOID InBuffer,DWORD InLength,LPVOID OutBuffer) -{ - DWORD OutLength=0; - if (m_lpAes==NULL||OutBuffer==NULL) - { - return 0; - } - UCHAR *lpCurInBuff=(UCHAR *)InBuffer; - UCHAR *lpCurOutBuff=(UCHAR *)OutBuffer; - long blocknum=InLength/16; - long leftnum=InLength%16; - if(leftnum) - { - return 0; - } - for(long i=0;iInvCipher(lpCurInBuff,lpCurOutBuff); - lpCurInBuff+=16; - lpCurOutBuff+=16; - OutLength+=16; - } - - UCHAR *lpExtraInBuff=lpCurOutBuff-16; - DWORD dwExtraBytes=*((LPDWORD)lpExtraInBuff); - return (OutLength-dwExtraBytes); - -} +#include "taesclass.h" + +Aes::~Aes() +{ + +} +Aes::Aes() +{ + +} +//////////////////////////////////////////////////////////////////////////////////////////////// +//构造函数 +Aes::Aes(int keysize,unsigned char* keyBytes) +{ + SetNbNkNr(keysize); //设置密钥块数,轮数 + memcpy(key,keyBytes,keysize); //字符串拷贝函数,把keyBytes的keysize个字符复制到key中 + KeyExpansion(); //密钥扩展,必须提前做的初始化 +} +//////////////////////////////////////////////////////////////////////////////////////////////// +void Aes::SetNbNkNr(int keySize) +{ + Nb=4; + if(keySize==Bits128) + { + Nk=4; //4*4字节,128位密钥,10轮加密 + Nr=10; + } + else if(keySize==Bits192) + { + Nk=6; //6*4字节,192位密钥,12轮加密 + Nr=12; + } + else if(keySize==Bits256) + { + Nk=8; //8*4字节,256位密钥,14轮加密 + Nr=14; + } +} +//////////////////////////////////////////////////////////////////////////////////////////////// +void Aes::KeyExpansion() +{ + + memset(w,0,16*15); + for(int row=0;row 6 && (row % Nk == 4) ) //这个还没有搞清楚 + { + temp = SubWord(temp); + } + + // w[row] = w[row-Nk] xor temp + w[4*row+0] = (byte) ( (int) w[4*(row-Nk)+0] ^ (int)temp[0] ); + w[4*row+1] = (byte) ( (int) w[4*(row-Nk)+1] ^ (int)temp[1] ); + w[4*row+2] = (byte) ( (int) w[4*(row-Nk)+2] ^ (int)temp[2] ); + w[4*row+3] = (byte) ( (int) w[4*(row-Nk)+3] ^ (int)temp[3] ); + } // for loop + +} +//////////////////////////////////////////////////////////////////////////////////////////////// +//密钥移位函数 +unsigned char* Aes::RotWord(unsigned char* word) +{ + byte* temp = new byte[4]; + temp[0] = word[1]; + temp[1] = word[2]; + temp[2] = word[3]; + temp[3] = word[0]; + return temp; +} +//////////////////////////////////////////////////////////////////////////////////////////////// +//密钥字代换函数 +unsigned char* Aes::SubWord(unsigned char* word) +{ + byte* temp = new byte[4]; + for(int j=0;j<4;j++) + { + temp[j] = AesSbox[16*(word[j] >> 4)+(word[j] & 0x0f)]; //实际上也可以写成AesSbox[[j]];因为两者相等 + } + return temp; + +} +//////////////////////////////////////////////////////////////////////////////////////////////// +//Aes加密函数 +void Aes::Cipher(unsigned char* input, unsigned char* output) +{ + memset(&State[0][0],0,16); + for(int i=0;i<4*Nb;i++) //这里是先写列后写行的,即输入是一列一列的进来的 + { + State[i%4][i/4]=input[i]; //换成先写行后写列也是可以的,只要在输出时也是这样就可以了 + } + AddRoundKey(0); //轮密钥加 + + for (int round = 1; round <= (Nr - 1); round++) // main round loop + { + SubBytes(); //字节代换 + ShiftRows(); //行移位 + MixColumns(); //列混淆 + AddRoundKey(round); //轮密钥加 + } // main round loop + + SubBytes(); //字节代换 + ShiftRows(); //行移位 + AddRoundKey(Nr); //轮密钥加 + + // output = state + for (int i = 0; i < (4 * Nb); i++) + { + output[i] = State[i % 4][ i / 4]; + } + +} +//////////////////////////////////////////////////////////////////////////////////////////////// +//Aes解密函数 +void Aes::InvCipher(unsigned char* input,unsigned char* output) +{ + memset(&State[0][0],0,16); + for (int i = 0; i < (4 * Nb); i++) + { + State[i % 4][ i / 4] = input[i]; + } + + AddRoundKey(Nr); + + for (int round = Nr-1; round >= 1; round--) // main round loop + { + InvShiftRows(); + InvSubBytes(); + AddRoundKey(round); + InvMixColumns(); + } // end main round loop for InvCipher + + InvShiftRows(); + InvSubBytes(); + AddRoundKey(0); + + // output = state + for (int i = 0; i < (4 * Nb); i++) + { + output[i] = State[i % 4][ i / 4]; + } +} +//////////////////////////////////////////////////////////////////////////////////////////////// +//轮密钥加 +void Aes::AddRoundKey(int round) +{ + int i,j; //i行 j列 //因为密钥w是一列一列排列的,即 k0 k4 k8 k12 + for(j=0;j<4;j++) // k1 k5 k9 k13 + { // k2 k6 k10k14 + for(i=0;i<4;i++) // k3 k7 k11k15 + { // 所以i行j列的下标是4*((round*4)+j)+i即16*round+4*j+i + State[i][j]=(unsigned char)((int)State[i][j]^(int)w[4*((round*4)+j)+i]); + } + } +} +//////////////////////////////////////////////////////////////////////////////////////////////// +//字节代换函数 +void Aes::SubBytes() //Page 103 +{ + int i,j; + for(j=0;j<4;j++) + { + for(i=0;i<4;i++) + { + State[i][j]=AesSbox[State[i][j]]; + //因为 16*(State[i][j]>>4)+State[i][j]&0x0f=State[i][j] + + + } + } +} + +void Aes::InvSubBytes() +{ + int i,j; + for(j=0;j<4;j++) + { + for(i=0;i<4;i++) + { + State[i][j]=AesiSbox[State[i][j]]; //因为 16*(State[i][j]>>4)+State[i][j]&0x0f=State[i][j] + } + } + +} +//////////////////////////////////////////////////////////////////////////////////////////////// +void Aes::ShiftRows() +{ + unsigned char temp[4*4]; //Page105 + int i,j; + for(j=0;j<4;j++) + { + for(i=0;i<4;i++) + { + temp[4*i+j]=State[i][j]; + } + } + for(i=1;i<4;i++) + { + for(j=0;j<4;j++) + { + if(i==1)State[i][j]=temp[4*i+(j+1)%4]; //第一行左移1位 + else if(i==2)State[i][j]=temp[4*i+(j+2)%4]; //第二行左移2位 + else if(i==3)State[i][j]=temp[4*i+(j+3)%4]; //第三行左移3位 + } + } + +} +void Aes::InvShiftRows() +{ + unsigned char temp[4*4]; + int i,j; + for(j=0;j<4;j++) + { + for(i=0;i<4;i++) + { + temp[4*i+j]=State[i][j]; + } + } + for(i=1;i<4;i++) + { + for(j=0;j<4;j++) + { + //if(i==1)State[i][j]=temp[4*i+(j-1)%4]; 在此犯了一个错误 -1%4=-1 而不是3,所以采用了下面再加一个4的做法 + if(i==1)State[i][j]=temp[4*i+(j+3)%4]; //第一行右移1位 j-1+4=j+3 + else if(i==2)State[i][j]=temp[4*i+(j+2)%4]; //第二行右移2位 j-2+4=j+2 + else if(i==3)State[i][j]=temp[4*i+(j+1)%4]; //第三行右移3位 j-3+4=j+2 + } + } + +} +//////////////////////////////////////////////////////////////////////////////////////////////// +void Aes::MixColumns() +{ + unsigned char temp[4*4]; + int i,j; + for(j=0;j<4;j++) //2 3 1 1 列混淆矩阵 Page107 + { //1 2 3 1 + for(i=0;i<4;i++) //1 1 2 3 + { //3 1 1 2 + temp[4*i+j]=State[i][j]; + } + } + for(j=0;j<4;j++) + { + State[0][j] = (unsigned char) ( (int)gfmultby02(temp[0+j]) ^ (int)gfmultby03(temp[4*1+j]) ^ + (int)gfmultby01(temp[4*2+j]) ^ (int)gfmultby01(temp[4*3+j]) ); + State[1][j] = (unsigned char) ( (int)gfmultby01(temp[0+j]) ^ (int)gfmultby02(temp[4*1+j]) ^ + (int)gfmultby03(temp[4*2+j]) ^ (int)gfmultby01(temp[4*3+j]) ); + State[2][j] = (unsigned char) ( (int)gfmultby01(temp[0+j]) ^ (int)gfmultby01(temp[4*1+j]) ^ + (int)gfmultby02(temp[4*2+j]) ^ (int)gfmultby03(temp[4*3+j]) ); + State[3][j] = (unsigned char) ( (int)gfmultby03(temp[0+j]) ^ (int)gfmultby01(temp[4*1+j]) ^ + (int)gfmultby01(temp[4*2+j]) ^ (int)gfmultby02(temp[4*3+j]) ); + } + +} +void Aes::InvMixColumns() +{ + unsigned char temp[4*4]; + int i,j; + for (i = 0; i < 4; i++) // copy State into temp[] + { + for (j = 0; j < 4; j++) //0e 0b 0d 09 逆变换矩阵 Page108 + { //09 0e 0b 0d + temp[4*i+j] = State[i][j]; //0d 09 0e 0b + } //0b 0d 09 0e + } + + for (j = 0; j < 4; j++) + { + State[0][j] = (unsigned char) ( (int)gfmultby0e(temp[j]) ^ (int)gfmultby0b(temp[4+j]) ^ + (int)gfmultby0d(temp[4*2+j]) ^ (int)gfmultby09(temp[4*3+j]) ); + State[1][j] = (unsigned char) ( (int)gfmultby09(temp[j]) ^ (int)gfmultby0e(temp[4+j]) ^ + (int)gfmultby0b(temp[4*2+j]) ^ (int)gfmultby0d(temp[4*3+j]) ); + State[2][j] = (unsigned char) ( (int)gfmultby0d(temp[j]) ^ (int)gfmultby09(temp[4+j]) ^ + (int)gfmultby0e(temp[4*2+j]) ^ (int)gfmultby0b(temp[4*3+j]) ); + State[3][j] = (unsigned char) ( (int)gfmultby0b(temp[j]) ^ (int)gfmultby0d(temp[4+j]) ^ + (int)gfmultby09(temp[4*2+j]) ^ (int)gfmultby0e(temp[4*3+j]) ); + } +} +//////////////////////////////////////////////////////////////////////////////////////////////// +unsigned char Aes::gfmultby01(unsigned char b) +{ + return b; +} +unsigned char Aes::gfmultby02(unsigned char b) +{ + if (b < 0x80) + return (unsigned char)(int)(b <<1); + else + return (unsigned char)( (int)(b << 1) ^ (int)(0x1b) ); +} + +unsigned char Aes::gfmultby03(unsigned char b) +{ + return (unsigned char) ( (int)gfmultby02(b) ^ (int)b ); +} + +unsigned char Aes::gfmultby09(unsigned char b) +{ + return (unsigned char)( (int)gfmultby02(gfmultby02(gfmultby02(b))) ^ (int)b ); +} + +unsigned char Aes::gfmultby0b(unsigned char b) +{ + return (unsigned char)( (int)gfmultby02(gfmultby02(gfmultby02(b))) ^ + (int)gfmultby02(b) ^ (int)b ); +} + +unsigned char Aes::gfmultby0d(unsigned char b) +{ + return (unsigned char)( (int)gfmultby02(gfmultby02(gfmultby02(b))) ^ + (int)gfmultby02(gfmultby02(b)) ^ (int)(b) ); +} + +unsigned char Aes::gfmultby0e(unsigned char b) +{ + return (unsigned char)( (int)gfmultby02(gfmultby02(gfmultby02(b))) ^ + (int)gfmultby02(gfmultby02(b)) ^(int)gfmultby02(b) ); +} + +TAesClass::TAesClass() +{ + m_lpAes=NULL; + InitializePrivateKey(16,(unsigned char*)"\x79\x76\x68\x6B\x77\x66\x6E\x68\x72\x65\x73\x63\x6C\x6B\x70\x6E"); +} + +TAesClass::~TAesClass() +{ + if (m_lpAes!=NULL) + { + delete m_lpAes; + } +} +//------------------------------------------------------------------------------------------------------------ +// 编写人员:wfnhddd +// +// 函数名称:InitializeAes +// +// 函数描述:初始化AES 密钥,密钥用于加密解密 +// +// 调用参数:详细说明参考 MSDN 中的相关描述或相关的开发文档 +// +// 返回数值:无 +// +// 最近修改:2009 年 08 月 07 日 +//------------------------------------------------------------------------------------------------------------ + + +VOID TAesClass::InitializePrivateKey(DWORD KeySize,UCHAR *KeyBytes) +{ + if (m_lpAes) + { + delete m_lpAes; + m_lpAes=NULL; + } + m_lpAes=new Aes(KeySize,KeyBytes); + +} + +//------------------------------------------------------------------------------------------------------------ +// 编写人员:wfnhddd +// +// 函数名称:OnAesEncrypt +// +// 函数描述:用AES加密算法加密数据 +// +// 调用参数:详细说明参考 MSDN 中的相关描述或相关的开发文档 +// +// 返回数值:加密后的数据大小 ,错误返回值 0 +// +// 最近修改:2009 年 08 月 07 日 +//------------------------------------------------------------------------------------------------------------ + +DWORD TAesClass::OnAesEncrypt(LPVOID InBuffer,DWORD InLength,LPVOID OutBuffer) +{ + DWORD OutLength=0; + if (m_lpAes==NULL||OutBuffer==NULL) + { + return 0; + } + + UCHAR *lpCurInBuff=(UCHAR *)InBuffer; + UCHAR *lpCurOutBuff=(UCHAR *)OutBuffer; + long blocknum=InLength/16; + long leftnum=InLength%16; + for(long i=0;iCipher(lpCurInBuff,lpCurOutBuff); + lpCurInBuff+=16; + lpCurOutBuff+=16; + OutLength+=16; + } + if(leftnum) //多余出leftnum 字节 则加密时 多出16-leftnum 个字节 + { + UCHAR inbuff[16]; + memset(inbuff,0,16); + memcpy(inbuff,lpCurInBuff,leftnum); + m_lpAes->Cipher(inbuff,lpCurOutBuff); + lpCurOutBuff+=16; + OutLength+=16; + } + //新增16个字节,用以确定增加的字节数 + UCHAR extrabuff[16]; + memset(extrabuff,0,16); + *((LPDWORD)extrabuff)=16+(16-leftnum)%16; //多出16+(16-leftnum)%16个字节 + m_lpAes->Cipher(extrabuff,lpCurOutBuff); + OutLength+=16; + return OutLength; + +} + + +//------------------------------------------------------------------------------------------------------------ +// 编写人员:wfnhddd +// +// 函数名称:OnAesUncrypt +// +// 函数描述:用AES加密算法解密数据 +// +// 调用参数:详细说明参考 MSDN 中的相关描述或相关的开发文档 +// +// 返回数值:解密后的数据大小 ,错误返回值 0 +// +// 最近修改:2009 年 08 月 07 日 +//------------------------------------------------------------------------------------------------------------ +DWORD TAesClass::OnAesUncrypt(LPVOID InBuffer,DWORD InLength,LPVOID OutBuffer) +{ + DWORD OutLength=0; + if (m_lpAes==NULL||OutBuffer==NULL) + { + return 0; + } + UCHAR *lpCurInBuff=(UCHAR *)InBuffer; + UCHAR *lpCurOutBuff=(UCHAR *)OutBuffer; + long blocknum=InLength/16; + long leftnum=InLength%16; + if(leftnum) + { + return 0; + } + for(long i=0;iInvCipher(lpCurInBuff,lpCurOutBuff); + lpCurInBuff+=16; + lpCurOutBuff+=16; + OutLength+=16; + } + + UCHAR *lpExtraInBuff=lpCurOutBuff-16; + DWORD dwExtraBytes=*((LPDWORD)lpExtraInBuff); + return (OutLength-dwExtraBytes); + +} diff --git a/LedOK/base/taesclass.h b/LedOK/base/taesclass.h index 6d69cd1..0fdaeec 100644 --- a/LedOK/base/taesclass.h +++ b/LedOK/base/taesclass.h @@ -1,133 +1,133 @@ -#ifndef TAESCLASS_H -#define TAESCLASS_H -#include -#include -#include -#include - -typedef unsigned long DWORD; -typedef unsigned char UCHAR,*PUCHAR; -typedef void *PVOID,*LPVOID; -typedef unsigned char byte; -typedef DWORD *PDWORD,*LPDWORD; - -#ifndef VOID -#define VOID void -#endif - -//#pragma once - -//enum KeySize { Bits128, Bits192, Bits256 }; // key size, in bits, for construtor -#define Bits128 16 -#define Bits192 24 -#define Bits256 32 - -unsigned char AesSbox[16*16]= -{// populate the Sbox matrix - /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ - /*0*/ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, - /*1*/ 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, - /*2*/ 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, - /*3*/ 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, - /*4*/ 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, - /*5*/ 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, - /*6*/ 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, - /*7*/ 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, - /*8*/ 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, - /*9*/ 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, - /*a*/ 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, - /*b*/ 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, - /*c*/ 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, - /*d*/ 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, - /*e*/ 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, - /*f*/ 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 -}; - -unsigned char AesiSbox[16*16]= -{ - // populate the iSbox matrix - /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ - /*0*/ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, - /*1*/ 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, - /*2*/ 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, - /*3*/ 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, - /*4*/ 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, - /*5*/ 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, - /*6*/ 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, - /*7*/ 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, - /*8*/ 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, - /*9*/ 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, - /*a*/ 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, - /*b*/ 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, - /*c*/ 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, - /*d*/ 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, - /*e*/ 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, - /*f*/ 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d -}; -unsigned char AesRcon[11*4]= -{ - 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, - 0x1b, 0x00, 0x00, 0x00, - 0x36, 0x00, 0x00, 0x00 -}; - - -class Aes // Advanced Encryption Standard -{ -public: - ~Aes(); - Aes(); - Aes(int keySize, unsigned char* keyBytes); - unsigned char State[4][4]; - void Cipher(unsigned char* input, unsigned char* output); // encipher 16-bit input - void InvCipher(unsigned char* input, unsigned char* output); // decipher 16-bit input -private: - int Nb; // block size in 32-bit words. Always 4 for AES. (128 bits). - int Nk; // key size in 32-bit words. 4, 6, 8. (128, 192, 256 bits). - int Nr; // number of rounds. 10, 12, 14. - - unsigned char key[32]; - unsigned char w[16*15]; - - void SetNbNkNr(int keySize); - void AddRoundKey(int round); //轮密钥加 - void SubBytes(); //S盒字节代换 - void InvSubBytes(); //逆S盒字节代换 - void ShiftRows(); //行移位 - void InvShiftRows(); - void MixColumns(); //列混淆 - void InvMixColumns(); - unsigned char gfmultby01(unsigned char b); - unsigned char gfmultby02(unsigned char b); - unsigned char gfmultby03(unsigned char b); - unsigned char gfmultby09(unsigned char b); - unsigned char gfmultby0b(unsigned char b); - unsigned char gfmultby0d(unsigned char b); - unsigned char gfmultby0e(unsigned char b); - void KeyExpansion(); //密钥扩展 - unsigned char* SubWord(unsigned char* word); //密钥S盒字代换 - unsigned char* RotWord(unsigned char* word); //密钥移位 - -}; - -class TAesClass -{ -public: - TAesClass(); - ~TAesClass(); - void InitializePrivateKey(DWORD KeySize,UCHAR *KeyBytes); //AES 密钥初始化 - DWORD OnAesEncrypt(LPVOID InBuffer,DWORD InLength,LPVOID OutBuffer); //AES 加密数据 - DWORD OnAesUncrypt(LPVOID InBuffer,DWORD InLength,LPVOID OutBuffer); //AES 解密数据 -private: - Aes * m_lpAes; -}; - -#endif +#ifndef TAESCLASS_H +#define TAESCLASS_H +#include +#include +#include +#include + +typedef unsigned long DWORD; +typedef unsigned char UCHAR,*PUCHAR; +typedef void *PVOID,*LPVOID; +typedef unsigned char byte; +typedef DWORD *PDWORD,*LPDWORD; + +#ifndef VOID +#define VOID void +#endif + +//#pragma once + +//enum KeySize { Bits128, Bits192, Bits256 }; // key size, in bits, for construtor +#define Bits128 16 +#define Bits192 24 +#define Bits256 32 + +unsigned char AesSbox[16*16]= +{// populate the Sbox matrix + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ + /*0*/ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + /*1*/ 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + /*2*/ 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + /*3*/ 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + /*4*/ 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + /*5*/ 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + /*6*/ 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + /*7*/ 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + /*8*/ 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + /*9*/ 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + /*a*/ 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + /*b*/ 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + /*c*/ 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + /*d*/ 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + /*e*/ 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + /*f*/ 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 +}; + +unsigned char AesiSbox[16*16]= +{ + // populate the iSbox matrix + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ + /*0*/ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, + /*1*/ 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, + /*2*/ 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, + /*3*/ 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, + /*4*/ 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, + /*5*/ 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, + /*6*/ 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, + /*7*/ 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, + /*8*/ 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, + /*9*/ 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, + /*a*/ 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, + /*b*/ 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, + /*c*/ 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, + /*d*/ 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, + /*e*/ 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, + /*f*/ 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d +}; +unsigned char AesRcon[11*4]= +{ + 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, + 0x1b, 0x00, 0x00, 0x00, + 0x36, 0x00, 0x00, 0x00 +}; + + +class Aes // Advanced Encryption Standard +{ +public: + ~Aes(); + Aes(); + Aes(int keySize, unsigned char* keyBytes); + unsigned char State[4][4]; + void Cipher(unsigned char* input, unsigned char* output); // encipher 16-bit input + void InvCipher(unsigned char* input, unsigned char* output); // decipher 16-bit input +private: + int Nb; // block size in 32-bit words. Always 4 for AES. (128 bits). + int Nk; // key size in 32-bit words. 4, 6, 8. (128, 192, 256 bits). + int Nr; // number of rounds. 10, 12, 14. + + unsigned char key[32]; + unsigned char w[16*15]; + + void SetNbNkNr(int keySize); + void AddRoundKey(int round); //轮密钥加 + void SubBytes(); //S盒字节代换 + void InvSubBytes(); //逆S盒字节代换 + void ShiftRows(); //行移位 + void InvShiftRows(); + void MixColumns(); //列混淆 + void InvMixColumns(); + unsigned char gfmultby01(unsigned char b); + unsigned char gfmultby02(unsigned char b); + unsigned char gfmultby03(unsigned char b); + unsigned char gfmultby09(unsigned char b); + unsigned char gfmultby0b(unsigned char b); + unsigned char gfmultby0d(unsigned char b); + unsigned char gfmultby0e(unsigned char b); + void KeyExpansion(); //密钥扩展 + unsigned char* SubWord(unsigned char* word); //密钥S盒字代换 + unsigned char* RotWord(unsigned char* word); //密钥移位 + +}; + +class TAesClass +{ +public: + TAesClass(); + ~TAesClass(); + void InitializePrivateKey(DWORD KeySize,UCHAR *KeyBytes); //AES 密钥初始化 + DWORD OnAesEncrypt(LPVOID InBuffer,DWORD InLength,LPVOID OutBuffer); //AES 加密数据 + DWORD OnAesUncrypt(LPVOID InBuffer,DWORD InLength,LPVOID OutBuffer); //AES 解密数据 +private: + Aes * m_lpAes; +}; + +#endif diff --git a/LedOK/base/updateledset3dialog.cpp b/LedOK/base/updateledset3dialog.cpp index 52665f9..494ca56 100644 --- a/LedOK/base/updateledset3dialog.cpp +++ b/LedOK/base/updateledset3dialog.cpp @@ -1,81 +1,81 @@ -#include "updateledset3dialog.h" -#include "ui_updateledset3dialog.h" -#include -#include - -extern const QString DEFS_LEDSET_URL = "https://www.ledok.cn/download/definitions/ledset3updates.json"; - -UpdateLedset3Dialog::UpdateLedset3Dialog(QWidget *parent) : - BaseDlg(parent), - ui(new Ui::UpdateLedset3Dialog) -{ - setAttribute(Qt::WA_DeleteOnClose); - ui->setupUi(this); - ui->pushButton_2->setVisible(false); - - QString strCurApkVersion=""; - QSettings settings; - strCurApkVersion = settings.value(DEFS_LEDSET_URL).toString(); - if(strCurApkVersion.isEmpty()) strCurApkVersion="0.0.0"; - strCurApkVersion="0.0.0"; - - ui->label_2->setText(tr("CurVersion")+":"+strCurApkVersion); - ui->label_2->setVisible(false); - - QSimpleUpdater *m_updater=QSimpleUpdater::getInstance(); - connect(ui->pushButton_2, SIGNAL(clicked()), this, SLOT(OnCheckForUpdates())); - connect(m_updater,SIGNAL(checkingFinished(QString)),this,SLOT(updateChangelog(QString))); - connect(m_updater,SIGNAL(downloadFinished(QString,QString)),this,SLOT(OnDownloadFinished(QString,QString))); - - m_updater->getInstance()->setModuleVersion(DEFS_LEDSET_URL,strCurApkVersion); - m_updater->getInstance()->setNotifyOnUpdate(DEFS_LEDSET_URL,false); - m_updater->getInstance()->setNotifyOnFinish(DEFS_LEDSET_URL,false); - m_updater->getInstance()->setCompareBySameString(DEFS_LEDSET_URL,true); - m_updater->getInstance()->checkForUpdates(DEFS_LEDSET_URL); - ui->pushButton->setProperty("ssType", "progManageTool"); - ui->pushButton_2->setProperty("ssType", "progManageTool"); -} - -UpdateLedset3Dialog::~UpdateLedset3Dialog() -{ - delete ui; -} -void UpdateLedset3Dialog::OnDownloadFinished( QString url, QString filepath) -{ - ui->label_2->setText(tr("CurVersion")+":"+m_updater->getInstance()->getLatestVersion(DEFS_LEDSET_URL)); - ui->textEdit->setText(tr("Apk is download finished from internet,you can select LED Screen SYNC firmware now!")); - ui->pushButton_2->setVisible(false); - QSettings settings; - settings.setValue(url, m_strLastestVersion); - settings.setValue("ledset", filepath); -} - -void UpdateLedset3Dialog::OnCheckForUpdates() -{ - m_updater->getInstance()->setNotifyOnUpdate(DEFS_LEDSET_URL,true); - m_updater->getInstance()->setNotifyOnFinish(DEFS_LEDSET_URL,false); - // m_updater->getInstance()->setUseCustomInstallProcedures(DEFS_LEDSET_URL,true); - m_updater->getInstance()->setNoNotifyDownload(DEFS_LEDSET_URL,true); - m_updater->getInstance()->setCompareBySameString(DEFS_LEDSET_URL,true); - m_updater->getInstance()->setMandatoryUpdate(DEFS_LEDSET_URL,false); - m_updater->getInstance()->checkForUpdates(DEFS_LEDSET_URL); - -} -void UpdateLedset3Dialog::updateChangelog(QString strTip) -{ - Q_UNUSED(strTip) - - if(m_updater->getInstance()->getUpdateAvailable(DEFS_LEDSET_URL)) - { - QString strtip=tr("LatestVersion:"); - m_strLastestVersion=m_updater->getInstance()->getLatestVersion(DEFS_LEDSET_URL); - strtip+= m_strLastestVersion +"\r\n"; - strtip+= tr("Update log:")+"\r\n"+m_updater->getInstance()->getChangelog (DEFS_LEDSET_URL) ; - ui->textEdit->setText(strtip); - ui->pushButton_2->setVisible(true); - } - else { - ui->textEdit->setText(tr("The current version is already the latest version,,you can select LED Screen SYNC firmware now!")); - } - disconnect(m_updater,SIGNAL(checkingFinished(QString)),this,SLOT(updateChangelog(QString))); -} +#include "updateledset3dialog.h" +#include "ui_updateledset3dialog.h" +#include +#include + +extern const QString DEFS_LEDSET_URL = "https://www.ledok.cn/download/definitions/ledset3updates.json"; + +UpdateLedset3Dialog::UpdateLedset3Dialog(QWidget *parent) : + BaseDlg(parent), + ui(new Ui::UpdateLedset3Dialog) +{ + setAttribute(Qt::WA_DeleteOnClose); + ui->setupUi(this); + ui->pushButton_2->setVisible(false); + + QString strCurApkVersion=""; + QSettings settings; + strCurApkVersion = settings.value(DEFS_LEDSET_URL).toString(); + if(strCurApkVersion.isEmpty()) strCurApkVersion="0.0.0"; + strCurApkVersion="0.0.0"; + + ui->label_2->setText(tr("CurVersion")+":"+strCurApkVersion); + ui->label_2->setVisible(false); + + QSimpleUpdater *m_updater=QSimpleUpdater::getInstance(); + connect(ui->pushButton_2, SIGNAL(clicked()), this, SLOT(OnCheckForUpdates())); + connect(m_updater,SIGNAL(checkingFinished(QString)),this,SLOT(updateChangelog(QString))); + connect(m_updater,SIGNAL(downloadFinished(QString,QString)),this,SLOT(OnDownloadFinished(QString,QString))); + + m_updater->getInstance()->setModuleVersion(DEFS_LEDSET_URL,strCurApkVersion); + m_updater->getInstance()->setNotifyOnUpdate(DEFS_LEDSET_URL,false); + m_updater->getInstance()->setNotifyOnFinish(DEFS_LEDSET_URL,false); + m_updater->getInstance()->setCompareBySameString(DEFS_LEDSET_URL,true); + m_updater->getInstance()->checkForUpdates(DEFS_LEDSET_URL); + ui->pushButton->setProperty("ssType", "progManageTool"); + ui->pushButton_2->setProperty("ssType", "progManageTool"); +} + +UpdateLedset3Dialog::~UpdateLedset3Dialog() +{ + delete ui; +} +void UpdateLedset3Dialog::OnDownloadFinished( QString url, QString filepath) +{ + ui->label_2->setText(tr("CurVersion")+":"+m_updater->getInstance()->getLatestVersion(DEFS_LEDSET_URL)); + ui->textEdit->setText(tr("Apk is download finished from internet,you can select LED Screen SYNC firmware now!")); + ui->pushButton_2->setVisible(false); + QSettings settings; + settings.setValue(url, m_strLastestVersion); + settings.setValue("ledset", filepath); +} + +void UpdateLedset3Dialog::OnCheckForUpdates() +{ + m_updater->getInstance()->setNotifyOnUpdate(DEFS_LEDSET_URL,true); + m_updater->getInstance()->setNotifyOnFinish(DEFS_LEDSET_URL,false); + // m_updater->getInstance()->setUseCustomInstallProcedures(DEFS_LEDSET_URL,true); + m_updater->getInstance()->setNoNotifyDownload(DEFS_LEDSET_URL,true); + m_updater->getInstance()->setCompareBySameString(DEFS_LEDSET_URL,true); + m_updater->getInstance()->setMandatoryUpdate(DEFS_LEDSET_URL,false); + m_updater->getInstance()->checkForUpdates(DEFS_LEDSET_URL); + +} +void UpdateLedset3Dialog::updateChangelog(QString strTip) +{ + Q_UNUSED(strTip) + + if(m_updater->getInstance()->getUpdateAvailable(DEFS_LEDSET_URL)) + { + QString strtip=tr("LatestVersion:"); + m_strLastestVersion=m_updater->getInstance()->getLatestVersion(DEFS_LEDSET_URL); + strtip+= m_strLastestVersion +"\r\n"; + strtip+= tr("Update log:")+"\r\n"+m_updater->getInstance()->getChangelog (DEFS_LEDSET_URL) ; + ui->textEdit->setText(strtip); + ui->pushButton_2->setVisible(true); + } + else { + ui->textEdit->setText(tr("The current version is already the latest version,,you can select LED Screen SYNC firmware now!")); + } + disconnect(m_updater,SIGNAL(checkingFinished(QString)),this,SLOT(updateChangelog(QString))); +} diff --git a/LedOK/base/updateledset3dialog.h b/LedOK/base/updateledset3dialog.h index 2458b2c..716a9f4 100644 --- a/LedOK/base/updateledset3dialog.h +++ b/LedOK/base/updateledset3dialog.h @@ -1,30 +1,30 @@ -#ifndef UPDATELEDSET3DIALOG_H -#define UPDATELEDSET3DIALOG_H - -#include -#include - -namespace Ui { -class UpdateLedset3Dialog; -} - -class UpdateLedset3Dialog : public BaseDlg -{ - Q_OBJECT - -public: - explicit UpdateLedset3Dialog(QWidget *parent = nullptr); - ~UpdateLedset3Dialog(); - -private: - Ui::UpdateLedset3Dialog *ui; - QSimpleUpdater *m_updater; - QString m_strLastestVersion=""; -protected slots: - void OnCheckForUpdates() ; - void updateChangelog(QString); - void OnDownloadFinished( QString url, QString filepath); - -}; - -#endif // UPDATELEDSET3DIALOG_H +#ifndef UPDATELEDSET3DIALOG_H +#define UPDATELEDSET3DIALOG_H + +#include +#include + +namespace Ui { +class UpdateLedset3Dialog; +} + +class UpdateLedset3Dialog : public BaseDlg +{ + Q_OBJECT + +public: + explicit UpdateLedset3Dialog(QWidget *parent = nullptr); + ~UpdateLedset3Dialog(); + +private: + Ui::UpdateLedset3Dialog *ui; + QSimpleUpdater *m_updater; + QString m_strLastestVersion=""; +protected slots: + void OnCheckForUpdates() ; + void updateChangelog(QString); + void OnDownloadFinished( QString url, QString filepath); + +}; + +#endif // UPDATELEDSET3DIALOG_H diff --git a/LedOK/base/updateledset3dialog.ui b/LedOK/base/updateledset3dialog.ui index 86c3828..1ddf1e9 100644 --- a/LedOK/base/updateledset3dialog.ui +++ b/LedOK/base/updateledset3dialog.ui @@ -1,204 +1,204 @@ - - - UpdateLedset3Dialog - - - - 0 - 0 - 381 - 272 - - - - - - 0 - 0 - 382 - 275 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - 0 - - - - - LedSet3.0 Update - - - Qt::AlignCenter - - - - - - - - 30 - 24 - - - - X - - - - - - - - - border-top: 2px solid gray; - - - Qt::Horizontal - - - - - - - - - - - - 0 - 0 - - - - - 64 - 64 - - - - image: url(:/res/ledset.png); - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - 0 - 0 - - - - - 14 - - - - V1.0.0 - - - Qt::AlignCenter - - - - - - - true - - - - - - - - 0 - 0 - - - - - 80 - 0 - - - - - 80 - 16777215 - - - - Update - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - pushButton - clicked() - UpdateLedset3Dialog - close() - - - 355 - 22 - - - 190 - 135 - - - - - + + + UpdateLedset3Dialog + + + + 0 + 0 + 381 + 272 + + + + + + 0 + 0 + 382 + 275 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + 0 + + + + + LedSet3.0 Update + + + Qt::AlignCenter + + + + + + + + 30 + 24 + + + + X + + + + + + + + + border-top: 2px solid gray; + + + Qt::Horizontal + + + + + + + + + + + + 0 + 0 + + + + + 64 + 64 + + + + image: url(:/res/ledset.png); + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + 0 + 0 + + + + + 14 + + + + V1.0.0 + + + Qt::AlignCenter + + + + + + + true + + + + + + + + 0 + 0 + + + + + 80 + 0 + + + + + 80 + 16777215 + + + + Update + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + pushButton + clicked() + UpdateLedset3Dialog + close() + + + 355 + 22 + + + 190 + 135 + + + + + diff --git a/LedOK/base/updaterdialog.cpp b/LedOK/base/updaterdialog.cpp deleted file mode 100644 index 23a1b46..0000000 --- a/LedOK/base/updaterdialog.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include "updaterdialog.h" -#include "cfg.h" -#include "ui_updaterdialog.h" - -UpdaterDialog::UpdaterDialog(QWidget *parent) : BaseDlg(parent), ui(new Ui::UpdaterDialog) { - setAttribute(Qt::WA_DeleteOnClose); - ui->setupUi(this); - ui->pushButton_2->setVisible(false); - ui->label_2->setText(tr("CurVersion")+":"+APP_VERSION); - QSimpleUpdater *m_updater = QSimpleUpdater::getInstance(); - connect(ui->pushButton_2, SIGNAL(clicked()), this, SLOT(OnCheckForUpdates())); - connect(m_updater, SIGNAL(checkingFinished(QString)), this, SLOT(updateChangelog(QString))); - m_updater->setModuleVersion(UpdVerUrl, APP_VERSION); - m_updater->setNotifyOnUpdate(UpdVerUrl, false); - m_updater->setNotifyOnFinish(UpdVerUrl, false); - m_updater->checkForUpdates(UpdVerUrl); -} - -UpdaterDialog::~UpdaterDialog(){ - delete ui; -} -void UpdaterDialog::OnCheckForUpdates(){ - QSimpleUpdater::getInstance()->setNotifyOnUpdate(UpdVerUrl, true); - QSimpleUpdater::getInstance()->setNotifyOnFinish(UpdVerUrl, false); - QSimpleUpdater::getInstance()->setMandatoryUpdate(UpdVerUrl, true); - QSimpleUpdater::getInstance()->checkForUpdates(UpdVerUrl); -} -void UpdaterDialog::updateChangelog(QString){ - if(QSimpleUpdater::getInstance()->getUpdateAvailable(UpdVerUrl)){ - QString strtip = tr("LatestVersion:") + QSimpleUpdater::getInstance()->getLatestVersion(UpdVerUrl) + "\r\n" - + tr("Update log:") + "\r\n" + QSimpleUpdater::getInstance()->getChangelog(UpdVerUrl); - ui->textEdit->setText(strtip); - ui->pushButton_2->setVisible(true); - } else { - ui->textEdit->setText(tr("The current version is already the latest version") + "\r\n\r\n" - + tr("Update log:") + "\r\n" + QSimpleUpdater::getInstance()->getChangelog(UpdVerUrl)); - } -} diff --git a/LedOK/base/updaterdialog.h b/LedOK/base/updaterdialog.h deleted file mode 100644 index 202f0e8..0000000 --- a/LedOK/base/updaterdialog.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef UPDATERDIALOG_H -#define UPDATERDIALOG_H - -#include -#include - -namespace Ui { -class UpdaterDialog; -} - -class UpdaterDialog : public BaseDlg -{ - Q_OBJECT - -public: - explicit UpdaterDialog(QWidget *parent = nullptr); - ~UpdaterDialog(); -private: - Ui::UpdaterDialog *ui; - -protected slots: - void OnCheckForUpdates() ; - void updateChangelog(QString); -}; - -#endif // UPDATERDIALOG_H diff --git a/LedOK/base/updaterdialog.ui b/LedOK/base/updaterdialog.ui deleted file mode 100644 index 93a2b69..0000000 --- a/LedOK/base/updaterdialog.ui +++ /dev/null @@ -1,193 +0,0 @@ - - - UpdaterDialog - - - - 0 - 0 - 500 - 400 - - - - - 0 - 0 - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - 0 - - - - - Software Update - - - Qt::AlignCenter - - - - - - - - 30 - 24 - - - - X - - - - - - - - - border-top: 2px solid gray; - - - Qt::Horizontal - - - - - - - - - - - - 0 - 0 - - - - - 64 - 64 - - - - image: url(:/res/Logo.png); - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - 0 - 0 - - - - - 14 - - - - V1.0 - - - Qt::AlignCenter - - - - - - - true - - - - - - - - 0 - 0 - - - - - 80 - 0 - - - - - 80 - 16777215 - - - - Update - - - - - - - - - - - - - - - - pushButton - clicked() - UpdaterDialog - close() - - - 364 - 29 - - - 199 - 78 - - - - - diff --git a/LedOK/base/waitingdlg.cpp b/LedOK/base/waitingdlg.cpp index 4e3ade1..0174a08 100644 --- a/LedOK/base/waitingdlg.cpp +++ b/LedOK/base/waitingdlg.cpp @@ -1,50 +1,61 @@ -#include "waitingdlg.h" -#include -#include - -WaitingDlg::WaitingDlg(QWidget *parent, QString text, QString sucText) : BaseDlg{parent}, sucText(sucText) { - setAttribute(Qt::WA_DeleteOnClose); - setModal(true); - - auto pal = palette(); - pal.setBrush(QPalette::Window, QColor(0xdddddd)); - setPalette(pal); - - auto vBox = new QVBoxLayout(this); - vBox->addStretch(); - - mIndicator = new CustomProgressIndicator(this); - mIndicator->setDisplayModel(1); - mIndicator->setColor(QColor(0x0088dd)); - mIndicator->startAnimation(); - vBox->addWidget(mIndicator, 0, Qt::AlignCenter); - - vBox->addStretch(); - - fdText = new QLabel(text); - fdText->setAlignment(Qt::AlignCenter); - auto font = fdText->font(); - font.setPixelSize(18); - font.setBold(true); - fdText->setFont(font); - pal = fdText->palette(); - pal.setBrush(QPalette::WindowText, QColor(0x0088dd)); - fdText->setPalette(pal); - vBox->addWidget(fdText); - - vBox->addStretch(); -} - -void WaitingDlg::timerEvent(QTimerEvent *event) { - if(closeTimerId==event->timerId()) { - killTimer(closeTimerId); - closeTimerId = 0; - close(); - } else BaseDlg::timerEvent(event); -} -void WaitingDlg::success() { - fdText->setText(sucText.isEmpty() ? tr("Success") : sucText); - mIndicator->setBackground(":/res/success.png"); - mIndicator->stopAnimation(); - closeTimerId = startTimer(800); -} +#include "waitingdlg.h" +#include +#include +#include + +WaitingDlg::WaitingDlg(QWidget *parent, QString text, QString sucText) : BaseDlg{parent}, sucText(sucText) { + setAttribute(Qt::WA_DeleteOnClose); + setModal(true); + + auto pal = palette(); + pal.setBrush(QPalette::Window, QColor(0xdddddd)); + setPalette(pal); + + auto vBox = new QVBoxLayout(this); + vBox->setContentsMargins(6, 3, 6, 6); + vBox->addStretch(); + + btnAbort = new QPushButton("X"); + btnAbort->setStyleSheet(R"rrr( +QPushButton {border-radius: 4px; padding: 2px 6px; background: transparent;} +QPushButton:hover {background: rgba(0,0,0,0.2);} +QPushButton:pressed {background: rgba(0,0,0,0.3);} +)rrr"); + connect(btnAbort, &QPushButton::clicked, this, &QDialog::reject); + vBox->addWidget(btnAbort, 0, Qt::AlignRight); + + mIndicator = new CustomProgressIndicator(this); + mIndicator->setDisplayModel(1); + mIndicator->setColor(QColor(0x0088dd)); + mIndicator->startAnimation(); + vBox->addWidget(mIndicator, 0, Qt::AlignCenter); + + vBox->addStretch(); + + fdText = new QLabel(text); + fdText->setAlignment(Qt::AlignCenter); + auto font = fdText->font(); + font.setPixelSize(18); + font.setBold(true); + fdText->setFont(font); + pal = fdText->palette(); + pal.setBrush(QPalette::WindowText, QColor(0x0088dd)); + fdText->setPalette(pal); + vBox->addWidget(fdText); + + vBox->addStretch(); +} + +void WaitingDlg::timerEvent(QTimerEvent *event) { + if(closeTimerId==event->timerId()) { + killTimer(closeTimerId); + closeTimerId = 0; + close(); + } else BaseDlg::timerEvent(event); +} +void WaitingDlg::success() { + fdText->setText(sucText.isEmpty() ? tr("Success") : sucText); + mIndicator->setBackground(":/res/success.png"); + mIndicator->stopAnimation(); + closeTimerId = startTimer(800); +} diff --git a/LedOK/base/waitingdlg.h b/LedOK/base/waitingdlg.h index 4799136..cccab19 100644 --- a/LedOK/base/waitingdlg.h +++ b/LedOK/base/waitingdlg.h @@ -1,25 +1,25 @@ -#ifndef WAITINGDLG_H -#define WAITINGDLG_H - -#include "basedlg.h" -#include "base/customprogressindicator.h" -#include - -class WaitingDlg : public BaseDlg { - Q_OBJECT -public: - explicit WaitingDlg(QWidget *parent = nullptr, QString text = 0, QString sucText = 0); - - QLabel *fdText; - QString sucText; - CustomProgressIndicator *mIndicator; -public slots: - void success(); - -protected: - void timerEvent(QTimerEvent *) override; -private: - int closeTimerId{0}; -}; - -#endif // WAITINGDLG_H +#ifndef WAITINGDLG_H +#define WAITINGDLG_H + +#include "basedlg.h" +#include "base/customprogressindicator.h" +#include + +class WaitingDlg : public BaseDlg { + Q_OBJECT +public: + explicit WaitingDlg(QWidget *parent = nullptr, QString text = 0, QString sucText = 0); + + QPushButton *btnAbort; + QLabel *fdText; + QString sucText; + CustomProgressIndicator *mIndicator; +public slots: + void success(); +protected: + void timerEvent(QTimerEvent *) override; +private: + int closeTimerId{0}; +}; + +#endif // WAITINGDLG_H diff --git a/LedOK/base/x_checkboxdelegate.cpp b/LedOK/base/x_checkboxdelegate.cpp index 4489bc5..9ba27d8 100644 --- a/LedOK/base/x_checkboxdelegate.cpp +++ b/LedOK/base/x_checkboxdelegate.cpp @@ -1,116 +1,116 @@ -/* - delegate.cpp - - A delegate that allows the user to change integer values from the model - using a spin box widget. -*/ - -#include "x_checkboxdelegate.h" - -#include -#include -#include -X_CheckBoxDelegate::X_CheckBoxDelegate(QObject *parent) - : QStyledItemDelegate(parent) -{ - -} - -QWidget *X_CheckBoxDelegate::createEditor(QWidget *parent, - const QStyleOptionViewItem & option , - const QModelIndex & index ) const -{ -// if(index.column()>=3&&index.column()<=9) -// { -// QCheckBox *editor = new QCheckBox(parent); -// // editor->setFrame(false); - -// ///editor->setAlignment(Qt::AlignHCenter); -// // editor->setDisplayFormat("hh:mm"); - -// return editor; - -// } - - if(index.column()>=3&&index.column()<=9) - { - QCheckBox *editor=new QCheckBox(parent); - editor->installEventFilter(const_cast(this)); - return editor; - } - else - return QStyledItemDelegate::createEditor(parent,option,index); - - return nullptr; -} - -//void X_CheckBoxDelegate::setEditorData(QWidget *editor, -// const QModelIndex &index) const -//{ -// if(index.column()>=3&&index.column()<=9) -// { -// bool data = index.model()->data(index, Qt::UserRole).toBool(); -// QCheckBox *checkBox = static_cast(editor); -// checkBox->setChecked(data); - -// } -// else -// QStyledItemDelegate::setEditorData(editor,index); - -//} - -//void X_CheckBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, -// const QModelIndex &index) const -//{ -// QCheckBox *checkBox = static_cast(editor); -// bool value = checkBox->isChecked(); -// model->setData(index, value, Qt::UserRole); -//} -// 绘制复选框 -void X_CheckBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const -{ - QStyleOptionViewItem viewOption(option); - initStyleOption(&viewOption, index); - if (option.state.testFlag(QStyle::State_HasFocus)) - viewOption.state = viewOption.state ^ QStyle::State_HasFocus; - - QStyledItemDelegate::paint(painter, viewOption, index); - - if (index.column()>=3&&index.column()<=9) - { - bool data = index.model()->data(index, Qt::UserRole).toBool(); - - QStyleOptionButton checkBoxStyle; - checkBoxStyle.state = data ? QStyle::State_On : QStyle::State_Off; - checkBoxStyle.state |= QStyle::State_Enabled; - checkBoxStyle.iconSize = QSize(20, 20); - checkBoxStyle.rect = option.rect; - - QCheckBox checkBox; - QApplication::style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &checkBoxStyle, painter, &checkBox); - } -} - -// 响应鼠标事件,更新数据 -bool X_CheckBoxDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) -{ - QRect decorationRect = option.rect; - - QMouseEvent *mouseEvent = static_cast(event); - if (event->type() == QEvent::MouseButtonPress && decorationRect.contains(mouseEvent->pos())) - { - if (index.column()>=3&&index.column()<=9) - { - bool data = model->data(index, Qt::UserRole).toBool(); - model->setData(index, !data, Qt::UserRole); - } - } - - return QStyledItemDelegate::editorEvent(event, model, option, index); -} -void X_CheckBoxDelegate::updateEditorGeometry(QWidget *editor, - const QStyleOptionViewItem &option, const QModelIndex &/* index */) const -{ - editor->setGeometry(option.rect); -} - +/* + delegate.cpp + + A delegate that allows the user to change integer values from the model + using a spin box widget. +*/ + +#include "x_checkboxdelegate.h" + +#include +#include +#include +X_CheckBoxDelegate::X_CheckBoxDelegate(QObject *parent) + : QStyledItemDelegate(parent) +{ + +} + +QWidget *X_CheckBoxDelegate::createEditor(QWidget *parent, + const QStyleOptionViewItem & option , + const QModelIndex & index ) const +{ +// if(index.column()>=3&&index.column()<=9) +// { +// QCheckBox *editor = new QCheckBox(parent); +// // editor->setFrame(false); + +// ///editor->setAlignment(Qt::AlignHCenter); +// // editor->setDisplayFormat("hh:mm"); + +// return editor; + +// } + + if(index.column()>=3&&index.column()<=9) + { + QCheckBox *editor=new QCheckBox(parent); + editor->installEventFilter(const_cast(this)); + return editor; + } + else + return QStyledItemDelegate::createEditor(parent,option,index); + + return nullptr; +} + +//void X_CheckBoxDelegate::setEditorData(QWidget *editor, +// const QModelIndex &index) const +//{ +// if(index.column()>=3&&index.column()<=9) +// { +// bool data = index.model()->data(index, Qt::UserRole).toBool(); +// QCheckBox *checkBox = static_cast(editor); +// checkBox->setChecked(data); + +// } +// else +// QStyledItemDelegate::setEditorData(editor,index); + +//} + +//void X_CheckBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, +// const QModelIndex &index) const +//{ +// QCheckBox *checkBox = static_cast(editor); +// bool value = checkBox->isChecked(); +// model->setData(index, value, Qt::UserRole); +//} +// 绘制复选框 +void X_CheckBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + QStyleOptionViewItem viewOption(option); + initStyleOption(&viewOption, index); + if (option.state.testFlag(QStyle::State_HasFocus)) + viewOption.state = viewOption.state ^ QStyle::State_HasFocus; + + QStyledItemDelegate::paint(painter, viewOption, index); + + if (index.column()>=3&&index.column()<=9) + { + bool data = index.model()->data(index, Qt::UserRole).toBool(); + + QStyleOptionButton checkBoxStyle; + checkBoxStyle.state = data ? QStyle::State_On : QStyle::State_Off; + checkBoxStyle.state |= QStyle::State_Enabled; + checkBoxStyle.iconSize = QSize(20, 20); + checkBoxStyle.rect = option.rect; + + QCheckBox checkBox; + QApplication::style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &checkBoxStyle, painter, &checkBox); + } +} + +// 响应鼠标事件,更新数据 +bool X_CheckBoxDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) +{ + QRect decorationRect = option.rect; + + QMouseEvent *mouseEvent = static_cast(event); + if (event->type() == QEvent::MouseButtonPress && decorationRect.contains(mouseEvent->pos())) + { + if (index.column()>=3&&index.column()<=9) + { + bool data = model->data(index, Qt::UserRole).toBool(); + model->setData(index, !data, Qt::UserRole); + } + } + + return QStyledItemDelegate::editorEvent(event, model, option, index); +} +void X_CheckBoxDelegate::updateEditorGeometry(QWidget *editor, + const QStyleOptionViewItem &option, const QModelIndex &/* index */) const +{ + editor->setGeometry(option.rect); +} + diff --git a/LedOK/base/x_checkboxdelegate.h b/LedOK/base/x_checkboxdelegate.h index 6f2297b..b227936 100644 --- a/LedOK/base/x_checkboxdelegate.h +++ b/LedOK/base/x_checkboxdelegate.h @@ -1,73 +1,73 @@ -#ifndef X_CHECKBOXDELEGATE_H -#define X_CHECKBOXDELEGATE_H -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * 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. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "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 COPYRIGHT -** OWNER OR CONTRIBUTORS 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." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include - -//! [0] -class X_CheckBoxDelegate : public QStyledItemDelegate -{ - Q_OBJECT - -public: - X_CheckBoxDelegate(QObject *parent = nullptr); - QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override; -// void setEditorData(QWidget *editor, const QModelIndex &index) const override; -// void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override; - void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override; - void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; - bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) override; - - -}; -//! [0] - -#endif // X_CHECKBOXDELEGATE_H +#ifndef X_CHECKBOXDELEGATE_H +#define X_CHECKBOXDELEGATE_H +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * 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. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "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 COPYRIGHT +** OWNER OR CONTRIBUTORS 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." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +//! [0] +class X_CheckBoxDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + X_CheckBoxDelegate(QObject *parent = nullptr); + QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override; +// void setEditorData(QWidget *editor, const QModelIndex &index) const override; +// void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override; + void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override; + void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; + bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) override; + + +}; +//! [0] + +#endif // X_CHECKBOXDELEGATE_H diff --git a/LedOK/base/x_spinboxdelegate.cpp b/LedOK/base/x_spinboxdelegate.cpp index 06f0383..c20f789 100644 --- a/LedOK/base/x_spinboxdelegate.cpp +++ b/LedOK/base/x_spinboxdelegate.cpp @@ -1,35 +1,35 @@ -#include "x_spinboxdelegate.h" -/* - A delegate that allows the user to change integer values from the model - using a spin box widget. -*/ -#include - -SpinBoxDelegate::SpinBoxDelegate(QObject *parent, int iFlag) : QStyledItemDelegate(parent) { - m_iFlag=iFlag; -} - -QWidget *SpinBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &index) const { - if(index.column()!=0) return 0; - QSpinBox *editor = new QSpinBox(parent); - editor->setFrame(false); - editor->setMinimum(0); - if(m_iFlag==0) editor->setMaximum(100);//亮度最大值 - else if(m_iFlag==1) editor->setMaximum(15);//音量最大值 - editor->setAlignment(Qt::AlignHCenter); - return editor; -} -void SpinBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const{ - int value = index.model()->data(index, Qt::EditRole).toInt(); - QSpinBox *spinBox = static_cast(editor); - spinBox->setValue(value); -} -void SpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const{ - QSpinBox *spinBox = static_cast(editor); - spinBox->interpretText(); - int value = spinBox->value(); - model->setData(index, value, Qt::EditRole); -} -void SpinBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &) const { - editor->setGeometry(option.rect); -} +#include "x_spinboxdelegate.h" +/* + A delegate that allows the user to change integer values from the model + using a spin box widget. +*/ +#include + +SpinBoxDelegate::SpinBoxDelegate(QObject *parent, int iFlag) : QStyledItemDelegate(parent) { + m_iFlag=iFlag; +} + +QWidget *SpinBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &index) const { + if(index.column()!=0) return 0; + QSpinBox *editor = new QSpinBox(parent); + editor->setFrame(false); + editor->setMinimum(0); + if(m_iFlag==0) editor->setMaximum(100);//亮度最大值 + else if(m_iFlag==1) editor->setMaximum(15);//音量最大值 + editor->setAlignment(Qt::AlignHCenter); + return editor; +} +void SpinBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const{ + int value = index.model()->data(index, Qt::EditRole).toInt(); + QSpinBox *spinBox = static_cast(editor); + spinBox->setValue(value); +} +void SpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const{ + QSpinBox *spinBox = static_cast(editor); + spinBox->interpretText(); + int value = spinBox->value(); + model->setData(index, value, Qt::EditRole); +} +void SpinBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &) const { + editor->setGeometry(option.rect); +} diff --git a/LedOK/base/x_spinboxdelegate.h b/LedOK/base/x_spinboxdelegate.h index 4561f88..90d67d4 100644 --- a/LedOK/base/x_spinboxdelegate.h +++ b/LedOK/base/x_spinboxdelegate.h @@ -1,67 +1,67 @@ -#ifndef X_SPINBOXDELEGATE_H -#define X_SPINBOXDELEGATE_H -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * 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. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "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 COPYRIGHT -** OWNER OR CONTRIBUTORS 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." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include -class SpinBoxDelegate : public QStyledItemDelegate { - Q_OBJECT -public: - SpinBoxDelegate(QObject *parent = 0,int iFlag=0); - - QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override; - void setEditorData(QWidget *editor, const QModelIndex &index) const override; - void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override; - void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override; -public: - int m_iFlag=0; -}; -#endif // X_SPINBOXDELEGATE_H +#ifndef X_SPINBOXDELEGATE_H +#define X_SPINBOXDELEGATE_H +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * 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. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "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 COPYRIGHT +** OWNER OR CONTRIBUTORS 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." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +class SpinBoxDelegate : public QStyledItemDelegate { + Q_OBJECT +public: + SpinBoxDelegate(QObject *parent = 0,int iFlag=0); + + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override; + void setEditorData(QWidget *editor, const QModelIndex &index) const override; + void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override; + void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override; +public: + int m_iFlag=0; +}; +#endif // X_SPINBOXDELEGATE_H diff --git a/LedOK/base/x_timeeditdelegate.cpp b/LedOK/base/x_timeeditdelegate.cpp index 4b9306b..7bc424d 100644 --- a/LedOK/base/x_timeeditdelegate.cpp +++ b/LedOK/base/x_timeeditdelegate.cpp @@ -1,62 +1,62 @@ -#include "X_timeEditDelegate.h" -/* - delegate.cpp - - A delegate that allows the user to change integer values from the model - using a spin box widget. -*/ - -#include "X_timeEditDelegate.h" - -#include - -X_timeEditDelegate::X_timeEditDelegate(QObject *parent) - : QStyledItemDelegate(parent) -{ -} - -QWidget *X_timeEditDelegate::createEditor(QWidget *parent, - const QStyleOptionViewItem &/* option */, - const QModelIndex & index ) const -{ - if(index.column()==1||index.column()==2) - { - QTimeEdit *editor = new QTimeEdit(parent); - editor->setFrame(false); - - editor->setAlignment(Qt::AlignHCenter); - editor->setDisplayFormat("hh:mm"); - - return editor; - - } - return nullptr; -} - -void X_timeEditDelegate::setEditorData(QWidget *editor, - const QModelIndex &index) const -{ - QString value = index.model()->data(index, Qt::EditRole).toString(); - - QTimeEdit *spinBoxTimeEdit = static_cast(editor); - QTime qtime=QTime::fromString(value,"hh:mm"); - spinBoxTimeEdit->setTime(qtime); - -} - -void X_timeEditDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, - const QModelIndex &index) const -{ - QTimeEdit *spinBoxTimeEdit = static_cast(editor); - spinBoxTimeEdit->interpretText(); - QString value = spinBoxTimeEdit->time().toString("hh:mm"); - - model->setData(index, value, Qt::EditRole); -} - -void X_timeEditDelegate::updateEditorGeometry(QWidget *editor, - const QStyleOptionViewItem &option, const QModelIndex &/* index */) const -{ - editor->setGeometry(option.rect); -} - +#include "X_timeEditDelegate.h" +/* + delegate.cpp + + A delegate that allows the user to change integer values from the model + using a spin box widget. +*/ + +#include "X_timeEditDelegate.h" + +#include + +X_timeEditDelegate::X_timeEditDelegate(QObject *parent) + : QStyledItemDelegate(parent) +{ +} + +QWidget *X_timeEditDelegate::createEditor(QWidget *parent, + const QStyleOptionViewItem &/* option */, + const QModelIndex & index ) const +{ + if(index.column()==1||index.column()==2) + { + QTimeEdit *editor = new QTimeEdit(parent); + editor->setFrame(false); + + editor->setAlignment(Qt::AlignHCenter); + editor->setDisplayFormat("hh:mm"); + + return editor; + + } + return nullptr; +} + +void X_timeEditDelegate::setEditorData(QWidget *editor, + const QModelIndex &index) const +{ + QString value = index.model()->data(index, Qt::EditRole).toString(); + + QTimeEdit *spinBoxTimeEdit = static_cast(editor); + QTime qtime=QTime::fromString(value,"hh:mm"); + spinBoxTimeEdit->setTime(qtime); + +} + +void X_timeEditDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, + const QModelIndex &index) const +{ + QTimeEdit *spinBoxTimeEdit = static_cast(editor); + spinBoxTimeEdit->interpretText(); + QString value = spinBoxTimeEdit->time().toString("hh:mm"); + + model->setData(index, value, Qt::EditRole); +} + +void X_timeEditDelegate::updateEditorGeometry(QWidget *editor, + const QStyleOptionViewItem &option, const QModelIndex &/* index */) const +{ + editor->setGeometry(option.rect); +} + diff --git a/LedOK/base/x_timeeditdelegate.h b/LedOK/base/x_timeeditdelegate.h index 5f98dc3..0595724 100644 --- a/LedOK/base/x_timeeditdelegate.h +++ b/LedOK/base/x_timeeditdelegate.h @@ -1,75 +1,75 @@ -#ifndef X_TIMEEDITDELEGATE_H -#define X_TIMEEDITDELEGATE_H -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * 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. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "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 COPYRIGHT -** OWNER OR CONTRIBUTORS 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." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include - -//! [0] -class X_timeEditDelegate : public QStyledItemDelegate -{ - Q_OBJECT - -public: - X_timeEditDelegate(QObject *parent = 0); - - QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, - const QModelIndex &index) const override; - - void setEditorData(QWidget *editor, const QModelIndex &index) const override; - void setModelData(QWidget *editor, QAbstractItemModel *model, - const QModelIndex &index) const override; - - void updateEditorGeometry(QWidget *editor, - const QStyleOptionViewItem &option, const QModelIndex &index) const override; -}; -//! [0] - -#endif // X_TIMEEDITDELEGATE_H +#ifndef X_TIMEEDITDELEGATE_H +#define X_TIMEEDITDELEGATE_H +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * 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. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "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 COPYRIGHT +** OWNER OR CONTRIBUTORS 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." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +//! [0] +class X_timeEditDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + X_timeEditDelegate(QObject *parent = 0); + + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, + const QModelIndex &index) const override; + + void setEditorData(QWidget *editor, const QModelIndex &index) const override; + void setModelData(QWidget *editor, QAbstractItemModel *model, + const QModelIndex &index) const override; + + void updateEditorGeometry(QWidget *editor, + const QStyleOptionViewItem &option, const QModelIndex &index) const override; +}; +//! [0] + +#endif // X_TIMEEDITDELEGATE_H diff --git a/LedOK/base/x_uimsgboxok.cpp b/LedOK/base/x_uimsgboxok.cpp index f6dc786..29a92b5 100644 --- a/LedOK/base/x_uimsgboxok.cpp +++ b/LedOK/base/x_uimsgboxok.cpp @@ -1,60 +1,60 @@ -#include "x_uimsgboxok.h" -#include "ui_x_uimsgboxok.h" -#include -#include - -X_UIMsgBoxOk::X_UIMsgBoxOk(QWidget *parent) : - BaseDlg(parent), - ui(new Ui::X_UIMsgBoxOk) -{ - setAttribute(Qt::WA_DeleteOnClose); - ui->setupUi(this); - m_bExitTypeFlag=0; -} - -X_UIMsgBoxOk::~X_UIMsgBoxOk() -{ - delete ui; -} -X_UIMsgBoxOk::X_UIMsgBoxOk(QString strTitle,QString text, QWidget *parent) : - BaseDlg(parent), - ui(new Ui::X_UIMsgBoxOk) -{ - setAttribute(Qt::WA_DeleteOnClose); - ui->setupUi(this); - ui->lInfoTip->adjustSize(); - ui->label_3->setText(strTitle); - //让QLabel能够自动判断并换行显示: -// ui->lInfoTip->setGeometry(QRect(328, 240, 329, 27*4)); //四倍行距 - ui->lInfoTip->setWordWrap(true); - ui->lInfoTip->setAlignment(Qt::AlignTop); - ui->lInfoTip->setText(text); - ui->pushButton_3->setVisible(false); - m_bExitTypeFlag=0; - ui->pushButton->setProperty("ssType", "progManageTool"); - ui->pushButton_2->setProperty("ssType", "progManageTool"); - ui->pushButton_3->setProperty("ssType", "progManageTool"); -} -X_UIMsgBoxOk::X_UIMsgBoxOk(QString strTitle,QString text, QWidget *parent,int iType) : - BaseDlg(parent), - ui(new Ui::X_UIMsgBoxOk) -{ - setAttribute(Qt::WA_DeleteOnClose); - ui->setupUi(this); - m_bExitTypeFlag=0; - ui->lInfoTip->adjustSize(); - ui->label_3->setText(strTitle); - //让QLabel能够自动判断并换行显示: -// ui->lInfoTip->setGeometry(QRect(328, 240, 329, 27*4)); //四倍行距 - ui->lInfoTip->setWordWrap(true); - ui->lInfoTip->setAlignment(Qt::AlignTop); - ui->lInfoTip->setText(text); - ui->pushButton_3->setVisible(false); - if(iType==1) { - ui->lInfoTip->setStyleSheet("background:rgba(206,206,206,1)"); - ui->frame->setStyleSheet("QFrame{background:rgba(206,206,206,1)}"); - setStyleSheet("X_UIMsgBoxOk{background:rgba(206,206,206,1)}"); - ui->pushButton->setProperty("ssType", "progManageTool"); - ui->pushButton_2->setProperty("ssType", "progManageTool"); - } -} +#include "x_uimsgboxok.h" +#include "ui_x_uimsgboxok.h" +#include +#include + +X_UIMsgBoxOk::X_UIMsgBoxOk(QWidget *parent) : + BaseDlg(parent), + ui(new Ui::X_UIMsgBoxOk) +{ + setAttribute(Qt::WA_DeleteOnClose); + ui->setupUi(this); + m_bExitTypeFlag=0; +} + +X_UIMsgBoxOk::~X_UIMsgBoxOk() +{ + delete ui; +} +X_UIMsgBoxOk::X_UIMsgBoxOk(QString strTitle,QString text, QWidget *parent) : + BaseDlg(parent), + ui(new Ui::X_UIMsgBoxOk) +{ + setAttribute(Qt::WA_DeleteOnClose); + ui->setupUi(this); + ui->lInfoTip->adjustSize(); + ui->label_3->setText(strTitle); + //让QLabel能够自动判断并换行显示: +// ui->lInfoTip->setGeometry(QRect(328, 240, 329, 27*4)); //四倍行距 + ui->lInfoTip->setWordWrap(true); + ui->lInfoTip->setAlignment(Qt::AlignTop); + ui->lInfoTip->setText(text); + ui->pushButton_3->setVisible(false); + m_bExitTypeFlag=0; + ui->pushButton->setProperty("ssType", "progManageTool"); + ui->pushButton_2->setProperty("ssType", "progManageTool"); + ui->pushButton_3->setProperty("ssType", "progManageTool"); +} +X_UIMsgBoxOk::X_UIMsgBoxOk(QString strTitle,QString text, QWidget *parent,int iType) : + BaseDlg(parent), + ui(new Ui::X_UIMsgBoxOk) +{ + setAttribute(Qt::WA_DeleteOnClose); + ui->setupUi(this); + m_bExitTypeFlag=0; + ui->lInfoTip->adjustSize(); + ui->label_3->setText(strTitle); + //让QLabel能够自动判断并换行显示: +// ui->lInfoTip->setGeometry(QRect(328, 240, 329, 27*4)); //四倍行距 + ui->lInfoTip->setWordWrap(true); + ui->lInfoTip->setAlignment(Qt::AlignTop); + ui->lInfoTip->setText(text); + ui->pushButton_3->setVisible(false); + if(iType==1) { + ui->lInfoTip->setStyleSheet("background:rgba(206,206,206,1)"); + ui->frame->setStyleSheet("QFrame{background:rgba(206,206,206,1)}"); + setStyleSheet("X_UIMsgBoxOk{background:rgba(206,206,206,1)}"); + ui->pushButton->setProperty("ssType", "progManageTool"); + ui->pushButton_2->setProperty("ssType", "progManageTool"); + } +} diff --git a/LedOK/base/x_uimsgboxok.h b/LedOK/base/x_uimsgboxok.h index a8a9697..da5cb6c 100644 --- a/LedOK/base/x_uimsgboxok.h +++ b/LedOK/base/x_uimsgboxok.h @@ -1,24 +1,24 @@ -#ifndef X_UIMSGBOXOK_H -#define X_UIMSGBOXOK_H - -#include -namespace Ui { -class X_UIMsgBoxOk; -} - -class X_UIMsgBoxOk : public BaseDlg -{ - Q_OBJECT - -public: - explicit X_UIMsgBoxOk(QWidget *parent = nullptr); - X_UIMsgBoxOk(QString strTitle, QString text, QWidget *parent = nullptr); - X_UIMsgBoxOk(QString strTitle, QString text, QWidget *parent = nullptr,int iType=0); - ~X_UIMsgBoxOk(); - int m_bExitTypeFlag=0; - -private: - Ui::X_UIMsgBoxOk *ui; -}; - -#endif // X_UIMSGBOXOK_H +#ifndef X_UIMSGBOXOK_H +#define X_UIMSGBOXOK_H + +#include +namespace Ui { +class X_UIMsgBoxOk; +} + +class X_UIMsgBoxOk : public BaseDlg +{ + Q_OBJECT + +public: + explicit X_UIMsgBoxOk(QWidget *parent = nullptr); + X_UIMsgBoxOk(QString strTitle, QString text, QWidget *parent = nullptr); + X_UIMsgBoxOk(QString strTitle, QString text, QWidget *parent = nullptr,int iType=0); + ~X_UIMsgBoxOk(); + int m_bExitTypeFlag=0; + +private: + Ui::X_UIMsgBoxOk *ui; +}; + +#endif // X_UIMSGBOXOK_H diff --git a/LedOK/base/x_uimsgboxok.ui b/LedOK/base/x_uimsgboxok.ui index 332fc76..109d6d4 100644 --- a/LedOK/base/x_uimsgboxok.ui +++ b/LedOK/base/x_uimsgboxok.ui @@ -1,243 +1,243 @@ - - - X_UIMsgBoxOk - - - - 0 - 0 - 426 - 200 - - - - - 0 - 0 - - - - - - - true - - - - 0 - 0 - - - - QFrame::Box - - - - - - - - - - - 0 - 0 - - - - QFrame::Sunken - - - 0 - - - TextLabel - - - Qt::AlignCenter - - - - - - - - 31 - 23 - - - - X - - - - - - - - - border-top: 2px solid gray; - - - 1 - - - 0 - - - Qt::Horizontal - - - - - - - - - - - - 0 - 0 - - - - - 32 - 32 - - - - image: url(:/res/tip.png); - - - QFrame::NoFrame - - - QFrame::Plain - - - 0 - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - 0 - 0 - - - - TextLabel - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - OK - - - - - - - Cancel - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - - - - - pushButton - clicked() - X_UIMsgBoxOk - accept() - - - 128 - 119 - - - 127 - 75 - - - - - pushButton_2 - clicked() - X_UIMsgBoxOk - close() - - - 220 - 31 - - - 127 - 75 - - - - - + + + X_UIMsgBoxOk + + + + 0 + 0 + 426 + 200 + + + + + 0 + 0 + + + + + + + true + + + + 0 + 0 + + + + QFrame::Box + + + + + + + + + + + 0 + 0 + + + + QFrame::Sunken + + + 0 + + + TextLabel + + + Qt::AlignCenter + + + + + + + + 31 + 23 + + + + X + + + + + + + + + border-top: 2px solid gray; + + + 1 + + + 0 + + + Qt::Horizontal + + + + + + + + + + + + 0 + 0 + + + + + 32 + 32 + + + + image: url(:/res/tip.png); + + + QFrame::NoFrame + + + QFrame::Plain + + + 0 + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + 0 + 0 + + + + TextLabel + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + OK + + + + + + + Cancel + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + + + pushButton + clicked() + X_UIMsgBoxOk + accept() + + + 128 + 119 + + + 127 + 75 + + + + + pushButton_2 + clicked() + X_UIMsgBoxOk + close() + + + 220 + 31 + + + 127 + 75 + + + + + diff --git a/LedOK/basedlg.cpp b/LedOK/basedlg.cpp index 2f3b661..74dc2ab 100644 --- a/LedOK/basedlg.cpp +++ b/LedOK/basedlg.cpp @@ -48,7 +48,7 @@ bool BaseDlg::nativeEvent(const QByteArray &eventType, void *message, long *){ MSG *msg = (MSG*)message; if(msg->message==WM_NCACTIVATE){ isActive = msg->wParam; - repaint(); + update(); } } return false; diff --git a/LedOK/basewin.cpp b/LedOK/basewin.cpp index 8844959..b64c42e 100644 --- a/LedOK/basewin.cpp +++ b/LedOK/basewin.cpp @@ -122,7 +122,7 @@ bool BaseWin::nativeEvent(const QByteArray &eventType, void *message, long *){ MSG *msg = (MSG*)message; if(msg->message==WM_NCACTIVATE){ isActive = msg->wParam; - repaint(); + update(); } } return false; diff --git a/LedOK/communication/hpptclient.cpp b/LedOK/communication/hpptclient.cpp index beb2586..5c9b787 100644 --- a/LedOK/communication/hpptclient.cpp +++ b/LedOK/communication/hpptclient.cpp @@ -1,193 +1,193 @@ -#include "hpptclient.h" - -//HpptClient* HpptClient::gInstance = nullptr; -HpptClient::HpptClient(QObject *p): QObject(p) { - connect(&mNetAccessManager, &QNetworkAccessManager::finished, this, [this](QNetworkReply *reply) { - if(reply->property("data").isValid()) onHttpPostRspFinished(reply); - else onHttpGetRspFinished(reply); - }); -} -void HpptClient::clearRp(QNetworkReply *rp) { - if(rp) - { - QString url = rp->request().url().toString(); - QString postMD5 = rp->property("postMD5").toString(); - QString postData = rp->property("data").toByteArray(); - - if(postMD5.isEmpty()) - { - //清理对应缓存 - mDownloadDataCache.remove(url); - - //解除正在处理状态 - mProcessingRq.remove(url); - } - else - { - //清理对应缓存 - mDownloadDataCache.remove(postMD5); - - - //解除正在处理状态 - mProcessingRq.remove(postMD5); - } - - mRedirectMap.remove(url); - mRedirectMap.remove(postMD5); - - //qDebug() << "delete cache, url:" << url << " postMOD5:" << postMD5; - rp->deleteLater(); - } -} - -void HpptClient::onHttpGetRspProgress(qint64 bytesReceived, qint64 bytesTotal) -{ - Q_UNUSED(bytesReceived) - if(sender() == NULL) - { - return ; - } - - QNetworkReply* rp = qobject_cast(sender()); - if(rp == NULL) - { - return; - } - - //qDebug() << "http get rsp progress:" << rp->url().toString() << bytesReceived << "/" << bytesTotal; - if(bytesTotal <= 0) - { - return; - } - - QString url = rp->url().toString(); - - mDownloadDataCache[url].append(rp->readAll()); - -} - -void HpptClient::onHttpGetRspFinished(QNetworkReply *reply) { - QByteArray rpData; - QString url = reply->url().toString(); - int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - QString strUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toString(); - - switch(statusCode) { - case 200: { - rpData = mDownloadDataCache[reply->url().toString()]; - QString redirectUrl = mRedirectMap[url];//重定向的url地址 - if(redirectUrl.isEmpty()) emit httpGetRspReady(url, rpData); - else emit httpGetRspReady(redirectUrl, rpData); - } - break; - case 301: - case 302: { - if(!strUrl.isEmpty()) { - QString turl = mRedirectMap[url]; - if(turl.isEmpty()) mRedirectMap[strUrl] = url; - else mRedirectMap[strUrl] = turl; - httpGet(strUrl); - } - } - break; - default: // error - { - qDebug() << url << "[get error:" << statusCode << "]"; - QString redirectUrl = mRedirectMap[url]; - if(redirectUrl.isEmpty()) emit httpGetRspReady(url, QByteArray()); - else emit httpGetRspReady(redirectUrl, QByteArray()); - } - break; - } - clearRp(reply); -} - -void HpptClient::onHttpPostRspProgress(qint64, qint64 bytesTotal){ - if(sender() == NULL) return; - QNetworkReply* rp = qobject_cast(sender()); - if(rp == NULL) return; - if(bytesTotal <= 0) return; - mDownloadDataCache[rp->property("postMD5").toString()].append(rp->readAll()); -} - -void HpptClient::onHttpPostRspFinished(QNetworkReply *reply) { - QString url = reply->url().toString(); - QString postMD5 = reply->property("postMD5").toString(); - - int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - switch(statusCode) { - case 200: { - auto rpData = mDownloadDataCache[postMD5]; - QString redirectMD5 = mRedirectMap[postMD5]; - QString redirectUrl = mRedirectMap[url]; - if(redirectMD5.isEmpty() || redirectUrl.isEmpty()) emit httpPostRspReady(url, postMD5, rpData); - else emit httpPostRspReady(redirectUrl, redirectMD5, rpData); - } - break; - case 301: - case 302: { - auto redireUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toString(); - if(!redireUrl.isEmpty()) { - QString turl = mRedirectMap[url];//direct by - if(turl.isEmpty()) mRedirectMap[redireUrl] = url; - else mRedirectMap[redireUrl] = turl; - - QByteArray postData = reply->property("data").toByteArray(); - QByteArray d = redireUrl.toUtf8() + postData; - QString md5 = QCryptographicHash::hash(d, QCryptographicHash::Md5); - QString tPostMD5 = mRedirectMap[md5];//direct by - if(tPostMD5.isEmpty()) mRedirectMap[md5] = postMD5; - else mRedirectMap[md5] = tPostMD5; - httpPost(redireUrl, postData); - } - } - break; - default: - QString redirectMD5 = mRedirectMap[postMD5]; - QString redirectUrl = mRedirectMap[url]; - if(redirectMD5.isEmpty() || redirectUrl.isEmpty()) - { - emit httpPostRspReady(url, postMD5, QByteArray()); - } - else - { - emit httpPostRspReady(redirectUrl, redirectMD5, QByteArray()); - } - break; - } - clearRp(reply); -} - - -void HpptClient::httpGet(const QString &url) { - if(mProcessingRq.value(url, false)) return;//ignore when rq processing - auto values = mRedirectMap.values(); - for(int i = 0; i < values.count(); i++) if(values[i] == url) return;//ignore when redirect processing - mProcessingRq.insert(url, true); - - QNetworkRequest request{url}; - QSslConfiguration config = request.sslConfiguration(); - config.setPeerVerifyMode(QSslSocket::VerifyNone); - config.setProtocol(QSsl::TlsV1SslV3); - request.setSslConfiguration(config); - - QNetworkReply* rp = mNetAccessManager.get(request); - connect(rp, &QNetworkReply::downloadProgress, this, &HpptClient::onHttpGetRspProgress); -} - -QByteArray HpptClient::httpPost(const QString &url, const QByteArray &data) { - QByteArray md5 = QCryptographicHash::hash(url.toUtf8() + data, QCryptographicHash::Md5); - if(mProcessingRq.value(md5, false)) return md5;//ignore when rq processing - auto values = mRedirectMap.values(); - for(int i=0; i < values.count(); i++) if(values[i] == md5) return md5; //ignore when redirect processing - mProcessingRq.insert(md5, true); - - QNetworkRequest request{url}; - request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");//add by alahover 20200304 - QNetworkReply* reply = mNetAccessManager.post(request, data); - reply->setProperty("postMD5", md5); - reply->setProperty("url", url); - reply->setProperty("data", data); - connect(reply, &QNetworkReply::downloadProgress, this, &HpptClient::onHttpPostRspProgress); - return md5; -} +#include "hpptclient.h" + +//HpptClient* HpptClient::gInstance = nullptr; +HpptClient::HpptClient(QObject *p): QObject(p) { + connect(&mNetAccessManager, &QNetworkAccessManager::finished, this, [this](QNetworkReply *reply) { + if(reply->property("data").isValid()) onHttpPostRspFinished(reply); + else onHttpGetRspFinished(reply); + }); +} +void HpptClient::clearRp(QNetworkReply *rp) { + if(rp) + { + QString url = rp->request().url().toString(); + QString postMD5 = rp->property("postMD5").toString(); + QString postData = rp->property("data").toByteArray(); + + if(postMD5.isEmpty()) + { + //清理对应缓存 + mDownloadDataCache.remove(url); + + //解除正在处理状态 + mProcessingRq.remove(url); + } + else + { + //清理对应缓存 + mDownloadDataCache.remove(postMD5); + + + //解除正在处理状态 + mProcessingRq.remove(postMD5); + } + + mRedirectMap.remove(url); + mRedirectMap.remove(postMD5); + + //qDebug() << "delete cache, url:" << url << " postMOD5:" << postMD5; + rp->deleteLater(); + } +} + +void HpptClient::onHttpGetRspProgress(qint64 bytesReceived, qint64 bytesTotal) +{ + Q_UNUSED(bytesReceived) + if(sender() == NULL) + { + return ; + } + + QNetworkReply* rp = qobject_cast(sender()); + if(rp == NULL) + { + return; + } + + //qDebug() << "http get rsp progress:" << rp->url().toString() << bytesReceived << "/" << bytesTotal; + if(bytesTotal <= 0) + { + return; + } + + QString url = rp->url().toString(); + + mDownloadDataCache[url].append(rp->readAll()); + +} + +void HpptClient::onHttpGetRspFinished(QNetworkReply *reply) { + QByteArray rpData; + QString url = reply->url().toString(); + int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + QString strUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toString(); + + switch(statusCode) { + case 200: { + rpData = mDownloadDataCache[reply->url().toString()]; + QString redirectUrl = mRedirectMap[url];//重定向的url地址 + if(redirectUrl.isEmpty()) emit httpGetRspReady(url, rpData); + else emit httpGetRspReady(redirectUrl, rpData); + } + break; + case 301: + case 302: { + if(!strUrl.isEmpty()) { + QString turl = mRedirectMap[url]; + if(turl.isEmpty()) mRedirectMap[strUrl] = url; + else mRedirectMap[strUrl] = turl; + httpGet(strUrl); + } + } + break; + default: // error + { + qDebug() << url << "[get error:" << statusCode << "]"; + QString redirectUrl = mRedirectMap[url]; + if(redirectUrl.isEmpty()) emit httpGetRspReady(url, QByteArray()); + else emit httpGetRspReady(redirectUrl, QByteArray()); + } + break; + } + clearRp(reply); +} + +void HpptClient::onHttpPostRspProgress(qint64, qint64 bytesTotal){ + if(sender() == NULL) return; + QNetworkReply* rp = qobject_cast(sender()); + if(rp == NULL) return; + if(bytesTotal <= 0) return; + mDownloadDataCache[rp->property("postMD5").toString()].append(rp->readAll()); +} + +void HpptClient::onHttpPostRspFinished(QNetworkReply *reply) { + QString url = reply->url().toString(); + QString postMD5 = reply->property("postMD5").toString(); + + int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + switch(statusCode) { + case 200: { + auto rpData = mDownloadDataCache[postMD5]; + QString redirectMD5 = mRedirectMap[postMD5]; + QString redirectUrl = mRedirectMap[url]; + if(redirectMD5.isEmpty() || redirectUrl.isEmpty()) emit httpPostRspReady(url, postMD5, rpData); + else emit httpPostRspReady(redirectUrl, redirectMD5, rpData); + } + break; + case 301: + case 302: { + auto redireUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toString(); + if(!redireUrl.isEmpty()) { + QString turl = mRedirectMap[url];//direct by + if(turl.isEmpty()) mRedirectMap[redireUrl] = url; + else mRedirectMap[redireUrl] = turl; + + QByteArray postData = reply->property("data").toByteArray(); + QByteArray d = redireUrl.toUtf8() + postData; + QString md5 = QCryptographicHash::hash(d, QCryptographicHash::Md5); + QString tPostMD5 = mRedirectMap[md5];//direct by + if(tPostMD5.isEmpty()) mRedirectMap[md5] = postMD5; + else mRedirectMap[md5] = tPostMD5; + httpPost(redireUrl, postData); + } + } + break; + default: + QString redirectMD5 = mRedirectMap[postMD5]; + QString redirectUrl = mRedirectMap[url]; + if(redirectMD5.isEmpty() || redirectUrl.isEmpty()) + { + emit httpPostRspReady(url, postMD5, QByteArray()); + } + else + { + emit httpPostRspReady(redirectUrl, redirectMD5, QByteArray()); + } + break; + } + clearRp(reply); +} + + +void HpptClient::httpGet(const QString &url) { + if(mProcessingRq.value(url, false)) return;//ignore when rq processing + auto values = mRedirectMap.values(); + for(int i = 0; i < values.count(); i++) if(values[i] == url) return;//ignore when redirect processing + mProcessingRq.insert(url, true); + + QNetworkRequest request{url}; + QSslConfiguration config = request.sslConfiguration(); + config.setPeerVerifyMode(QSslSocket::VerifyNone); + config.setProtocol(QSsl::TlsV1SslV3); + request.setSslConfiguration(config); + + QNetworkReply* rp = mNetAccessManager.get(request); + connect(rp, &QNetworkReply::downloadProgress, this, &HpptClient::onHttpGetRspProgress); +} + +QByteArray HpptClient::httpPost(const QString &url, const QByteArray &data) { + QByteArray md5 = QCryptographicHash::hash(url.toUtf8() + data, QCryptographicHash::Md5); + if(mProcessingRq.value(md5, false)) return md5;//ignore when rq processing + auto values = mRedirectMap.values(); + for(int i=0; i < values.count(); i++) if(values[i] == md5) return md5; //ignore when redirect processing + mProcessingRq.insert(md5, true); + + QNetworkRequest request{url}; + request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");//add by alahover 20200304 + QNetworkReply* reply = mNetAccessManager.post(request, data); + reply->setProperty("postMD5", md5); + reply->setProperty("url", url); + reply->setProperty("data", data); + connect(reply, &QNetworkReply::downloadProgress, this, &HpptClient::onHttpPostRspProgress); + return md5; +} diff --git a/LedOK/communication/hpptclient.h b/LedOK/communication/hpptclient.h index 351c2c0..6fdd2d7 100644 --- a/LedOK/communication/hpptclient.h +++ b/LedOK/communication/hpptclient.h @@ -1,46 +1,46 @@ -#ifndef HPPTCLIENT_H -#define HPPTCLIENT_H - -#include -#include -#include -#include -class HpptClient : public QObject { - Q_OBJECT -public: - HpptClient(QObject *p = nullptr); - - void httpGet(const QString& url); - /// \return 返回url+data的md5 - QByteArray httpPost(const QString& url, const QByteArray &data); - -signals: - /// \brief httpGetRspReady http get 请求得到回复 - /// \param url 请求的地址 - /// \param data 回复的数据(如果isEmpty则表示请求出错了) - void httpGetRspReady(QString url, QByteArray data); - - /// \brief httpPostRspReady http post 请求得到回复 - /// \param url 请求的地址 - /// \param postMD5 是post的时候url+数据的md5 - /// \param data data是回复的数据(如果isEmpty则表示请求出错了) - void httpPostRspReady(QString url, QString postMD5, QByteArray data); - -private slots: - void clearRp(QNetworkReply* rp); - - void onHttpGetRspProgress(qint64 bytesReceived, qint64 bytesTotal); //* http get 回复进度 - void onHttpGetRspFinished(QNetworkReply *reply); //* http get 处理完毕 - - void onHttpPostRspProgress(qint64 bytesReceived, qint64 bytesTotal); //* http post 回复进度 - void onHttpPostRspFinished(QNetworkReply *reply); //* http get 处理完毕 - -private: - QNetworkAccessManager mNetAccessManager; - QString mCacheRoot; //* 缓存目录 - QMap mProcessingRq; //* 当前正在处理的请求url 和是否正在处理 - QMap mDownloadDataCache; //* 数据缓存url -> data | postMD5 -> data - QMap mRedirectMap; //* 重定向关系 -}; - -#endif // HPPTCLIENT_H +#ifndef HPPTCLIENT_H +#define HPPTCLIENT_H + +#include +#include +#include +#include +class HpptClient : public QObject { + Q_OBJECT +public: + HpptClient(QObject *p = nullptr); + + void httpGet(const QString& url); + /// \return 返回url+data的md5 + QByteArray httpPost(const QString& url, const QByteArray &data); + +signals: + /// \brief httpGetRspReady http get 请求得到回复 + /// \param url 请求的地址 + /// \param data 回复的数据(如果isEmpty则表示请求出错了) + void httpGetRspReady(QString url, QByteArray data); + + /// \brief httpPostRspReady http post 请求得到回复 + /// \param url 请求的地址 + /// \param postMD5 是post的时候url+数据的md5 + /// \param data data是回复的数据(如果isEmpty则表示请求出错了) + void httpPostRspReady(QString url, QString postMD5, QByteArray data); + +private slots: + void clearRp(QNetworkReply* rp); + + void onHttpGetRspProgress(qint64 bytesReceived, qint64 bytesTotal); //* http get 回复进度 + void onHttpGetRspFinished(QNetworkReply *reply); //* http get 处理完毕 + + void onHttpPostRspProgress(qint64 bytesReceived, qint64 bytesTotal); //* http post 回复进度 + void onHttpPostRspFinished(QNetworkReply *reply); //* http get 处理完毕 + +private: + QNetworkAccessManager mNetAccessManager; + QString mCacheRoot; //* 缓存目录 + QMap mProcessingRq; //* 当前正在处理的请求url 和是否正在处理 + QMap mDownloadDataCache; //* 数据缓存url -> data | postMD5 -> data + QMap mRedirectMap; //* 重定向关系 +}; + +#endif // HPPTCLIENT_H diff --git a/LedOK/communication/taserialthread.cpp b/LedOK/communication/taserialthread.cpp index 6030b5a..c846678 100644 --- a/LedOK/communication/taserialthread.cpp +++ b/LedOK/communication/taserialthread.cpp @@ -1,130 +1,130 @@ -#include "taserialthread.h" -#include -TA_SerialThread::TA_SerialThread() -{ - portCnt = 0; - portNewCnt=0; - m_arrSerial = new QSerialPort[10]; - m_arrNewSerial=new QSerialPortInfo[10]; -} - -TA_SerialThread::~TA_SerialThread() -{ - -} - -void TA_SerialThread::run() -{ - -} - -void TA_SerialThread::SearchPort(void) { - portNewCnt=0; - //查找可用的串口 - foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) { - if(portNewCnt > 9) break; - m_arrNewSerial[portNewCnt]=info; - portNewCnt++; - } - - for (int i=0;i +TA_SerialThread::TA_SerialThread() +{ + portCnt = 0; + portNewCnt=0; + m_arrSerial = new QSerialPort[10]; + m_arrNewSerial=new QSerialPortInfo[10]; +} + +TA_SerialThread::~TA_SerialThread() +{ + +} + +void TA_SerialThread::run() +{ + +} + +void TA_SerialThread::SearchPort(void) { + portNewCnt=0; + //查找可用的串口 + foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) { + if(portNewCnt > 9) break; + m_arrNewSerial[portNewCnt]=info; + portNewCnt++; + } + + for (int i=0;i -#include -#include -#include - -class TA_SerialThread:public QThread -{ -public: - TA_SerialThread(); - ~TA_SerialThread(); - -public: - uint8_t portCnt; - uint8_t portNewCnt; - QSerialPort *m_arrSerial;//ptr point to an array,maxium port num is 5 - QSerialPortInfo *m_arrNewSerial;//ptr point to an array,maxium port num is 5 - -public: - void SearchPort(void); - void InitPortName(uint8_t portIndex,const QString &portName); - void InitPortBaudRate(uint8_t portIndex,qint32 baudRate); - void InitPortDataBits(uint8_t portIndex,QSerialPort::DataBits dataBits); - void InitPortParity(uint8_t portIndex,QSerialPort::Parity parity); - void InitPortStopBits(uint8_t portIndex,QSerialPort::StopBits stopBits); - bool OpenPort(uint8_t portIndex); - void ClosePort(uint8_t portIndex); - void SendDataBuf(uint8_t portIndex,const QByteArray &str); - QByteArray GetDataBuf(uint8_t portIndex); - -private slots: - void run(); -}; -#endif // TASERIALTHREAD_H +#ifndef TASERIALTHREAD_H +#define TASERIALTHREAD_H + +#include +#include +#include +#include + +class TA_SerialThread:public QThread +{ +public: + TA_SerialThread(); + ~TA_SerialThread(); + +public: + uint8_t portCnt; + uint8_t portNewCnt; + QSerialPort *m_arrSerial;//ptr point to an array,maxium port num is 5 + QSerialPortInfo *m_arrNewSerial;//ptr point to an array,maxium port num is 5 + +public: + void SearchPort(void); + void InitPortName(uint8_t portIndex,const QString &portName); + void InitPortBaudRate(uint8_t portIndex,qint32 baudRate); + void InitPortDataBits(uint8_t portIndex,QSerialPort::DataBits dataBits); + void InitPortParity(uint8_t portIndex,QSerialPort::Parity parity); + void InitPortStopBits(uint8_t portIndex,QSerialPort::StopBits stopBits); + bool OpenPort(uint8_t portIndex); + void ClosePort(uint8_t portIndex); + void SendDataBuf(uint8_t portIndex,const QByteArray &str); + QByteArray GetDataBuf(uint8_t portIndex); + +private slots: + void run(); +}; +#endif // TASERIALTHREAD_H diff --git a/LedOK/css.css b/LedOK/css.css new file mode 100644 index 0000000..78a4844 --- /dev/null +++ b/LedOK/css.css @@ -0,0 +1,176 @@ +QLineEdit,QComboBox,QAbstractSpinBox { + border: 1px solid #aaa; + border-radius: 3px; + padding: 2px; +} + +QGroupBox { + border: 1px solid #aaa; + border-radius: 3px; + margin-top: 0.5em; + padding-top: 0.4em; +} +QGroupBox::title { + subcontrol-origin: margin; + left: 0.5em; +} + +QComboBox::drop-down, +QAbstractSpinBox::up-button, +QAbstractSpinBox::down-button { + border: 0; +} +QComboBox::down-arrow, +QAbstractSpinBox::down-arrow { + image: url(:/res/ArrowDropDown.png); +} +QComboBox::down-arrow:on, +QAbstractSpinBox::up-arrow { + image: url(:/res/ArrowDropUp.png); +} + +QAbstractSpinBox::up-arrow:pressed { + top: -1px; +} +QAbstractSpinBox::down-arrow:pressed { + top: 1px; +} + +QCheckBox::indicator, QTreeWidget::indicator { + border-image: url(:/res/CheckBoxUnchecked.png); width: 1em; height: 1em; margin-left: 0.25em; +} +QCheckBox::indicator:checked, QTreeWidget::indicator:checked { + border-image: url(:/res/CheckBoxChecked.png); +} +QCheckBox::indicator:disabled { + background-color: #666; +} + +ExtendedGroupBox::indicator { + border-image: url(:/res/groupbox-unchecked.png); +} +ExtendedGroupBox::indicator:checked { + border-image: url(:/res/groupbox-checked.png); +} + +QScrollArea { + border : 0; +} +QScrollBar:vertical { + width: 12px; +} +QScrollBar:horizontal { + height: 12px; +} + +QMenu { + background-color: #eee; + border: 2px solid #ccc; +} +QMenu::item { + background-color: transparent; +} +QMenu::item:selected { + background-color: #8CD; +} + +QListWidget { + selection-background-color: #8ce; +} + +LoColorSelector { + border: 1px solid #aaa; + border-radius: 4px; + background-color: transparent; + padding: 3px 6px; + max-height: 30px; +} + +QTreeWidget[ssType="topList"]::item { + border-right: 1px solid #ddd; + border-bottom: 1px solid #ddd; + height: 40px; +} +QTreeWidget[ssType="topList"] QHeaderView::section { + border-top: 1px solid #aaa; + border-bottom: 1px solid #aaa; + border-left: 0; + border-right: 0; + height: 36px; +} +QTreeWidget[ssType="topList"]::item:hover { + background-color: #ddd; +} + + + +QPushButton[ssType="progManageTool"] { + border-radius: 4px; + background-color: #19c; + color: #000; + padding: 3px 6px; +} +QPushButton[ssType="progManageTool"]:hover { + background-color: #08b; + color: #fff; +} +QPushButton[ssType="progManageTool"]:pressed { + background-color: #07a; +} +QPushButton[ssType="progManageTool"]:disabled { + background-color: #bbb; + color: #777; +} + + +LoQTitleBar QPushButton { + border-radius: 4px; + icon-size: 20px; + width: 32px; + height: 28px; +} +LoQTitleBar QPushButton:press, +LoQTitleBar QPushButton:hover { + background-color: #C1C1C1; +} +LoQTitleBar QPushButton::menu-indicator { + image: none; +} + + +QToolButton[ss="MainTab"], +QToolButton[ss="CtrlTab"] { + border: none; +} +QToolButton[ss="MainTab"]:checked, +QToolButton[ss="MainTab"]:hover { + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ddd, stop: 1.0 #8cd); + font-size: 15px; + color: #04d; +} +QToolButton[ss="CtrlTab"]:checked, +QToolButton[ss="CtrlTab"]:hover { + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #eee, stop: 1.0 #ade); + font-size: 15px; + color: #04d; +} + + +QPushButton#bnSelectFile { + border-radius: 4px; + background-color: #19c; + border: 1px solid #888; + padding: 3px 6px; +} +QPushButton#bnSelectFile:pressed { + background: transparent; +} + +QPushButton[style="multiTool"] { + border-radius: 4px; + padding: 3px 6px; +} +QPushButton[style="multiTool"]:hover { + background-color: rgba(226,226,226,1); +} + diff --git a/LedOK/wDevicesManager/controlpowerschedule.cpp b/LedOK/device/controlpowerschedule.cpp similarity index 97% rename from LedOK/wDevicesManager/controlpowerschedule.cpp rename to LedOK/device/controlpowerschedule.cpp index 17947f2..1405429 100644 --- a/LedOK/wDevicesManager/controlpowerschedule.cpp +++ b/LedOK/device/controlpowerschedule.cpp @@ -1,557 +1,555 @@ -#include "controlpowerschedule.h" -#include "ui_controlpowerschedule.h" - -#include -#include -#include -#include -#include -#include -#include -#include "cfg.h" -#include "QSettings" -#include "base/x_spinboxdelegate.h" -#include "base/x_timeeditdelegate.h" -#include "base/x_checkboxdelegate.h" -#include "tools.h" - -ControlPowerSchedule::ControlPowerSchedule(QWidget *parent,QList *list) : - QWidget(parent), - ui(new Ui::ControlPowerSchedule) -{ - m_pLedlist=list; - ui->setupUi(this); - ui->labelPowerScheduleTip->setVisible(false); - refreshLable(); -setStyleSheet(Tools::styleSheet()); - ui->pushButtonAdd->setProperty("ssType", "progManageTool"); - ui->pushButtonAdd->setFlat(true); - ui->pushButtonDelete->setProperty("ssType", "progManageTool"); - ui->pushButtonDelete->setFlat(true); - ui->pushButtonClear->setProperty("ssType", "progManageTool"); - ui->pushButtonClear->setFlat(true); - ui->pushButtonApply->setProperty("ssType", "progManageTool"); - ui->pushButtonApply->setFlat(true); - ui->pushButtonImport->setProperty("ssType", "progManageTool"); - ui->pushButtonExport->setProperty("ssType", "progManageTool"); - ui->pushButtonReadback->setProperty("ssType", "progManageTool"); - ui->pushButtonClearSchedule->setProperty("ssType", "progManageTool"); - - m_pModel = new QStandardItemModel(this); - m_pModel->setColumnCount(10); - m_pModel->setHeaderData(0,Qt::Horizontal, tr("Power On State")); - m_pModel->setHeaderData(1,Qt::Horizontal, tr("Start Time")); - m_pModel->setHeaderData(2,Qt::Horizontal, tr("End Time")); - m_pModel->setHeaderData(3,Qt::Horizontal, tr("SUN")); - m_pModel->setHeaderData(4,Qt::Horizontal, tr("MON")); - m_pModel->setHeaderData(5,Qt::Horizontal, tr("TUE")); - m_pModel->setHeaderData(6,Qt::Horizontal, tr("WED")); - m_pModel->setHeaderData(7,Qt::Horizontal, tr("THU")); - m_pModel->setHeaderData(8,Qt::Horizontal, tr("FRI")); - m_pModel->setHeaderData(9,Qt::Horizontal, tr("SAT")); - ui->tableView->setModel(m_pModel); - - X_timeEditDelegate *pStartTimeDelegate=new X_timeEditDelegate(this); - ui->tableView->setItemDelegateForColumn(1,pStartTimeDelegate); - ui->tableView->setItemDelegateForColumn(2,pStartTimeDelegate); - X_CheckBoxDelegate *WeekDelegate=new X_CheckBoxDelegate(this); - ui->tableView->setItemDelegateForColumn(3,WeekDelegate); - ui->tableView->setItemDelegateForColumn(4,WeekDelegate); - ui->tableView->setItemDelegateForColumn(5,WeekDelegate); - ui->tableView->setItemDelegateForColumn(6,WeekDelegate); - ui->tableView->setItemDelegateForColumn(7,WeekDelegate); - ui->tableView->setItemDelegateForColumn(8,WeekDelegate); - ui->tableView->setItemDelegateForColumn(9,WeekDelegate); - - - ReadOnlyDelegate* readOnlyDelegate = new ReadOnlyDelegate(); - ui->tableView->setItemDelegateForColumn(0, readOnlyDelegate); //设置某列只读 - - ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); - // ui->tableView->verticalHeader()->hide(); - ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows); - ui->tableView->setFocusPolicy(Qt::NoFocus); - - - MARCO_DEFINE_CONTROL_FUNC2(parent->parent()->parent(),parent->parent()) - - connect(ui->pushButtonAdd,SIGNAL(clicked()),this,SLOT(OnClickAdd())); - connect(ui->pushButtonImport,SIGNAL(clicked()),this,SLOT(OnClickImport())); - connect(ui->pushButtonExport,SIGNAL(clicked()),this,SLOT(OnClickExport())); - connect(ui->pushButtonDelete,SIGNAL(clicked()),this,SLOT(OnClickDelete())); - connect(ui->pushButtonClear,SIGNAL(clicked()),this,SLOT(OnClickClear())); - connect(ui->pushButtonApply,SIGNAL(clicked()),this,SLOT(OnClickApply())); - connect(ui->pushButtonReadback,SIGNAL(clicked()),this,SLOT(OnClickReadback())); - connect(ui->pushButtonClearSchedule,SIGNAL(clicked()),this,SLOT(OnClickClearSchedule())); - - -} - -ControlPowerSchedule::~ControlPowerSchedule() -{ - delete ui; - if(pHpptClient != nullptr) - { - qDebug() <<"delete pHpptClient in ~NetComm"; - delete pHpptClient; - pHpptClient=nullptr; - } - if(pHpptClientAll != nullptr) - { - qDebug() <<"delete pHpptClientAll in ~NetComm"; - delete pHpptClientAll; - pHpptClientAll=nullptr; - } -} -void ControlPowerSchedule::refreshLable() -{ - ui->pushButtonAdd->setText(tr("Add")); - ui->pushButtonApply->setText(tr("Apply")); - ui->pushButtonClear->setText(tr("Clear")); - ui->pushButtonDelete->setText(tr("Delete")); - ui->pushButtonImport->setText(tr("Import")); - ui->pushButtonExport->setText(tr("Export")); -} - -void ControlPowerSchedule::onSelectedDeviceList(QList *list) -{ - m_pLedlist=list; - if(m_pLedlist==nullptr) - return; - if(m_pLedlist->count()==1) - { - ui->pushButtonReadback->setEnabled(true); - } - else { - ui->pushButtonReadback->setEnabled(false); - } - MACRO_DEFINE_CONTROL_FUNC3 - -} -//获取到httpPost的应答,如果参数变化需要出发修改控件item的内容 -void ControlPowerSchedule::OnProHttpResponse(QString url, QString postMD5, QByteArray data) -{ - Q_UNUSED(postMD5) - //qDebug()<< url + "\r\n"+m_strUrl; - if(url == m_strUrl) - { - QJsonParseError parseJsonErr; - QJsonDocument document = QJsonDocument::fromJson(data,&parseJsonErr); - if(!(parseJsonErr.error == QJsonParseError::NoError)) - { - if(data.size()==0) - qDebug()<<"json is empty"; - else - qDebug()<m_strCardId +"---------"+ strType; - if(strType == "GetTimingScreenTask") - { - JieXiJsonTaskPower(jsonObject["screenTask"].toObject()); - } - else if(strType == "SetTimingScreenTask") - { - } - - MACRO_ASKTIME_STOP - MACRO_POSTING_DLG_UNLOCK - - } - } -} -//获取到httpPost的应答,如果参数变化需要出发修改控件item的内容 -void ControlPowerSchedule::OnProHttpResponseAll(QString url, QString postMD5, QByteArray data) -{ - Q_UNUSED(postMD5) - //qDebug()<< url + "\r\n"+m_strUrl; - if(url == m_strUrl) - { - QJsonParseError parseJsonErr; - QJsonDocument document = QJsonDocument::fromJson(data,&parseJsonErr); - if(!(parseJsonErr.error == QJsonParseError::NoError)) - { - if(data.size()==0) - qDebug()<<"json is empty"; - else - qDebug()<m_strCardId +"---------"+ strType; - if(strType == "GetTimingScreenTask") - { - emit sigHaveSchedule(JieXiJsonTaskPower(jsonObject["screenTask"].toObject())); - } - } - } -} - -void ControlPowerSchedule::OnControlTypeSwitchIndexChanged(int index) -{ - if(index==Setting_PowerControl) - { - m_bSelected=true; - if(m_pLedCard!=nullptr) - onReadbackAllThisPage(); - } - else { - m_bSelected=false; - } -} -void ControlPowerSchedule::onReadbackAllThisPage() -{ - if(m_pLedlist==nullptr) - return; - if(m_pLedlist->count()!=1) - return; - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "GetTimingScreenTask"); - HttpPostByTypeJsonObject(pHpptClientAll,m_strUrl,json); - -} -void ControlPowerSchedule::OnClickAdd() -{ - QList Item; - Item.append(new QStandardItem(tr("On"))); - Item.append(new QStandardItem("00:00")); - Item.append(new QStandardItem("01:00")); -// Item.append(new QStandardItem(true)); -// Item.append(new QStandardItem(true)); -// Item.append(new QStandardItem(true)); -// Item.append(new QStandardItem(true)); -// Item.append(new QStandardItem(true)); -// Item.append(new QStandardItem(true)); -// Item.append(new QStandardItem(true)); - - Item.at(0)->setTextAlignment(Qt::AlignCenter); - Item.at(1)->setTextAlignment(Qt::AlignCenter); - Item.at(2)->setTextAlignment(Qt::AlignCenter); - m_pModel->appendRow(Item); - //m_lineEidt[i]->installEventFilter(this); - //Item.at(0)->setdsetValidator(new QRegExpValidator(rx, this)); - int i=m_pModel->rowCount()-1; - m_pModel->setData(m_pModel->index(i, 3),true,Qt::UserRole); - m_pModel->setData(m_pModel->index(i, 4),true,Qt::UserRole); - m_pModel->setData(m_pModel->index(i, 5),true,Qt::UserRole); - m_pModel->setData(m_pModel->index(i, 6),true,Qt::UserRole); - m_pModel->setData(m_pModel->index(i, 7),true,Qt::UserRole); - m_pModel->setData(m_pModel->index(i, 8),true,Qt::UserRole); - m_pModel->setData(m_pModel->index(i, 9),true,Qt::UserRole); - - if(m_pModel->rowCount()>0) - { - ui->labelPowerScheduleTip->setVisible(true); - - } - else { - ui->labelPowerScheduleTip->setVisible(false); - - } -} -void ControlPowerSchedule::OnClickImport(){ - QSettings settings; - QString strDir="/"; - if(settings.value("lasOpendFileDlgtDir").isValid()) - { - strDir=settings.value("lasOpendFileDlgtDir").toString(); - } - QFileDialog dlg; - QString strBrightScheduleFile = QFileDialog::getOpenFileName(this, "open file dialog", - strDir, - tr("PowerSchedule (*.pjs)")); - if(strBrightScheduleFile.isEmpty()) - return; - QFile fJson(strBrightScheduleFile); - if(fJson.open(QIODevice::ReadOnly)){ - QJsonDocument jBrightSchedule = QJsonDocument::fromJson(fJson.readAll()); - QJsonObject oTaskPower=jBrightSchedule.object(); - JieXiJsonTaskPower(oTaskPower); - fJson.close(); - } -} -bool ControlPowerSchedule::JieXiJsonTaskPower(QJsonObject oTaskPower) -{ - OnClickClear(); - QJsonArray oSchedules; - oSchedules=oTaskPower["schedules"].toArray(); - if(oSchedules.count()>0) - { - ui->labelPowerScheduleTip->setVisible(true); - } - else - { - ui->labelPowerScheduleTip->setVisible(false); - } - //bool bHaveSchedule=false; - for(int i=0;i Item; - Item.append(new QStandardItem(tr("On"))); - Item.append(new QStandardItem(oSchedule["startTime"].toString())); - Item.append(new QStandardItem(oSchedule["endTime"].toString())); - Item.at(0)->setTextAlignment(Qt::AlignCenter); - Item.at(1)->setTextAlignment(Qt::AlignCenter); - Item.at(2)->setTextAlignment(Qt::AlignCenter); - m_pModel->appendRow(Item); - if(oSchedule["filterType"].toString()=="None") - { - m_pModel->setData(m_pModel->index(i, 3),true,Qt::UserRole); - m_pModel->setData(m_pModel->index(i, 4),true,Qt::UserRole); - m_pModel->setData(m_pModel->index(i, 5),true,Qt::UserRole); - m_pModel->setData(m_pModel->index(i, 6),true,Qt::UserRole); - m_pModel->setData(m_pModel->index(i, 7),true,Qt::UserRole); - m_pModel->setData(m_pModel->index(i, 8),true,Qt::UserRole); - m_pModel->setData(m_pModel->index(i, 9),true,Qt::UserRole); - } - else if(oSchedule["filterType"].toString()=="Week") - { - QJsonArray oWeeks; - oWeeks=oSchedule["weekFilter"].toArray(); - for(int m=0;m<7;m++) - { - bool bHave=false; - for (int j=0;jsetData(m_pModel->index(i, m+3),bHave,Qt::UserRole); - } - - - } - - - - - } - if(oSchedules.count()>0) - return true; - else { - return false; - } -} -void ControlPowerSchedule::OnClickExport(){ - QSettings settings; - QString strDir="/"; - if(settings.value("lasOpendFileDlgtDir").isValid()) { - strDir=settings.value("lasOpendFileDlgtDir").toString(); - } - QFileDialog dlg; - QString saveFileName = dlg.getSaveFileName(this, tr("Save File"), strDir, tr("PowerSchedule (*.pjs)")); - - if( saveFileName.isEmpty() ) - return; - settings.setValue("lasOpendFileDlgtDir",saveFileName); - QJsonObject oTaskPower=GetJsonObjectPowerSchedule(); - QJsonDocument tPowerScheduleJsonDoc; - tPowerScheduleJsonDoc.setObject(oTaskPower); - - QFile f(saveFileName); - if(f.open(QIODevice::WriteOnly)) { - f.write(tPowerScheduleJsonDoc.toJson()); - f.close(); - } -} -void ControlPowerSchedule::OnClickDelete() -{ - if(m_pModel->rowCount()>0) - { - QModelIndexList selected = ui->tableView->selectionModel()->selectedRows(0); - if(selected.count()>0) - m_pModel->removeRows(selected.begin()->row(),selected.count()); - } - if(m_pModel->rowCount()>0) - { - ui->labelPowerScheduleTip->setVisible(true); - } - else { - ui->labelPowerScheduleTip->setVisible(false); - } -} -void ControlPowerSchedule:: OnClickClear() -{ - //QModelIndexList selected = ui->tableView->selectionModel()->selectedRows(0); - - if(m_pModel->rowCount()>0) - { - m_pModel->removeRows(0,m_pModel->rowCount()); - - } - if(m_pModel->rowCount()>0) - { - ui->labelPowerScheduleTip->setVisible(true); - - } - else { - ui->labelPowerScheduleTip->setVisible(false); - - } -} -extern QWidget *gMainWin; -void ControlPowerSchedule::OnClickApply() { - if(m_pLedlist==nullptr) return; - if(m_pLedlist->count()<=1){ - if(m_pLedCard==nullptr||m_pLedlist->count()==0){ - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - } - if(m_pModel->rowCount()<=0) { - auto btn = QMessageBox::question(gMainWin, tr("Tip Info"), tr("Clear schedule task?")); - if(btn == QMessageBox::Yes) { - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "CleanTimingScreenTask"); - MACRO_DEFINE_TIPDLG_FUCN(tr("CleanTimingScreenTask"),tr("Success"),tr("failed")) - } - } else { - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "SetTimingScreenTask"); - QJsonObject oTaskPower=GetJsonObjectPowerSchedule(); - json.insert("screenTask", oTaskPower); - MACRO_DEFINE_TIPDLG_FUCN(tr("SetTimingScreenTask"),tr("Success"),tr("failed")) - } - -} -void ControlPowerSchedule::OnClickReadback() { - if(m_pLedlist==nullptr) return; - if(m_pLedlist->count()<=1) { - if(m_pLedCard==nullptr||m_pLedlist->count()==0) { - QMessageBox::information(gMainWin, tr("Tip"),tr("NoSelectedController")); - return; - } - } - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "GetTimingScreenTask"); - MACRO_DEFINE_TIPDLG_FUCN(tr("GetTimingScreenTask"),tr("Success"),tr("failed")) - -} -void ControlPowerSchedule::OnClickClearSchedule() -{ - if(m_pLedlist==nullptr) - return; - if(m_pLedlist->count()<=1) - { - if(m_pLedCard==nullptr||m_pLedlist->count()==0) - { - QMessageBox::information(gMainWin, tr("Tip"),tr("NoSelectedController")); - return; - } - } - auto btn = QMessageBox::question(gMainWin, tr("Tip Info"), tr("Clear schedule task?")); - if(btn == QMessageBox::Yes) { - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "CleanTimingScreenTask"); - MACRO_DEFINE_TIPDLG_FUCN(tr("CleanTimingScreenTask"),tr("Success"),tr("failed")) - } -} -QJsonObject ControlPowerSchedule::GetJsonObjectPowerSchedule() -{ - QJsonObject oTaskPower; - QJsonArray oItems; - - oTaskPower["createDate"] = QJsonValue::Null; - oTaskPower["createBy"] = "alahover"; - oTaskPower["name"] = "TimingScreen"; - - QJsonArray oSchedules; - for(int i=0; irowCount(); i++) - { - - QJsonObject oSchedule; - oSchedule["timeType"] = "Range"; - oSchedule["startTime"] = m_pModel->data(m_pModel->index(i, 1)).toString();; - oSchedule["endTime"] = m_pModel->data(m_pModel->index(i, 2)).toString();; - oSchedule["dateType"] = "All"; - oSchedule["startDate"] = QJsonValue::Null; - oSchedule["endDate"] = QJsonValue::Null; - oSchedule["monthFilter"] = QJsonArray(); - - bool bSun=m_pModel->data(m_pModel->index(i, 3),Qt::UserRole).toBool(); - bool bMon=m_pModel->data(m_pModel->index(i, 4),Qt::UserRole).toBool(); - bool bTur=m_pModel->data(m_pModel->index(i, 5),Qt::UserRole).toBool(); - bool bWed=m_pModel->data(m_pModel->index(i, 6),Qt::UserRole).toBool(); - bool bThu=m_pModel->data(m_pModel->index(i, 7),Qt::UserRole).toBool(); - bool bFri=m_pModel->data(m_pModel->index(i, 8),Qt::UserRole).toBool(); - bool bSat=m_pModel->data(m_pModel->index(i, 9),Qt::UserRole).toBool(); - - - if(bMon && bTur && bWed && bThu && bFri && bSat && bSun) - { - oSchedule["filterType"] = "None"; - oSchedule["weekFilter"] = QJsonArray(); - - } - else { - oSchedule["filterType"] = "Week"; - QJsonArray tempArray; - if( bSun) - { - tempArray.append(0); - } - if(bMon) - { - tempArray.append(1); - } - if(bTur) - { - tempArray.append(2); - } - if( bWed) - { - tempArray.append(3); - } - if( bThu) - { - tempArray.append(4); - } - if( bFri) - { - tempArray.append(5); - } - if( bSat) - { - tempArray.append(6); - } - - - oSchedule["weekFilter"] = tempArray; - - } - - - oSchedules.append(oSchedule); - } - - oTaskPower["schedules"] = oSchedules; - return oTaskPower; - -} - -void ControlPowerSchedule::DeletePostingDlg() -{ - if(m_PostingDlg!=nullptr) - { - delete m_PostingDlg; - m_PostingDlg=nullptr; - } -} +#include "controlpowerschedule.h" +#include "ui_controlpowerschedule.h" + +#include +#include +#include +#include +#include +#include +#include +#include "cfg.h" +#include "QSettings" +#include "base/x_spinboxdelegate.h" +#include "base/x_timeeditdelegate.h" +#include "base/x_checkboxdelegate.h" +#include "tools.h" + +ControlPowerSchedule::ControlPowerSchedule(QWidget *parent,QList *list) : + QWidget(parent), + ui(new Ui::ControlPowerSchedule) +{ + m_pLedlist=list; + ui->setupUi(this); + ui->labelPowerScheduleTip->setVisible(false); + refreshLable(); +setStyleSheet(css); + ui->pushButtonAdd->setProperty("ssType", "progManageTool"); + ui->pushButtonAdd->setFlat(true); + ui->pushButtonDelete->setProperty("ssType", "progManageTool"); + ui->pushButtonDelete->setFlat(true); + ui->pushButtonClear->setProperty("ssType", "progManageTool"); + ui->pushButtonClear->setFlat(true); + ui->pushButtonApply->setProperty("ssType", "progManageTool"); + ui->pushButtonApply->setFlat(true); + ui->pushButtonImport->setProperty("ssType", "progManageTool"); + ui->pushButtonExport->setProperty("ssType", "progManageTool"); + ui->pushButtonReadback->setProperty("ssType", "progManageTool"); + ui->pushButtonClearSchedule->setProperty("ssType", "progManageTool"); + + m_pModel = new QStandardItemModel(this); + m_pModel->setColumnCount(10); + m_pModel->setHeaderData(0,Qt::Horizontal, tr("Power On State")); + m_pModel->setHeaderData(1,Qt::Horizontal, tr("Start Time")); + m_pModel->setHeaderData(2,Qt::Horizontal, tr("End Time")); + m_pModel->setHeaderData(3,Qt::Horizontal, tr("SUN")); + m_pModel->setHeaderData(4,Qt::Horizontal, tr("MON")); + m_pModel->setHeaderData(5,Qt::Horizontal, tr("TUE")); + m_pModel->setHeaderData(6,Qt::Horizontal, tr("WED")); + m_pModel->setHeaderData(7,Qt::Horizontal, tr("THU")); + m_pModel->setHeaderData(8,Qt::Horizontal, tr("FRI")); + m_pModel->setHeaderData(9,Qt::Horizontal, tr("SAT")); + ui->tableView->setModel(m_pModel); + + X_timeEditDelegate *pStartTimeDelegate=new X_timeEditDelegate(this); + ui->tableView->setItemDelegateForColumn(1,pStartTimeDelegate); + ui->tableView->setItemDelegateForColumn(2,pStartTimeDelegate); + X_CheckBoxDelegate *WeekDelegate=new X_CheckBoxDelegate(this); + ui->tableView->setItemDelegateForColumn(3,WeekDelegate); + ui->tableView->setItemDelegateForColumn(4,WeekDelegate); + ui->tableView->setItemDelegateForColumn(5,WeekDelegate); + ui->tableView->setItemDelegateForColumn(6,WeekDelegate); + ui->tableView->setItemDelegateForColumn(7,WeekDelegate); + ui->tableView->setItemDelegateForColumn(8,WeekDelegate); + ui->tableView->setItemDelegateForColumn(9,WeekDelegate); + + + ReadOnlyDelegate* readOnlyDelegate = new ReadOnlyDelegate(); + ui->tableView->setItemDelegateForColumn(0, readOnlyDelegate); //设置某列只读 + + ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); + // ui->tableView->verticalHeader()->hide(); + ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows); + ui->tableView->setFocusPolicy(Qt::NoFocus); + + + MARCO_DEFINE_CONTROL_FUNC2(parent->parent()->parent(),parent->parent()) + + connect(ui->pushButtonAdd,SIGNAL(clicked()),this,SLOT(OnClickAdd())); + connect(ui->pushButtonImport,SIGNAL(clicked()),this,SLOT(OnClickImport())); + connect(ui->pushButtonExport,SIGNAL(clicked()),this,SLOT(OnClickExport())); + connect(ui->pushButtonDelete,SIGNAL(clicked()),this,SLOT(OnClickDelete())); + connect(ui->pushButtonClear,SIGNAL(clicked()),this,SLOT(OnClickClear())); + connect(ui->pushButtonApply,SIGNAL(clicked()),this,SLOT(OnClickApply())); + connect(ui->pushButtonReadback,SIGNAL(clicked()),this,SLOT(OnClickReadback())); + connect(ui->pushButtonClearSchedule,SIGNAL(clicked()),this,SLOT(OnClickClearSchedule())); + + +} + +ControlPowerSchedule::~ControlPowerSchedule() +{ + delete ui; + if(pHpptClient != nullptr) + { + qDebug() <<"delete pHpptClient in ~NetComm"; + delete pHpptClient; + pHpptClient=nullptr; + } + if(pHpptClientAll != nullptr) + { + qDebug() <<"delete pHpptClientAll in ~NetComm"; + delete pHpptClientAll; + pHpptClientAll=nullptr; + } +} +void ControlPowerSchedule::refreshLable() +{ + ui->pushButtonAdd->setText(tr("Add")); + ui->pushButtonApply->setText(tr("Apply")); + ui->pushButtonClear->setText(tr("Clear")); + ui->pushButtonDelete->setText(tr("Delete")); + ui->pushButtonImport->setText(tr("Import")); + ui->pushButtonExport->setText(tr("Export")); +} + +void ControlPowerSchedule::onSelectedDeviceList(QList *list) +{ + m_pLedlist=list; + if(m_pLedlist==nullptr) + return; + if(m_pLedlist->count()==1) + { + ui->pushButtonReadback->setEnabled(true); + } + else { + ui->pushButtonReadback->setEnabled(false); + } + MACRO_DEFINE_CONTROL_FUNC3 + +} +//获取到httpPost的应答,如果参数变化需要出发修改控件item的内容 +void ControlPowerSchedule::OnProHttpResponse(QString url, QString postMD5, QByteArray data) +{ + Q_UNUSED(postMD5) + //qDebug()<< url + "\r\n"+m_strUrl; + if(url == m_strUrl) + { + QJsonParseError parseJsonErr; + QJsonDocument document = QJsonDocument::fromJson(data,&parseJsonErr); + if(!(parseJsonErr.error == QJsonParseError::NoError)) + { + if(data.size()==0) + qDebug()<<"json is empty"; + else + qDebug()<count()!=1) + return; + QJsonObject json; + json.insert("_id", getRandomString(10)); + json.insert("_type", "GetTimingScreenTask"); + HttpPostByTypeJsonObject(pHpptClientAll,m_strUrl,json); + +} +void ControlPowerSchedule::OnClickAdd() +{ + QList Item; + Item.append(new QStandardItem(tr("On"))); + Item.append(new QStandardItem("00:00")); + Item.append(new QStandardItem("01:00")); +// Item.append(new QStandardItem(true)); +// Item.append(new QStandardItem(true)); +// Item.append(new QStandardItem(true)); +// Item.append(new QStandardItem(true)); +// Item.append(new QStandardItem(true)); +// Item.append(new QStandardItem(true)); +// Item.append(new QStandardItem(true)); + + Item.at(0)->setTextAlignment(Qt::AlignCenter); + Item.at(1)->setTextAlignment(Qt::AlignCenter); + Item.at(2)->setTextAlignment(Qt::AlignCenter); + m_pModel->appendRow(Item); + //m_lineEidt[i]->installEventFilter(this); + //Item.at(0)->setdsetValidator(new QRegExpValidator(rx, this)); + int i=m_pModel->rowCount()-1; + m_pModel->setData(m_pModel->index(i, 3),true,Qt::UserRole); + m_pModel->setData(m_pModel->index(i, 4),true,Qt::UserRole); + m_pModel->setData(m_pModel->index(i, 5),true,Qt::UserRole); + m_pModel->setData(m_pModel->index(i, 6),true,Qt::UserRole); + m_pModel->setData(m_pModel->index(i, 7),true,Qt::UserRole); + m_pModel->setData(m_pModel->index(i, 8),true,Qt::UserRole); + m_pModel->setData(m_pModel->index(i, 9),true,Qt::UserRole); + + if(m_pModel->rowCount()>0) + { + ui->labelPowerScheduleTip->setVisible(true); + + } + else { + ui->labelPowerScheduleTip->setVisible(false); + + } +} +void ControlPowerSchedule::OnClickImport(){ + QSettings settings; + QString strDir="/"; + if(settings.value("lasOpendFileDlgtDir").isValid()) + { + strDir=settings.value("lasOpendFileDlgtDir").toString(); + } + QFileDialog dlg; + QString strBrightScheduleFile = QFileDialog::getOpenFileName(this, "open file dialog", + strDir, + tr("PowerSchedule (*.pjs)")); + if(strBrightScheduleFile.isEmpty()) + return; + QFile fJson(strBrightScheduleFile); + if(fJson.open(QIODevice::ReadOnly)){ + QJsonDocument jBrightSchedule = QJsonDocument::fromJson(fJson.readAll()); + QJsonObject oTaskPower=jBrightSchedule.object(); + JieXiJsonTaskPower(oTaskPower); + fJson.close(); + } +} +bool ControlPowerSchedule::JieXiJsonTaskPower(QJsonObject oTaskPower) +{ + OnClickClear(); + QJsonArray oSchedules; + oSchedules=oTaskPower["schedules"].toArray(); + if(oSchedules.count()>0) + { + ui->labelPowerScheduleTip->setVisible(true); + } + else + { + ui->labelPowerScheduleTip->setVisible(false); + } + //bool bHaveSchedule=false; + for(int i=0;i Item; + Item.append(new QStandardItem(tr("On"))); + Item.append(new QStandardItem(oSchedule["startTime"].toString())); + Item.append(new QStandardItem(oSchedule["endTime"].toString())); + Item.at(0)->setTextAlignment(Qt::AlignCenter); + Item.at(1)->setTextAlignment(Qt::AlignCenter); + Item.at(2)->setTextAlignment(Qt::AlignCenter); + m_pModel->appendRow(Item); + if(oSchedule["filterType"].toString()=="None") + { + m_pModel->setData(m_pModel->index(i, 3),true,Qt::UserRole); + m_pModel->setData(m_pModel->index(i, 4),true,Qt::UserRole); + m_pModel->setData(m_pModel->index(i, 5),true,Qt::UserRole); + m_pModel->setData(m_pModel->index(i, 6),true,Qt::UserRole); + m_pModel->setData(m_pModel->index(i, 7),true,Qt::UserRole); + m_pModel->setData(m_pModel->index(i, 8),true,Qt::UserRole); + m_pModel->setData(m_pModel->index(i, 9),true,Qt::UserRole); + } + else if(oSchedule["filterType"].toString()=="Week") + { + QJsonArray oWeeks; + oWeeks=oSchedule["weekFilter"].toArray(); + for(int m=0;m<7;m++) + { + bool bHave=false; + for (int j=0;jsetData(m_pModel->index(i, m+3),bHave,Qt::UserRole); + } + + + } + + + + + } + if(oSchedules.count()>0) + return true; + else { + return false; + } +} +void ControlPowerSchedule::OnClickExport(){ + QSettings settings; + QString strDir="/"; + if(settings.value("lasOpendFileDlgtDir").isValid()) { + strDir=settings.value("lasOpendFileDlgtDir").toString(); + } + QFileDialog dlg; + QString saveFileName = dlg.getSaveFileName(this, tr("Save File"), strDir, tr("PowerSchedule (*.pjs)")); + + if( saveFileName.isEmpty() ) + return; + settings.setValue("lasOpendFileDlgtDir",saveFileName); + QJsonObject oTaskPower=GetJsonObjectPowerSchedule(); + QJsonDocument tPowerScheduleJsonDoc; + tPowerScheduleJsonDoc.setObject(oTaskPower); + + QFile f(saveFileName); + if(f.open(QIODevice::WriteOnly)) { + f.write(tPowerScheduleJsonDoc.toJson()); + f.close(); + } +} +void ControlPowerSchedule::OnClickDelete() +{ + if(m_pModel->rowCount()>0) + { + QModelIndexList selected = ui->tableView->selectionModel()->selectedRows(0); + if(selected.count()>0) + m_pModel->removeRows(selected.begin()->row(),selected.count()); + } + if(m_pModel->rowCount()>0) + { + ui->labelPowerScheduleTip->setVisible(true); + } + else { + ui->labelPowerScheduleTip->setVisible(false); + } +} +void ControlPowerSchedule:: OnClickClear() +{ + //QModelIndexList selected = ui->tableView->selectionModel()->selectedRows(0); + + if(m_pModel->rowCount()>0) + { + m_pModel->removeRows(0,m_pModel->rowCount()); + + } + if(m_pModel->rowCount()>0) + { + ui->labelPowerScheduleTip->setVisible(true); + + } + else { + ui->labelPowerScheduleTip->setVisible(false); + + } +} +extern QWidget *gMainWin; +void ControlPowerSchedule::OnClickApply() { + if(m_pLedlist==nullptr) return; + if(m_pLedlist->count()<=1){ + if(m_pLedCard==nullptr||m_pLedlist->count()==0){ + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + } + if(m_pModel->rowCount()<=0) { + auto btn = QMessageBox::question(gMainWin, tr("Tip Info"), tr("Clear schedule task?")); + if(btn == QMessageBox::Yes) { + QJsonObject json; + json.insert("_id", getRandomString(10)); + json.insert("_type", "CleanTimingScreenTask"); + MACRO_DEFINE_TIPDLG_FUCN(tr("CleanTimingScreenTask"),tr("Success"),tr("failed")) + } + } else { + QJsonObject json; + json.insert("_id", getRandomString(10)); + json.insert("_type", "SetTimingScreenTask"); + QJsonObject oTaskPower=GetJsonObjectPowerSchedule(); + json.insert("screenTask", oTaskPower); + MACRO_DEFINE_TIPDLG_FUCN(tr("SetTimingScreenTask"),tr("Success"),tr("failed")) + } + +} +void ControlPowerSchedule::OnClickReadback() { + if(m_pLedlist==nullptr) return; + if(m_pLedlist->count()<=1) { + if(m_pLedCard==nullptr||m_pLedlist->count()==0) { + QMessageBox::information(gMainWin, tr("Tip"),tr("NoSelectedController")); + return; + } + } + QJsonObject json; + json.insert("_id", getRandomString(10)); + json.insert("_type", "GetTimingScreenTask"); + MACRO_DEFINE_TIPDLG_FUCN(tr("GetTimingScreenTask"),tr("Success"),tr("failed")) + +} +void ControlPowerSchedule::OnClickClearSchedule() +{ + if(m_pLedlist==nullptr) + return; + if(m_pLedlist->count()<=1) + { + if(m_pLedCard==nullptr||m_pLedlist->count()==0) + { + QMessageBox::information(gMainWin, tr("Tip"),tr("NoSelectedController")); + return; + } + } + auto btn = QMessageBox::question(gMainWin, tr("Tip Info"), tr("Clear schedule task?")); + if(btn == QMessageBox::Yes) { + QJsonObject json; + json.insert("_id", getRandomString(10)); + json.insert("_type", "CleanTimingScreenTask"); + MACRO_DEFINE_TIPDLG_FUCN(tr("CleanTimingScreenTask"),tr("Success"),tr("failed")) + } +} +QJsonObject ControlPowerSchedule::GetJsonObjectPowerSchedule() +{ + QJsonObject oTaskPower; + QJsonArray oItems; + + oTaskPower["createDate"] = QJsonValue::Null; + oTaskPower["createBy"] = "alahover"; + oTaskPower["name"] = "TimingScreen"; + + QJsonArray oSchedules; + for(int i=0; irowCount(); i++) + { + + QJsonObject oSchedule; + oSchedule["timeType"] = "Range"; + oSchedule["startTime"] = m_pModel->data(m_pModel->index(i, 1)).toString();; + oSchedule["endTime"] = m_pModel->data(m_pModel->index(i, 2)).toString();; + oSchedule["dateType"] = "All"; + oSchedule["startDate"] = QJsonValue::Null; + oSchedule["endDate"] = QJsonValue::Null; + oSchedule["monthFilter"] = QJsonArray(); + + bool bSun=m_pModel->data(m_pModel->index(i, 3),Qt::UserRole).toBool(); + bool bMon=m_pModel->data(m_pModel->index(i, 4),Qt::UserRole).toBool(); + bool bTur=m_pModel->data(m_pModel->index(i, 5),Qt::UserRole).toBool(); + bool bWed=m_pModel->data(m_pModel->index(i, 6),Qt::UserRole).toBool(); + bool bThu=m_pModel->data(m_pModel->index(i, 7),Qt::UserRole).toBool(); + bool bFri=m_pModel->data(m_pModel->index(i, 8),Qt::UserRole).toBool(); + bool bSat=m_pModel->data(m_pModel->index(i, 9),Qt::UserRole).toBool(); + + + if(bMon && bTur && bWed && bThu && bFri && bSat && bSun) + { + oSchedule["filterType"] = "None"; + oSchedule["weekFilter"] = QJsonArray(); + + } + else { + oSchedule["filterType"] = "Week"; + QJsonArray tempArray; + if( bSun) + { + tempArray.append(0); + } + if(bMon) + { + tempArray.append(1); + } + if(bTur) + { + tempArray.append(2); + } + if( bWed) + { + tempArray.append(3); + } + if( bThu) + { + tempArray.append(4); + } + if( bFri) + { + tempArray.append(5); + } + if( bSat) + { + tempArray.append(6); + } + + + oSchedule["weekFilter"] = tempArray; + + } + + + oSchedules.append(oSchedule); + } + + oTaskPower["schedules"] = oSchedules; + return oTaskPower; + +} + +void ControlPowerSchedule::DeletePostingDlg() +{ + if(m_PostingDlg!=nullptr) + { + delete m_PostingDlg; + m_PostingDlg=nullptr; + } +} diff --git a/LedOK/wDevicesManager/controlpowerschedule.h b/LedOK/device/controlpowerschedule.h similarity index 95% rename from LedOK/wDevicesManager/controlpowerschedule.h rename to LedOK/device/controlpowerschedule.h index f7d1c75..1222321 100644 --- a/LedOK/wDevicesManager/controlpowerschedule.h +++ b/LedOK/device/controlpowerschedule.h @@ -1,77 +1,77 @@ -#ifndef CONTROLPOWERSCHEDULE_H -#define CONTROLPOWERSCHEDULE_H - -#include -#include -#include -#include -#include -#include -namespace Ui { -class ControlPowerSchedule; -} - -class ControlPowerSchedule : public QWidget -{ - Q_OBJECT - -public: - explicit ControlPowerSchedule(QWidget *parent = nullptr,QList *m_pLedlist=nullptr); - ~ControlPowerSchedule(); -private: - Ui::ControlPowerSchedule *ui; -protected slots: - void refreshLable(); - void OnClickAdd(); - void OnClickImport(); - void OnClickExport(); - void OnClickDelete(); - void OnClickClear(); - void OnClickApply(); - void OnClickReadback(); - void OnClickClearSchedule(); - //类似的控制操作信号和槽函数和变量定义 - signals: - void sigSend(QJsonObject &,QString); - void sigHaveSchedule(bool); - - protected slots: - void DeletePostingDlg(); - void OnProHttpResponse(QString url, QString postMD5, QByteArray data); - void OnProHttpResponseAll(QString url, QString postMD5, QByteArray data); - void onSelectedDeviceList(QList *); - void onReadbackAllThisPage(); - void OnControlTypeSwitchIndexChanged(int index); - private: - QList *m_pLedlist=nullptr; - LedCard *m_pLedCard = nullptr; - LedCard *m_oldLedlist = nullptr; - HpptClient *pHpptClient = nullptr; - HpptClient *pHpptClientAll = nullptr; - QString m_strUrl=""; - LoEmptyDialog * m_PostingDlg=nullptr; - QTimer *m_pGetAskTimer=nullptr; - bool m_bSelected=false; - QStandardItemModel * m_pModel; - bool JieXiJsonTaskPower(QJsonObject oTaskPower); - QJsonObject GetJsonObjectPowerSchedule(); - - -}; -class ReadOnlyDelegate: public QStyledItemDelegate -{ - Q_OBJECT -public: - ReadOnlyDelegate(QWidget *parent = nullptr):QStyledItemDelegate(parent) - {} - - QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, -const QModelIndex &index) const override //final - { - Q_UNUSED(parent) - Q_UNUSED(option) - Q_UNUSED(index) - return nullptr; - } -}; -#endif // CONTROLPOWERSCHEDULE_H +#ifndef CONTROLPOWERSCHEDULE_H +#define CONTROLPOWERSCHEDULE_H + +#include +#include +#include +#include +#include +#include +namespace Ui { +class ControlPowerSchedule; +} + +class ControlPowerSchedule : public QWidget +{ + Q_OBJECT + +public: + explicit ControlPowerSchedule(QWidget *parent = nullptr,QList *m_pLedlist=nullptr); + ~ControlPowerSchedule(); + void refreshLable(); +private: + Ui::ControlPowerSchedule *ui; +protected slots: + void OnClickAdd(); + void OnClickImport(); + void OnClickExport(); + void OnClickDelete(); + void OnClickClear(); + void OnClickApply(); + void OnClickReadback(); + void OnClickClearSchedule(); + //类似的控制操作信号和槽函数和变量定义 + signals: + void sigSend(QJsonObject &,QString); + void sigHaveSchedule(bool); + + protected slots: + void DeletePostingDlg(); + void OnProHttpResponse(QString url, QString postMD5, QByteArray data); + void OnProHttpResponseAll(QString url, QString postMD5, QByteArray data); + void onSelectedDeviceList(QList *); + void onReadbackAllThisPage(); + void OnControlTypeSwitchIndexChanged(int index); + private: + QList *m_pLedlist=nullptr; + LedCard *m_pLedCard = nullptr; + LedCard *m_oldLedlist = nullptr; + HpptClient *pHpptClient = nullptr; + HpptClient *pHpptClientAll = nullptr; + QString m_strUrl=""; + LoEmptyDialog * m_PostingDlg=nullptr; + QTimer *m_pGetAskTimer=nullptr; + bool m_bSelected=false; + QStandardItemModel * m_pModel; + bool JieXiJsonTaskPower(QJsonObject oTaskPower); + QJsonObject GetJsonObjectPowerSchedule(); + + +}; +class ReadOnlyDelegate: public QStyledItemDelegate +{ + Q_OBJECT +public: + ReadOnlyDelegate(QWidget *parent = nullptr):QStyledItemDelegate(parent) + {} + + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, +const QModelIndex &index) const override //final + { + Q_UNUSED(parent) + Q_UNUSED(option) + Q_UNUSED(index) + return nullptr; + } +}; +#endif // CONTROLPOWERSCHEDULE_H diff --git a/LedOK/wDevicesManager/controlpowerschedule.ui b/LedOK/device/controlpowerschedule.ui similarity index 96% rename from LedOK/wDevicesManager/controlpowerschedule.ui rename to LedOK/device/controlpowerschedule.ui index c608179..22d0305 100644 --- a/LedOK/wDevicesManager/controlpowerschedule.ui +++ b/LedOK/device/controlpowerschedule.ui @@ -1,255 +1,255 @@ - - - ControlPowerSchedule - - - - 0 - 0 - 422 - 300 - - - - Form - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - Edit area - - - - - - - - 10 - - - 0 - - - - - - 60 - 30 - - - - Add - - - - - - - - 60 - 30 - - - - Delete - - - - - - - - 60 - 30 - - - - Clear - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 30 - - - - Import - - - - - - - - 0 - 30 - - - - Export - - - - - - - - - It is power off state outside the schedule time period - - - - - - - background-color: #FFFFFF; - - - - - - - - - - - - Send command - - - - - - 0 - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 60 - 30 - - - - Apply - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 30 - - - - Clear Schedule - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 30 - - - - Readback - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - - - - - + + + ControlPowerSchedule + + + + 0 + 0 + 422 + 300 + + + + Form + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Edit area + + + + + + + + 10 + + + 0 + + + + + + 60 + 30 + + + + Add + + + + + + + + 60 + 30 + + + + Delete + + + + + + + + 60 + 30 + + + + Clear + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 30 + + + + Import + + + + + + + + 0 + 30 + + + + Export + + + + + + + + + It is power off state outside the schedule time period + + + + + + + background-color: #FFFFFF; + + + + + + + + + + + + Send command + + + + + + 0 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 60 + 30 + + + + Apply + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 30 + + + + Clear Schedule + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 30 + + + + Readback + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + + + diff --git a/LedOK/device/controlpowerwidget.cpp b/LedOK/device/controlpowerwidget.cpp new file mode 100644 index 0000000..f2cf965 --- /dev/null +++ b/LedOK/device/controlpowerwidget.cpp @@ -0,0 +1,155 @@ +#include "controlpowerwidget.h" +#include "gutil/qgui.h" +#include "globaldefine.h" +#include "base/waitingdlg.h" +#include "tools.h" +#include + +ControlPowerWidget::ControlPowerWidget(QWidget *parent, QList *list) : QWidget(parent) { + auto vBox = new VBox(this); + + lbScreenCfg = new QLabel; + lbScreenCfg->setAlignment(Qt::AlignCenter); + vBox->addWidget(lbScreenCfg); + + auto hBox = new HBox(vBox); + hBox->addStretch(); + + fdManual = new QRadioButton; + hBox->addWidget(fdManual); + hBox->addSpacing(40); + + fdSchedule = new QRadioButton; + hBox->addWidget(fdSchedule); + hBox->addStretch(); + + auto stack = new QStackedLayout(vBox); + { + auto vBox = new VBox(stack); + vBox->addSpacing(20); + + auto hBox = new HBox(vBox); + hBox->addStretch(); + + lbScreen = new QLabel; + hBox->addWidget(lbScreen); + + fdScreen = new SwitchControl; + fdScreen->setMinimumSize(QSize(80, 33)); + fdScreen->setSliderColor(QColor(0, 0, 0), QColor(0, 160, 230)); + fdScreen->setBgColor(QColor(200,200,200), QColor(0x00cc00)); + fdScreen->setTextColor(QColor(100,100,100), QColor(0, 160, 230)); + connect(fdScreen, &SwitchControl::checkedChanged, this, [this](bool checked) { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "SetScreenOn"); + json.insert("_type", "SetScreenOn"); + json.insert("on", checked); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, (checked ? tr("SetScreenOn") : tr("SetScreenOff"))+" ..."); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + if(checked) foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("SetScreenOn")) + } + else foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("SetScreenOff")) + } + } + }); + hBox->addWidget(fdScreen); + hBox->addStretch(); + + btnScreenGet = new QPushButton; + btnScreenGet->setMinimumSize(QSize(60, 30)); + btnScreenGet->setProperty("ssType", "progManageTool"); + connect(btnScreenGet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "IsScreenOn"); + json.insert("_type", "IsScreenOn"); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("IsScreenOn")+" ..."); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg] { + Def_CtrlSingleGetReply + waitingDlg->success(); + fdScreen->setCheckedStatus(json["on"].toBool()); + }); + } else { + foreach(auto card, *gSelCards) { + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + auto cardId = card->m_strCardId; + connect(reply, &QNetworkReply::finished, this, [reply, cardId] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(err.isEmpty()) err = json["on"].toBool() ? tr("On") : tr("Off"); + gFdResInfo->append(cardId+" "+tr("IsScreenOn")+" "+err); + }); + } + } + }); + vBox->addWidget(btnScreenGet, 0, Qt::AlignCenter); + vBox->addStretch(); + } + m_pSchedule = new ControlPowerSchedule(this, list); + connect(m_pSchedule, &ControlPowerSchedule::sigHaveSchedule, this, [=](bool b) { + if(b) fdSchedule->setChecked(true); + else fdManual->setChecked(true); + }); + stack->addWidget(m_pSchedule); + + connect(fdSchedule, &QRadioButton::toggled, stack, &QStackedLayout::setCurrentIndex); + fdManual->setChecked(true); + + connect(gDevicePanel, &DevicePanel::sigSelectedDeviceList, this, [this] { + if(isVisible()) init(); + }); + transUi(); +} + +void ControlPowerWidget::showEvent(QShowEvent *event) { + QWidget::showEvent(event); + init(); +} +void ControlPowerWidget::init() { + bool isSingle = gSelCards->count()==1; + if(! isSingle) return; + auto card = gSelCards->at(0); + + QJsonObject json; + json.insert("_id", "IsScreenOn"); + json.insert("_type", "IsScreenOn"); + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + connect(reply, &QNetworkReply::finished, this, [this, reply] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) return; + fdScreen->setCheckedStatus(json["on"].toBool()); + }); +} + +void ControlPowerWidget::changeEvent(QEvent *event) { + QWidget::changeEvent(event); + if(event->type() == QEvent::LanguageChange) transUi(); +} +void ControlPowerWidget::transUi() { + lbScreenCfg->setText(tr("Power Configuration")); + fdManual->setText(tr("Manual")); + fdSchedule->setText(tr("Schedule")); + + lbScreen->setText(tr("Power")); + fdScreen->setText(tr("Off"), tr("On")); + btnScreenGet->setText(tr("Readback")); + + m_pSchedule->refreshLable(); +} diff --git a/LedOK/device/controlpowerwidget.h b/LedOK/device/controlpowerwidget.h new file mode 100644 index 0000000..04e507b --- /dev/null +++ b/LedOK/device/controlpowerwidget.h @@ -0,0 +1,29 @@ +#ifndef CONTROLPOWERWIDGET_H +#define CONTROLPOWERWIDGET_H + +#include +#include +#include + +class ControlPowerWidget : public QWidget { + Q_OBJECT +public: + explicit ControlPowerWidget(QWidget *parent = nullptr,QList *m_pLedlist=nullptr); +protected: + void showEvent(QShowEvent *event) override; + void init(); + void changeEvent(QEvent *) override; + void transUi(); +private: + ControlPowerSchedule *m_pSchedule=nullptr; + + QLabel *lbScreenCfg; + QRadioButton *fdManual; + QRadioButton *fdSchedule; + + QLabel *lbScreen; + SwitchControl *fdScreen; + QPushButton *btnScreenGet; +}; + +#endif // CONTROLPOWERWIDGET_H diff --git a/LedOK/wDevicesManager/controltestwidget.cpp b/LedOK/device/controltestwidget.cpp similarity index 97% rename from LedOK/wDevicesManager/controltestwidget.cpp rename to LedOK/device/controltestwidget.cpp index 4ead2ea..dfb96b1 100644 --- a/LedOK/wDevicesManager/controltestwidget.cpp +++ b/LedOK/device/controltestwidget.cpp @@ -1,558 +1,545 @@ -#include "controltestwidget.h" -#include "ui_controltestwidget.h" -#include "base/x_uimsgboxok.h" -#include "QFileDialog" -#include "QDir" -#include -#include -#include -#include -#include -#include -#include "tools.h" -ControlTestWidget::ControlTestWidget(QWidget *parent,QList *list) : - QWidget(parent), - ui(new Ui::ControlTestWidget) -{ - m_pLedlist=list; - ui->setupUi(this); - refreshLable(); -setStyleSheet(Tools::styleSheet()); - ui->pushButtonStartLine->setProperty("ssType", "progManageTool"); - ui->pushButtonStartGray->setProperty("ssType", "progManageTool"); - ui->pushButtonStartColor->setProperty("ssType", "progManageTool"); - ui->pushButtonStopTest->setProperty("ssType", "progManageTool"); - ui->pushButton->setProperty("ssType", "progManageTool"); - ui->pushButton_2->setProperty("ssType", "progManageTool"); - ui->pushButton_3->setProperty("ssType", "progManageTool"); - ui->pushButton_4->setProperty("ssType", "progManageTool"); - ui->pushButton_5->setProperty("ssType", "progManageTool"); - ui->pushButton_6->setProperty("ssType", "progManageTool"); - ui->pushButton_7->setProperty("ssType", "progManageTool"); - ui->pushButton_8->setProperty("ssType", "progManageTool"); - ui->pushButton_9->setProperty("ssType", "progManageTool"); - ui->pushButton_10->setProperty("ssType", "progManageTool"); - ui->pushButton_11->setProperty("ssType", "progManageTool"); - ui->pushButton_12->setProperty("ssType", "progManageTool"); - ui->pushButton_13->setProperty("ssType", "progManageTool"); - - ui->spinBoxLineSpeed->setValue(10); - ui->spinBoxLineDistance->setValue(15); - ui->spinBoxGraySpeed->setValue(10); - ui->spinBoxGrayValue->setValue(0); - ui->radioButtonWhite->setChecked(true); - ui->radioButton_White->setChecked(true); - ui->checkBoxHorizontal->setChecked(true); - ui->checkBoxVertical->setChecked(true); - ui->checkBoxSlash->setChecked(true); - ui->checkBox_red->setChecked(true); - ui->checkBox_green->setChecked(true); - ui->checkBox_blue->setChecked(true); - ui->checkBox_white->setChecked(true); - - - connect(ui->pushButtonStartLine,SIGNAL(clicked()),this,SLOT(OnStartTestLine())); - connect(ui->pushButtonStartGray,SIGNAL(clicked()),this,SLOT(OnStartTestGray())); - connect(ui->pushButtonStartColor,SIGNAL(clicked()),this,SLOT(OnStartTestColor())); - connect(ui->pushButtonStopTest,SIGNAL(clicked()),this,SLOT(OnStopTest())); - - connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(OnpushButton1())); - connect(ui->pushButton_2,SIGNAL(clicked()),this,SLOT(OnpushButton2())); - connect(ui->pushButton_3,SIGNAL(clicked()),this,SLOT(OnpushButton3())); - connect(ui->pushButton_4,SIGNAL(clicked()),this,SLOT(OnpushButton4())); - connect(ui->pushButton_5,SIGNAL(clicked()),this,SLOT(OnpushButton5())); - connect(ui->pushButton_6,SIGNAL(clicked()),this,SLOT(OnpushButton6())); - connect(ui->pushButton_7,SIGNAL(clicked()),this,SLOT(OnpushButton7())); - connect(ui->pushButton_8,SIGNAL(clicked()),this,SLOT(OnpushButton8())); - connect(ui->pushButton_9,SIGNAL(clicked()),this,SLOT(OnpushButton9())); - connect(ui->pushButton_10,SIGNAL(clicked()),this,SLOT(OnpushButton0())); - connect(ui->pushButton_11,SIGNAL(clicked()),this,SLOT(OnpushButtonClear())); - connect(ui->pushButton_12,SIGNAL(clicked()),this,SLOT(OnpushButtonReset())); - connect(ui->pushButton_13,SIGNAL(clicked()),this,SLOT(OnpushButtonAnycast())); - - ui->pushButton_13->setEnabled(false); - - MARCO_DEFINE_CONTROL_FUNC2(parent->parent(),parent) - - connect(this,SIGNAL(sigTcpSend(int)),parent->parent(),SLOT(OnControlTcpSend(int))); - ui->lineEdit->setValidator(new QIntValidator(0, 100, this)); - - -} - -ControlTestWidget::~ControlTestWidget() -{ - delete ui; - if(pHpptClient != nullptr) - { - qDebug() <<"delete pHpptClient in ~NetComm"; - delete pHpptClient; - pHpptClient=nullptr; - } - if(pHpptClientAll != nullptr) - { - qDebug() <<"delete pHpptClientAll in ~NetComm"; - delete pHpptClientAll; - pHpptClientAll=nullptr; - } -} -void ControlTestWidget::refreshLable() -{ - ui->labelTestScreen->setText(tr("Test Screen")); - ui->groupBox->setTitle(tr("Line test")); - ui->radioButtonRed->setText(tr("Red")); - ui->radioButtonGreen->setText(tr("Green")); - ui->radioButtonBlue->setText(tr("Blue")); - ui->radioButtonWhite->setText(tr("White")); - ui->radioButton_red->setText(tr("Red")); - ui->radioButton_Green->setText(tr("Green")); - ui->radioButton_Blue->setText(tr("Blue")); - ui->radioButton_White->setText(tr("White")); - ui->checkBoxVertical->setText(tr("Vertical")); - ui->checkBoxHorizontal->setText(tr("Horizontal")); - ui->checkBoxSlash->setText(tr("Slash")); - ui->label->setText(tr("Speed")); - ui->label_5->setText(tr("ms(>10)")); - ui->checkBoxHorizontal->setText(tr("Horizontal")); - ui->label_2->setText(tr("Line Distance")); - ui->pushButtonStartLine->setText(tr("Test")); - ui->groupBox_2->setTitle(tr("Gradation test")); - ui->checkBoxShowInfo->setText(tr("Only the gray value is displayed")); - ui->checkBox_red->setText(tr("Red")); - ui->checkBox_green->setText(tr("Green")); - ui->checkBox_blue->setText(tr("Blue")); - ui->checkBox_white->setText(tr("White")); - ui->label_3->setText(tr("Speed")); - ui->label_4->setText(tr("GrayValue")); - ui->pushButtonStartGray->setText(tr("Test")); - ui->groupBox_3->setTitle(tr("Color test")); - ui->checkBoxGradient->setText(tr("Gradient")); - ui->radioButton_red->setText(tr("Red")); - ui->radioButton_Green->setText(tr("Green")); - ui->radioButton_Blue->setText(tr("Blue")); - ui->radioButton_White->setText(tr("White")); - ui->pushButtonStopTest->setText(tr("Stop")); - ui->pushButton_11->setText(tr("Clear")); - ui->pushButton_12->setText(tr("Reset")); - ui->pushButton_13->setText(tr("Anycast")); - -} -void ControlTestWidget::OnStartTestLine() -{ - if(m_pLedlist==nullptr) - return; - if(m_pLedlist->count()<=1) - { - if(m_pLedCard==nullptr||m_pLedlist->count()==0) - { - X_UIMsgBoxOk *pDlg=new X_UIMsgBoxOk(tr("Tip"),tr("NoSelectedController"),this,1); - pDlg->exec(); - return; - } - } - - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "TestScreen"); - json.insert("mode", 1);// 0:停止; 1:斜线; 2:灰度; 3:颜色;4:渐变 - json.insert("speed", ui->spinBoxLineSpeed->value()); - if(ui->radioButtonRed->isChecked()) - json.insert("color", "#FFFF0000"); - else if(ui->radioButtonGreen->isChecked()) - json.insert("color", "#FF00FF00"); - else if(ui->radioButtonBlue->isChecked()) - json.insert("color", "#FF0000FF"); - else - json.insert("color", "#FFFFFFFF"); - - json.insert("interval", ui->spinBoxLineDistance->value()); - json.insert("horizonalLine", ui->checkBoxHorizontal->isChecked()); - json.insert("verticalLine", ui->checkBoxVertical->isChecked()); - json.insert("slantLine", ui->checkBoxSlash->isChecked()); - json.insert("runLimit", ui->spinBoxGrayValue->value()); - json.insert("showInfo", !ui->checkBoxShowInfo->isChecked()); - json.insert("red", ui->checkBox_red->isChecked()); - json.insert("green", ui->checkBox_green->isChecked()); - json.insert("blue", ui->checkBox_blue->isChecked()); - json.insert("white", ui->checkBox_white->isChecked()); - - MACRO_DEFINE_TIPDLG_FUCN(tr("StartTest"),tr("Success"),tr("failed")) - -} -void ControlTestWidget::OnStartTestGray() -{ - if(m_pLedlist==nullptr) - return; - if(m_pLedlist->count()<=1) - { - if(m_pLedCard==nullptr||m_pLedlist->count()==0) - { - X_UIMsgBoxOk *pDlg=new X_UIMsgBoxOk(tr("Tip"),tr("NoSelectedController"),this,1); - pDlg->exec(); - return; - } - } - - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "TestScreen"); - json.insert("mode", 2);// 0:停止; 1:斜线; 2:灰度; 3:颜色;4:渐变 - json.insert("speed", ui->spinBoxGraySpeed->value()); - // qDebug()<<"speed="<spinBoxGraySpeed->value(); - if(ui->radioButtonRed->isChecked()) - json.insert("color", "#FFFF0000"); - else if(ui->radioButtonGreen->isChecked()) - json.insert("color", "#FF00FF00"); - else if(ui->radioButtonBlue->isChecked()) - json.insert("color", "#FF0000FF"); - else - json.insert("color", "#FFFFFFFF"); - json.insert("interval", ui->spinBoxLineDistance->value()); - json.insert("horizonalLine", ui->checkBoxHorizontal->isChecked()); - json.insert("verticalLine", ui->checkBoxVertical->isChecked()); - json.insert("slantLine", ui->checkBoxSlash->isChecked()); - json.insert("runLimit", ui->spinBoxGrayValue->value()); - json.insert("showInfo", !ui->checkBoxShowInfo->isChecked()); - json.insert("red", ui->checkBox_red->isChecked()); - json.insert("green", ui->checkBox_green->isChecked()); - json.insert("blue", ui->checkBox_blue->isChecked()); - json.insert("white", ui->checkBox_white->isChecked()); - - MACRO_DEFINE_TIPDLG_FUCN(tr("StartTest"),tr("Success"),tr("failed")) - -} -void ControlTestWidget::OnStartTestColor() -{ - if(m_pLedlist==nullptr) - return; - if(m_pLedlist->count()<=1) - { - if(m_pLedCard==nullptr||m_pLedlist->count()==0) - { - X_UIMsgBoxOk *pDlg=new X_UIMsgBoxOk(tr("Tip"),tr("NoSelectedController"),this,1); - pDlg->exec(); - return; - } - } - - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "TestScreen"); - if(ui->checkBoxGradient->isChecked()) - json.insert("mode", 4);// 0:停止; 1:斜线; 2:灰度; 3:颜色;4:渐变 - else - json.insert("mode", 3);// 0:停止; 1:斜线; 2:灰度; 3:颜色;4:渐变 - json.insert("speed", ui->spinBoxLineSpeed->value()); - if(ui->radioButton_red->isChecked()) - json.insert("color", "#FFFF0000"); - else if(ui->radioButton_Green->isChecked()) - json.insert("color", "#FF00FF00"); - else if(ui->radioButton_Blue->isChecked()) - json.insert("color", "#FF0000FF"); - else - json.insert("color", "#FFFFFFFF"); - - json.insert("interval", ui->spinBoxLineDistance->value()); - json.insert("horizonalLine", ui->checkBoxHorizontal->isChecked()); - json.insert("verticalLine", ui->checkBoxVertical->isChecked()); - json.insert("slantLine", ui->checkBoxSlash->isChecked()); - json.insert("runLimit", ui->spinBoxGrayValue->value()); - json.insert("showInfo", !ui->checkBoxShowInfo->isChecked()); - json.insert("red", ui->checkBox_red->isChecked()); - json.insert("green", ui->checkBox_green->isChecked()); - json.insert("blue", ui->checkBox_blue->isChecked()); - json.insert("white", ui->checkBox_white->isChecked()); - - MACRO_DEFINE_TIPDLG_FUCN(tr("StartTest"),tr("Success"),tr("failed")) - -} -void ControlTestWidget::OnStopTest() -{ - - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "TestScreen"); - json.insert("mode", 0); - MACRO_DEFINE_TIPDLG_FUCN(tr("StopTest"),tr("Success"),tr("failed")) -} - -void ControlTestWidget::OnpushButton1() -{ - if(ui->lineEdit->text().contains("-")) - ui->lineEdit->clear(); - ui->lineEdit->setText(ui->lineEdit->text()+"1"); - ui->pushButton_13->setEnabled(true); -} -void ControlTestWidget::OnpushButton2() -{ - if(ui->lineEdit->text().contains("-")) - ui->lineEdit->clear(); - ui->lineEdit->setText(ui->lineEdit->text()+"2"); - ui->pushButton_13->setEnabled(true); -} -void ControlTestWidget::OnpushButton3() -{ - if(ui->lineEdit->text().contains("-")) - ui->lineEdit->clear(); - ui->lineEdit->setText(ui->lineEdit->text()+"3"); - ui->pushButton_13->setEnabled(true); -} -void ControlTestWidget::OnpushButton4() -{ - if(ui->lineEdit->text().contains("-")) - ui->lineEdit->clear(); - ui->lineEdit->setText(ui->lineEdit->text()+"4"); - ui->pushButton_13->setEnabled(true); -} -void ControlTestWidget::OnpushButton5() -{ - if(ui->lineEdit->text().contains("-")) - ui->lineEdit->clear(); - ui->lineEdit->setText(ui->lineEdit->text()+"5"); - ui->pushButton_13->setEnabled(true); -} -void ControlTestWidget::OnpushButton6() -{ - if(ui->lineEdit->text().contains("-")) - ui->lineEdit->clear(); - ui->lineEdit->setText(ui->lineEdit->text()+"6"); - ui->pushButton_13->setEnabled(true); -} -void ControlTestWidget::OnpushButton7() -{ - if(ui->lineEdit->text().contains("-")) - ui->lineEdit->clear(); - ui->lineEdit->setText(ui->lineEdit->text()+"7"); - ui->pushButton_13->setEnabled(true); -} -void ControlTestWidget::OnpushButton8() -{ - if(ui->lineEdit->text().contains("-")) - ui->lineEdit->clear(); - ui->lineEdit->setText(ui->lineEdit->text()+"8"); - ui->pushButton_13->setEnabled(true); -} -void ControlTestWidget::OnpushButton9() -{ - if(ui->lineEdit->text().contains("-")) - ui->lineEdit->clear(); - ui->lineEdit->setText(ui->lineEdit->text()+"9"); - ui->pushButton_13->setEnabled(true); -} -void ControlTestWidget::OnpushButton0() -{ - if(ui->lineEdit->text().contains("-")) - ui->lineEdit->clear(); - ui->lineEdit->setText(ui->lineEdit->text()+"0"); - ui->pushButton_13->setEnabled(true); -} -void ControlTestWidget::OnpushButtonClear() -{ - ui->lineEdit->clear(); - ui->pushButton_13->setEnabled(false); -} - -void ControlTestWidget::OnpushButtonReset() -{ - if(m_pLedlist==nullptr) - return; - if(m_pLedCard==nullptr||m_pLedlist->count()==0) - { - X_UIMsgBoxOk *pDlg=new X_UIMsgBoxOk(tr("Tip"),tr("NoSelectedController"),this,1); - pDlg->exec(); - return; - } - int iIndex= ui->lineEdit->text().toInt(); - if(m_pLedlist->count()==1) - { - - SendAnycastCmd(m_pLedCard->m_strCardIp,0); - } - else { - emit sigTcpSend(iIndex); - - } - ui->lineEdit->setText("-"+tr("loopback mode")+"-"); - ui->pushButton_13->setEnabled(false); -} -void ControlTestWidget::OnpushButtonAnycast() -{ - if(m_pLedlist==nullptr) - return; - if(m_pLedCard==nullptr||m_pLedlist->count()==0) - { - X_UIMsgBoxOk *pDlg=new X_UIMsgBoxOk(tr("Tip"),tr("NoSelectedController"),this,1); - pDlg->exec(); - return; - } - int iIndex= ui->lineEdit->text().toInt(); - if(m_pLedlist->count()==1) - { - - SendAnycastCmd(m_pLedCard->m_strCardIp,iIndex); - } - else { - emit sigTcpSend(iIndex); - - } - - - - - - ui->lineEdit->setText(tr("Anycast")+" - "+ui->lineEdit->text()); - ui->pushButton_13->setEnabled(false); -} -void ControlTestWidget::SendAnycastCmd(QString strIp,int iProgramIndex) -{ - - QTcpSocket *send = new QTcpSocket(); - connect(send, SIGNAL(connected()), this, SLOT(connect_sucessful())); - connect(send, SIGNAL(error(QAbstractSocket::SocketError)),this, SLOT(show_error(QAbstractSocket::SocketError))); - send->connectToHost(QHostAddress(strIp),31299); - - ST_ANSY_PROGRAM_PACKET tempStreadPakcet; - tempStreadPakcet.SyncHead[0]=0x7e; - tempStreadPakcet.SyncHead[1]=0x7e; - tempStreadPakcet.SyncHead[2]=0x55; - tempStreadPakcet.ucCommType=0x97; - tempStreadPakcet.iBaoLiu=0; - tempStreadPakcet.iLength=4; - unsigned char uctemp[4]={0}; - uctemp[0]=iProgramIndex; - - memcpy(tempStreadPakcet.pDataBuffer,uctemp,4); - tempStreadPakcet.pDataBuffer[tempStreadPakcet.iLength]=GetCheckCodeIn8(&tempStreadPakcet.ucCommType,tempStreadPakcet.iLength+sizeof(tempStreadPakcet.iBaoLiu)+sizeof(tempStreadPakcet.ucCommType)+sizeof(tempStreadPakcet.iLength)); - int iLenPacket=3*sizeof(unsigned char)+sizeof(char)+sizeof(int)+sizeof(int)+tempStreadPakcet.iLength+sizeof(char);/////除正文外的协议结构大小; - QByteArray databuf = QByteArray(reinterpret_cast(&tempStreadPakcet), iLenPacket); - if(!send->waitForConnected(10000)) //等待连接返回 - { - qDebug()<exec(); - send->close(); - delete send; - return ; - } - send->write(databuf); - if(send->waitForBytesWritten(3000)) - { - QByteArray readBuf=send->read(send->bytesAvailable()); - qDebug()<<"recv anycast success ack"; - if(iProgramIndex==0) - { - X_UIMsgBoxOk *pDlg=new X_UIMsgBoxOk(tr("Tip"),tr("Reset loop mode")+":"+tr("success"),this,1); - pDlg->exec(); - - } - else { - X_UIMsgBoxOk *pDlg=new X_UIMsgBoxOk(tr("Tip"),tr("Anycast")+":"+tr("success"),this,1); - pDlg->exec(); - - } - //emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("Anycast")+":"+tr("success")); - } - send->close(); - delete send; - -} -void ControlTestWidget::onSelectedDeviceList(QList *list) -{ - m_pLedlist=list; - MACRO_DEFINE_CONTROL_FUNC3 -} -void ControlTestWidget::OnControlTypeSwitchIndexChanged(int index) -{ - if(index==Setting_Encrypt) - { - m_bSelected=true; - if(m_pLedCard!=nullptr) - onReadbackAllThisPage(); - } - else { - m_bSelected=false; - } -} -void ControlTestWidget::onReadbackAllThisPage() -{ - if(m_pLedlist==nullptr) - return; - if(m_pLedlist->count()!=1) - return; -} -//获取到httpPost的应答,如果参数变化需要出发修改控件item的内容 -void ControlTestWidget::OnProHttpResponse(QString url, QString postMD5, QByteArray data) -{ - Q_UNUSED(postMD5) - //qDebug()<< url + "\r\n"+m_strUrl; - if(url == m_strUrl) - { - QJsonParseError parseJsonErr; - QJsonDocument document = QJsonDocument::fromJson(data,&parseJsonErr); - if(!(parseJsonErr.error == QJsonParseError::NoError)) - { - if(data.size()==0) - qDebug()<<"json is empty"; - else - qDebug()<m_strCardId +"---------"+ strType; - if(strType == "TestScreen") - { - - } - MACRO_ASKTIME_STOP - MACRO_POSTING_DLG_UNLOCK - - } - } -} - -//获取到httpPost的应答,如果参数变化需要出发修改控件item的内容 -void ControlTestWidget::OnProHttpResponseAll(QString url, QString postMD5, QByteArray data) -{ - Q_UNUSED(postMD5) - //qDebug()<< url + "\r\n"+m_strUrl; - if(url == m_strUrl) - { - QJsonParseError parseJsonErr; - QJsonDocument document = QJsonDocument::fromJson(data,&parseJsonErr); - if(!(parseJsonErr.error == QJsonParseError::NoError)) - { - if(data.size()==0) - qDebug()<<"json is empty"; - else - qDebug()<m_strCardId +"---------"+ strType; - if(strType == "TestScreen") - { - - - } - MACRO_ASKTIME_STOP - MACRO_POSTING_DLG_UNLOCK - - } - } -} -void ControlTestWidget::DeletePostingDlg() -{ - if(m_PostingDlg!=nullptr) - { - delete m_PostingDlg; - m_PostingDlg=nullptr; - } -} - - +#include "controltestwidget.h" +#include "ui_controltestwidget.h" +#include "base/x_uimsgboxok.h" +#include "QFileDialog" +#include "QDir" +#include +#include +#include +#include +#include +#include +#include "tools.h" +ControlTestWidget::ControlTestWidget(QWidget *parent,QList *list) : + QWidget(parent), + ui(new Ui::ControlTestWidget) +{ + m_pLedlist=list; + ui->setupUi(this); + refreshLable(); +setStyleSheet(css); + ui->pushButtonStartLine->setProperty("ssType", "progManageTool"); + ui->pushButtonStartGray->setProperty("ssType", "progManageTool"); + ui->pushButtonStartColor->setProperty("ssType", "progManageTool"); + ui->pushButtonStopTest->setProperty("ssType", "progManageTool"); + ui->pushButton->setProperty("ssType", "progManageTool"); + ui->pushButton_2->setProperty("ssType", "progManageTool"); + ui->pushButton_3->setProperty("ssType", "progManageTool"); + ui->pushButton_4->setProperty("ssType", "progManageTool"); + ui->pushButton_5->setProperty("ssType", "progManageTool"); + ui->pushButton_6->setProperty("ssType", "progManageTool"); + ui->pushButton_7->setProperty("ssType", "progManageTool"); + ui->pushButton_8->setProperty("ssType", "progManageTool"); + ui->pushButton_9->setProperty("ssType", "progManageTool"); + ui->pushButton_10->setProperty("ssType", "progManageTool"); + ui->pushButton_11->setProperty("ssType", "progManageTool"); + ui->pushButton_12->setProperty("ssType", "progManageTool"); + ui->pushButton_13->setProperty("ssType", "progManageTool"); + + ui->spinBoxLineSpeed->setValue(10); + ui->spinBoxLineDistance->setValue(15); + ui->spinBoxGraySpeed->setValue(10); + ui->spinBoxGrayValue->setValue(0); + ui->radioButtonWhite->setChecked(true); + ui->radioButton_White->setChecked(true); + ui->checkBoxHorizontal->setChecked(true); + ui->checkBoxVertical->setChecked(true); + ui->checkBoxSlash->setChecked(true); + ui->checkBox_red->setChecked(true); + ui->checkBox_green->setChecked(true); + ui->checkBox_blue->setChecked(true); + ui->checkBox_white->setChecked(true); + + + connect(ui->pushButtonStartLine,SIGNAL(clicked()),this,SLOT(OnStartTestLine())); + connect(ui->pushButtonStartGray,SIGNAL(clicked()),this,SLOT(OnStartTestGray())); + connect(ui->pushButtonStartColor,SIGNAL(clicked()),this,SLOT(OnStartTestColor())); + connect(ui->pushButtonStopTest,SIGNAL(clicked()),this,SLOT(OnStopTest())); + + connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(OnpushButton1())); + connect(ui->pushButton_2,SIGNAL(clicked()),this,SLOT(OnpushButton2())); + connect(ui->pushButton_3,SIGNAL(clicked()),this,SLOT(OnpushButton3())); + connect(ui->pushButton_4,SIGNAL(clicked()),this,SLOT(OnpushButton4())); + connect(ui->pushButton_5,SIGNAL(clicked()),this,SLOT(OnpushButton5())); + connect(ui->pushButton_6,SIGNAL(clicked()),this,SLOT(OnpushButton6())); + connect(ui->pushButton_7,SIGNAL(clicked()),this,SLOT(OnpushButton7())); + connect(ui->pushButton_8,SIGNAL(clicked()),this,SLOT(OnpushButton8())); + connect(ui->pushButton_9,SIGNAL(clicked()),this,SLOT(OnpushButton9())); + connect(ui->pushButton_10,SIGNAL(clicked()),this,SLOT(OnpushButton0())); + connect(ui->pushButton_11,SIGNAL(clicked()),this,SLOT(OnpushButtonClear())); + connect(ui->pushButton_12,SIGNAL(clicked()),this,SLOT(OnpushButtonReset())); + connect(ui->pushButton_13,SIGNAL(clicked()),this,SLOT(OnpushButtonAnycast())); + + ui->pushButton_13->setEnabled(false); + + MARCO_DEFINE_CONTROL_FUNC2(parent->parent(),parent) + + connect(this,SIGNAL(sigTcpSend(int)),parent->parent(),SLOT(OnControlTcpSend(int))); + ui->lineEdit->setValidator(new QIntValidator(0, 100, this)); + + +} + +ControlTestWidget::~ControlTestWidget() +{ + delete ui; + if(pHpptClient != nullptr) + { + qDebug() <<"delete pHpptClient in ~NetComm"; + delete pHpptClient; + pHpptClient=nullptr; + } + if(pHpptClientAll != nullptr) + { + qDebug() <<"delete pHpptClientAll in ~NetComm"; + delete pHpptClientAll; + pHpptClientAll=nullptr; + } +} +void ControlTestWidget::refreshLable() +{ + ui->labelTestScreen->setText(tr("Test Screen")); + ui->groupBox->setTitle(tr("Line test")); + ui->radioButtonRed->setText(tr("Red")); + ui->radioButtonGreen->setText(tr("Green")); + ui->radioButtonBlue->setText(tr("Blue")); + ui->radioButtonWhite->setText(tr("White")); + ui->radioButton_red->setText(tr("Red")); + ui->radioButton_Green->setText(tr("Green")); + ui->radioButton_Blue->setText(tr("Blue")); + ui->radioButton_White->setText(tr("White")); + ui->checkBoxVertical->setText(tr("Vertical")); + ui->checkBoxHorizontal->setText(tr("Horizontal")); + ui->checkBoxSlash->setText(tr("Slash")); + ui->label->setText(tr("Speed")); + ui->label_5->setText(tr("ms(>10)")); + ui->checkBoxHorizontal->setText(tr("Horizontal")); + ui->label_2->setText(tr("Line Distance")); + ui->pushButtonStartLine->setText(tr("Test")); + ui->groupBox_2->setTitle(tr("Gradation test")); + ui->checkBoxShowInfo->setText(tr("Only the gray value is displayed")); + ui->checkBox_red->setText(tr("Red")); + ui->checkBox_green->setText(tr("Green")); + ui->checkBox_blue->setText(tr("Blue")); + ui->checkBox_white->setText(tr("White")); + ui->label_3->setText(tr("Speed")); + ui->label_4->setText(tr("GrayValue")); + ui->pushButtonStartGray->setText(tr("Test")); + ui->groupBox_3->setTitle(tr("Color test")); + ui->checkBoxGradient->setText(tr("Gradient")); + ui->radioButton_red->setText(tr("Red")); + ui->radioButton_Green->setText(tr("Green")); + ui->radioButton_Blue->setText(tr("Blue")); + ui->radioButton_White->setText(tr("White")); + ui->pushButtonStopTest->setText(tr("Stop")); + ui->pushButton_11->setText(tr("Clear")); + ui->pushButton_12->setText(tr("Reset")); + ui->pushButton_13->setText(tr("Anycast")); + +} +void ControlTestWidget::OnStartTestLine() +{ + if(m_pLedlist==nullptr) + return; + if(m_pLedlist->count()<=1) + { + if(m_pLedCard==nullptr||m_pLedlist->count()==0) + { + X_UIMsgBoxOk *pDlg=new X_UIMsgBoxOk(tr("Tip"),tr("NoSelectedController"),this,1); + pDlg->exec(); + return; + } + } + + QJsonObject json; + json.insert("_id", getRandomString(10)); + json.insert("_type", "TestScreen"); + json.insert("mode", 1);// 0:停止; 1:斜线; 2:灰度; 3:颜色;4:渐变 + json.insert("speed", ui->spinBoxLineSpeed->value()); + if(ui->radioButtonRed->isChecked()) + json.insert("color", "#FFFF0000"); + else if(ui->radioButtonGreen->isChecked()) + json.insert("color", "#FF00FF00"); + else if(ui->radioButtonBlue->isChecked()) + json.insert("color", "#FF0000FF"); + else + json.insert("color", "#FFFFFFFF"); + + json.insert("interval", ui->spinBoxLineDistance->value()); + json.insert("horizonalLine", ui->checkBoxHorizontal->isChecked()); + json.insert("verticalLine", ui->checkBoxVertical->isChecked()); + json.insert("slantLine", ui->checkBoxSlash->isChecked()); + json.insert("runLimit", ui->spinBoxGrayValue->value()); + json.insert("showInfo", !ui->checkBoxShowInfo->isChecked()); + json.insert("red", ui->checkBox_red->isChecked()); + json.insert("green", ui->checkBox_green->isChecked()); + json.insert("blue", ui->checkBox_blue->isChecked()); + json.insert("white", ui->checkBox_white->isChecked()); + + MACRO_DEFINE_TIPDLG_FUCN(tr("StartTest"),tr("Success"),tr("failed")) + +} +void ControlTestWidget::OnStartTestGray() +{ + if(m_pLedlist==nullptr) + return; + if(m_pLedlist->count()<=1) + { + if(m_pLedCard==nullptr||m_pLedlist->count()==0) + { + X_UIMsgBoxOk *pDlg=new X_UIMsgBoxOk(tr("Tip"),tr("NoSelectedController"),this,1); + pDlg->exec(); + return; + } + } + + QJsonObject json; + json.insert("_id", getRandomString(10)); + json.insert("_type", "TestScreen"); + json.insert("mode", 2);// 0:停止; 1:斜线; 2:灰度; 3:颜色;4:渐变 + json.insert("speed", ui->spinBoxGraySpeed->value()); + // qDebug()<<"speed="<spinBoxGraySpeed->value(); + if(ui->radioButtonRed->isChecked()) + json.insert("color", "#FFFF0000"); + else if(ui->radioButtonGreen->isChecked()) + json.insert("color", "#FF00FF00"); + else if(ui->radioButtonBlue->isChecked()) + json.insert("color", "#FF0000FF"); + else + json.insert("color", "#FFFFFFFF"); + json.insert("interval", ui->spinBoxLineDistance->value()); + json.insert("horizonalLine", ui->checkBoxHorizontal->isChecked()); + json.insert("verticalLine", ui->checkBoxVertical->isChecked()); + json.insert("slantLine", ui->checkBoxSlash->isChecked()); + json.insert("runLimit", ui->spinBoxGrayValue->value()); + json.insert("showInfo", !ui->checkBoxShowInfo->isChecked()); + json.insert("red", ui->checkBox_red->isChecked()); + json.insert("green", ui->checkBox_green->isChecked()); + json.insert("blue", ui->checkBox_blue->isChecked()); + json.insert("white", ui->checkBox_white->isChecked()); + + MACRO_DEFINE_TIPDLG_FUCN(tr("StartTest"),tr("Success"),tr("failed")) + +} +void ControlTestWidget::OnStartTestColor() +{ + if(m_pLedlist==nullptr) + return; + if(m_pLedlist->count()<=1) + { + if(m_pLedCard==nullptr||m_pLedlist->count()==0) + { + X_UIMsgBoxOk *pDlg=new X_UIMsgBoxOk(tr("Tip"),tr("NoSelectedController"),this,1); + pDlg->exec(); + return; + } + } + + QJsonObject json; + json.insert("_id", getRandomString(10)); + json.insert("_type", "TestScreen"); + if(ui->checkBoxGradient->isChecked()) + json.insert("mode", 4);// 0:停止; 1:斜线; 2:灰度; 3:颜色;4:渐变 + else + json.insert("mode", 3);// 0:停止; 1:斜线; 2:灰度; 3:颜色;4:渐变 + json.insert("speed", ui->spinBoxLineSpeed->value()); + if(ui->radioButton_red->isChecked()) + json.insert("color", "#FFFF0000"); + else if(ui->radioButton_Green->isChecked()) + json.insert("color", "#FF00FF00"); + else if(ui->radioButton_Blue->isChecked()) + json.insert("color", "#FF0000FF"); + else + json.insert("color", "#FFFFFFFF"); + + json.insert("interval", ui->spinBoxLineDistance->value()); + json.insert("horizonalLine", ui->checkBoxHorizontal->isChecked()); + json.insert("verticalLine", ui->checkBoxVertical->isChecked()); + json.insert("slantLine", ui->checkBoxSlash->isChecked()); + json.insert("runLimit", ui->spinBoxGrayValue->value()); + json.insert("showInfo", !ui->checkBoxShowInfo->isChecked()); + json.insert("red", ui->checkBox_red->isChecked()); + json.insert("green", ui->checkBox_green->isChecked()); + json.insert("blue", ui->checkBox_blue->isChecked()); + json.insert("white", ui->checkBox_white->isChecked()); + + MACRO_DEFINE_TIPDLG_FUCN(tr("StartTest"),tr("Success"),tr("failed")) + +} +void ControlTestWidget::OnStopTest() +{ + + QJsonObject json; + json.insert("_id", getRandomString(10)); + json.insert("_type", "TestScreen"); + json.insert("mode", 0); + MACRO_DEFINE_TIPDLG_FUCN(tr("StopTest"),tr("Success"),tr("failed")) +} + +void ControlTestWidget::OnpushButton1() +{ + if(ui->lineEdit->text().contains("-")) + ui->lineEdit->clear(); + ui->lineEdit->setText(ui->lineEdit->text()+"1"); + ui->pushButton_13->setEnabled(true); +} +void ControlTestWidget::OnpushButton2() +{ + if(ui->lineEdit->text().contains("-")) + ui->lineEdit->clear(); + ui->lineEdit->setText(ui->lineEdit->text()+"2"); + ui->pushButton_13->setEnabled(true); +} +void ControlTestWidget::OnpushButton3() +{ + if(ui->lineEdit->text().contains("-")) + ui->lineEdit->clear(); + ui->lineEdit->setText(ui->lineEdit->text()+"3"); + ui->pushButton_13->setEnabled(true); +} +void ControlTestWidget::OnpushButton4() +{ + if(ui->lineEdit->text().contains("-")) + ui->lineEdit->clear(); + ui->lineEdit->setText(ui->lineEdit->text()+"4"); + ui->pushButton_13->setEnabled(true); +} +void ControlTestWidget::OnpushButton5() +{ + if(ui->lineEdit->text().contains("-")) + ui->lineEdit->clear(); + ui->lineEdit->setText(ui->lineEdit->text()+"5"); + ui->pushButton_13->setEnabled(true); +} +void ControlTestWidget::OnpushButton6() +{ + if(ui->lineEdit->text().contains("-")) + ui->lineEdit->clear(); + ui->lineEdit->setText(ui->lineEdit->text()+"6"); + ui->pushButton_13->setEnabled(true); +} +void ControlTestWidget::OnpushButton7() +{ + if(ui->lineEdit->text().contains("-")) + ui->lineEdit->clear(); + ui->lineEdit->setText(ui->lineEdit->text()+"7"); + ui->pushButton_13->setEnabled(true); +} +void ControlTestWidget::OnpushButton8() +{ + if(ui->lineEdit->text().contains("-")) + ui->lineEdit->clear(); + ui->lineEdit->setText(ui->lineEdit->text()+"8"); + ui->pushButton_13->setEnabled(true); +} +void ControlTestWidget::OnpushButton9() +{ + if(ui->lineEdit->text().contains("-")) + ui->lineEdit->clear(); + ui->lineEdit->setText(ui->lineEdit->text()+"9"); + ui->pushButton_13->setEnabled(true); +} +void ControlTestWidget::OnpushButton0() +{ + if(ui->lineEdit->text().contains("-")) + ui->lineEdit->clear(); + ui->lineEdit->setText(ui->lineEdit->text()+"0"); + ui->pushButton_13->setEnabled(true); +} +void ControlTestWidget::OnpushButtonClear() +{ + ui->lineEdit->clear(); + ui->pushButton_13->setEnabled(false); +} + +void ControlTestWidget::OnpushButtonReset() +{ + if(m_pLedlist==nullptr) + return; + if(m_pLedCard==nullptr||m_pLedlist->count()==0) + { + X_UIMsgBoxOk *pDlg=new X_UIMsgBoxOk(tr("Tip"),tr("NoSelectedController"),this,1); + pDlg->exec(); + return; + } + int iIndex= ui->lineEdit->text().toInt(); + if(m_pLedlist->count()==1) + { + + SendAnycastCmd(m_pLedCard->m_strCardIp,0); + } + else { + emit sigTcpSend(iIndex); + + } + ui->lineEdit->setText("-"+tr("loopback mode")+"-"); + ui->pushButton_13->setEnabled(false); +} +void ControlTestWidget::OnpushButtonAnycast() +{ + if(m_pLedlist==nullptr) + return; + if(m_pLedCard==nullptr||m_pLedlist->count()==0) + { + X_UIMsgBoxOk *pDlg=new X_UIMsgBoxOk(tr("Tip"),tr("NoSelectedController"),this,1); + pDlg->exec(); + return; + } + int iIndex= ui->lineEdit->text().toInt(); + if(m_pLedlist->count()==1) + { + + SendAnycastCmd(m_pLedCard->m_strCardIp,iIndex); + } + else { + emit sigTcpSend(iIndex); + + } + + + + + + ui->lineEdit->setText(tr("Anycast")+" - "+ui->lineEdit->text()); + ui->pushButton_13->setEnabled(false); +} +void ControlTestWidget::SendAnycastCmd(QString strIp,int iProgramIndex) +{ + + QTcpSocket *send = new QTcpSocket(); + connect(send, SIGNAL(connected()), this, SLOT(connect_sucessful())); + connect(send, SIGNAL(error(QAbstractSocket::SocketError)),this, SLOT(show_error(QAbstractSocket::SocketError))); + send->connectToHost(QHostAddress(strIp),31299); + + ST_ANSY_PROGRAM_PACKET tempStreadPakcet; + tempStreadPakcet.SyncHead[0]=0x7e; + tempStreadPakcet.SyncHead[1]=0x7e; + tempStreadPakcet.SyncHead[2]=0x55; + tempStreadPakcet.ucCommType=0x97; + tempStreadPakcet.iBaoLiu=0; + tempStreadPakcet.iLength=4; + unsigned char uctemp[4]={0}; + uctemp[0]=iProgramIndex; + + memcpy(tempStreadPakcet.pDataBuffer,uctemp,4); + tempStreadPakcet.pDataBuffer[tempStreadPakcet.iLength]=GetCheckCodeIn8(&tempStreadPakcet.ucCommType,tempStreadPakcet.iLength+sizeof(tempStreadPakcet.iBaoLiu)+sizeof(tempStreadPakcet.ucCommType)+sizeof(tempStreadPakcet.iLength)); + int iLenPacket=3*sizeof(unsigned char)+sizeof(char)+sizeof(int)+sizeof(int)+tempStreadPakcet.iLength+sizeof(char);/////除正文外的协议结构大小; + QByteArray databuf = QByteArray(reinterpret_cast(&tempStreadPakcet), iLenPacket); + if(!send->waitForConnected(10000)) //等待连接返回 + { + qDebug()<exec(); + send->close(); + delete send; + return ; + } + send->write(databuf); + if(send->waitForBytesWritten(3000)) + { + QByteArray readBuf=send->read(send->bytesAvailable()); + qDebug()<<"recv anycast success ack"; + if(iProgramIndex==0) + { + X_UIMsgBoxOk *pDlg=new X_UIMsgBoxOk(tr("Tip"),tr("Reset loop mode")+":"+tr("success"),this,1); + pDlg->exec(); + + } + else { + X_UIMsgBoxOk *pDlg=new X_UIMsgBoxOk(tr("Tip"),tr("Anycast")+":"+tr("success"),this,1); + pDlg->exec(); + + } + //emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("Anycast")+":"+tr("success")); + } + send->close(); + delete send; + +} +void ControlTestWidget::onSelectedDeviceList(QList *list) +{ + m_pLedlist=list; + MACRO_DEFINE_CONTROL_FUNC3 +} +void ControlTestWidget::OnControlTypeSwitchIndexChanged(int index) +{ + if(index==Setting_Encrypt) + { + m_bSelected=true; + if(m_pLedCard!=nullptr) + onReadbackAllThisPage(); + } + else { + m_bSelected=false; + } +} +void ControlTestWidget::onReadbackAllThisPage() +{ + if(m_pLedlist==nullptr) + return; + if(m_pLedlist->count()!=1) + return; +} +//获取到httpPost的应答,如果参数变化需要出发修改控件item的内容 +void ControlTestWidget::OnProHttpResponse(QString url, QString postMD5, QByteArray data) +{ + Q_UNUSED(postMD5) + //qDebug()<< url + "\r\n"+m_strUrl; + if(url == m_strUrl) + { + QJsonParseError parseJsonErr; + QJsonDocument document = QJsonDocument::fromJson(data,&parseJsonErr); + if(!(parseJsonErr.error == QJsonParseError::NoError)) + { + if(data.size()==0) + qDebug()<<"json is empty"; + else + qDebug()< -#include -#include -#include -namespace Ui { -class ControlTestWidget; -} - -class ControlTestWidget : public QWidget -{ - Q_OBJECT - -public: - explicit ControlTestWidget(QWidget *parent = nullptr,QList *m_pLedlist=nullptr); - ~ControlTestWidget(); - -private: - Ui::ControlTestWidget *ui; -protected slots: - void OnStartTestLine(); - void OnStartTestGray(); - void OnStartTestColor(); - void OnStopTest(); - - void OnpushButton1(); - void OnpushButton2(); - void OnpushButton3(); - void OnpushButton4(); - void OnpushButton5(); - void OnpushButton6(); - void OnpushButton7(); - void OnpushButton8(); - void OnpushButton9(); - void OnpushButton0(); - void OnpushButtonClear(); - void OnpushButtonReset(); - void OnpushButtonAnycast(); - void refreshLable(); - //类似的控制操作信号和槽函数和变量定义 - signals: - void sigTcpSend(int); - void sigSend(QJsonObject &,QString); - protected slots: - void DeletePostingDlg(); - void OnProHttpResponse(QString url, QString postMD5, QByteArray data); - void OnProHttpResponseAll(QString url, QString postMD5, QByteArray data); - void onSelectedDeviceList(QList *); - void onReadbackAllThisPage(); - void OnControlTypeSwitchIndexChanged(int index); - private: - QList *m_pLedlist=nullptr; - LedCard *m_pLedCard = nullptr; - LedCard *m_oldLedlist = nullptr; - HpptClient *pHpptClient = nullptr; - HpptClient *pHpptClientAll = nullptr; - QString m_strUrl=""; - LoEmptyDialog * m_PostingDlg=nullptr; - QTimer *m_pGetAskTimer=nullptr; - bool m_bSelected=false; - void SendAnycastCmd(QString strIp,int iProgramIndex); - -}; - -#endif // CONTROLTESTWIDGET_H +#ifndef CONTROLTESTWIDGET_H +#define CONTROLTESTWIDGET_H + +#include +#include +#include +#include +namespace Ui { +class ControlTestWidget; +} + +class ControlTestWidget : public QWidget +{ + Q_OBJECT + +public: + explicit ControlTestWidget(QWidget *parent = nullptr,QList *m_pLedlist=nullptr); + ~ControlTestWidget(); + +private: + Ui::ControlTestWidget *ui; +protected slots: + void OnStartTestLine(); + void OnStartTestGray(); + void OnStartTestColor(); + void OnStopTest(); + + void OnpushButton1(); + void OnpushButton2(); + void OnpushButton3(); + void OnpushButton4(); + void OnpushButton5(); + void OnpushButton6(); + void OnpushButton7(); + void OnpushButton8(); + void OnpushButton9(); + void OnpushButton0(); + void OnpushButtonClear(); + void OnpushButtonReset(); + void OnpushButtonAnycast(); + void refreshLable(); + //类似的控制操作信号和槽函数和变量定义 + signals: + void sigTcpSend(int); + void sigSend(QJsonObject &,QString); + protected slots: + void DeletePostingDlg(); + void OnProHttpResponse(QString url, QString postMD5, QByteArray data); + void OnProHttpResponseAll(QString url, QString postMD5, QByteArray data); + void onSelectedDeviceList(QList *); + void onReadbackAllThisPage(); + void OnControlTypeSwitchIndexChanged(int index); + private: + QList *m_pLedlist=nullptr; + LedCard *m_pLedCard = nullptr; + LedCard *m_oldLedlist = nullptr; + HpptClient *pHpptClient = nullptr; + HpptClient *pHpptClientAll = nullptr; + QString m_strUrl=""; + LoEmptyDialog * m_PostingDlg=nullptr; + QTimer *m_pGetAskTimer=nullptr; + bool m_bSelected=false; + void SendAnycastCmd(QString strIp,int iProgramIndex); + +}; + +#endif // CONTROLTESTWIDGET_H diff --git a/LedOK/wDevicesManager/controltestwidget.ui b/LedOK/device/controltestwidget.ui similarity index 97% rename from LedOK/wDevicesManager/controltestwidget.ui rename to LedOK/device/controltestwidget.ui index 42a8f1a..c23ae96 100644 --- a/LedOK/wDevicesManager/controltestwidget.ui +++ b/LedOK/device/controltestwidget.ui @@ -1,1016 +1,1016 @@ - - - ControlTestWidget - - - - 0 - 0 - 872 - 609 - - - - - 0 - 0 - - - - Form - - - - - - - Arial - 12 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - Test Screen - - - Qt::AlignCenter - - - - - - - Qt::Horizontal - - - - - - - true - - - - - 0 - 0 - 832 - 536 - - - - - - - 0 - - - 10 - - - - - 0 - - - 0 - - - - - Line test - - - - 0 - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Red - - - - - - - Green - - - - - - - Blue - - - - - - - White - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Vertical - - - - - - - Slash - - - - - - - Horizontal - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Speed - - - - - - - 99999 - - - - - - - ms(>10) - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 20 - 20 - - - - - - - - Line Distance - - - - - - - 128 - - - - - - - px - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - 60 - 30 - - - - - 80 - 16777215 - - - - Test - - - - - - - - - - Gradation test - - - - 0 - - - - - Only the gray value is displayed - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Red - - - - - - - Green - - - - - - - Blue - - - - - - - White - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Speed - - - - - - - - 60 - 0 - - - - 10 - - - 99999 - - - - - - - (>10) - - - - - - - GrayValue - - - - - - - 255 - - - - - - - (0-255) - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - 60 - 30 - - - - - 80 - 16777215 - - - - Test - - - - - - - - - - Color test - - - - 0 - - - - - Gradient - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Red - - - - - - - Green - - - - - - - Blue - - - - - - - White - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - 60 - 30 - - - - - 80 - 16777215 - - - - Test - - - - - - - - - - 0 - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 60 - 30 - - - - Stop - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - Qt::Vertical - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - 0 - - - 0 - - - - - - 0 - 36 - - - - - 194 - 16777215 - - - - false - - - color: rgb(0, 255, 0); -background-color: rgb(0, 0, 0); - - - Qt::AlignCenter - - - - - - - QLayout::SetMaximumSize - - - - - - 60 - 0 - - - - - 60 - 30 - - - - 8 - - - - - - - - 60 - 0 - - - - - 60 - 30 - - - - 2 - - - - - - - - 60 - 0 - - - - - 60 - 30 - - - - 3 - - - - - - - - 60 - 0 - - - - - 60 - 30 - - - - 6 - - - - - - - - 60 - 0 - - - - - 60 - 30 - - - - 4 - - - - - - - - 60 - 0 - - - - - 60 - 30 - - - - 5 - - - - - - - - 30 - 30 - - - - - 60 - 0 - - - - - 60 - 30 - - - - 1 - - - - - - - - 60 - 0 - - - - - 60 - 30 - - - - 9 - - - - - - - - 60 - 0 - - - - - 60 - 30 - - - - 7 - - - - - - - - 60 - 0 - - - - - 60 - 30 - - - - 0 - - - - - - - - 60 - 0 - - - - - 60 - 30 - - - - Clear - - - - - - - - 60 - 0 - - - - - 60 - 30 - - - - Reset - - - - - - - - - - 0 - 30 - - - - - 194 - 30 - - - - Anycast - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - - - - + + + ControlTestWidget + + + + 0 + 0 + 872 + 609 + + + + + 0 + 0 + + + + Form + + + + + + + Arial + 12 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Test Screen + + + Qt::AlignCenter + + + + + + + Qt::Horizontal + + + + + + + true + + + + + 0 + 0 + 832 + 536 + + + + + + + 0 + + + 10 + + + + + 0 + + + 0 + + + + + Line test + + + + 0 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Red + + + + + + + Green + + + + + + + Blue + + + + + + + White + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Vertical + + + + + + + Slash + + + + + + + Horizontal + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Speed + + + + + + + 99999 + + + + + + + ms(>10) + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + Line Distance + + + + + + + 128 + + + + + + + px + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 60 + 30 + + + + + 80 + 16777215 + + + + Test + + + + + + + + + + Gradation test + + + + 0 + + + + + Only the gray value is displayed + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Red + + + + + + + Green + + + + + + + Blue + + + + + + + White + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Speed + + + + + + + + 60 + 0 + + + + 10 + + + 99999 + + + + + + + (>10) + + + + + + + GrayValue + + + + + + + 255 + + + + + + + (0-255) + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 60 + 30 + + + + + 80 + 16777215 + + + + Test + + + + + + + + + + Color test + + + + 0 + + + + + Gradient + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Red + + + + + + + Green + + + + + + + Blue + + + + + + + White + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 60 + 30 + + + + + 80 + 16777215 + + + + Test + + + + + + + + + + 0 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 60 + 30 + + + + Stop + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + Qt::Vertical + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 0 + + + 0 + + + + + + 0 + 36 + + + + + 194 + 16777215 + + + + false + + + color: rgb(0, 255, 0); +background-color: rgb(0, 0, 0); + + + Qt::AlignCenter + + + + + + + QLayout::SetMaximumSize + + + + + + 60 + 0 + + + + + 60 + 30 + + + + 8 + + + + + + + + 60 + 0 + + + + + 60 + 30 + + + + 2 + + + + + + + + 60 + 0 + + + + + 60 + 30 + + + + 3 + + + + + + + + 60 + 0 + + + + + 60 + 30 + + + + 6 + + + + + + + + 60 + 0 + + + + + 60 + 30 + + + + 4 + + + + + + + + 60 + 0 + + + + + 60 + 30 + + + + 5 + + + + + + + + 30 + 30 + + + + + 60 + 0 + + + + + 60 + 30 + + + + 1 + + + + + + + + 60 + 0 + + + + + 60 + 30 + + + + 9 + + + + + + + + 60 + 0 + + + + + 60 + 30 + + + + 7 + + + + + + + + 60 + 0 + + + + + 60 + 30 + + + + 0 + + + + + + + + 60 + 0 + + + + + 60 + 30 + + + + Clear + + + + + + + + 60 + 0 + + + + + 60 + 30 + + + + Reset + + + + + + + + + + 0 + 30 + + + + + 194 + 30 + + + + Anycast + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + + diff --git a/LedOK/wDevicesManager/controlvolumeschedule.cpp b/LedOK/device/controlvolumeschedule.cpp similarity index 97% rename from LedOK/wDevicesManager/controlvolumeschedule.cpp rename to LedOK/device/controlvolumeschedule.cpp index 9ff2ccd..4efcdd4 100644 --- a/LedOK/wDevicesManager/controlvolumeschedule.cpp +++ b/LedOK/device/controlvolumeschedule.cpp @@ -1,530 +1,528 @@ -#include "controlvolumeschedule.h" -#include "ui_controlvolumeschedule.h" -#include "base/x_uimsgboxok.h" -#include "QFileDialog" -#include "QDir" -#include -#include -#include -#include -#include -#include -#include "QSettings" -#include "base/x_spinboxdelegate.h" -#include "base/x_timeeditdelegate.h" -#include "base/x_checkboxdelegate.h" -#include "tools.h" -ControlVolumeSchedule::ControlVolumeSchedule(QWidget *parent,QList *list) : - QWidget(parent), - ui(new Ui::ControlVolumeSchedule) -{ - m_pLedlist=list; - ui->setupUi(this); - refreshLable(); -setStyleSheet(Tools::styleSheet()); - ui->pushButtonAdd->setProperty("ssType", "progManageTool"); - ui->pushButtonAdd->setFlat(true); - ui->pushButtonDelete->setProperty("ssType", "progManageTool"); - ui->pushButtonDelete->setFlat(true); - ui->pushButtonClear->setProperty("ssType", "progManageTool"); - ui->pushButtonClear->setFlat(true); - ui->pushButtonApply->setProperty("ssType", "progManageTool"); - ui->pushButtonApply->setFlat(true); - ui->pushButtonImport->setProperty("ssType", "progManageTool"); - ui->pushButtonExport->setProperty("ssType", "progManageTool"); - ui->pushButtonReadback->setProperty("ssType", "progManageTool"); - ui->lineEdit->setText("10"); - m_pModel = new QStandardItemModel(this); - m_pModel->setColumnCount(10); - m_pModel->setHeaderData(0,Qt::Horizontal, tr("Volume value")); - m_pModel->setHeaderData(1,Qt::Horizontal, tr("Start Time")); - m_pModel->setHeaderData(2,Qt::Horizontal, tr("End Time")); - m_pModel->setHeaderData(3,Qt::Horizontal, tr("SUN")); - m_pModel->setHeaderData(4,Qt::Horizontal, tr("MON")); - m_pModel->setHeaderData(5,Qt::Horizontal, tr("TUE")); - m_pModel->setHeaderData(6,Qt::Horizontal, tr("WED")); - m_pModel->setHeaderData(7,Qt::Horizontal, tr("THU")); - m_pModel->setHeaderData(8,Qt::Horizontal, tr("FRI")); - m_pModel->setHeaderData(9,Qt::Horizontal, tr("SAT")); - ui->tableView->setModel(m_pModel); - SpinBoxDelegate *pVolumeDelegate=new SpinBoxDelegate(this,1); - ui->tableView->setItemDelegateForColumn(0,pVolumeDelegate); - - X_timeEditDelegate *pStartTimeDelegate=new X_timeEditDelegate(this); - ui->tableView->setItemDelegateForColumn(1,pStartTimeDelegate); - ui->tableView->setItemDelegateForColumn(2,pStartTimeDelegate); - X_CheckBoxDelegate *WeekDelegate=new X_CheckBoxDelegate(this); - ui->tableView->setItemDelegateForColumn(3,WeekDelegate); - ui->tableView->setItemDelegateForColumn(4,WeekDelegate); - ui->tableView->setItemDelegateForColumn(5,WeekDelegate); - ui->tableView->setItemDelegateForColumn(6,WeekDelegate); - ui->tableView->setItemDelegateForColumn(7,WeekDelegate); - ui->tableView->setItemDelegateForColumn(8,WeekDelegate); - ui->tableView->setItemDelegateForColumn(9,WeekDelegate); - - - ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); - // ui->tableView->verticalHeader()->hide(); - ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows); - ui->tableView->setFocusPolicy(Qt::NoFocus); - - - MARCO_DEFINE_CONTROL_FUNC2(parent->parent()->parent(),parent->parent()) - - connect(ui->pushButtonAdd,SIGNAL(clicked()),this,SLOT(OnClickAdd())); - connect(ui->pushButtonImport,SIGNAL(clicked()),this,SLOT(OnClickImport())); - connect(ui->pushButtonExport,SIGNAL(clicked()),this,SLOT(OnClickExport())); - connect(ui->pushButtonDelete,SIGNAL(clicked()),this,SLOT(OnClickDelete())); - connect(ui->pushButtonClear,SIGNAL(clicked()),this,SLOT(OnClickClear())); - connect(ui->pushButtonApply,SIGNAL(clicked()),this,SLOT(OnClickApply())); - connect(ui->pushButtonReadback,SIGNAL(clicked()),this,SLOT(OnClickReadback())); -} - -ControlVolumeSchedule::~ControlVolumeSchedule() -{ - delete ui; - if(pHpptClient != nullptr) - { - qDebug() <<"delete pHpptClient in ~NetComm"; - delete pHpptClient; - pHpptClient=nullptr; - } - if(pHpptClientAll != nullptr) - { - qDebug() <<"delete pHpptClientAll in ~NetComm"; - delete pHpptClientAll; - pHpptClientAll=nullptr; - } -} -void ControlVolumeSchedule::refreshLable() -{ - ui->pushButtonAdd->setText(tr("Add")); - ui->pushButtonApply->setText(tr("Apply")); - ui->pushButtonClear->setText(tr("Clear")); - ui->pushButtonDelete->setText(tr("Delete")); - ui->pushButtonImport->setText(tr("Import")); - ui->pushButtonExport->setText(tr("Export")); - - ui->labelVolumeScheduleTip->setText(tr("Default volume tip")); - ui->labelDefalutVolume->setText(tr("Default volume")); - -} - -void ControlVolumeSchedule::onSelectedDeviceList(QList *list) -{ - m_pLedlist=list; - if(m_pLedlist==nullptr) - return; - if(m_pLedlist->count()==1) - { - ui->pushButtonReadback->setEnabled(true); - } - else { - ui->pushButtonReadback->setEnabled(false); - } - MACRO_DEFINE_CONTROL_FUNC3 - -} -//获取到httpPost的应答,如果参数变化需要出发修改控件item的内容 -void ControlVolumeSchedule::OnProHttpResponse(QString url, QString postMD5, QByteArray data) -{ - Q_UNUSED(postMD5) - //qDebug()<< url + "\r\n"+m_strUrl; - if(url == m_strUrl) - { - QJsonParseError parseJsonErr; - QJsonDocument document = QJsonDocument::fromJson(data,&parseJsonErr); - if(!(parseJsonErr.error == QJsonParseError::NoError)) - { - if(data.size()==0) - qDebug()<<"json is empty"; - else - qDebug()<m_strCardId +"---------"+ strType; - if(strType == "GetAutoVolumeTask") - { - JieXiJsonTaskVolume(jsonObject["taskVolume"].toObject()); - } - else if(strType == "SetAutoVolumeTask") - { - } - - MACRO_ASKTIME_STOP - MACRO_POSTING_DLG_UNLOCK - - } - } -} -//获取到httpPost的应答,如果参数变化需要出发修改控件item的内容 -void ControlVolumeSchedule::OnProHttpResponseAll(QString url, QString postMD5, QByteArray data) -{ - Q_UNUSED(postMD5) - //qDebug()<< url + "\r\n"+m_strUrl; - if(url == m_strUrl) - { - QJsonParseError parseJsonErr; - QJsonDocument document = QJsonDocument::fromJson(data,&parseJsonErr); - if(!(parseJsonErr.error == QJsonParseError::NoError)) - { - if(data.size()==0) - qDebug()<<"json is empty"; - else - qDebug()<m_strCardId +"---------"+ strType; - if(strType == "GetAutoVolumeTask") - { - emit sigHaveSchedule(JieXiJsonTaskVolume(jsonObject["taskVolume"].toObject())); - - } - } - } -} - -void ControlVolumeSchedule::OnControlTypeSwitchIndexChanged(int index) -{ - if(index==Setting_Volume) - { - m_bSelected=true; - if(m_pLedCard!=nullptr) - onReadbackAllThisPage(); - } - else { - m_bSelected=false; - } -} -void ControlVolumeSchedule::onReadbackAllThisPage() -{ - if(m_pLedlist==nullptr) - return; - if(m_pLedlist->count()!=1) - return; - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "GetAutoVolumeTask"); - HttpPostByTypeJsonObject(pHpptClientAll,m_strUrl,json); - -} -void ControlVolumeSchedule::OnClickAdd() -{ - QList Item; - Item.append(new QStandardItem(tr("10"))); - Item.append(new QStandardItem("00:00")); - Item.append(new QStandardItem("01:00")); -// Item.append(new QStandardItem(true)); -// Item.append(new QStandardItem(true)); -// Item.append(new QStandardItem(true)); -// Item.append(new QStandardItem(true)); -// Item.append(new QStandardItem(true)); -// Item.append(new QStandardItem(true)); -// Item.append(new QStandardItem(true)); - - Item.at(0)->setTextAlignment(Qt::AlignCenter); - Item.at(1)->setTextAlignment(Qt::AlignCenter); - Item.at(2)->setTextAlignment(Qt::AlignCenter); - m_pModel->appendRow(Item); - //m_lineEidt[i]->installEventFilter(this); - //Item.at(0)->setdsetValidator(new QRegExpValidator(rx, this)); - int i=m_pModel->rowCount()-1; - m_pModel->setData(m_pModel->index(i, 3),true,Qt::UserRole); - m_pModel->setData(m_pModel->index(i, 4),true,Qt::UserRole); - m_pModel->setData(m_pModel->index(i, 5),true,Qt::UserRole); - m_pModel->setData(m_pModel->index(i, 6),true,Qt::UserRole); - m_pModel->setData(m_pModel->index(i, 7),true,Qt::UserRole); - m_pModel->setData(m_pModel->index(i, 8),true,Qt::UserRole); - m_pModel->setData(m_pModel->index(i, 9),true,Qt::UserRole); - - if(m_pModel->rowCount()>0) - { - ui->labelVolumeScheduleTip->setVisible(true); - } - else { - ui->labelVolumeScheduleTip->setVisible(false); - } -} -void ControlVolumeSchedule::OnClickImport() { - QSettings settings; - QString strDir="/"; - if(settings.value("lasOpendFileDlgtDir").isValid()) - { - strDir=settings.value("lasOpendFileDlgtDir").toString(); - } - QFileDialog dlg; - QString strBrightScheduleFile = QFileDialog::getOpenFileName(this, "open file dialog", - strDir, - tr("Volume Schedule (*.vols)")); - if(strBrightScheduleFile.isEmpty()) - return; - QFile fJson(strBrightScheduleFile); - if(fJson.open(QIODevice::ReadOnly)){ - QJsonDocument jBrightSchedule = QJsonDocument::fromJson(fJson.readAll()); - QJsonObject oTaskVolume=jBrightSchedule.object(); - JieXiJsonTaskVolume(oTaskVolume); - fJson.close(); - } -} -bool ControlVolumeSchedule::JieXiJsonTaskVolume(QJsonObject oTaskVolume) -{ - OnClickClear(); - QJsonArray items; - QString strDefaultVolume=QString::number(oTaskVolume["defaultVolume"].toInt()); - if(!strDefaultVolume.isEmpty()) - ui->lineEdit->setText(strDefaultVolume); - items=oTaskVolume["items"].toArray(); - for(int i=0;i Item; - Item.append(new QStandardItem(QString::number(item["volume"].toInt()))); - Item.append(new QStandardItem(oSchedule["startTime"].toString())); - Item.append(new QStandardItem(oSchedule["endTime"].toString())); - - Item.at(0)->setTextAlignment(Qt::AlignCenter); - Item.at(1)->setTextAlignment(Qt::AlignCenter); - Item.at(2)->setTextAlignment(Qt::AlignCenter); - //m_lineEidt[i]->installEventFilter(this); - //Item.at(0)->setdsetValidator(new QRegExpValidator(rx, this)); - m_pModel->appendRow(Item); - if(oSchedule["filterType"].toString()=="None") - { - m_pModel->setData(m_pModel->index(i, 3),true,Qt::UserRole); - m_pModel->setData(m_pModel->index(i, 4),true,Qt::UserRole); - m_pModel->setData(m_pModel->index(i, 5),true,Qt::UserRole); - m_pModel->setData(m_pModel->index(i, 6),true,Qt::UserRole); - m_pModel->setData(m_pModel->index(i, 7),true,Qt::UserRole); - m_pModel->setData(m_pModel->index(i, 8),true,Qt::UserRole); - m_pModel->setData(m_pModel->index(i, 9),true,Qt::UserRole); - } - else if(oSchedule["filterType"].toString()=="Week") - { - QJsonArray oWeeks; - oWeeks=oSchedule["weekFilter"].toArray(); - for(int m=0;m<7;m++) - { - bool bHave=false; - for (int j=0;jsetData(m_pModel->index(i, m+3),bHave,Qt::UserRole); - } - } - } - if(items.count()>0) - return true; - else { - return false; - } -} -void ControlVolumeSchedule::OnClickExport() { - QSettings settings; - QString strDir="/"; - if(settings.value("lasOpendFileDlgtDir").isValid()) { - strDir=settings.value("lasOpendFileDlgtDir").toString(); - } - QFileDialog dlg; - QString saveFileName = dlg.getSaveFileName(this, tr("Save File"), strDir, tr("Volume Schedule (*.vols)")); - - if( saveFileName.isEmpty() ) - return; - settings.setValue("lasOpendFileDlgtDir",saveFileName); - QJsonObject oTaskSync=GetJsonObjectVolumeSchedule(); - QJsonDocument tSyncScheduleJsonDoc; - tSyncScheduleJsonDoc.setObject(oTaskSync); - - QFile f(saveFileName); - if(f.open(QIODevice::WriteOnly)) { - f.write(tSyncScheduleJsonDoc.toJson()); - f.close(); - } -} -void ControlVolumeSchedule::OnClickDelete() -{ - if(m_pModel->rowCount()>0) - { - QModelIndexList selected = ui->tableView->selectionModel()->selectedRows(0); - if(selected.count()>0) - m_pModel->removeRows(selected.begin()->row(),selected.count()); - - } - if(m_pModel->rowCount()>0) - { - ui->labelVolumeScheduleTip->setVisible(true); - } - else { - ui->labelVolumeScheduleTip->setVisible(false); - } -} -void ControlVolumeSchedule:: OnClickClear() -{ - //QModelIndexList selected = ui->tableView->selectionModel()->selectedRows(0); - - if(m_pModel->rowCount()>0) - m_pModel->removeRows(0,m_pModel->rowCount()); - if(m_pModel->rowCount()>0) - { - ui->labelVolumeScheduleTip->setVisible(true); - } - else { - ui->labelVolumeScheduleTip->setVisible(false); - } - } -void ControlVolumeSchedule::OnClickApply() -{ - if(m_pLedlist==nullptr) - return; - - if(m_pLedlist->count()<=1) - { - if(m_pLedCard==nullptr||m_pLedlist->count()==0) - { - X_UIMsgBoxOk *pDlg=new X_UIMsgBoxOk(tr("Tip"),tr("NoSelectedController"),this,1); - pDlg->exec(); - return; - } - } - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "SetAutoVolumeTask"); - QJsonObject oTaskVolume=GetJsonObjectVolumeSchedule(); - json.insert("taskVolume", oTaskVolume); - MACRO_DEFINE_TIPDLG_FUCN(tr("SetAutoVolumeTask"),tr("Success"),tr("failed")) - -} -void ControlVolumeSchedule::OnClickReadback() -{ - if(m_pLedlist==nullptr) - return; - if(m_pLedlist->count()<=1) - { - if(m_pLedCard==nullptr||m_pLedlist->count()==0) - { - X_UIMsgBoxOk *pDlg=new X_UIMsgBoxOk(tr("Tip"),tr("NoSelectedController"),this,1); - pDlg->exec(); - return; - } - } - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "GetAutoVolumeTask"); - MACRO_DEFINE_TIPDLG_FUCN(tr("GetAutoVolumeTask"),tr("Success"),tr("failed")) - -} -QJsonObject ControlVolumeSchedule::GetJsonObjectVolumeSchedule() -{ - QJsonObject oTaskVolume; - QJsonArray oItems; - - oTaskVolume["createDate"] = QJsonValue::Null; - oTaskVolume["createBy"] = "alahover"; - oTaskVolume["defaultVolume"] = ui->lineEdit->text().toInt(); - oTaskVolume["volume"] = ui->lineEdit->text().toInt(); - oTaskVolume["name"] = "TimingVolume"; - - - for(int i=0; irowCount(); i++) - { - QJsonObject oItem; - oItem["volume"] = m_pModel->data(m_pModel->index(i, 0)).toInt(); - - QJsonArray oSchedules; - QJsonObject oSchedule; - oSchedule["timeType"] = "Range"; - oSchedule["startTime"] = m_pModel->data(m_pModel->index(i, 1)).toString();; - oSchedule["endTime"] = m_pModel->data(m_pModel->index(i, 2)).toString();; - oSchedule["dateType"] = "All"; - oSchedule["startDate"] = QJsonValue::Null; - oSchedule["endDate"] = QJsonValue::Null; - oSchedule["monthFilter"] = QJsonArray(); - - bool bSun=m_pModel->data(m_pModel->index(i, 3),Qt::UserRole).toBool(); - bool bMon=m_pModel->data(m_pModel->index(i, 4),Qt::UserRole).toBool(); - bool bTur=m_pModel->data(m_pModel->index(i, 5),Qt::UserRole).toBool(); - bool bWed=m_pModel->data(m_pModel->index(i, 6),Qt::UserRole).toBool(); - bool bThu=m_pModel->data(m_pModel->index(i, 7),Qt::UserRole).toBool(); - bool bFri=m_pModel->data(m_pModel->index(i, 8),Qt::UserRole).toBool(); - bool bSat=m_pModel->data(m_pModel->index(i, 9),Qt::UserRole).toBool(); - - - if(bMon && bTur && bWed && bThu && bFri && bSat && bSun) - { - oSchedule["filterType"] = "None"; - oSchedule["weekFilter"] = QJsonArray(); - - } - else { - oSchedule["filterType"] = "Week"; - QJsonArray tempArray; - if( bSun) - { - tempArray.append(0); - } - if(bMon) - { - tempArray.append(1); - } - if(bTur) - { - tempArray.append(2); - } - if( bWed) - { - tempArray.append(3); - } - if( bThu) - { - tempArray.append(4); - } - if( bFri) - { - tempArray.append(5); - } - if( bSat) - { - tempArray.append(6); - } - - - oSchedule["weekFilter"] = tempArray; - - } - - - oSchedules.append(oSchedule); - oItem["schedules"] = oSchedules; - oItems.append(oItem); - } - - oTaskVolume["items"] = oItems; - return oTaskVolume; - -} -void ControlVolumeSchedule::DeletePostingDlg() -{ - if(m_PostingDlg!=nullptr) - { - delete m_PostingDlg; - m_PostingDlg=nullptr; - } -} +#include "controlvolumeschedule.h" +#include "ui_controlvolumeschedule.h" +#include "base/x_uimsgboxok.h" +#include "QFileDialog" +#include "QDir" +#include +#include +#include +#include +#include +#include +#include "QSettings" +#include "base/x_spinboxdelegate.h" +#include "base/x_timeeditdelegate.h" +#include "base/x_checkboxdelegate.h" +#include "tools.h" +ControlVolumeSchedule::ControlVolumeSchedule(QWidget *parent,QList *list) : + QWidget(parent), + ui(new Ui::ControlVolumeSchedule) +{ + m_pLedlist=list; + ui->setupUi(this); + refreshLable(); +setStyleSheet(css); + ui->pushButtonAdd->setProperty("ssType", "progManageTool"); + ui->pushButtonAdd->setFlat(true); + ui->pushButtonDelete->setProperty("ssType", "progManageTool"); + ui->pushButtonDelete->setFlat(true); + ui->pushButtonClear->setProperty("ssType", "progManageTool"); + ui->pushButtonClear->setFlat(true); + ui->pushButtonApply->setProperty("ssType", "progManageTool"); + ui->pushButtonApply->setFlat(true); + ui->pushButtonImport->setProperty("ssType", "progManageTool"); + ui->pushButtonExport->setProperty("ssType", "progManageTool"); + ui->pushButtonReadback->setProperty("ssType", "progManageTool"); + ui->lineEdit->setText("10"); + m_pModel = new QStandardItemModel(this); + m_pModel->setColumnCount(10); + m_pModel->setHeaderData(0,Qt::Horizontal, tr("Volume value")); + m_pModel->setHeaderData(1,Qt::Horizontal, tr("Start Time")); + m_pModel->setHeaderData(2,Qt::Horizontal, tr("End Time")); + m_pModel->setHeaderData(3,Qt::Horizontal, tr("SUN")); + m_pModel->setHeaderData(4,Qt::Horizontal, tr("MON")); + m_pModel->setHeaderData(5,Qt::Horizontal, tr("TUE")); + m_pModel->setHeaderData(6,Qt::Horizontal, tr("WED")); + m_pModel->setHeaderData(7,Qt::Horizontal, tr("THU")); + m_pModel->setHeaderData(8,Qt::Horizontal, tr("FRI")); + m_pModel->setHeaderData(9,Qt::Horizontal, tr("SAT")); + ui->tableView->setModel(m_pModel); + SpinBoxDelegate *pVolumeDelegate=new SpinBoxDelegate(this,1); + ui->tableView->setItemDelegateForColumn(0,pVolumeDelegate); + + X_timeEditDelegate *pStartTimeDelegate=new X_timeEditDelegate(this); + ui->tableView->setItemDelegateForColumn(1,pStartTimeDelegate); + ui->tableView->setItemDelegateForColumn(2,pStartTimeDelegate); + X_CheckBoxDelegate *WeekDelegate=new X_CheckBoxDelegate(this); + ui->tableView->setItemDelegateForColumn(3,WeekDelegate); + ui->tableView->setItemDelegateForColumn(4,WeekDelegate); + ui->tableView->setItemDelegateForColumn(5,WeekDelegate); + ui->tableView->setItemDelegateForColumn(6,WeekDelegate); + ui->tableView->setItemDelegateForColumn(7,WeekDelegate); + ui->tableView->setItemDelegateForColumn(8,WeekDelegate); + ui->tableView->setItemDelegateForColumn(9,WeekDelegate); + + + ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); + // ui->tableView->verticalHeader()->hide(); + ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows); + ui->tableView->setFocusPolicy(Qt::NoFocus); + + + MARCO_DEFINE_CONTROL_FUNC2(parent->parent()->parent(),parent->parent()) + + connect(ui->pushButtonAdd,SIGNAL(clicked()),this,SLOT(OnClickAdd())); + connect(ui->pushButtonImport,SIGNAL(clicked()),this,SLOT(OnClickImport())); + connect(ui->pushButtonExport,SIGNAL(clicked()),this,SLOT(OnClickExport())); + connect(ui->pushButtonDelete,SIGNAL(clicked()),this,SLOT(OnClickDelete())); + connect(ui->pushButtonClear,SIGNAL(clicked()),this,SLOT(OnClickClear())); + connect(ui->pushButtonApply,SIGNAL(clicked()),this,SLOT(OnClickApply())); + connect(ui->pushButtonReadback,SIGNAL(clicked()),this,SLOT(OnClickReadback())); +} + +ControlVolumeSchedule::~ControlVolumeSchedule() +{ + delete ui; + if(pHpptClient != nullptr) + { + qDebug() <<"delete pHpptClient in ~NetComm"; + delete pHpptClient; + pHpptClient=nullptr; + } + if(pHpptClientAll != nullptr) + { + qDebug() <<"delete pHpptClientAll in ~NetComm"; + delete pHpptClientAll; + pHpptClientAll=nullptr; + } +} +void ControlVolumeSchedule::refreshLable() +{ + ui->pushButtonAdd->setText(tr("Add")); + ui->pushButtonApply->setText(tr("Apply")); + ui->pushButtonClear->setText(tr("Clear")); + ui->pushButtonDelete->setText(tr("Delete")); + ui->pushButtonImport->setText(tr("Import")); + ui->pushButtonExport->setText(tr("Export")); + + ui->labelVolumeScheduleTip->setText(tr("Default volume tip")); + ui->labelDefalutVolume->setText(tr("Default volume")); + +} + +void ControlVolumeSchedule::onSelectedDeviceList(QList *list) +{ + m_pLedlist=list; + if(m_pLedlist==nullptr) + return; + if(m_pLedlist->count()==1) + { + ui->pushButtonReadback->setEnabled(true); + } + else { + ui->pushButtonReadback->setEnabled(false); + } + MACRO_DEFINE_CONTROL_FUNC3 + +} +//获取到httpPost的应答,如果参数变化需要出发修改控件item的内容 +void ControlVolumeSchedule::OnProHttpResponse(QString url, QString postMD5, QByteArray data) +{ + Q_UNUSED(postMD5) + //qDebug()<< url + "\r\n"+m_strUrl; + if(url == m_strUrl) + { + QJsonParseError parseJsonErr; + QJsonDocument document = QJsonDocument::fromJson(data,&parseJsonErr); + if(!(parseJsonErr.error == QJsonParseError::NoError)) + { + if(data.size()==0) + qDebug()<<"json is empty"; + else + qDebug()<count()!=1) + return; + QJsonObject json; + json.insert("_id", getRandomString(10)); + json.insert("_type", "GetAutoVolumeTask"); + HttpPostByTypeJsonObject(pHpptClientAll,m_strUrl,json); + +} +void ControlVolumeSchedule::OnClickAdd() +{ + QList Item; + Item.append(new QStandardItem(tr("10"))); + Item.append(new QStandardItem("00:00")); + Item.append(new QStandardItem("01:00")); +// Item.append(new QStandardItem(true)); +// Item.append(new QStandardItem(true)); +// Item.append(new QStandardItem(true)); +// Item.append(new QStandardItem(true)); +// Item.append(new QStandardItem(true)); +// Item.append(new QStandardItem(true)); +// Item.append(new QStandardItem(true)); + + Item.at(0)->setTextAlignment(Qt::AlignCenter); + Item.at(1)->setTextAlignment(Qt::AlignCenter); + Item.at(2)->setTextAlignment(Qt::AlignCenter); + m_pModel->appendRow(Item); + //m_lineEidt[i]->installEventFilter(this); + //Item.at(0)->setdsetValidator(new QRegExpValidator(rx, this)); + int i=m_pModel->rowCount()-1; + m_pModel->setData(m_pModel->index(i, 3),true,Qt::UserRole); + m_pModel->setData(m_pModel->index(i, 4),true,Qt::UserRole); + m_pModel->setData(m_pModel->index(i, 5),true,Qt::UserRole); + m_pModel->setData(m_pModel->index(i, 6),true,Qt::UserRole); + m_pModel->setData(m_pModel->index(i, 7),true,Qt::UserRole); + m_pModel->setData(m_pModel->index(i, 8),true,Qt::UserRole); + m_pModel->setData(m_pModel->index(i, 9),true,Qt::UserRole); + + if(m_pModel->rowCount()>0) + { + ui->labelVolumeScheduleTip->setVisible(true); + } + else { + ui->labelVolumeScheduleTip->setVisible(false); + } +} +void ControlVolumeSchedule::OnClickImport() { + QSettings settings; + QString strDir="/"; + if(settings.value("lasOpendFileDlgtDir").isValid()) + { + strDir=settings.value("lasOpendFileDlgtDir").toString(); + } + QFileDialog dlg; + QString strBrightScheduleFile = QFileDialog::getOpenFileName(this, "open file dialog", + strDir, + tr("Volume Schedule (*.vols)")); + if(strBrightScheduleFile.isEmpty()) + return; + QFile fJson(strBrightScheduleFile); + if(fJson.open(QIODevice::ReadOnly)){ + QJsonDocument jBrightSchedule = QJsonDocument::fromJson(fJson.readAll()); + QJsonObject oTaskVolume=jBrightSchedule.object(); + JieXiJsonTaskVolume(oTaskVolume); + fJson.close(); + } +} +bool ControlVolumeSchedule::JieXiJsonTaskVolume(QJsonObject oTaskVolume) +{ + OnClickClear(); + QJsonArray items; + QString strDefaultVolume=QString::number(oTaskVolume["defaultVolume"].toInt()); + if(!strDefaultVolume.isEmpty()) + ui->lineEdit->setText(strDefaultVolume); + items=oTaskVolume["items"].toArray(); + for(int i=0;i Item; + Item.append(new QStandardItem(QString::number(item["volume"].toInt()))); + Item.append(new QStandardItem(oSchedule["startTime"].toString())); + Item.append(new QStandardItem(oSchedule["endTime"].toString())); + + Item.at(0)->setTextAlignment(Qt::AlignCenter); + Item.at(1)->setTextAlignment(Qt::AlignCenter); + Item.at(2)->setTextAlignment(Qt::AlignCenter); + //m_lineEidt[i]->installEventFilter(this); + //Item.at(0)->setdsetValidator(new QRegExpValidator(rx, this)); + m_pModel->appendRow(Item); + if(oSchedule["filterType"].toString()=="None") + { + m_pModel->setData(m_pModel->index(i, 3),true,Qt::UserRole); + m_pModel->setData(m_pModel->index(i, 4),true,Qt::UserRole); + m_pModel->setData(m_pModel->index(i, 5),true,Qt::UserRole); + m_pModel->setData(m_pModel->index(i, 6),true,Qt::UserRole); + m_pModel->setData(m_pModel->index(i, 7),true,Qt::UserRole); + m_pModel->setData(m_pModel->index(i, 8),true,Qt::UserRole); + m_pModel->setData(m_pModel->index(i, 9),true,Qt::UserRole); + } + else if(oSchedule["filterType"].toString()=="Week") + { + QJsonArray oWeeks; + oWeeks=oSchedule["weekFilter"].toArray(); + for(int m=0;m<7;m++) + { + bool bHave=false; + for (int j=0;jsetData(m_pModel->index(i, m+3),bHave,Qt::UserRole); + } + } + } + if(items.count()>0) + return true; + else { + return false; + } +} +void ControlVolumeSchedule::OnClickExport() { + QSettings settings; + QString strDir="/"; + if(settings.value("lasOpendFileDlgtDir").isValid()) { + strDir=settings.value("lasOpendFileDlgtDir").toString(); + } + QFileDialog dlg; + QString saveFileName = dlg.getSaveFileName(this, tr("Save File"), strDir, tr("Volume Schedule (*.vols)")); + + if( saveFileName.isEmpty() ) + return; + settings.setValue("lasOpendFileDlgtDir",saveFileName); + QJsonObject oTaskSync=GetJsonObjectVolumeSchedule(); + QJsonDocument tSyncScheduleJsonDoc; + tSyncScheduleJsonDoc.setObject(oTaskSync); + + QFile f(saveFileName); + if(f.open(QIODevice::WriteOnly)) { + f.write(tSyncScheduleJsonDoc.toJson()); + f.close(); + } +} +void ControlVolumeSchedule::OnClickDelete() +{ + if(m_pModel->rowCount()>0) + { + QModelIndexList selected = ui->tableView->selectionModel()->selectedRows(0); + if(selected.count()>0) + m_pModel->removeRows(selected.begin()->row(),selected.count()); + + } + if(m_pModel->rowCount()>0) + { + ui->labelVolumeScheduleTip->setVisible(true); + } + else { + ui->labelVolumeScheduleTip->setVisible(false); + } +} +void ControlVolumeSchedule:: OnClickClear() +{ + //QModelIndexList selected = ui->tableView->selectionModel()->selectedRows(0); + + if(m_pModel->rowCount()>0) + m_pModel->removeRows(0,m_pModel->rowCount()); + if(m_pModel->rowCount()>0) + { + ui->labelVolumeScheduleTip->setVisible(true); + } + else { + ui->labelVolumeScheduleTip->setVisible(false); + } + } +void ControlVolumeSchedule::OnClickApply() +{ + if(m_pLedlist==nullptr) + return; + + if(m_pLedlist->count()<=1) + { + if(m_pLedCard==nullptr||m_pLedlist->count()==0) + { + X_UIMsgBoxOk *pDlg=new X_UIMsgBoxOk(tr("Tip"),tr("NoSelectedController"),this,1); + pDlg->exec(); + return; + } + } + QJsonObject json; + json.insert("_id", getRandomString(10)); + json.insert("_type", "SetAutoVolumeTask"); + QJsonObject oTaskVolume=GetJsonObjectVolumeSchedule(); + json.insert("taskVolume", oTaskVolume); + MACRO_DEFINE_TIPDLG_FUCN(tr("SetAutoVolumeTask"),tr("Success"),tr("failed")) + +} +void ControlVolumeSchedule::OnClickReadback() +{ + if(m_pLedlist==nullptr) + return; + if(m_pLedlist->count()<=1) + { + if(m_pLedCard==nullptr||m_pLedlist->count()==0) + { + X_UIMsgBoxOk *pDlg=new X_UIMsgBoxOk(tr("Tip"),tr("NoSelectedController"),this,1); + pDlg->exec(); + return; + } + } + QJsonObject json; + json.insert("_id", getRandomString(10)); + json.insert("_type", "GetAutoVolumeTask"); + MACRO_DEFINE_TIPDLG_FUCN(tr("GetAutoVolumeTask"),tr("Success"),tr("failed")) + +} +QJsonObject ControlVolumeSchedule::GetJsonObjectVolumeSchedule() +{ + QJsonObject oTaskVolume; + QJsonArray oItems; + + oTaskVolume["createDate"] = QJsonValue::Null; + oTaskVolume["createBy"] = "alahover"; + oTaskVolume["defaultVolume"] = ui->lineEdit->text().toInt(); + oTaskVolume["volume"] = ui->lineEdit->text().toInt(); + oTaskVolume["name"] = "TimingVolume"; + + + for(int i=0; irowCount(); i++) + { + QJsonObject oItem; + oItem["volume"] = m_pModel->data(m_pModel->index(i, 0)).toInt(); + + QJsonArray oSchedules; + QJsonObject oSchedule; + oSchedule["timeType"] = "Range"; + oSchedule["startTime"] = m_pModel->data(m_pModel->index(i, 1)).toString();; + oSchedule["endTime"] = m_pModel->data(m_pModel->index(i, 2)).toString();; + oSchedule["dateType"] = "All"; + oSchedule["startDate"] = QJsonValue::Null; + oSchedule["endDate"] = QJsonValue::Null; + oSchedule["monthFilter"] = QJsonArray(); + + bool bSun=m_pModel->data(m_pModel->index(i, 3),Qt::UserRole).toBool(); + bool bMon=m_pModel->data(m_pModel->index(i, 4),Qt::UserRole).toBool(); + bool bTur=m_pModel->data(m_pModel->index(i, 5),Qt::UserRole).toBool(); + bool bWed=m_pModel->data(m_pModel->index(i, 6),Qt::UserRole).toBool(); + bool bThu=m_pModel->data(m_pModel->index(i, 7),Qt::UserRole).toBool(); + bool bFri=m_pModel->data(m_pModel->index(i, 8),Qt::UserRole).toBool(); + bool bSat=m_pModel->data(m_pModel->index(i, 9),Qt::UserRole).toBool(); + + + if(bMon && bTur && bWed && bThu && bFri && bSat && bSun) + { + oSchedule["filterType"] = "None"; + oSchedule["weekFilter"] = QJsonArray(); + + } + else { + oSchedule["filterType"] = "Week"; + QJsonArray tempArray; + if( bSun) + { + tempArray.append(0); + } + if(bMon) + { + tempArray.append(1); + } + if(bTur) + { + tempArray.append(2); + } + if( bWed) + { + tempArray.append(3); + } + if( bThu) + { + tempArray.append(4); + } + if( bFri) + { + tempArray.append(5); + } + if( bSat) + { + tempArray.append(6); + } + + + oSchedule["weekFilter"] = tempArray; + + } + + + oSchedules.append(oSchedule); + oItem["schedules"] = oSchedules; + oItems.append(oItem); + } + + oTaskVolume["items"] = oItems; + return oTaskVolume; + +} +void ControlVolumeSchedule::DeletePostingDlg() +{ + if(m_PostingDlg!=nullptr) + { + delete m_PostingDlg; + m_PostingDlg=nullptr; + } +} diff --git a/LedOK/wDevicesManager/controlvolumeschedule.h b/LedOK/device/controlvolumeschedule.h similarity index 95% rename from LedOK/wDevicesManager/controlvolumeschedule.h rename to LedOK/device/controlvolumeschedule.h index 72770bb..85cf53f 100644 --- a/LedOK/wDevicesManager/controlvolumeschedule.h +++ b/LedOK/device/controlvolumeschedule.h @@ -1,60 +1,60 @@ -#ifndef CONTROLVOLUMESCHEDULE_H -#define CONTROLVOLUMESCHEDULE_H - -#include -#include -#include -#include -#include -#include - -namespace Ui { -class ControlVolumeSchedule; -} - -class ControlVolumeSchedule : public QWidget -{ - Q_OBJECT - -public: - explicit ControlVolumeSchedule(QWidget *parent = nullptr,QList *m_pLedlist=nullptr); - ~ControlVolumeSchedule(); -protected slots: - void refreshLable(); - void OnClickAdd(); - void OnClickImport(); - void OnClickExport(); - void OnClickDelete(); - void OnClickClear(); - void OnClickApply(); - void OnClickReadback(); -private: - Ui::ControlVolumeSchedule *ui; - //类似的控制操作信号和槽函数和变量定义 - signals: - void sigSend(QJsonObject &,QString); - void sigHaveSchedule(bool); - protected slots: - void DeletePostingDlg(); - void OnProHttpResponse(QString url, QString postMD5, QByteArray data); - void OnProHttpResponseAll(QString url, QString postMD5, QByteArray data); - void onSelectedDeviceList(QList *); - void onReadbackAllThisPage(); - void OnControlTypeSwitchIndexChanged(int index); - private: - QList *m_pLedlist=nullptr; - LedCard *m_pLedCard = nullptr; - LedCard *m_oldLedlist = nullptr; - HpptClient *pHpptClient = nullptr; - HpptClient *pHpptClientAll = nullptr; - QString m_strUrl=""; - LoEmptyDialog * m_PostingDlg=nullptr; - QTimer *m_pGetAskTimer=nullptr; - bool m_bSelected=false; - QStandardItemModel * m_pModel; - bool JieXiJsonTaskVolume(QJsonObject oTaskVolume); - QJsonObject GetJsonObjectVolumeSchedule(); - -}; - -#endif // CONTROLVOLUMESCHEDULE_H +#ifndef CONTROLVOLUMESCHEDULE_H +#define CONTROLVOLUMESCHEDULE_H + +#include +#include +#include +#include +#include +#include + +namespace Ui { +class ControlVolumeSchedule; +} + +class ControlVolumeSchedule : public QWidget +{ + Q_OBJECT + +public: + explicit ControlVolumeSchedule(QWidget *parent = nullptr,QList *m_pLedlist=nullptr); + ~ControlVolumeSchedule(); + void refreshLable(); +protected slots: + void OnClickAdd(); + void OnClickImport(); + void OnClickExport(); + void OnClickDelete(); + void OnClickClear(); + void OnClickApply(); + void OnClickReadback(); +private: + Ui::ControlVolumeSchedule *ui; + //类似的控制操作信号和槽函数和变量定义 + signals: + void sigSend(QJsonObject &,QString); + void sigHaveSchedule(bool); + protected slots: + void DeletePostingDlg(); + void OnProHttpResponse(QString url, QString postMD5, QByteArray data); + void OnProHttpResponseAll(QString url, QString postMD5, QByteArray data); + void onSelectedDeviceList(QList *); + void onReadbackAllThisPage(); + void OnControlTypeSwitchIndexChanged(int index); + private: + QList *m_pLedlist=nullptr; + LedCard *m_pLedCard = nullptr; + LedCard *m_oldLedlist = nullptr; + HpptClient *pHpptClient = nullptr; + HpptClient *pHpptClientAll = nullptr; + QString m_strUrl=""; + LoEmptyDialog * m_PostingDlg=nullptr; + QTimer *m_pGetAskTimer=nullptr; + bool m_bSelected=false; + QStandardItemModel * m_pModel; + bool JieXiJsonTaskVolume(QJsonObject oTaskVolume); + QJsonObject GetJsonObjectVolumeSchedule(); + +}; + +#endif // CONTROLVOLUMESCHEDULE_H diff --git a/LedOK/wDevicesManager/controlvolumeschedule.ui b/LedOK/device/controlvolumeschedule.ui similarity index 96% rename from LedOK/wDevicesManager/controlvolumeschedule.ui rename to LedOK/device/controlvolumeschedule.ui index bfda2a2..7bfb54f 100644 --- a/LedOK/wDevicesManager/controlvolumeschedule.ui +++ b/LedOK/device/controlvolumeschedule.ui @@ -1,251 +1,251 @@ - - - ControlVolumeSchedule - - - - 0 - 0 - 708 - 447 - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - Defalut volume tip - - - true - - - - - - - - - 10 - - - 0 - - - - - - 60 - 30 - - - - Add - - - - - - - - 60 - 30 - - - - Delete - - - - - - - - 60 - 30 - - - - Clear - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Default Volume - - - - - - - - 30 - 16777215 - - - - background-color: #FFFFFF; - - - - - - - (0-15) - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 30 - - - - Import - - - - - - - - 0 - 30 - - - - Export - - - - - - - - - background-color: #FFFFFF; - - - - - - - 0 - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 60 - 30 - - - - Apply - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 30 - - - - Readback - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - - - - + + + ControlVolumeSchedule + + + + 0 + 0 + 708 + 447 + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Defalut volume tip + + + true + + + + + + + + + 10 + + + 0 + + + + + + 60 + 30 + + + + Add + + + + + + + + 60 + 30 + + + + Delete + + + + + + + + 60 + 30 + + + + Clear + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Default Volume + + + + + + + + 30 + 16777215 + + + + background-color: #FFFFFF; + + + + + + + (0-15) + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 30 + + + + Import + + + + + + + + 0 + 30 + + + + Export + + + + + + + + + background-color: #FFFFFF; + + + + + + + 0 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 60 + 30 + + + + Apply + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 30 + + + + Readback + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + + diff --git a/LedOK/device/controlvolumewidget.cpp b/LedOK/device/controlvolumewidget.cpp new file mode 100644 index 0000000..66a8baf --- /dev/null +++ b/LedOK/device/controlvolumewidget.cpp @@ -0,0 +1,154 @@ +#include "controlvolumewidget.h" +#include "gutil/qgui.h" +#include "globaldefine.h" +#include "base/waitingdlg.h" +#include "tools.h" +#include + +ControlVolumeWidget::ControlVolumeWidget(QWidget *parent,QList *list) : QWidget(parent) { + auto vBox = new VBox(this); + + lbVolumeControl = new QLabel; + lbVolumeControl->setAlignment(Qt::AlignCenter); + vBox->addWidget(lbVolumeControl); + + auto hBox = new HBox(vBox); + hBox->addStretch(); + + fdManual = new QRadioButton; + hBox->addWidget(fdManual); + hBox->addSpacing(40); + + fdSchedule = new QRadioButton; + hBox->addWidget(fdSchedule); + hBox->addStretch(); + + auto stack = new QStackedLayout(vBox); + { + auto vBox = new VBox(stack); + vBox->addSpacing(20); + + auto hBox = new HBox(vBox); + hBox->addStretch(); + + lbVolume = new QLabel; + hBox->addWidget(lbVolume); + + fdVolume = new QSlider(Qt::Horizontal); + fdVolume->setTickPosition(QSlider::TicksAbove); + fdVolume->setRange(0, 15); + connect(fdVolume, &QSlider::sliderReleased, this, [=] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "SetVolume"); + json.insert("_type", "SetVolume"); + json.insert("volume", fdVolume->value()); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("SetVolume")+" ..."); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("SetVolume")) + } + } + }); + hBox->addWidget(fdVolume); + + auto lbCurVol = new QLabel; + lbCurVol->setMinimumWidth(30); + connect(fdVolume, &QSlider::valueChanged, lbCurVol, (void(QLabel::*)(int))&QLabel::setNum); + hBox->addWidget(lbCurVol); + hBox->addStretch(); + + fdVolumeGet = new QPushButton; + fdVolumeGet->setMinimumSize(QSize(60, 30)); + fdVolumeGet->setProperty("ssType", "progManageTool"); + connect(fdVolumeGet, &QPushButton::clicked, this, [=] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "GetVolume"); + json.insert("_type", "GetVolume"); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("GetVolume")+" ..."); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg] { + Def_CtrlSingleGetReply + waitingDlg->success(); + fdVolume->setValue(json["volume"].toInt()); + }); + } else { + foreach(auto card, *gSelCards) { + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + auto cardId = card->m_strCardId; + connect(reply, &QNetworkReply::finished, this, [reply, cardId] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(err.isEmpty()) err = QString::number(json["volume"].toInt()); + gFdResInfo->append(cardId+" "+tr("GetVolume")+" "+err); + }); + } + } + }); + vBox->addWidget(fdVolumeGet, 0, Qt::AlignCenter); + vBox->addStretch(); + } + m_pSchedule = new ControlVolumeSchedule(this, list); + connect(m_pSchedule, &ControlVolumeSchedule::sigHaveSchedule, this, [=](bool b) { + if(b) fdSchedule->setChecked(true); + else fdManual->setChecked(true); + }); + stack->addWidget(m_pSchedule); + + connect(fdSchedule, &QRadioButton::toggled, stack, &QStackedLayout::setCurrentIndex); + fdManual->setChecked(true); + + connect(gDevicePanel, &DevicePanel::sigSelectedDeviceList, this, [this] { + if(isVisible()) init(); + }); + transUi(); +} + +void ControlVolumeWidget::showEvent(QShowEvent *event) { + QWidget::showEvent(event); + init(); +} +void ControlVolumeWidget::init() { + bool isSingle = gSelCards->count()==1; + if(! isSingle) return; + auto card = gSelCards->at(0); + + QJsonObject json; + json.insert("_id", "GetVolume"); + json.insert("_type", "GetVolume"); + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + connect(reply, &QNetworkReply::finished, this, [this, reply] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) return; + fdVolume->setValue(json["volume"].toInt()); + }); +} + +void ControlVolumeWidget::changeEvent(QEvent *event) { + QWidget::changeEvent(event); + if(event->type() == QEvent::LanguageChange) transUi(); +} +void ControlVolumeWidget::transUi() { + lbVolumeControl->setText(tr("Volume Control")); + fdManual->setText(tr("Manual")); + fdSchedule->setText(tr("Schedule")); + + lbVolume->setText(tr("Volume")); + fdVolumeGet->setText(tr("Readback")); + + m_pSchedule->refreshLable(); +} diff --git a/LedOK/device/controlvolumewidget.h b/LedOK/device/controlvolumewidget.h new file mode 100644 index 0000000..d9a14db --- /dev/null +++ b/LedOK/device/controlvolumewidget.h @@ -0,0 +1,31 @@ +#ifndef CONTROLVOLUMEWIDGET_H +#define CONTROLVOLUMEWIDGET_H + +#include +#include +#include "QStackedWidget" +#include + +class ControlVolumeWidget : public QWidget { + Q_OBJECT +public: + explicit ControlVolumeWidget(QWidget *parent = nullptr,QList *m_pLedlist=nullptr); +protected: + void showEvent(QShowEvent *event) override; + void init(); + void changeEvent(QEvent *) override; + void transUi(); + +private: + ControlVolumeSchedule *m_pSchedule; + + QLabel *lbVolumeControl; + QRadioButton *fdManual; + QRadioButton *fdSchedule; + + QLabel *lbVolume; + QSlider *fdVolume; + QPushButton *fdVolumeGet; +}; + +#endif // CONTROLVOLUMEWIDGET_H diff --git a/LedOK/device/ctrladvancedpanel.cpp b/LedOK/device/ctrladvancedpanel.cpp new file mode 100644 index 0000000..3d68ac5 --- /dev/null +++ b/LedOK/device/ctrladvancedpanel.cpp @@ -0,0 +1,2436 @@ +#include "ctrladvancedpanel.h" +#include "deviceitem.h" +#include "globaldefine.h" +#include "base/waitingdlg.h" +#include "base/changepasswordform.h" +#include "base/updateledset3dialog.h" +#include "passwordindlg.h" +#include "tools.h" +#include "gutil/qgui.h" +#include "gutil/qnetwork.h" +#include "program/ephoto.h" +#include "upgradeapkdialog.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +CtrlAdvancedPanel::CtrlAdvancedPanel(QWidget *parent) : QWidget(parent) { + setFocusPolicy(Qt::StrongFocus); + + auto vBox = new QVBoxLayout(this); + + lbTitle = new QLabel; + lbTitle->setAlignment(Qt::AlignCenter); + vBox->addWidget(lbTitle); + + auto hBox = new HBox(vBox); + + lbScreenWidth = new QLabel; + hBox->addWidget(lbScreenWidth); + + fdScreenWidth = new QLineEdit; + fdScreenWidth->setMaximumWidth(60); + hBox->addWidget(fdScreenWidth); + + lbScreenHeight = new QLabel; + hBox->addWidget(lbScreenHeight); + + fdScreenHeight = new QLineEdit; + fdScreenHeight->setMaximumWidth(60); + hBox->addWidget(fdScreenHeight); + + btnScreenSet = new QPushButton; + btnScreenSet->setProperty("ssType", "progManageTool"); + connect(btnScreenSet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + auto width = fdScreenWidth->text(); + if(width.isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"),tr("InputWidthTip")); + fdScreenWidth->setFocus(); + return; + } + auto height = fdScreenHeight->text(); + if(height.isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"),tr("InputHeightTip")); + fdScreenHeight->setFocus(); + return; + } + QJsonObject json; + json.insert("_id", "SetScreenSize"); + json.insert("_type", "SetScreenSize"); + json.insert("width", width.toInt()); + json.insert("height", height.toInt()); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("SetScreenSize")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("SetScreenSize")) + } + } + }); + hBox->addWidget(btnScreenSet); + + hBox->addSpacing(20); + + lbAlias = new QLabel; + hBox->addWidget(lbAlias); + + fdAlias = new QLineEdit; + fdAlias->setMaximumWidth(200); + hBox->addWidget(fdAlias); + + btnAliasSet = new QPushButton; + btnAliasSet->setProperty("ssType", "progManageTool"); + connect(btnAliasSet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + auto alias = fdAlias->text(); + if(alias.isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"),tr("InputAliasTip")); + fdAlias->setFocus(); + return; + } + QJsonObject json; + json.insert("_id", "SetCardAlias"); + json.insert("_type", "SetCardAlias"); + json.insert("alias", QString::fromLatin1(alias.toUtf8().toBase64())); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("SetCardAlias")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("SetCardAlias")) + } + } + }); + hBox->addWidget(btnAliasSet); + + hBox->addStretch(); + + hBox = new HBox(vBox); + + labelWebServer = new QLabel; + hBox->addWidget(labelWebServer); + + fdWebServerAddr = new QComboBox; + fdWebServerAddr->addItem(tr("www.m2mled.net")); + fdWebServerAddr->addItem(tr("www.ledaips.com")); + fdWebServerAddr->addItem(tr("https://www.taxihub.cn:2340")); + fdWebServerAddr->addItem(tr("https://www.ledaips.com:2340")); + fdWebServerAddr->addItem(tr("https://www.36taxi.com:2340")); + fdWebServerAddr->addItem(tr("www.tlzxled.com")); + fdWebServerAddr->setMinimumWidth(260); + fdWebServerAddr->setEditable(true); + hBox->addWidget(fdWebServerAddr); + + lbCompanyId = new QLabel; + hBox->addWidget(lbCompanyId); + + fdCompanyId = new QLineEdit; + fdCompanyId->setFixedWidth(100); + hBox->addWidget(fdCompanyId); + + btnWebServerSet = new QPushButton; + btnWebServerSet->setProperty("ssType", "progManageTool"); + connect(btnWebServerSet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + + QString serverAddr = fdWebServerAddr->currentText(); + if(serverAddr.isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"),tr("InputWebServerAddressTip")); + fdWebServerAddr->setFocus(); + return; + } + auto companyId = fdCompanyId->text(); + if(companyId.isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"),tr("InputCompanyIdTip")); + fdCompanyId->setFocus(); + return; + } + auto res = QMessageBox::question(gMainWin, tr("Tip Info"), tr("Do you want to modify webserveraddress and companyId?")); + if(res != QMessageBox::Yes) return; + QJsonObject json; + json.insert("_id", "SetOnlineAddr"); + json.insert("_type", "SetOnlineAddr"); + json.insert("server", serverAddr); + json.insert("companyID", companyId); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("SetOnlineAddr")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("SetOnlineAddr")) + } + } + }); + hBox->addWidget(btnWebServerSet); + + hBox->addStretch(); + + hBox = new HBox(vBox); + + label = new QLabel; + hBox->addWidget(label); + + fdRealtimeServer = new QComboBox; + fdRealtimeServer->addItem(tr("www.ledokcloud.com/realtime")); + fdRealtimeServer->setMinimumWidth(260); + fdRealtimeServer->setEditable(true); + hBox->addWidget(fdRealtimeServer); + + btnRealtimeServerSet = new QPushButton; + btnRealtimeServerSet->setProperty("ssType", "progManageTool"); + connect(btnRealtimeServerSet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "SetRealtimeServer"); + json.insert("_type", "SetRealtimeServer"); + json.insert("server", fdRealtimeServer->currentText()); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("SetRealtimeServer")+" ..."); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("SetRealtimeServer")) + } + } + }); + hBox->addWidget(btnRealtimeServerSet); + + btnRealtimeClear = new QPushButton; + btnRealtimeClear->setProperty("ssType", "progManageTool"); + connect(btnRealtimeClear, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + fdRealtimeServer->clearEditText(); + QJsonObject json; + json.insert("_id", "SetRealtimeServer"); + json.insert("_type", "SetRealtimeServer"); + json.insert("server", ""); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("ClearRealtimeServer")+" ..."); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("ClearRealtimeServer")) + } + } + }); + hBox->addWidget(btnRealtimeClear); + + hBox->addStretch(); + + + hBox = new HBox(vBox); + + btnWareUpdate = new QPushButton; + btnWareUpdate->setMinimumSize(100, 30); + btnWareUpdate->setProperty("ssType", "progManageTool"); + connect(btnWareUpdate, &QPushButton::clicked, this, [] { + UpgradeApkDialog dlg(gMainWin); + dlg.exec(); + }); + hBox->addWidget(btnWareUpdate); + + lbWareTip = new QLabel; + hBox->addWidget(lbWareTip); + hBox->addStretch(); + + hBox = new HBox(vBox); + + btnApkCheck = new QPushButton; + btnApkCheck->setProperty("ssType", "progManageTool"); + connect(btnApkCheck, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "CheckSoftVersions"); + json.insert("_type", "CheckSoftVersions"); + if(gSelCards->count() != 1) return; + auto waitingDlg = new WaitingDlg(this, tr("Check Apk Version")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg] { + Def_CtrlSingleGetReply + waitingDlg->close(); + fdPkg->clear(); + auto apps = json["apps"].toArray(); + auto infoDlg = new QDialog(this); + infoDlg->setWindowFlag(Qt::WindowContextHelpButtonHint, false); + infoDlg->resize(500, 500); + infoDlg->setWindowTitle(tr("Software Version Info")); + auto vBox = new QVBoxLayout(infoDlg); + vBox->setContentsMargins(0, 0, 0, 0); + auto table = new Table{ + {"apk", "Apk"}, + {"ver", tr("Version")}, + {"pkg", tr("Package")} + }; + table->setDefs(); + table->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); + table->setRowCount(apps.size()); + vBox->addWidget(table); + for(int i=0; isetItem(i, "apk", new QTableWidgetItem{app["appName"].toString()}); + table->setItem(i, "ver", new QTableWidgetItem{app["versionName"].toString()}); + table->setItem(i, "pkg", new QTableWidgetItem{packageName}); + if(! (packageName.endsWith(".cardsystem") || packageName.endsWith(".systemcore") || packageName.endsWith(".update"))) fdPkg->addItem(packageName); + } + infoDlg->show(); + }); + }); + hBox->addWidget(btnApkCheck); + + fdPkg = new QComboBox; + fdPkg->setEditable(true); + fdPkg->setMinimumWidth(200); + hBox->addWidget(fdPkg); + + fdUninstall = new QPushButton; + fdUninstall->setProperty("ssType", "progManageTool"); + connect(fdUninstall, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + auto pkg = fdPkg->currentText(); + if(pkg.isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("Package name is null")); + return; + } + QJsonObject json; + json.insert("_id", "UninstallSoftware"); + json.insert("_type", "UninstallSoftware"); + json.insert("packageName", pkg); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("UninstallSoftware")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("UninstallSoftware")) + } + } + }); + hBox->addWidget(fdUninstall); + + btnIsRunning = new QPushButton; + btnIsRunning->setProperty("ssType", "progManageTool"); + connect(btnIsRunning, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + auto pkg = fdPkg->currentText(); + if(pkg.isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("Package name is null")); + return; + } + QJsonObject json; + json.insert("_id", "IsSoftwareRunning"); + json.insert("_type", "IsSoftwareRunning"); + json.insert("packageName", pkg); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("Check apk running status")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSingleGetReply + waitingDlg->close(); + QMessageBox::information(gMainWin, tr("Tip"), json["running"].toBool() ? tr("running") : tr("no running")); + }); + } else { + foreach(auto card, *gSelCards) { + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + auto cardId = card->m_strCardId; + connect(reply, &QNetworkReply::finished, this, [reply, cardId] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + gFdResInfo->append(cardId+" "+tr("Check apk running status")+" "+(err.isEmpty() ? (json["running"].toBool() ? tr("running") : tr("no running")) : err)); + }); + } + } + }); + hBox->addWidget(btnIsRunning); + hBox->addStretch(); + + hBox = new HBox(vBox); + + btnRestart = new QPushButton; + btnRestart->setProperty("ssType", "progManageTool"); + connect(btnRestart, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "RestartAndroid"); + json.insert("_type", "RestartAndroid"); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("RestartAndroid")+" ..."); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("RestartAndroid")) + } + } + }); + hBox->addWidget(btnRestart); + + btnClearProg = new QPushButton; + btnClearProg->setProperty("ssType", "progManageTool"); + connect(btnClearProg, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("Clearing Program")+" ..."); + waitingDlg->show(); + auto card = gSelCards->at(0); + auto tcp = new QTcpSocket(); + auto timer = new QTimer(tcp); + timer->setSingleShot(true); + connect(timer, &QTimer::timeout, tcp, [=] { + waitingDlg->close(); + tcp->abort(); + tcp->deleteLater(); + QMessageBox::critical(gMainWin, tr("Tip"), tr("Clear Program")+" "+tr("Timeout")); + }); + connect(waitingDlg, &WaitingDlg::rejected, tcp, [=] { + timer->stop(); + tcp->abort(); + tcp->deleteLater(); + }); + connect(tcp, &QTcpSocket::connected, tcp, [tcp, timer] { + timer->stop(); + tcp->write("{\"_type\":\"DelPrograms\",\"_id\":\"DelPrograms\",\"zVer\":\"xixun1\"}"); + timer->start(10000); + }); + connect(tcp, &QTcpSocket::readyRead, tcp, [tcp, timer, waitingDlg] { + timer->stop(); + QByteArray resp = tcp->readAll(); + tcp->close(); + tcp->deleteLater(); + QJsonParseError parseErr; + QJsonDocument json = QJsonDocument::fromJson(resp, &parseErr); + if(parseErr.error != QJsonParseError::NoError) { + waitingDlg->close(); + QMessageBox::critical(gMainWin, tr("Tip"), parseErr.errorString()); + } else if(! json["success"].toBool()) { + waitingDlg->close(); + QMessageBox::critical(gMainWin, tr("Tip"), tr("Clear Program")+" "+tr("Failed")); + } else waitingDlg->success(); + }); + connect(tcp, &QTcpSocket::errorOccurred, tcp, [tcp, timer, waitingDlg](QAbstractSocket::SocketError err) { + timer->stop(); + tcp->close(); + tcp->deleteLater(); + waitingDlg->close(); + QMessageBox::critical(gMainWin, tr("Tip"), QString(socketErrKey(err))+" ("+QString::number(err)+") "+tcp->errorString()); + }); + tcp->connectToHost(card->m_strCardIp, 3333); + timer->start(10000); + } else { + foreach(auto card, *gSelCards) { + auto tcp = new QTcpSocket(); + auto timer = new QTimer(tcp); + timer->setSingleShot(true); + auto cardId = card->m_strCardId; + connect(timer, &QTimer::timeout, tcp, [tcp, cardId] { + tcp->abort(); + tcp->deleteLater(); + gFdResInfo->append(cardId+" "+tr("Clear Program")+" "+tr("Timeout")); + }); + connect(tcp, &QTcpSocket::connected, tcp, [tcp, timer] { + timer->stop(); + tcp->write("{\"_type\":\"DelPrograms\",\"_id\":\"DelPrograms\",\"zVer\":\"xixun1\"}"); + timer->start(10000); + }); + connect(tcp, &QTcpSocket::readyRead, tcp, [tcp, timer, cardId] { + timer->stop(); + QByteArray resp = tcp->readAll(); + tcp->close(); + tcp->deleteLater(); + QJsonParseError parseErr; + QJsonDocument json = QJsonDocument::fromJson(resp, &parseErr); + if(parseErr.error != QJsonParseError::NoError) gFdResInfo->append(cardId+" "+tr("Clear Program")+" "+parseErr.errorString()); + else if(! json["success"].toBool()) gFdResInfo->append(cardId+" "+tr("Clear Program")+" "+tr("Failed")); + else gFdResInfo->append(cardId+" "+tr("Clear Program")+" "+tr("Success")); + }); + connect(tcp, &QTcpSocket::errorOccurred, tcp, [tcp, timer, cardId](QAbstractSocket::SocketError err) { + timer->stop(); + tcp->close(); + tcp->deleteLater(); + gFdResInfo->append(cardId+" "+tr("Clear Program")+" "+QMetaEnum::fromType().valueToKey(err)+" ("+QString::number(err)+") "+tcp->errorString()); + }); + tcp->connectToHost(card->m_strCardIp, 3333); + timer->start(10000); + } + } + }); + + hBox->addWidget(btnClearProg); + + btnGetLog = new QPushButton; + btnGetLog->setProperty("ssType", "progManageTool"); + connect(btnGetLog, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("Getting Log")+" ..."); + waitingDlg->show(); + auto card = gSelCards->at(0); + auto reply = Tools::netManager().get(netReq("http://"+card->m_strCardIp+":2016/download?file=logs")); + connect(waitingDlg, &WaitingDlg::rejected, reply, [reply] { + reply->blockSignals(true); + reply->abort(); + reply->blockSignals(false); + reply->deleteLater(); + }); + connect(reply, &QNetworkReply::finished, this, [=] { + waitingDlg->close(); + QString err = checkReply(reply); + if(! err.isEmpty()) { + QMessageBox::critical(gMainWin, tr("Error"), err); + return; + } + QString logFile = QApplication::applicationDirPath()+"/log_"+card->m_strCardId+".txt"; + QFile file(logFile); + if(! file.open(QIODevice::WriteOnly)) { + QMessageBox::critical(gMainWin, tr("Error"), "Open for Write Fail"); + return; + } + file.write(reply->readAll()); + file.close(); + QProcess::execute("notepad", {logFile}); + }); + } + }); + hBox->addWidget(btnGetLog); + + hBox->addStretch(); + hBox = new HBox(vBox); + hBox->addWidget(lbTimingReboot = new QLabel); + + auto fdRebootTime = new QLineEdit; + fdRebootTime->setMaximumWidth(60); + hBox->addWidget(fdRebootTime); + + btnTimingRebootSet = new QPushButton; + btnTimingRebootSet->setProperty("ssType", "progManageTool"); + connect(btnTimingRebootSet, &QPushButton::clicked, this, [=] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "SetTimingReboot"); + json.insert("_type", "SetTimingReboot"); + json.insert("time", fdRebootTime->text()); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("Setting Timing Reboot")+" ..."); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("Set Timing Reboot")) + } + } + }); + hBox->addWidget(btnTimingRebootSet); + + btnTimingRebootGet = new QPushButton; + btnTimingRebootGet->setProperty("ssType", "progManageTool"); + connect(btnTimingRebootGet, &QPushButton::clicked, this, [=] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "GetTimingReboot"); + json.insert("_type", "GetTimingReboot"); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("Getting Timing Reboot")+" ..."); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [=] { + Def_CtrlSingleGetReply + waitingDlg->success(); + fdRebootTime->setText(json["time"].toString()); + }); + } else { + foreach(auto card, *gSelCards) { + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + auto cardId = card->m_strCardId; + connect(reply, &QNetworkReply::finished, this, [reply, cardId] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(err.isEmpty()) err = json["time"].toString(); + gFdResInfo->append(cardId+" "+tr("Get Timing Reboot")+" "+err); + }); + } + } + }); + hBox->addWidget(btnTimingRebootGet); + + hBox->addStretch(); + + grpM80 = new QGroupBox; + hBox = new HBox(grpM80); + + fdM80Resolu = new QComboBox; + fdM80Resolu->setMinimumWidth(160); + hBox->addWidget(fdM80Resolu); + + btnM80Set = new QPushButton(); + btnM80Set->setProperty("ssType", "progManageTool"); + connect(btnM80Set, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "SetSpecialResolution"); + json.insert("_type", "SetSpecialResolution"); + json.insert("displayResolution", fdM80Resolu->currentText()); //显示分辨率 + json.insert("totalResolution", fdM80Resolu->currentData().toString()); //显示分辨率 + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("SetSpecialResolution")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("SetSpecialResolution")) + } + } + }); + hBox->addWidget(btnM80Set); + + btnM80Refresh = new QPushButton(); + btnM80Refresh->setProperty("ssType", "progManageTool"); + connect(btnM80Refresh, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "GetSpecialResolution"); + json.insert("_type", "GetSpecialResolution"); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("GetSpecialResolution")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg] { + Def_CtrlSingleGetReply + waitingDlg->success(); + fdM80Resolu->setCurrentText(json["displayResolution"].toString()); + }); + } else { + foreach(auto card, *gSelCards) { + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + auto cardId = card->m_strCardId; + connect(reply, &QNetworkReply::finished, this, [reply, cardId] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(err.isEmpty()) err = tr("totalResolution")+"["+json["totalResolution"].toString()+"], "+tr("strCurDisplayResolution")+"["+json["displayResolution"].toString()+"]"; + gFdResInfo->append(cardId+" "+tr("GetSpecialResolution")+" "+err); + }); + } + } + }); + hBox->addWidget(btnM80Refresh); + + btnM80Restore = new QPushButton(); + btnM80Restore->setProperty("ssType", "progManageTool"); + connect(btnM80Restore, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "CleanDisplayScreenSize"); + json.insert("_type", "CleanDisplayScreenSize"); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("CleanDisplayScreenSize")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("CleanDisplayScreenSize")) + } + } + }); + hBox->addWidget(btnM80Restore); + + hBox->addStretch(); + + vBox->addWidget(grpM80); + + { + grpY50 = new QGroupBox; + hBox = new HBox(grpY50); + + auto fdY50Resolu = new QComboBox; + auto dirs = QDir(QApplication::applicationDirPath()+"/y50 param").entryList(QDir::Dirs | QDir::NoDotAndDotDot); + foreach(auto dir, dirs) fdY50Resolu->addItem(dir); + fdY50Resolu->setMinimumWidth(160); + hBox->addWidget(fdY50Resolu); + + btnY50Set = new QPushButton; + btnY50Set->setProperty("ssType", "progManageTool"); + connect(btnY50Set, &QPushButton::clicked, this, [=] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QFile qFile(QApplication::applicationDirPath()+"/y50 param/"+fdY50Resolu->currentText()+"/rk_lcd_parameters"); + if(! qFile.exists()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("File not exist")); + return; + } + if(! qFile.open(QIODevice::ReadOnly)) return; + auto fileData = qFile.readAll(); + qFile.close(); + + auto Boundary = "----QtLedOK_.oOo._"+QUuid::createUuid().toByteArray(QUuid::WithoutBraces); + QByteArray data; + data.append("--").append(Boundary).append("\r\nContent-Disposition: form-data; name=\"rk_lcd_parameters\"; filename=\"rk_lcd_parameters\"\r\n\r\n").append(fileData).append("\r\n"); + data.append("--").append(Boundary).append("--\r\n"); + + auto waitingDlg = new WaitingDlg(this, tr("Uploading")+" ..."); + waitingDlg->show(); + NetReq req("http://"+gSelCards->at(0)->m_strCardIp+":2016/upload?type=update_display"); + auto reply = req.timeout(120000).type("multipart/form-data; boundary="+Boundary).post(data); + connect(waitingDlg, &WaitingDlg::rejected, reply, [reply] { + reply->blockSignals(true); + reply->abort(); + reply->blockSignals(false); + reply->deleteLater(); + }); + connect(reply, &QNetworkReply::finished, this, [=] { + QString err = checkReply(reply); + if(! err.isEmpty()) { + waitingDlg->close(); + QMessageBox::critical(gMainWin, tr("Error"), err); + return; + } + waitingDlg->success(); + }); + }); + hBox->addWidget(btnY50Set); + + hBox->addStretch(); + + vBox->addWidget(grpY50); + } + + hBox = new HBox(vBox); + + lbDisMode = new QLabel; + hBox->addWidget(lbDisMode); + + fdDisMode = new QComboBox; + fdDisMode->setSizeAdjustPolicy(QComboBox::AdjustToContents); + fdDisMode->addItem("Full screen", 1); + fdDisMode->addItem("Part", 2); + hBox->addWidget(fdDisMode); + + btnDisModeSet = new QPushButton; + btnDisModeSet->setProperty("ssType", "progManageTool"); + connect(btnDisModeSet, &QPushButton::clicked, this, [=] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")+" ..."); + return; + } + QJsonObject json; + json.insert("_id", "SetDisplayModel"); + json.insert("_type", "SetDisplayModel"); + json.insert("model", fdDisMode->currentData().toInt()); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("Set Display Mode")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("Set Display Mode")) + } + } + }); + hBox->addWidget(btnDisModeSet); + + btnDisModeGet = new QPushButton; + btnDisModeGet->setProperty("ssType", "progManageTool"); + connect(btnDisModeGet, &QPushButton::clicked, this, [=] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "GetDisplayModel"); + json.insert("_type", "GetDisplayModel"); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("Get Display Mode")+" ..."); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [=] { + Def_CtrlSingleGetReply + waitingDlg->success(); + setCurrentData(fdDisMode, json["result"].toInt()); + }); + } else { + foreach(auto card, *gSelCards) { + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + auto cardId = card->m_strCardId; + connect(reply, &QNetworkReply::finished, this, [=] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(err.isEmpty()) { + auto result = json["result"].toInt(); + int idx = fdDisMode->findData(result); + if(idx!=-1) err = fdDisMode->itemText(idx); + else err = QString::number(result); + } + gFdResInfo->append(cardId+" "+tr("Get Display Mode")+" "+err); + }); + } + } + }); + hBox->addWidget(btnDisModeGet); + hBox->addSpacing(40); + + lbScreenPos = new QLabel; + hBox->addWidget(lbScreenPos); + + auto fdScreenPos = new QSpinBox; + fdScreenPos->setRange(0, 99999); + hBox->addWidget(fdScreenPos); + + lbScreenOff = new QLabel; + hBox->addWidget(lbScreenOff); + + auto fdScreenOff = new QSpinBox; + fdScreenOff->setRange(-9999, 99999); + hBox->addWidget(fdScreenOff); + + btnScreenOffSet = new QPushButton; + btnScreenOffSet->setProperty("ssType", "progManageTool"); + connect(btnScreenOffSet, &QPushButton::clicked, this, [=] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "ConfigScreen"); + json.insert("_type", "ConfigScreen"); + json.insert("index", fdScreenPos->value()); + json.insert("x", fdScreenOff->value()); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("Set Screen Offset")+" ..."); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("Set Screen Offset")) + } + } + }); + hBox->addWidget(btnScreenOffSet); + + btnScreenOffGet = new QPushButton; + btnScreenOffGet->setProperty("ssType", "progManageTool"); + connect(btnScreenOffGet, &QPushButton::clicked, this, [=] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "GetConfigScreen"); + json.insert("_type", "GetConfigScreen"); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("Get Screen Offset")+" ..."); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [=] { + Def_CtrlSingleGetReply + waitingDlg->success(); + fdScreenPos->setValue(json["offsetNum"].toInt()); + fdScreenOff->setValue(json["offsetValue"].toInt()); + }); + } else { + foreach(auto card, *gSelCards) { + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + auto cardId = card->m_strCardId; + connect(reply, &QNetworkReply::finished, this, [=] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(err.isEmpty()) { + err = lbScreenPos->text()+" "+QString::number(json["offsetNum"].toInt())+". "+lbScreenOff->text()+" "+QString::number(json["offsetValue"].toInt()); + } + gFdResInfo->append(cardId+" "+tr("Get Screen Offset")+" "+err); + }); + } + } + }); + hBox->addWidget(btnScreenOffGet); + hBox->addStretch(); + + hBox = new HBox(vBox); + + btnLedSet3 = new QPushButton; + btnLedSet3->setMinimumHeight(34); + btnLedSet3->setProperty("ssType", "progManageTool"); + connect(btnLedSet3, &QPushButton::clicked, this, [this] { + QString strLedSetFile = QApplication::applicationDirPath()+"/LedSet/LedSet3.0.exe"; + QFileInfo cc22(strLedSetFile); + if(cc22.exists()) { + QProcess::startDetached(strLedSetFile,QStringList()); + return; + } + QSettings reg("HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\sysolution\\LedSet3.0", QSettings::NativeFormat); + QString strLedsetPath = reg.value("Program_path").toString(); + if(!strLedsetPath.isEmpty()) { + QFileInfo cc(strLedsetPath); + if(cc.exists()) QProcess::startDetached(strLedsetPath,QStringList()); + else { + auto res = QMessageBox::question(gMainWin, tr("Tip Info"), tr("Can not find LedSet3.0.exe,down you need download and install it")+strLedsetPath); + if(res == QMessageBox::Yes) { + UpdateLedset3Dialog *pDlg=new UpdateLedset3Dialog(this); + pDlg->exec(); + } + } + return; + } + QSettings reg1("HKEY_LOCAL_MACHINE\\SOFTWARE\\sysolution\\LedSet3.0", QSettings::NativeFormat); + strLedsetPath = reg1.value("Program_path").toString(); + QFileInfo cc(strLedsetPath); + if(!strLedsetPath.isEmpty()) { + if(cc.exists()) QProcess::startDetached(strLedsetPath,QStringList()); + else { + QString str1="C:/Program Files/sysolution/LedSet3.0/LedSet3.0.exe"; + QFileInfo cc1(str1); + if(cc1.exists()) QProcess::startDetached(str1,QStringList()); + else { + QString str2="C:/Program Files (x86)/sysolution/LedSet3.0/LedSet3.0.exe"; + QFileInfo cc2(str1); + if(cc2.exists()) QProcess::startDetached(str2,QStringList()); + else { + auto res = QMessageBox::question(gMainWin, tr("Tip Info"), tr("Can not find LedSet3.0.exe,down you need download and install it")+strLedsetPath); + if(res == QMessageBox::Yes) { + UpdateLedset3Dialog *pDlg=new UpdateLedset3Dialog(this); + pDlg->exec(); + } + } + } + } + } else { + QString str1="C:/Program Files/sysolution/LedSet3.0/LedSet3.0.exe"; + QFileInfo cc1(str1); + if(cc1.exists()) QProcess::startDetached(str1,QStringList()); + else { + QString str2="C:/Program Files (x86)/sysolution/LedSet3.0/LedSet3.0.exe"; + QFileInfo cc2(str1); + if(cc2.exists())QProcess::startDetached(str2,QStringList()); + else { + auto res = QMessageBox::question(gMainWin, tr("Tip Info"), tr("Can not find LedSet3.0.exe,down you need download and install it")+strLedsetPath); + if(res == QMessageBox::Yes) { + UpdateLedset3Dialog *pDlg=new UpdateLedset3Dialog(this); + pDlg->exec(); + } + } + } + } + }); + hBox->addWidget(btnLedSet3); + + btnLedSet4 = new QPushButton; + btnLedSet4->setMinimumHeight(34); + btnLedSet4->setProperty("ssType", "progManageTool"); + connect(btnLedSet4, &QPushButton::clicked, btnLedSet4, [] { + QFileInfo file("LedSet4.0/LedSet4.0.exe"); + if(file.exists()) QProcess::startDetached(file.absoluteFilePath(), QStringList()); + }); + hBox->addWidget(btnLedSet4); + + + auto line = new QFrame; + line->setFrameShape(QFrame::HLine); + line->setFrameShadow(QFrame::Sunken); + vBox->addWidget(line); + + hBox = new HBox(vBox); + btnBindTaxiIc = new QPushButton; + btnBindTaxiIc->setProperty("ssType", "progManageTool"); + connect(btnBindTaxiIc, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QString icFile = QFileDialog::getOpenFileName(this, "open file dialog", "", tr("indentity voucher (*.ic)")); + if(icFile.isEmpty()) return; + QFile file(icFile); + if(! file.open(QIODevice::ReadOnly)) { + QMessageBox::information(gMainWin, tr("Tip"), tr("Open file Failed")); + return; + } + auto data = file.readAll(); + file.close(); + QJsonParseError jsonErr; + QJsonDocument icJson = QJsonDocument::fromJson(data, &jsonErr); + if(jsonErr.error != QJsonParseError::NoError) { + QMessageBox::information(gMainWin, tr("Tip"), "JsonError "+jsonErr.errorString()+"\n"+data); + return; + } + QJsonObject jsonCommand; + jsonCommand.insert("action", "BindAccount"); + jsonCommand.insert("accountIdToken", icJson["account_id_token"]); + jsonCommand.insert("server", icJson["taxiServerURL"]); + jsonCommand.insert("tlsServer", icJson["taxiServerTLSURL"]); + QJsonObject json; + json.insert("action", "InvokeTaxiAppFunction"); + json.insert("jsonCommand", jsonCommand); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("InvokeTaxiAppFunction")); + waitingDlg->show(); + auto reply = Tools::netManager().post(reqForJson("http://"+gSelCards->at(0)->m_strCardIp+":3000"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + connect(waitingDlg, &WaitingDlg::rejected, reply, [reply] { + reply->blockSignals(true); + reply->abort(); + reply->blockSignals(false); + reply->deleteLater(); + }); + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + QString err = checkReply(reply); + if(! err.isEmpty()) { + waitingDlg->close(); + QMessageBox::critical(gMainWin, tr("Error"), err); + return; + } + auto data = reply->readAll(); + QJsonParseError jsonErr; + QJsonDocument json = QJsonDocument::fromJson(data, &jsonErr); + if(jsonErr.error != QJsonParseError::NoError) { + waitingDlg->close(); + QMessageBox::critical(gMainWin, tr("Error"), "JsonError "+jsonErr.errorString()+"\n"+data); + return; + } + if(json["result"].toString() != "true") { + waitingDlg->close(); + QMessageBox::critical(gMainWin, tr("Error"), data); + return; + } + waitingDlg->success(); + }); + } else { + foreach(auto card, *gSelCards) { + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":3000"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + auto cardId = card->m_strCardId; + connect(reply, &QNetworkReply::finished, this, [reply, cardId] { + QString err = checkReply(reply); + if(! err.isEmpty()) { + gFdResInfo->append(cardId+" "+tr("InvokeTaxiAppFunction")+" "+tr("Error")+" "+err); + return; + } + auto data = reply->readAll(); + QJsonParseError jsonErr; + QJsonDocument json = QJsonDocument::fromJson(data, &jsonErr); + if(jsonErr.error != QJsonParseError::NoError) { + gFdResInfo->append(cardId+" "+tr("InvokeTaxiAppFunction")+" "+tr("Error")+" JsonError "+jsonErr.errorString()+"\n"+data); + return; + } + if(json["result"].toString() != "true") { + gFdResInfo->append(cardId+" "+tr("InvokeTaxiAppFunction")+" "+tr("Error")+" "+data); + return; + } + gFdResInfo->append(cardId+" "+tr("InvokeTaxiAppFunction")+" "+QCoreApplication::translate("Def","Success")); + }); + } + } + }); + hBox->addWidget(btnBindTaxiIc); + hBox->addStretch(); + + + grpHighForBusy = new QGroupBox; + grpHighForBusy->setVisible(false); + hBox = new HBox(grpHighForBusy); + + fdHighForBusy = new QRadioButton; + fdHighForBusy->setChecked(true); + hBox->addWidget(fdHighForBusy); + + fdTopLevelLH = new QRadioButton; + hBox->addWidget(fdTopLevelLH); + + btnHighForBusySet = new QPushButton; + btnHighForBusySet->setProperty("ssType", "progManageTool"); + connect(btnHighForBusySet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "SetHighForBusy"); + json.insert("_type", "SetHighForBusy"); + json.insert("busyState", fdTopLevelLH->isChecked() ? 0 : 1); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("SetHighForBusy")+" ..."); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("SetHighForBusy")) + } + } + }); + hBox->addWidget(btnHighForBusySet); + + btnGetTopLevel = new QPushButton; + btnGetTopLevel->setProperty("ssType", "progManageTool"); + connect(btnGetTopLevel, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "GetStateForBusy"); + json.insert("_type", "GetStateForBusy"); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("GetStateForBusy")+" ..."); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg] { + Def_CtrlSingleGetReply + waitingDlg->success(); + if(json["result"].toInt()==0) fdTopLevelLH->setChecked(true); + else fdHighForBusy->setChecked(true); + }); + } else { + foreach(auto card, *gSelCards) { + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + auto cardId = card->m_strCardId; + connect(reply, &QNetworkReply::finished, this, [reply, cardId] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(err.isEmpty()) err = json["result"].toInt() ? tr("Service:High Out of service:Low") : tr("Service:Low Out of service:High"); + gFdResInfo->append(cardId+" "+tr("GetStateForBusy")+" "+err); + }); + } + } + }); + hBox->addWidget(btnGetTopLevel); + + hBox->addStretch(); + + vBox->addWidget(grpHighForBusy); + + grpMinMaxBrightness = new QGroupBox(); + grpMinMaxBrightness->setVisible(false); + hBox = new HBox(grpMinMaxBrightness); + + lbMinBright = new QLabel(); + hBox->addWidget(lbMinBright); + + fdMinBright = new QLineEdit("1"); + fdMinBright->setPlaceholderText("1"); + fdMinBright->setMaximumWidth(50); + hBox->addWidget(fdMinBright); + hBox->addWidget(new QLabel("%")); + + btnMinBrightSet = new QPushButton; + btnMinBrightSet->setProperty("ssType", "progManageTool"); + connect(btnMinBrightSet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "SetMinBrightness"); + json.insert("_type", "SetMinBrightness"); + json.insert("minBrightnessPercentage", fdMinBright->text().toInt()); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("SetMinBrightness")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("SetMinBrightness")) + } + } + }); + hBox->addWidget(btnMinBrightSet); + + btnMinBrightGet = new QPushButton(); + btnMinBrightGet->setProperty("ssType", "progManageTool"); + connect(btnMinBrightGet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "GetMinBrightness"); + json.insert("_type", "GetMinBrightness"); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("GetMinBrightness")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg] { + Def_CtrlSingleGetReply + waitingDlg->success(); + fdMinBright->setText(QString::number(json["minBrightnessPercentage"].toInt())); + }); + } else { + foreach(auto card, *gSelCards) { + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + auto cardId = card->m_strCardId; + connect(reply, &QNetworkReply::finished, this, [reply, cardId] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(err.isEmpty()) err = QString::number(json["minBrightnessPercentage"].toInt()); + gFdResInfo->append(cardId+" "+tr("GetMinBrightness")+" "+err); + }); + } + } + }); + hBox->addWidget(btnMinBrightGet); + + hBox->addSpacing(10); + + label_3 = new QLabel(); + hBox->addWidget(label_3); + + fdMaxBright = new QLineEdit("100"); + fdMaxBright->setPlaceholderText("100"); + fdMaxBright->setMaximumWidth(50); + hBox->addWidget(fdMaxBright); + hBox->addWidget(new QLabel("%")); + + btnMaxBrightSet = new QPushButton; + btnMaxBrightSet->setProperty("ssType", "progManageTool"); + connect(btnMaxBrightSet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "SetMaxBrightness"); + json.insert("_type", "SetMaxBrightness"); + json.insert("maxBrightnessPercentage", fdMaxBright->text().toInt()); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("SetMaxBrightness")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("SetMaxBrightness")) + } + } + }); + hBox->addWidget(btnMaxBrightSet); + + btnMaxBrightGet = new QPushButton; + btnMaxBrightGet->setProperty("ssType", "progManageTool"); + connect(btnMaxBrightGet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "GetMaxBrightness"); + json.insert("_type", "GetMaxBrightness"); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("GetMaxBrightness")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg] { + Def_CtrlSingleGetReply + waitingDlg->success(); + fdMaxBright->setText(QString::number(json["maxBrightnessPercentage"].toInt())); + }); + } else { + foreach(auto card, *gSelCards) { + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + auto cardId = card->m_strCardId; + connect(reply, &QNetworkReply::finished, this, [reply, cardId] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(err.isEmpty()) err = QString::number(json["maxBrightnessPercentage"].toInt()); + gFdResInfo->append(cardId+" "+tr("GetMaxBrightness")+" "+err); + }); + } + } + }); + hBox->addWidget(btnMaxBrightGet); + + hBox->addStretch(); + vBox->addWidget(grpMinMaxBrightness); + + vBox->addSpacing(20); + + grpBoxHiddenSettings = new QGroupBox; + grpBoxHiddenSettings->setVisible(false); + { + auto vBox = new QVBoxLayout(grpBoxHiddenSettings); + vBox->setContentsMargins(6,6,6,6); + + hBox = new HBox(vBox); + + btnSetBack = new QPushButton; + btnSetBack->setProperty("ssType", "progManageTool"); + connect(btnSetBack, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QColorDialog colorDlg(this); + colorDlg.setOption(QColorDialog::DontUseNativeDialog); + + if(colorDlg.exec() != QColorDialog::Accepted) return; + QColor color = colorDlg.selectedColor(); + if(! color.isValid()) return; + QJsonObject json; + json.insert("_id", "SetWallpaper"); + json.insert("_type", "SetWallpaper"); + json.insert("rgb", color.name()); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("Setting Wallpaper")+" ..."); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("Set Wallpaper")) + } + } + }); + hBox->addWidget(btnSetBack); + + btnSysUpd = new QPushButton; + btnSysUpd->setProperty("ssType", "progManageTool"); + connect(btnSysUpd, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "SystemUpdate"); + json.insert("_type", "SystemUpdate"); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("System Updating")+" ..."); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("System Update")) + } + } + }); + hBox->addWidget(btnSysUpd); + + hBox->addSpacing(20); + + btnMcuUpd = new QPushButton; + btnMcuUpd->setProperty("ssType", "progManageTool"); + connect(btnMcuUpd, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + auto filePath = QFileDialog::getOpenFileName(this, "Open File", QString(), ".bin file (*.bin)"); + if(filePath.isEmpty()) return; + QFile qFile(filePath); + if(! qFile.exists()) return; + if(! qFile.open(QIODevice::ReadOnly)) return; + auto fileData = qFile.readAll(); + qFile.close(); + + auto nameBytes = QFileInfo(filePath).fileName().toUtf8(); + auto Boundary = "----QtLedOK_.oOo._"+QUuid::createUuid().toByteArray(QUuid::WithoutBraces); + QByteArray data; + data.append("--").append(Boundary).append("\r\nContent-Disposition: form-data; name=\"").append(nameBytes).append("\"; filename=\"").append(nameBytes).append("\"\r\n\r\n").append(fileData).append("\r\n"); + data.append("--").append(Boundary).append("--\r\n"); + + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("MCU Uploading")+" ..."); + waitingDlg->show(); + NetReq req("http://"+gSelCards->at(0)->m_strCardIp+":2016/upload?type=mcu_update"); + auto reply = req.timeout(120000).type("multipart/form-data; boundary="+Boundary).post(data); + connect(waitingDlg, &WaitingDlg::rejected, reply, [reply] { + reply->blockSignals(true); + reply->abort(); + reply->blockSignals(false); + reply->deleteLater(); + }); + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + QString err = checkReply(reply); + if(! err.isEmpty()) { + waitingDlg->close(); + QMessageBox::critical(gMainWin, tr("Error"), err); + return; + } + waitingDlg->success(); + }); + } else { + foreach(auto card, *gSelCards) { + auto cardId = card->m_strCardId; + NetReq req("http://"+card->m_strCardIp+":2016/upload?type=mcu_update"); + auto reply = req.timeout(120000).type("multipart/form-data; boundary="+Boundary).post(data); + connect(reply, &QNetworkReply::finished, this, [=] { + QString err = checkReply(reply); + gFdResInfo->append(cardId+" "+tr("Update MCU")+" "+(err.isEmpty()?tr("Success"):err)); + }); + } + } + }); + hBox->addWidget(btnMcuUpd); + + btnMcuGet = new QPushButton; + btnMcuGet->setProperty("ssType", "progManageTool"); + connect(btnMcuGet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "SelectMCUVersion"); + json.insert("_type", "SelectMCUVersion"); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("Getting MCU Version")+" ..."); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSingleGetReply + waitingDlg->close(); + QMessageBox::information(gMainWin, tr("Tip"), tr("MCU Version")+": "+json["mcuVersion"].toString()); + }); + } else { + foreach(auto card, *gSelCards) { + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + auto cardId = card->m_strCardId; + connect(reply, &QNetworkReply::finished, this, [reply, cardId] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(err.isEmpty()) err = json["mcuVersion"].toString(); + gFdResInfo->append(cardId+" "+tr("MCU Version")+" "+err); + }); + } + } + }); + hBox->addWidget(btnMcuGet); + + hBox->addSpacing(20); + + btnPlayerBackSet = new QPushButton; + btnPlayerBackSet->setProperty("ssType", "progManageTool"); + connect(btnPlayerBackSet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QString file = QFileDialog::getOpenFileName(gMainWin, tr("Select File"), gFileHome, EPhoto::filters()); + if(file.isEmpty()) return; + QFileInfo info(file); + if(! info.isFile()) return; + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("Setting player background")+" ..."); + waitingDlg->btnAbort->hide(); + waitingDlg->show(); + auto thread = new PlayerBackSendThread(file, gSelCards->at(0)->m_strCardIp); + connect(thread, &PlayerBackSendThread::emErr, this, [waitingDlg](QString err) { + if(err.isEmpty()) waitingDlg->success(); + else { + waitingDlg->close(); + QMessageBox::critical(gMainWin, tr("Error"), err); + } + }); + thread->start(); + } else { + foreach(auto card, *gSelCards) { + auto thread = new PlayerBackSendThread(file, card->m_strCardIp); + auto cardId = card->m_strCardId; + connect(thread, &PlayerBackSendThread::emErr, this, [cardId](QString err) { + gFdResInfo->append(cardId+" "+tr("Set player background")+" "+(err.isEmpty() ? tr("Success") : err)); + }); + thread->start(); + } + } + }); + hBox->addWidget(btnPlayerBackSet); + + btnPlayerBackClear = new QPushButton; + btnPlayerBackClear->setProperty("ssType", "progManageTool"); + connect(btnPlayerBackClear, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("Clearing player background")+" ..."); + waitingDlg->show(); + auto card = gSelCards->at(0); + auto tcp = new QTcpSocket(); + auto timer = new QTimer(tcp); + timer->setSingleShot(true); + connect(timer, &QTimer::timeout, tcp, [tcp, waitingDlg] { + waitingDlg->close(); + tcp->abort(); + tcp->deleteLater(); + QMessageBox::critical(gMainWin, tr("Tip"), tr("Clear player background")+" "+tr("Timeout")); + }); + connect(waitingDlg, &WaitingDlg::rejected, tcp, [=] { + timer->stop(); + tcp->abort(); + tcp->deleteLater(); + }); + connect(tcp, &QTcpSocket::connected, tcp, [tcp, timer] { + timer->stop(); + tcp->write("{\"_type\":\"DelBackImg\",\"_id\":\"DelBackImg\",\"zVer\":\"xixun1\"}"); + timer->start(10000); + }); + connect(tcp, &QTcpSocket::readyRead, tcp, [tcp, timer, waitingDlg] { + timer->stop(); + QByteArray resp = tcp->readAll(); + tcp->close(); + tcp->deleteLater(); + QJsonParseError parseErr; + QJsonDocument json = QJsonDocument::fromJson(resp, &parseErr); + if(parseErr.error != QJsonParseError::NoError) { + waitingDlg->close(); + QMessageBox::critical(gMainWin, tr("Tip"), parseErr.errorString()); + } else if(! json["success"].toBool()) { + waitingDlg->close(); + QMessageBox::critical(gMainWin, tr("Tip"), tr("Clear player background")+" "+tr("Failed")); + } else waitingDlg->success(); + }); + connect(tcp, &QTcpSocket::errorOccurred, tcp, [tcp, timer, waitingDlg](QAbstractSocket::SocketError err) { + timer->stop(); + tcp->close(); + tcp->deleteLater(); + waitingDlg->close(); + QMessageBox::critical(gMainWin, tr("Tip"), QString(socketErrKey(err))+" ("+QString::number(err)+") "+tcp->errorString()); + }); + tcp->connectToHost(card->m_strCardIp, 3333); + timer->start(10000); + } else { + foreach(auto card, *gSelCards) { + auto tcp = new QTcpSocket(); + auto timer = new QTimer(tcp); + timer->setSingleShot(true); + auto cardId = card->m_strCardId; + connect(timer, &QTimer::timeout, tcp, [tcp, cardId] { + tcp->abort(); + tcp->deleteLater(); + gFdResInfo->append(cardId+" "+tr("Clear player background")+" "+tr("Timeout")); + }); + connect(tcp, &QTcpSocket::connected, tcp, [tcp, timer] { + timer->stop(); + tcp->write("{\"_type\":\"DelBackImg\",\"_id\":\"DelBackImg\",\"zVer\":\"xixun1\"}"); + timer->start(10000); + }); + connect(tcp, &QTcpSocket::readyRead, tcp, [tcp, timer, cardId] { + timer->stop(); + QByteArray resp = tcp->readAll(); + tcp->close(); + tcp->deleteLater(); + QJsonParseError parseErr; + QJsonDocument json = QJsonDocument::fromJson(resp, &parseErr); + if(parseErr.error != QJsonParseError::NoError) gFdResInfo->append(cardId+" "+tr("Clear player background")+" "+parseErr.errorString()); + else if(! json["success"].toBool()) gFdResInfo->append(cardId+" "+tr("Clear player background")+" "+tr("Failed")); + else gFdResInfo->append(cardId+" "+tr("Clear player background")+" "+tr("Success")); + }); + connect(tcp, &QTcpSocket::errorOccurred, tcp, [tcp, timer, cardId](QAbstractSocket::SocketError err) { + timer->stop(); + tcp->close(); + tcp->deleteLater(); + gFdResInfo->append(cardId+" "+tr("Clear player background")+" "+QMetaEnum::fromType().valueToKey(err)+" ("+QString::number(err)+") "+tcp->errorString()); + }); + tcp->connectToHost(card->m_strCardIp, 3333); + timer->start(10000); + } + } + }); + hBox->addWidget(btnPlayerBackClear); + + hBox->addStretch(); + + auto line = new QFrame; + line->setFrameStyle(QFrame::HLine | QFrame::Sunken); + vBox->addWidget(line); + + hBox = new HBox(vBox); + + lbRotate = new QLabel; + hBox->addWidget(lbRotate); + hBox->addSpacing(20); + + auto fdDeg0 = new QRadioButton("0°"); + hBox->addWidget(fdDeg0); + auto fdDeg90 = new QRadioButton("90°"); + hBox->addWidget(fdDeg90); + auto fdDeg180 = new QRadioButton("180°"); + hBox->addWidget(fdDeg180); + auto fdDeg270 = new QRadioButton("270°"); + hBox->addWidget(fdDeg270); + + hBox->addStretch(); + + auto btnGrp = new QButtonGroup; + btnGrp->addButton(fdDeg0, 0); + btnGrp->addButton(fdDeg90, 1); + btnGrp->addButton(fdDeg180, 2); + btnGrp->addButton(fdDeg270, 3); + connect(btnGrp, &QButtonGroup::idToggled, this, [this](int value, bool checked) { + if(! checked) return; + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "SetScreenRotation"); + json.insert("_type", "SetScreenRotation"); + json.insert("rotation", value); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("SetScreenRotation")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("SetScreenRotation")) + } + } + }); + + hBox = new HBox(vBox); + + lbBaudCfg = new QLabel; + hBox->addWidget(lbBaudCfg); + + line = new QFrame; + line->setFrameStyle(QFrame::HLine | QFrame::Sunken); + hBox->addWidget(line, 1); + + hBox = new HBox(vBox); + + lbBaudModel = new QLabel; + hBox->addWidget(lbBaudModel); + + auto fdBaudDevMod = new QComboBox; + fdBaudDevMod->addItems({ + "M5x/M6x", + "M7x/Y7x", + "E2x/Y6x", + "L20" + }); + hBox->addWidget(fdBaudDevMod); + + lbUart = new QLabel; + hBox->addWidget(lbUart); + + auto fdUart = new QComboBox; + fdUart->setEditable(true); + fdUart->setMinimumWidth(140); + fdUart->setSizeAdjustPolicy(QComboBox::AdjustToContents); + fdUart->addItems({ + "/dev/ttyS3", + "/dev/ttyS4", + "/dev/ttyS5" + }); + hBox->addWidget(fdUart); + + connect(fdBaudDevMod, &QComboBox::currentTextChanged, fdUart, [fdUart](const QString &text) { + fdUart->clear(); + if(text.startsWith("M5x")) fdUart->addItems({ + "/dev/ttyS3", + "/dev/ttyS4", + "/dev/ttyS5" + }); + else if(text.startsWith("M7x")) fdUart->addItem("/dev/ttyS4"); + else if(text.startsWith("E2x")) fdUart->addItems({ + "/dev/ttysWK0", + "/dev/ttysWK1", + "/dev/ttysWK2", + "/dev/ttysWK3", + "/dev/tty232", + "/dev/tty485", + "/dev/ttyTTL" + }); + else if(text.startsWith("L20")) fdUart->addItems({ + "/dev/ttyS0", + "/dev/ttyS1", + "/dev/ttyS4" + }); + }); + + lbBaud = new QLabel; + hBox->addWidget(lbBaud); + + auto fdBaud = new QLineEdit; + fdBaud->setMaximumWidth(70); + hBox->addWidget(fdBaud); + + btnBaudSet = new QPushButton; + btnBaudSet->setProperty("ssType", "progManageTool"); + connect(btnBaudSet, &QPushButton::clicked, this, [this, fdUart, fdBaud] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "SetBaudRateByCardType"); + json.insert("_type", "SetBaudRateByCardType"); + json.insert("uartName", fdUart->currentText()); + json.insert("baud", fdBaud->text().toInt()); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("Setting Baud Rate")+" ..."); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("Set Baud Rate")) + } + } + }); + hBox->addWidget(btnBaudSet); + + btnBaudGet = new QPushButton; + btnBaudGet->setProperty("ssType", "progManageTool"); + connect(btnBaudGet, &QPushButton::clicked, this, [this, fdUart, fdBaud] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "GetBaudRateByCardType"); + json.insert("_type", "GetBaudRateByCardType"); + json.insert("uartName", fdUart->currentText()); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("Getting Baud Rate")+" ..."); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, fdBaud, waitingDlg] { + Def_CtrlSingleGetReply + waitingDlg->success(); + fdBaud->setText(QString::number(json["baud"].toInt())); + }); + } else { + foreach(auto card, *gSelCards) { + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + auto cardId = card->m_strCardId; + connect(reply, &QNetworkReply::finished, this, [reply, cardId] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + gFdResInfo->append(cardId+" "+tr("Get Baud Rate")+" "+(err.isEmpty()?QString::number(json["baud"].toInt()):err)); + }); + } + } + }); + hBox->addWidget(btnBaudGet); + + hBox->addStretch(); + + + fdIsOpenADB = new QCheckBox; + connect(fdIsOpenADB, &QCheckBox::toggled, this, [this](bool checked) { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "OpenAdb"); + json.insert("_type", "OpenAdb"); + json.insert("open", checked); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("OpenAdb")+" ..."); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("OpenAdb")) + } + } + }); + vBox->addWidget(fdIsOpenADB); + + hBox = new HBox(vBox); + + lbCustomJson = new QLabel; + hBox->addWidget(lbCustomJson); + + hBox->addSpacing(40); + + btnSendCustomJson = new QPushButton; + btnSendCustomJson->setProperty("ssType", "progManageTool"); + connect(btnSendCustomJson, &QPushButton::clicked, this, [=] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + auto text = fdCustomJson->toPlainText().toUtf8(); + if(text.isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("Text is empty")); + return; + } + QJsonParseError jsonErr; + QJsonDocument json = QJsonDocument::fromJson(text, &jsonErr); + if(jsonErr.error != QJsonParseError::NoError) { + QMessageBox::information(gMainWin, tr("Tip"), tr("Json Parse Error")+jsonErr.errorString()); + return; + } + if(! json.isObject()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("Json isn't an Object")); + return; + } + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("AliIotSetting")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("AliIotSetting")) + } + } + }); + hBox->addWidget(btnSendCustomJson); + + hBox->addStretch(); + + fdCustomJson = new QTextEdit; + fdCustomJson->setMinimumHeight(120); + vBox->addWidget(fdCustomJson); + + + vBox->addWidget(new QLabel(tr("Traffic screen settings"))); + + hBox = new HBox(vBox); + + lbTraficProtocol = new QLabel; + lbTraficProtocol->setMinimumWidth(100); + hBox->addWidget(lbTraficProtocol); + + auto fdTraficProtocol = new QComboBox; + fdTraficProtocol->addItem("三思协议", 1); + hBox->addWidget(fdTraficProtocol); + + btnTraficProtSet = new QPushButton; + btnTraficProtSet->setProperty("ssType", "progManageTool"); + connect(btnTraficProtSet, &QPushButton::clicked, this, [this, fdTraficProtocol] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "SetProtocolType"); + json.insert("_type", "SetProtocolType"); + json.insert("protocolType", fdTraficProtocol->currentData().toInt()); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("Setting protocol ...")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("Set protocol")) + } + } + }); + hBox->addWidget(btnTraficProtSet); + + btnTraficProtGet = new QPushButton; + btnTraficProtGet->setProperty("ssType", "progManageTool"); + connect(btnTraficProtGet, &QPushButton::clicked, this, [this, fdTraficProtocol] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "GetProtocolType"); + json.insert("_type", "GetProtocolType"); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("Getting protocol ...")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg, fdTraficProtocol] { + Def_CtrlSingleGetReply + waitingDlg->success(); + setCurrentData(fdTraficProtocol, json["protocolType"].toInt()); + }); + } else { + foreach(auto card, *gSelCards) { + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + auto cardId = card->m_strCardId; + connect(reply, &QNetworkReply::finished, this, [reply, cardId, fdTraficProtocol] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(err.isEmpty()) { + auto protocolType = json["protocolType"].toInt(); + int idx = fdTraficProtocol->findData(protocolType); + if(idx!=-1) err = fdTraficProtocol->itemText(idx); + else err = QString::number(protocolType); + } + gFdResInfo->append(cardId+" "+tr("Get protocol")+" "+err); + }); + } + } + }); + hBox->addWidget(btnTraficProtGet); + hBox->addStretch(); + + hBox = new HBox(vBox); + + lbCardMode = new QLabel; + lbCardMode->setMinimumWidth(100); + hBox->addWidget(lbCardMode); + + fdServerType = new QComboBox; + fdServerType->setSizeAdjustPolicy(QComboBox::AdjustToContents); + fdServerType->addItem("服务端", 1); + fdServerType->addItem("客户端", 2); + hBox->addWidget(fdServerType); + + hBox->addSpacing(10); + + lbTraficPort = new QLabel; + hBox->addWidget(lbTraficPort); + + auto fdPort = new QSpinBox; + fdPort->setRange(0, 99999); + fdPort->setValue(5000); + hBox->addWidget(fdPort); + + btnTraficSet = new QPushButton; + btnTraficSet->setProperty("ssType", "progManageTool"); + connect(btnTraficSet, &QPushButton::clicked, this, [=] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "SetCardMode"); + json.insert("_type", "SetCardMode"); + json.insert("serverType", fdServerType->currentData().toInt()); + json.insert("port", fdPort->value()); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("Setting card work mode ...")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("Set card work mode")) + } + } + }); + hBox->addWidget(btnTraficSet); + + btnTraficGet = new QPushButton; + btnTraficGet->setProperty("ssType", "progManageTool"); + connect(btnTraficGet, &QPushButton::clicked, this, [=] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "GetCardMode"); + json.insert("_type", "GetCardMode"); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("Getting card work mode ...")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [=] { + Def_CtrlSingleGetReply + waitingDlg->success(); + setCurrentData(fdServerType, json["serverType"].toInt()); + fdPort->setValue(json["port"].toInt()); + }); + } else { + foreach(auto card, *gSelCards) { + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + auto cardId = card->m_strCardId; + connect(reply, &QNetworkReply::finished, this, [=] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(err.isEmpty()) { + err = tr("Card work mode")+": "; + auto serverType = json["serverType"].toInt(); + int idx = fdServerType->findData(serverType); + if(idx!=-1) err += fdServerType->itemText(idx); + else err += QString::number(serverType); + err += ". "+tr("Port")+": "+QString::number(json["port"].toInt()); + } + gFdResInfo->append(cardId+" "+tr("Get card work mode")+" "+err); + }); + } + } + }); + hBox->addWidget(btnTraficGet); + hBox->addStretch(); + } + vBox->addWidget(grpBoxHiddenSettings); + vBox->addStretch(); + + connect(gDevicePanel, &DevicePanel::sigSelectedDeviceList, this, [this] { + if(isVisible()) init(); + }); + transUi(); +} + +void CtrlAdvancedPanel::showEvent(QShowEvent *event) { + QWidget::showEvent(event); + init(); +} +void CtrlAdvancedPanel::init() { + if(! isPassed) { + hide(); + PasswordInChDlg dlg(gMainWin); + connect(dlg.btnBox, &QDialogButtonBox::accepted, &dlg, [&dlg]() { + QString passRaw = QSettings().value("advUiPs").toString(); + QString password = passRaw.isEmpty() ? "888" : QTextCodec::codecForName("GBK")->toUnicode(QByteArray::fromBase64(passRaw.toLocal8Bit())); + if(dlg.fdPassword->text() == password) dlg.accept(); + else QMessageBox::critical(&dlg, tr("Tip"),tr("Password is error")); + }); + if(dlg.exec()==QDialog::Accepted) { + isPassed = true; + show(); + } else return; + } + + bool isSingle = gSelCards->count()==1; + btnApkCheck->setEnabled(isSingle); + btnRestart->setEnabled(isSingle); + btnGetLog->setEnabled(isSingle); + + if(! isSingle) { + grpM80->setVisible(true); + grpY50->setVisible(true); + return; + } + auto card = gSelCards->at(0); + + auto isM80 = card->m_strCardId.startsWith("M8", Qt::CaseInsensitive); + grpM80->setVisible(isM80); + if(isM80) { + QJsonObject json; + json.insert("_id", "GetAllScreenSizeM80"); + json.insert("_type", "GetAllScreenSizeM80"); + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + connect(reply, &QNetworkReply::finished, this, [this, reply] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) return; + auto sizes = json["result"].toObject(); + fdM80Resolu->clear(); + auto send = sizes.constEnd(); + for(auto size=sizes.constBegin(); sizeaddItem(size.key(), size.value().toString()); + }); + } + + auto isY50 = card->m_strCardId.startsWith("st5", Qt::CaseInsensitive) + || card->m_strCardId.startsWith("m5s", Qt::CaseInsensitive) + || card->m_strCardId.startsWith("m6s", Qt::CaseInsensitive) + || card->m_strCardId.startsWith("m7s", Qt::CaseInsensitive) + || card->m_strCardId.startsWith("y5", Qt::CaseInsensitive); + grpY50->setVisible(isY50); + + QJsonObject json; + json.insert("_id", "GetScreenSize"); + json.insert("_type", "GetScreenSize"); + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + connect(reply, &QNetworkReply::finished, this, [this, reply] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) return; + fdScreenWidth->setText(QString::number(json["width"].toInt())); + fdScreenHeight->setText(QString::number(json["height"].toInt())); + }); + + json = QJsonObject(); + json.insert("_id", "GetCardAlias"); + json.insert("_type", "GetCardAlias"); + reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + connect(reply, &QNetworkReply::finished, this, [this, reply] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) return; + fdAlias->setText(QString::fromUtf8(QByteArray::fromBase64(json["alias"].toString().toLatin1()))); + }); + + json = QJsonObject(); + json.insert("_id", "GetOnlineAddr"); + json.insert("_type", "GetOnlineAddr"); + reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + connect(reply, &QNetworkReply::finished, this, [this, reply] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) return; + fdWebServerAddr->setCurrentText(json["server"].toString()); + fdCompanyId->setText(json["companuID"].toString()); + }); + + json = QJsonObject(); + json.insert("_id", "GetRealtimeServer"); + json.insert("_type", "GetRealtimeServer"); + reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + connect(reply, &QNetworkReply::finished, this, [this, reply] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) return; + fdRealtimeServer->setCurrentText(json["server"].toString()); + }); +} +void CtrlAdvancedPanel::changeEvent(QEvent *event) { + QWidget::changeEvent(event); + if(event->type() == QEvent::LanguageChange) transUi(); +} +void CtrlAdvancedPanel::transUi() { + btnBindTaxiIc->setText(tr("Binding *.ic account indentity voucher")); + btnGetTopLevel->setText(tr("Readback")); + btnLedSet3->setText(tr("Start LedSet3.0 configure LED module")); + btnLedSet4->setText(tr("Start LedSet4")); + + grpM80->setTitle("M80 "+tr("Config")); + btnM80Refresh->setText(tr("Refresh")); + btnM80Restore->setText(tr("Restore to default")); + btnM80Set->setText(tr("Set")); + + grpY50->setTitle("ST50 / M50S / M60S / M70S / Y5A "+tr("Resolution Config")); + fdDisMode->setItemText(0, tr("Full screen")); + fdDisMode->setItemText(1, tr("Part")); + btnY50Set->setText(tr("Set")); + + lbDisMode->setText(tr("Display Mode")); + btnDisModeSet->setText(tr("Set")); + btnDisModeGet->setText(tr("Get")); + + lbScreenPos->setText(tr("Screen Position")); + lbScreenOff->setText(tr("Offset")); + btnScreenOffSet->setText(tr("Set")); + btnScreenOffGet->setText(tr("Get")); + + btnAliasSet->setText(tr("Set")); + btnScreenSet->setText(tr("Set")); + btnHighForBusySet->setText(tr("Set")); + fdScreenHeight->setPlaceholderText(tr("Height")); + fdScreenWidth->setPlaceholderText(tr("Width")); + fdHighForBusy->setText(tr("Service:High Out of service:Low")); + fdTopLevelLH->setText(tr("Service:Low Out of service:High")); + lbRotate->setText(tr("Rotate")); + + grpBoxHiddenSettings->setTitle(tr("Hidden Settings")+" ("+tr("Click right button to hide")+")"); + btnSysUpd->setText(tr("System Update")); + btnMcuUpd->setText(tr("Update MCU")); + btnMcuGet->setText(tr("Get MCU Version")); + lbBaudCfg->setText(tr("Baud Config")); + lbBaudModel->setText(tr("Model")); + lbUart->setText(tr("Uart")); + lbBaud->setText(tr("Baud")); + btnBaudSet->setText(tr("Set")); + btnBaudGet->setText(tr("Get")); + fdIsOpenADB->setText(tr("Open ADB")); + lbCustomJson->setText(tr("Post Custom JSON")); + btnSendCustomJson->setText(tr("Send")); + + grpHighForBusy->setTitle(tr("Taxi top screen configuration")); + label->setText(tr("Realtimer Server Address:")); + lbTitle->setText(tr("Advanced")); + lbCompanyId->setText(tr("Compant ID:")); + labelWebServer->setText(tr("Web Server Address:")); + lbMinBright->setText(tr("Min brightness")); + label_3->setText(tr("Max brightness ")); + lbAlias->setText(tr("Alias")); + lbScreenHeight->setText(tr("Height")); + lbScreenWidth->setText(tr("Screen Width(pixel)")); + fdCompanyId->setPlaceholderText(tr("Compant ID")); + + btnWareUpdate->setText(tr("Firmware Management")); + lbWareTip->setText("(APK / FPGA "+tr("update or uninstall")+")"); + btnApkCheck->setText(tr("Check Apk")); + btnGetLog->setText(tr("Check Log")); + btnSetBack->setText(tr("Set Wallpaper")); + btnClearProg->setText(tr("Clear Program")); + btnPlayerBackSet->setText(tr("Set player background")); + btnPlayerBackClear->setText(tr("Clear player background")); + + btnRealtimeClear->setText(tr("Clear")); + btnMinBrightSet->setText(tr("Set")); + btnMinBrightGet->setText(tr("Readback")); + btnMaxBrightSet->setText(tr("Set")); + btnMaxBrightGet->setText(tr("Readback")); + btnRestart->setText(tr("Restart")); + btnIsRunning->setText(tr("Running check")); + btnRealtimeServerSet->setText(tr("Set")); + btnWebServerSet->setText(tr("Set")); + fdUninstall->setText(tr("Uninstall")); + + lbTimingReboot->setText(tr("Timing Reboot")); + btnTimingRebootSet->setText(tr("Set")); + btnTimingRebootGet->setText(tr("Get")); + + lbTraficProtocol->setText(tr("Protocol")); + lbCardMode->setText(tr("Card work mode")); + fdServerType->setItemText(0, tr("Server")); + fdServerType->setItemText(1, tr("Client")); + lbTraficPort->setText(tr("Port")); + btnTraficProtSet->setText(tr("Set")); + btnTraficProtGet->setText(tr("Get")); + btnTraficSet->setText(tr("Set")); + btnTraficGet->setText(tr("Get")); +} + +//void CtrlAdvancedPanel::onUpload(QString file) { +// if(file.length() < 3) return; +// QFile qFile(file); +// if(! qFile.exists()) return; +// bool isApk = ! file.endsWith(".rpd", Qt::CaseInsensitive); +// auto BOUNDARY = QUuid::createUuid().toByteArray(); +// QByteArray data; +// data.append("--").append(BOUNDARY).append("\r\n"); +// data.append("Content-Disposition: form-data;name=\"username\"\r\n\r\n"); +// data.append("10005\r\n"); +// //上传文件的头部 +// data.append("--").append(BOUNDARY).append("\r\n"); +// QFileInfo fileinfo(file); +// auto name = fileinfo.fileName().toUtf8(); +// data.append("Content-Disposition: form-data;name=\"").append(name).append("\";filename=\"").append(name).append("\"\r\n\r\n"); +// //上传文件内容 +// if(! qFile.open(QIODevice::ReadOnly)) return; +// data.append(qFile.readAll()); +// qFile.close(); +// data.append("\r\n"); +// data.append("--").append(BOUNDARY).append("\r\n"); + +// auto waitingDlg = new WaitingDlg(this, tr("Uploading")+" ..."); +// waitingDlg->show(); +// auto request = netReq("http://"+gSelCards->at(0)->m_strCardIp+":2016/upload?type="+(isApk ? "software":"hardware"), "multipart/form-data;boundary="+BOUNDARY, 0); +// auto reply = Tools::netManager().post(request, data); +// connect(waitingDlg, &WaitingDlg::rejected, reply, [reply] { +// reply->blockSignals(true); +// reply->abort(); +// reply->blockSignals(false); +// reply->deleteLater(); +// }); +// connect(reply, &QNetworkReply::uploadProgress, this, [=](qint64 bytesSent, qint64 bytesTotal) { +// if(bytesTotal<=0) return; +// waitingDlg->fdText->setText(tr("Uploading")+" "+QString::number(bytesSent*100/bytesTotal)+"%"); +// }); +// connect(reply, &QNetworkReply::finished, this, [=] { +// QString err = checkReply(reply); +// if(! err.isEmpty()) { +// waitingDlg->close(); +// QMessageBox::critical(gMainWin, tr("Error"), err); +// return; +// } +// waitingDlg->fdText->setText(tr("Installing")+" ..."); +// QJsonObject json; +// if(isApk) { +// json.insert("_id", "UpgradeSoftware"); +// json.insert("_type", "UpgradeSoftware"); +// json.insert("fileName", QFileInfo(file).fileName()); +// json.insert("isCustom", true); +// } else { +// json.insert("_id", "SynchronousHardwareVersion"); +// json.insert("_type", "SynchronousHardwareVersion"); +// } +// auto reply = Tools::netManager().post(reqForJson("http://"+gSelCards->at(0)->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); +// connect(reply, &QNetworkReply::finished, this, [=] { +// Def_CtrlSetReqAfter +// }); +// }); +//} +void messageHandler(QtMsgType type, const QMessageLogContext &, const QString &msg) { + auto cur = QDateTime::currentDateTime(); + QFile file("D:/LedOK-advanced-"+cur.toString("yy-MM-dd")+".log"); + file.open(QIODevice::WriteOnly | QIODevice::Append); + file.write(cur.toString("yy-MM-dd hh:mm:ss ").toUtf8()); + if(type==QtDebugMsg) file.write(" Debug: "); + else if(type==QtWarningMsg) file.write(" Warning: "); + else if(type==QtCriticalMsg)file.write("Critical: "); + else if(type==QtFatalMsg) file.write(" Fatal: "); + else if(type==QtInfoMsg) file.write(" Info: "); + else if(type==QtSystemMsg) file.write(" System: "); + file.write(msg.toUtf8()); + file.close(); +} +void CtrlAdvancedPanel::keyReleaseEvent(QKeyEvent *event) { + auto key = event->key(); + if(key == Qt::Key_F5) grpBoxHiddenSettings->setVisible(! grpBoxHiddenSettings->isVisible()); + else if(key == Qt::Key_F6) grpMinMaxBrightness->setVisible(! grpMinMaxBrightness->isVisible()); + else if(key == Qt::Key_F8) grpHighForBusy->setVisible(! grpHighForBusy->isVisible()); + else if(key == Qt::Key_F12) qInstallMessageHandler(messageHandler); + QWidget::keyPressEvent(event); +} +void CtrlAdvancedPanel::mouseReleaseEvent(QMouseEvent *event){ + if(event->button()==Qt::RightButton) grpBoxHiddenSettings->setVisible(! grpBoxHiddenSettings->isVisible()); +} + + +PlayerBackSendThread::PlayerBackSendThread(const QString &file, const QString &ip) : file(file), ip(ip) { + connect(this, &QThread::finished, this, &QThread::deleteLater); +} +void PlayerBackSendThread::run() { + TcpSocket tcp; + tcp.connectToHost(ip, 3333); + if(! tcp.waitForConnected()) { + emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when waitForConnected"); + tcp.close(); + return; + } + QFileInfo info(file); + auto baseName = info.baseName(); + auto remain = info.size(); + + auto req = QJsonObject(); + req.insert("_type", "proStart"); + req.insert("proName", "program"); + req.insert("proSize", remain); + req.insert("zVer","xixun1"); + auto resNum = tcp.write(QJsonDocument(req).toJson(QJsonDocument::Compact)); + if(resNum == -1 || ! tcp.waitForBytesWritten()) { + emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when write 'proStart'"); + tcp.close(); + return; + } + req = QJsonObject(); + req.insert("_type", "imgFileStart"); + req.insert("id", baseName); + req.insert("size", remain); + req.insert("zVer","xixun1"); + resNum = tcp.write(QJsonDocument(req).toJson(QJsonDocument::Compact)); + if(resNum == -1 || ! tcp.waitForBytesWritten()) { + emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when write 'imgFileStart'"); + tcp.close(); + return; + } + auto file = new QFile(info.filePath()); + if(! file->open(QFile::ReadOnly)) { + emit emErr(tr("Open file failed")+" "+file->errorString()); + tcp.close(); + return; + } + while(remain > 0) { + auto readed = file->read(qMin(4096LL, remain)); + if(readed.isEmpty()) { + emit emErr(tr("Read file failed")+" "+file->errorString()); + tcp.close(); + file->close(); + return; + } + resNum = tcp.write(readed); + if(resNum == -1) { + emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when write file: "+file->fileName()); + tcp.close(); + file->close(); + return; + } + if(! tcp.waitForBytesWritten()) { + emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when waitForWritten file: "+file->fileName()); + tcp.close(); + file->close(); + return; + } + remain -= resNum; + } + file->close(); + req = QJsonObject(); + req.insert("_type", "imgFileEnd"); + req.insert("id", baseName); + req.insert("zVer","xixun1"); + resNum = tcp.write(QJsonDocument(req).toJson(QJsonDocument::Compact)); + if(resNum == -1 || ! tcp.waitForBytesWritten()) { + emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when write 'fileEnd'"); + tcp.close(); + return; + } + req = QJsonObject(); + req.insert("_type", "proEnd"); + req.insert("proName", "program"); + req.insert("zVer","xixun1"); + resNum = tcp.write(QJsonDocument(req).toJson(QJsonDocument::Compact)); + if(resNum == -1 || ! tcp.waitForBytesWritten()) { + emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when write 'proEnd'"); + tcp.close(); + return; + }; + if(! tcp.waitForReadyRead()) { + emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when waitForRead 'proEnd'"); + tcp.close(); + return; + } + auto resp = tcp.readAll(); + if(resp.isEmpty()) { + emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when read 'proEnd'"); + tcp.close(); + return; + } + tcp.close(); + emit emErr(""); +} diff --git a/LedOK/device/ctrladvancedpanel.h b/LedOK/device/ctrladvancedpanel.h new file mode 100644 index 0000000..52b83a3 --- /dev/null +++ b/LedOK/device/ctrladvancedpanel.h @@ -0,0 +1,119 @@ +#ifndef CTRLADVANCEDPANEL_H +#define CTRLADVANCEDPANEL_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class CtrlAdvancedPanel : public QWidget { + Q_OBJECT +public: + explicit CtrlAdvancedPanel(QWidget *parent = nullptr); +protected: + void showEvent(QShowEvent *event) override; + void init(); + void changeEvent(QEvent *) override; + void transUi(); + + void keyReleaseEvent(QKeyEvent *) override; + void mouseReleaseEvent(QMouseEvent *) override; + +private: + bool isPassed{false}; + + QLabel *lbTitle; + QLabel *lbScreenWidth; + QLineEdit *fdScreenWidth; + QLabel *lbScreenHeight; + QLineEdit *fdScreenHeight; + QPushButton *btnScreenSet; + QLabel *lbAlias; + QLineEdit *fdAlias; + QPushButton *btnAliasSet; + QLabel *labelWebServer; + QComboBox *fdWebServerAddr; + QLabel *lbCompanyId; + QLineEdit *fdCompanyId; + QPushButton *btnWebServerSet; + QLabel *label; + QComboBox *fdRealtimeServer; + QPushButton *btnRealtimeServerSet; + QPushButton *btnRealtimeClear; + QPushButton *btnWareUpdate; + QLabel *lbWareTip; + QPushButton *btnApkCheck; + QComboBox *fdPkg; + QPushButton *fdUninstall; + QPushButton *btnIsRunning; + QPushButton *btnRestart; + QPushButton *btnClearProg; + QPushButton *btnGetLog; + QPushButton *btnSetBack, *btnPlayerBackSet, *btnPlayerBackClear; + + QLabel *lbTimingReboot; + QPushButton *btnTimingRebootSet, *btnTimingRebootGet; + + QGroupBox *grpM80, *grpY50; + QComboBox *fdM80Resolu, *fdDisMode; + QPushButton *btnM80Set, *btnY50Set; + QPushButton *btnM80Refresh; + QPushButton *btnM80Restore; + + QLabel *lbDisMode; + QPushButton *btnDisModeSet, *btnDisModeGet; + QLabel *lbScreenPos, *lbScreenOff; + QPushButton *btnScreenOffSet, *btnScreenOffGet; + + QGroupBox *grpHighForBusy; + QRadioButton *fdHighForBusy; + QRadioButton *fdTopLevelLH; + QPushButton *btnHighForBusySet; + QPushButton *btnGetTopLevel; + QPushButton *btnLedSet3; + QPushButton *btnLedSet4; + QPushButton *btnBindTaxiIc; + + QGroupBox *grpMinMaxBrightness; + QLabel *lbMinBright; + QLineEdit *fdMinBright; + QPushButton *btnMinBrightGet; + QPushButton *btnMinBrightSet; + QLabel *label_3; + QLineEdit *fdMaxBright; + QPushButton *btnMaxBrightGet; + QPushButton *btnMaxBrightSet; + + QGroupBox *grpBoxHiddenSettings; + QPushButton *btnSysUpd, *btnMcuUpd, *btnMcuGet; + QLabel *lbRotate, *lbBaudCfg, *lbBaudModel, *lbUart, *lbBaud; + QPushButton *btnBaudSet, *btnBaudGet; + QCheckBox *fdIsOpenADB; + QLabel *lbCustomJson; + QTextEdit *fdCustomJson; + QPushButton *btnSendCustomJson; + + QLabel *lbTraficProtocol, *lbCardMode, *lbTraficPort; + QComboBox *fdServerType; + QPushButton *btnTraficProtSet, *btnTraficProtGet, *btnTraficSet, *btnTraficGet; +}; + +class PlayerBackSendThread : public QThread { + Q_OBJECT +public: + PlayerBackSendThread(const QString &file, const QString &ip); + QString file, ip; + QString err; +protected: + void run(); +signals: + void emErr(QString); +}; + +#endif // CTRLADVANCEDPANEL_H diff --git a/LedOK/wDevicesManager/ctrlbrightpanel.cpp b/LedOK/device/ctrlbrightpanel.cpp similarity index 74% rename from LedOK/wDevicesManager/ctrlbrightpanel.cpp rename to LedOK/device/ctrlbrightpanel.cpp index d45da58..224cedf 100644 --- a/LedOK/wDevicesManager/ctrlbrightpanel.cpp +++ b/LedOK/device/ctrlbrightpanel.cpp @@ -1,902 +1,982 @@ -#include "ctrlbrightpanel.h" -#include "base/waitingdlg.h" -#include "globaldefine.h" -#include "deviceitem.h" -#include "tools.h" -#include "base/x_timeeditdelegate.h" -#include "xlsxdocument.h" -#include "xlsxworkbook.h" -#include -#include -#include -#include -#include -#include -#include -#include - -CtrlBrightPanel::CtrlBrightPanel(QWidget *parent) : QWidget(parent) { - auto vBox = new QVBoxLayout(this); - vBox->setContentsMargins(0,0,0,0); - vBox->addSpacing(8); - - lbBrightCfg = new QLabel; - lbBrightCfg->setAlignment(Qt::AlignCenter); - vBox->addWidget(lbBrightCfg); - - auto hBox = new QHBoxLayout(); - hBox->addStretch(); - - radioAuto = new QRadioButton(); - radioAuto->setChecked(true); - hBox->addWidget(radioAuto); - hBox->addSpacing(40); - - radioManual = new QRadioButton(); - hBox->addWidget(radioManual); - hBox->addSpacing(40); - - radioSchedule = new QRadioButton(); - hBox->addWidget(radioSchedule); - hBox->addStretch(); - - vBox->addLayout(hBox); - - auto line = new QFrame; - line->setFrameShape(QFrame::HLine); - line->setFrameShadow(QFrame::Sunken); - vBox->addWidget(line); - - auto autoPanel = new QWidget(); - { - auto vBox = new QVBoxLayout(autoPanel); - - fdBrightTip = new QLabel; - fdBrightTip->setAlignment(Qt::AlignCenter); - fdBrightTip->setWordWrap(true); - vBox->addWidget(fdBrightTip); - - auto hBox = new QHBoxLayout; - hBox->addStretch(); - - lbSensi = new QLabel; - lbSensi->setMinimumWidth(120); - lbSensi->setAlignment(Qt::AlignRight | Qt::AlignVCenter); - hBox->addWidget(lbSensi); - - fdSensi = new QSlider(Qt::Horizontal); - fdSensi->setRange(1, 100); - hBox->addWidget(fdSensi); - - auto lbSensiValue = new QLabel(QString::number(fdSensi->value())+"%"); - lbSensiValue->setMinimumWidth(40); - lbSensiValue->setAlignment(Qt::AlignRight | Qt::AlignVCenter); - connect(fdSensi, &QSlider::valueChanged, lbSensiValue, [lbSensiValue](int value) { - lbSensiValue->setText(QString::number(value)+"%"); - }); - hBox->addWidget(lbSensiValue); - - btnSensiSet = new QPushButton; - btnSensiSet->setMinimumSize(60, 30); - btnSensiSet->setProperty("ssType", "progManageTool"); - connect(btnSensiSet, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - QJsonObject json; - json.insert("_id", "SetBrightnessSensitivity"); - json.insert("_type", "SetBrightnessSensitivity"); - json.insert("sensitivity", fdSensi->value()); - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, tr("SetBrightnessSensitivity")); - Def_CtrlReqPre - connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { - Def_CtrlSetReqAfter - }); - } else { - foreach(auto card, *gSelCards) { - Def_CtrlSetMulti(tr("SetBrightnessSensitivity")) - } - } - }); - hBox->addWidget(btnSensiSet); - - btnSensiGet = new QPushButton; - btnSensiGet->setMinimumSize(60, 30); - btnSensiGet->setProperty("ssType", "progManageTool"); - connect(btnSensiGet, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - QJsonObject json; - json.insert("_id", "GetBrightnessSensitivity"); - json.insert("_type", "GetBrightnessSensitivity"); - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, tr("GetBrightnessSensitivity")); - Def_CtrlReqPre - connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg] { - Def_CtrlSingleGetReply - waitingDlg->success(); - fdSensi->setValue(json["sensitivity"].toInt()); - }); - } else { - foreach(auto card, *gSelCards) { - auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); - connect(reply, &QNetworkReply::finished, this, [reply, card] { - QJsonDocument json; - QString err = checkReplyForJson(reply, &json); - if(err.isEmpty()) err = QString::number(json["sensitivity"].toInt()); - gFdResInfo->append(card->m_strCardId+" "+tr("GetBrightnessSensitivity")+" "+err); - }); - } - } - }); - hBox->addWidget(btnSensiGet); - - hBox->addStretch(); - vBox->addLayout(hBox); - - hBox = new QHBoxLayout; - hBox->addStretch(); - - lbMinBright = new QLabel; - lbMinBright->setMinimumWidth(120); - lbMinBright->setAlignment(Qt::AlignRight | Qt::AlignVCenter); - hBox->addWidget(lbMinBright); - - fdMinBright = new QSlider(Qt::Horizontal); - fdMinBright->setRange(1, 100); - hBox->addWidget(fdMinBright); - - auto lbMinBrightValue = new QLabel(QString::number(fdMinBright->value())+"%"); - lbMinBrightValue->setMinimumWidth(40); - lbMinBrightValue->setAlignment(Qt::AlignRight | Qt::AlignVCenter); - connect(fdMinBright, &QSlider::valueChanged, lbSensiValue, [lbMinBrightValue](int value) { - lbMinBrightValue->setText(QString::number(value)+"%"); - }); - hBox->addWidget(lbMinBrightValue); - - btnMinBrightSet = new QPushButton; - btnMinBrightSet->setMinimumSize(60, 30); - btnMinBrightSet->setProperty("ssType", "progManageTool"); - connect(btnMinBrightSet, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - QJsonObject json; - json.insert("_id", "SetMinBrightness"); - json.insert("_type", "SetMinBrightness"); - auto brightPercent = fdMinBright->value(); - if(gSelCards->count() == 1) { - json.insert("brightness", (brightPercent * gSelCards->at(0)->BrightnessLevel + 50) / 100); - auto waitingDlg = new WaitingDlg(this, tr("SetMinBrightness")); - Def_CtrlReqPre - connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { - Def_CtrlSetReqAfter - }); - } else { - foreach(auto card, *gSelCards) { - json.insert("brightness", (brightPercent * card->BrightnessLevel + 50) / 100); - Def_CtrlSetMulti(tr("SetMinBrightness")); - } - } - }); - hBox->addWidget(btnMinBrightSet); - - btnMinBrightGet = new QPushButton; - btnMinBrightGet->setMinimumSize(60, 30); - btnMinBrightGet->setProperty("ssType", "progManageTool"); - connect(btnMinBrightGet, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - QJsonObject json; - json.insert("_id", "GetMinBrightness"); - json.insert("_type", "GetMinBrightness"); - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, tr("GetMinBrightness")); - Def_CtrlReqPre - connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg, card] { - Def_CtrlSingleGetReply - waitingDlg->success(); - fdMinBright->setValue(qRound(json["brightness"].toInt() * 100.0 / card->BrightnessLevel)); - }); - } else { - foreach(auto card, *gSelCards) { - auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); - connect(reply, &QNetworkReply::finished, this, [reply, card] { - QJsonDocument json; - QString err = checkReplyForJson(reply, &json); - gFdResInfo->append(card->m_strCardId+" "+tr("GetMinBrightness")+" "+(err.isEmpty()?QString::number(qRound(json["brightness"].toInt() * 100.0 / card->BrightnessLevel))+"%":err)); - }); - } - } - }); - hBox->addWidget(btnMinBrightGet); - - hBox->addStretch(); - vBox->addLayout(hBox); - - - line = new QFrame; - line->setFrameShape(QFrame::HLine); - line->setFrameShadow(QFrame::Sunken); - vBox->addWidget(line); - - fdSensiTypeTip = new QLabel; - fdSensiTypeTip->setAlignment(Qt::AlignCenter); - fdSensiTypeTip->setWordWrap(true); - vBox->addWidget(fdSensiTypeTip); - - hBox = new QHBoxLayout; - hBox->addStretch(); - - fdR68 = new QRadioButton("R68/RL3"); - hBox->addWidget(fdR68); - - fdRL2 = new QRadioButton("RL2"); - hBox->addWidget(fdRL2); - - hBox->addSpacing(20); - - btnUpload = new QPushButton; - btnUpload->setMinimumSize(60, 30); - btnUpload->setProperty("ssType", "progManageTool"); - connect(btnUpload, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - QString sensorName; - if(fdRL2->isChecked()) sensorName = fdRL2->text(); - else if(fdR68->isChecked()) sensorName = fdR68->text(); - else { - QMessageBox::information(gMainWin, tr("Tip"), tr("NeedSelectSensorTypeTip")); - return; - } - QString xlsxFile = QFileDialog::getOpenFileName(this, tr("Open file dialog"), "/", "brightness files(*.xlsx)"); - if(xlsxFile.isEmpty() || ! QFileInfo::exists(xlsxFile)) return; - QXlsx::Document xlsx(xlsxFile); - auto workbook = xlsx.workbook(); - QXlsx::Worksheet *sheet = 0; - if(workbook->sheetCount() < 2) { - sheet = xlsx.currentWorksheet(); - if(sheet==0) { - QMessageBox::information(gMainWin, tr("Tip"), tr("Not found current worksheet")); - return; - } - } else { - auto names = sensorName.split("/"); - foreach(auto name, names) { - auto idx = xlsx.sheetNames().indexOf(name); - if(idx > -1) { - workbook->setActiveSheet(idx); - sheet = dynamic_cast(workbook->sheet(idx)); - break; - } - } - if(sheet==0) { - QMessageBox::information(gMainWin, tr("Tip"), "Not found sheet "+sensorName); - return; - } - } - QJsonArray values; - for(int j=0; j<255; j++) { - auto val = sheet->read(3, j+3).toString(); - if(val.isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), "Cell is empty at 3, "+QString::number(j+3)); - return; - } - values.append(val); - } - QJsonObject json; - json.insert("_id", "SensorBrightnessTable"); - json.insert("_type", "SensorBrightnessTable"); - json.insert("values", values); - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, tr("SensorBrightnessTable")); - Def_CtrlReqPre; - connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { - Def_CtrlSetReqAfter; - }); - } else { - foreach(auto card, *gSelCards) { - Def_CtrlSetMulti(tr("SensorBrightnessTable")); - } - } - }); - hBox->addWidget(btnUpload); - - btnTableGet = new QPushButton(); - btnTableGet->setMinimumSize(60, 30); - btnTableGet->setProperty("ssType", "progManageTool"); - connect(btnTableGet, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - QString strSensorType; - if(fdRL2->isChecked()) strSensorType = fdRL2->text(); - else if(fdR68->isChecked()) strSensorType = fdR68->text(); - else { - QMessageBox::information(gMainWin, tr("Tip"), tr("NeedSelectSensorTypeTip")); - return; - } - QJsonObject json; - json.insert("_id", "GetSensorBrightnessTable"); - json.insert("_type", "GetSensorBrightnessTable"); - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, tr("GetSensorBrightnessTable")); - Def_CtrlReqPre - connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg, card, strSensorType] { - Def_CtrlSingleGetReply - waitingDlg->close(); - QStringList values = json["values"].toVariant().value(); - if(values.isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("no sensorBrightnessTable")); - return; - } - QString tempFile = QCoreApplication::applicationDirPath()+"/bright-template.xlsx"; - QFile tempQFile(tempFile); - if(! tempQFile.exists()) { - QMessageBox::information(gMainWin, tr("Tip"), tempFile+" is not exist"); - return; - } - QString selectFilter = "*.xlsx"; - QString savingFile = QFileDialog::getSaveFileName(this, tr("Save file"), card->m_strCardId + "BrightnessTable.xlsx", "brightness(*.xlsx );", &selectFilter, QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); - if(savingFile.isEmpty()) return; - tempQFile.copy(savingFile); - QXlsx::Document xlsx(savingFile); - xlsx.selectSheet(strSensorType); - for(int m=0; maddWidget(btnTableGet); - - hBox->addStretch(); - vBox->addLayout(hBox); - - - hBox = new QHBoxLayout; - hBox->addStretch(); - - lbCurBright = new QLabel; - hBox->addWidget(lbCurBright); - - fdCurBright = new QLabel; - hBox->addWidget(fdCurBright); - - btnCurBrightGet = new QPushButton; - btnCurBrightGet->setMinimumSize(60, 30); - btnCurBrightGet->setProperty("ssType", "progManageTool"); - connect(btnCurBrightGet, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - QJsonObject json; - json.insert("_id", "GetCurrentSensorBrightness"); - json.insert("_type", "GetCurrentSensorBrightness"); - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, tr("GetCurrentSensorBrightness")); - Def_CtrlReqPre - connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg, card] { - Def_CtrlSingleGetReply - waitingDlg->success(); - if(json["is485"].toBool()) fdR68->setChecked(true); - else fdRL2->setChecked(true); - fdCurBright->setText(QString::number(qRound(json["value"].toInt() * 100.0 / card->BrightnessLevel))+"%"); - }); - } else { - foreach(auto card, *gSelCards) { - auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); - connect(reply, &QNetworkReply::finished, this, [reply, card] { - QJsonDocument json; - QString err = checkReplyForJson(reply, &json); - if(err.isEmpty()) err = QString::number(qRound(json["value"].toInt() * 100.0 / card->BrightnessLevel))+"%"; - gFdResInfo->append(card->m_strCardId+" "+tr("GetBrightnessSensitivity")+" "+err); - }); - } - } - }); - hBox->addWidget(btnCurBrightGet); - - hBox->addStretch(); - vBox->addLayout(hBox); - vBox->addStretch(); - } - auto manualPanel = new QWidget; - { - auto vBox = new QVBoxLayout(manualPanel); - - auto hBox = new QHBoxLayout; - hBox->addStretch(); - - lbFixedBright = new QLabel; - hBox->addWidget(lbFixedBright); - - fdFixedBright = new QSlider(Qt::Horizontal); - fdFixedBright->setRange(1, 100); - hBox->addWidget(fdFixedBright); - - auto lbBrightValue = new QLabel(QString::number(fdFixedBright->value())+"%"); - lbBrightValue->setMinimumWidth(40); - lbBrightValue->setAlignment(Qt::AlignRight | Qt::AlignVCenter); - connect(fdFixedBright, &QSlider::valueChanged, lbBrightValue, [lbBrightValue](int value) { - lbBrightValue->setText(QString::number(value)+"%"); - }); - hBox->addWidget(lbBrightValue); - - hBox->addStretch(); - - vBox->addLayout(hBox); - vBox->addSpacing(20); - - hBox = new QHBoxLayout; - hBox->addStretch(); - - btnFixedSet = new QPushButton; - btnFixedSet->setMinimumSize(60, 30); - btnFixedSet->setProperty("ssType", "progManageTool"); - connect(btnFixedSet, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - QJsonObject json; - json.insert("_id", "SetBrightness"); - json.insert("_type", "SetBrightness"); - auto percent = fdFixedBright->value(); - if(gSelCards->count() == 1) { - json.insert("brightness", (percent * gSelCards->at(0)->BrightnessLevel + 50) / 100); - auto waitingDlg = new WaitingDlg(this, tr("SetBrightness")); - Def_CtrlReqPre - connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { - Def_CtrlSetReqAfter - }); - } else { - foreach(auto card, *gSelCards) { - json.insert("brightness", (percent * card->BrightnessLevel + 50) / 100); - Def_CtrlSetMulti(tr("SetBrightness")) - } - } - }); - hBox->addWidget(btnFixedSet); - - btnFixedGet = new QPushButton; - btnFixedGet->setMinimumSize(60, 30); - btnFixedGet->setProperty("ssType", "progManageTool"); - connect(btnFixedGet, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - QJsonObject json; - json.insert("_id", "GetBrightness"); - json.insert("_type", "GetBrightness"); - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, tr("GetBrightness")); - Def_CtrlReqPre - connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg, card] { - Def_CtrlSingleGetReply - waitingDlg->success(); - card->brightness = json["brightness"].toInt(); - fdFixedBright->setValue(qRound(card->brightness * 100.0 / card->BrightnessLevel)); - }); - } else { - foreach(auto card, *gSelCards) { - auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); - connect(reply, &QNetworkReply::finished, this, [reply, card] { - QJsonDocument json; - QString err = checkReplyForJson(reply, &json); - gFdResInfo->append(card->m_strCardId+" "+tr("Brightness")+" "+(err.isEmpty()?QString::number(qRound(json["brightness"].toInt() * 100.0 / card->BrightnessLevel))+"%":err)); - }); - } - } - }); - hBox->addWidget(btnFixedGet); - - hBox->addStretch(); - - vBox->addLayout(hBox); - vBox->addStretch(); - } - auto schedulePanel = new QWidget; - { - auto hBox = new QHBoxLayout(schedulePanel); - hBox->addStretch(); - auto vBox = new QVBoxLayout; - hBox->addLayout(vBox); - hBox->addStretch(); - - hBox = new QHBoxLayout(); - - fdScheTip = new QLabel; - fdScheTip->setWordWrap(true); - hBox->addWidget(fdScheTip); - - vBox->addLayout(hBox); - - hBox = new QHBoxLayout(); - - btnScheAdd = new QPushButton; - btnScheAdd->setMinimumSize(60, 30); - btnScheAdd->setProperty("ssType", "progManageTool"); - connect(btnScheAdd, &QPushButton::clicked, this, [this] { - int row = tableSche->rowCount(); - tableSche->insertRow(row); - - auto cellWgt = new QWidget; - auto hBox = new QHBoxLayout(cellWgt); - - auto slider = new QSlider(Qt::Horizontal); - slider->setRange(1, 100); - hBox->addWidget(slider); - - auto lb = new QLabel(QString::number(slider->value())+"%"); - connect(slider, &QSlider::valueChanged, lb, [lb](int value) { - lb->setText(QString::number(value)+"%"); - }); - hBox->addWidget(lb); - - tableSche->setCellWidget(row, "bright", cellWgt); - - auto timeEdit = new QTimeEdit(QTime(0, 0)); - timeEdit->setDisplayFormat("HH:mm"); - timeEdit->setAlignment(Qt::AlignCenter); - tableSche->setCellWidget(row, "start", timeEdit); - - timeEdit = new QTimeEdit(QTime(1, 0)); - timeEdit->setDisplayFormat("HH:mm"); - timeEdit->setAlignment(Qt::AlignCenter); - tableSche->setCellWidget(row, "end", timeEdit); - }); - hBox->addWidget(btnScheAdd); - - btnScheDel = new QPushButton; - btnScheDel->setMinimumSize(60, 30); - btnScheDel->setProperty("ssType", "progManageTool"); - connect(btnScheDel, &QPushButton::clicked, this, [this] { - auto selected = tableSche->selectedRanges(); - if(! selected.isEmpty()) tableSche->model()->removeRows(selected[0].topRow(), selected[0].rowCount()); - }); - hBox->addWidget(btnScheDel); - - btnScheClear = new QPushButton; - btnScheClear->setMinimumSize(60, 30); - btnScheClear->setProperty("ssType", "progManageTool"); - connect(btnScheClear, &QPushButton::clicked, this, [this] {tableSche->setRowCount(0);}); - hBox->addWidget(btnScheClear); - - hBox->addStretch(); - - lbDefBright = new QLabel; - lbDefBright->setAlignment(Qt::AlignRight | Qt::AlignVCenter); - lbDefBright->setMinimumWidth(120); - hBox->addWidget(lbDefBright); - - fdDefBright = new QSlider(Qt::Horizontal); - fdDefBright->setRange(0, 100); - fdDefBright->setValue(100); - fdDefBright->setMinimumWidth(120); - hBox->addWidget(fdDefBright); - - auto lbDefBrightValue = new QLabel(QString::number(fdDefBright->value())+"%"); - lbDefBrightValue->setMinimumWidth(40); - lbDefBrightValue->setAlignment(Qt::AlignRight | Qt::AlignVCenter); - connect(fdDefBright, &QSlider::valueChanged, lbDefBrightValue, [lbDefBrightValue](int value) { - lbDefBrightValue->setText(QString::number(value)+"%"); - }); - hBox->addWidget(lbDefBrightValue); - - hBox->addStretch(); - - btnScheImport = new QPushButton; - btnScheImport->setMinimumSize(QSize(60, 30)); - btnScheImport->setProperty("ssType", "progManageTool"); - connect(btnScheImport, &QPushButton::clicked, this, [this] { - auto dir = QSettings().value("CtrlScheduleDir").toString(); - if(dir.isEmpty()) dir = "/"; - QString scheFile = QFileDialog::getOpenFileName(this, tr("Import File"), dir, tr("BrightnessSchedule (*.bjs)")); - if(scheFile.isEmpty()) return; - QFile scheQFile(scheFile); - if(! scheQFile.open(QIODevice::ReadOnly)) return; - auto data = scheQFile.readAll(); - scheQFile.close(); - restoreScheduleJson(QJsonDocument::fromJson(data).object()); - }); - hBox->addWidget(btnScheImport); - - btnScheExport = new QPushButton; - btnScheExport->setMinimumSize(QSize(60, 30)); - btnScheExport->setProperty("ssType", "progManageTool"); - connect(btnScheExport, &QPushButton::clicked, this, [this] { - QSettings settings; - auto dir = settings.value("CtrlScheduleDir").toString(); - if(dir.isEmpty()) dir = "/"; - QString scheFile = QFileDialog::getSaveFileName(this, tr("Save File"), dir, tr("BrightnessSchedule (*.bjs)")); - if(scheFile.isEmpty()) return; - settings.setValue("CtrlScheduleDir", QFileInfo(scheFile).absolutePath()); - QFile scheQFile(scheFile); - if(! scheQFile.open(QIODevice::WriteOnly)) return; - scheQFile.write(QJsonDocument(getScheduleJson()).toJson()); - scheQFile.close(); - }); - hBox->addWidget(btnScheExport); - - vBox->addLayout(hBox); - - tableSche = new Table({ - {"bright", tr("BrightnessValue"), 300}, - {"start", tr("Start Time"), 100}, - {"end", tr("End Time"), 100} - }); - tableSche->setDefs(); - tableSche->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); - vBox->addWidget(tableSche); - - hBox = new QHBoxLayout(); - hBox->addStretch(); - - btnScheSet = new QPushButton; - btnScheSet->setMinimumSize(QSize(60, 30)); - btnScheSet->setProperty("ssType", "progManageTool"); - connect(btnScheSet, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - QJsonObject json; - json.insert("_id", "SetAutoBrightnessTask"); - json.insert("_type", "SetAutoBrightnessTask"); - if(gSelCards->count() == 1) { - json.insert("taskBrightness", getScheduleJson(gSelCards->at(0)->BrightnessLevel)); - auto waitingDlg = new WaitingDlg(this, tr("SetAutoBrightnessTask")); - Def_CtrlReqPre; - connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { - Def_CtrlSetReqAfter - }); - } else { - foreach(auto card, *gSelCards) { - json.insert("taskBrightness", getScheduleJson(card->BrightnessLevel)); - Def_CtrlSetMulti(tr("SetAutoBrightnessTask")) - } - } - }); - hBox->addWidget(btnScheSet); - - hBox->addStretch(); - - btnScheGet = new QPushButton; - btnScheGet->setMinimumSize(QSize(60, 30)); - btnScheGet->setProperty("ssType", "progManageTool"); - connect(btnScheGet, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - QJsonObject json; - json.insert("_id", "GetAutoBrightnessTask"); - json.insert("_type", "GetAutoBrightnessTask"); - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, tr("GetAutoBrightnessTask")); - Def_CtrlReqPre - connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg, card] { - Def_CtrlSingleGetReply - waitingDlg->success(); - restoreScheduleJson(json["taskBrightness"].toObject(), card->BrightnessLevel); - }); - } - }); - hBox->addWidget(btnScheGet); - - hBox->addStretch(); - vBox->addLayout(hBox); - } - auto stackBox = new QStackedLayout(vBox); - stackBox->addWidget(autoPanel); - stackBox->addWidget(manualPanel); - stackBox->addWidget(schedulePanel); - stackBox->setCurrentIndex(0); - - auto group = new QButtonGroup; - group->addButton(radioAuto, 0); - group->addButton(radioManual, 1); - group->addButton(radioSchedule, 2); - connect(group, &QButtonGroup::idToggled, stackBox, [stackBox](int idx, bool checked) { - if(checked) stackBox->setCurrentIndex(idx); - }); - - connect(gDevicePanel, &DevicePanel::sigSelectedDeviceList, this, [this] { - if(isVisible()) init(); - }); - transUi(); -} - -void CtrlBrightPanel::showEvent(QShowEvent *event) { - QWidget::showEvent(event); - init(); -} -void CtrlBrightPanel::init() { - bool isSingle = gSelCards->count()==1; - btnTableGet->setEnabled(isSingle); - btnScheGet->setEnabled(isSingle); - if(! isSingle) return; - auto card = gSelCards->at(0); - - mSensi = -1; - mTask = -1; - - QJsonObject json; - json.insert("_id", "GetAutoBrightnessTask"); - json.insert("_type", "GetAutoBrightnessTask"); - auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); - connect(reply, &QNetworkReply::finished, this, [this, reply, card] { - QJsonDocument json; - QString err = checkReplyForJson(reply, &json); - if(! err.isEmpty()) { - QMessageBox::critical(gMainWin, tr("Error"), err); - return; - } - mTask = restoreScheduleJson(json["taskBrightness"].toObject(), card->BrightnessLevel); - if(mTask) radioSchedule->setChecked(true); - else if(mSensi > 0) radioAuto->setChecked(true); - else if(mSensi == 0) radioManual->setChecked(true); - }); - - json = QJsonObject(); - json.insert("_id", "GetBrightnessSensitivity"); - json.insert("_type", "GetBrightnessSensitivity"); - reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); - connect(reply, &QNetworkReply::finished, this, [this, reply] { - QJsonDocument json; - QString err = checkReplyForJson(reply, &json); - if(! err.isEmpty()) { - QMessageBox::critical(gMainWin, tr("Error"), err); - return; - } - mSensi = json["sensitivity"].toInt(); - fdSensi->setValue(mSensi); - if(mTask != 0) return; - if(mSensi > 0) radioAuto->setChecked(true); - else radioManual->setChecked(true); - }); - - json = QJsonObject(); - json.insert("_id", "GetMinBrightness"); - json.insert("_type", "GetMinBrightness"); - reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); - connect(reply, &QNetworkReply::finished, this, [this, reply, card] { - QJsonDocument json; - QString err = checkReplyForJson(reply, &json); - if(! err.isEmpty()) { - QMessageBox::critical(gMainWin, tr("Error"), err); - return; - } - fdMinBright->setValue(qRound(json["brightness"].toInt() * 100.0 / card->BrightnessLevel)); - }); - - json = QJsonObject(); - json.insert("_id", "GetBrightness"); - json.insert("_type", "GetBrightness"); - reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); - connect(reply, &QNetworkReply::finished, this, [this, reply, card] { - QJsonDocument json; - QString err = checkReplyForJson(reply, &json); - if(! err.isEmpty()) { - QMessageBox::critical(gMainWin, tr("Error"), err); - return; - } - card->brightness = json["brightness"].toInt(); - fdFixedBright->setValue(qRound(card->brightness * 100.0 / card->BrightnessLevel)); - }); -} - -void CtrlBrightPanel::changeEvent(QEvent *event) { - QWidget::changeEvent(event); - if(event->type() == QEvent::LanguageChange) transUi(); -} -void CtrlBrightPanel::transUi() { - lbBrightCfg->setText(tr("Brightness Configuration")); - radioAuto->setText(tr("Auto")); - radioManual->setText(tr("Manual")); - radioSchedule->setText(tr("Schedule")); - - fdBrightTip->setText(tr("BrightTip1")); - fdSensiTypeTip->setText(tr("BrightTip2")); - lbSensi->setText(tr("Sensitivity")); - lbMinBright->setText(tr("Minbrightness")); - btnMinBrightSet->setText(tr("Set")); - btnSensiSet->setText(tr("Set")); - btnUpload->setText(tr("Upload")); - btnMinBrightGet->setText(tr("Readback")); - btnSensiGet->setText(tr("Readback")); - btnTableGet->setText(tr("ReadbackTable")); - btnCurBrightGet->setText(tr("Refresh")); - lbCurBright->setText(tr("Cur Brigntness")+": "); - - lbFixedBright->setText(tr("Brightness value")); - btnFixedSet->setText(tr("Set")); - btnFixedGet->setText(tr("Readback")); - - lbDefBright->setText(tr("Default brightness")); - btnScheAdd->setText(tr("Add")); - btnScheClear->setText(tr("Clear")); - btnScheDel->setText(tr("Delete")); - btnScheImport->setText(tr("Import")); - btnScheExport->setText(tr("Export")); - btnScheSet->setText(tr("Apply")); - btnScheGet->setText(tr("Readback")); - fdScheTip->setText(tr("Default brightness tip")); -} - -bool CtrlBrightPanel::restoreScheduleJson(QJsonObject obj, int max) { - tableSche->setRowCount(0); - fdDefBright->setValue(qRound(obj["defaultBrightness"].toInt() * 100.0 / max)); - auto jsitems = obj["items"].toArray(); - foreach(auto jsitem, jsitems) { - auto schedule = jsitem["schedules"][0]; - int row = tableSche->rowCount(); - tableSche->insertRow(row); - - auto cellWgt = new QWidget; - auto hBox = new QHBoxLayout(cellWgt); - - auto slider = new QSlider(Qt::Horizontal); - slider->setRange(1, 100); - slider->setValue(qRound(jsitem["brightness"].toInt() * 100.0 / max)); - hBox->addWidget(slider); - - auto lb = new QLabel(QString::number(slider->value())+"%"); - connect(slider, &QSlider::valueChanged, lb, [lb](int value) { - lb->setText(QString::number(value)+"%"); - }); - hBox->addWidget(lb); - tableSche->setCellWidget(row, "bright", cellWgt); - - auto timeEdit = new QTimeEdit(QTime::fromString(schedule["startTime"].toString(), "HH:mm")); - timeEdit->setDisplayFormat("HH:mm"); - timeEdit->setAlignment(Qt::AlignCenter); - tableSche->setCellWidget(row, "start", timeEdit); - - timeEdit = new QTimeEdit(QTime::fromString(schedule["endTime"].toString(), "HH:mm")); - timeEdit->setDisplayFormat("HH:mm"); - timeEdit->setAlignment(Qt::AlignCenter); - tableSche->setCellWidget(row, "end", timeEdit); - } - return jsitems.count() > 0; -} -QJsonObject CtrlBrightPanel::getScheduleJson(int max) { - QJsonObject obj; - obj["createDate"] = QJsonValue::Null; - obj["createBy"] = "alahover"; - obj["name"] = "TimingBrightness"; - auto def = (fdDefBright->value() * max + 50) / 100; - obj["defaultBrightness"] = def; - obj["brightness"] = def; - QJsonArray jsItems; - for(int i=0; irowCount(); i++) { - QJsonObject item; - item["brightness"] = (static_cast(tableSche->cellWidget(i, "bright")->layout()->itemAt(0)->widget())->value() * max + 50) / 100; - QJsonObject schedule; - schedule["timeType"] = "Range"; - schedule["startTime"] = static_cast(tableSche->cellWidget(i, "start"))->text(); - schedule["endTime"] = static_cast(tableSche->cellWidget(i, "end"))->text(); - schedule["dateType"] = "All"; - schedule["startDate"] = QJsonValue::Null; - schedule["endDate"] = QJsonValue::Null; - schedule["monthFilter"] = QJsonArray(); - schedule["filterType"] = "None"; - schedule["weekFilter"] = QJsonArray(); - item["schedules"] = QJsonArray{schedule}; - jsItems.append(item); - } - obj["items"] = jsItems; - return obj; -} +#include "ctrlbrightpanel.h" +#include "base/waitingdlg.h" +#include "globaldefine.h" +#include "deviceitem.h" +#include "tools.h" +#include "xlsxdocument.h" +#include "xlsxworkbook.h" +#include +#include +#include +#include +#include +#include +#include + +CtrlBrightPanel::CtrlBrightPanel(QWidget *parent) : QWidget(parent) { + auto vBox = new VBox(this); + vBox->setContentsMargins(0,0,0,0); + vBox->addSpacing(8); + + lbBrightCfg = new QLabel; + auto font = lbBrightCfg->font(); + font.setPixelSize(font.pixelSize()+2); + font.setBold(true); + lbBrightCfg->setFont(font); + lbBrightCfg->setAlignment(Qt::AlignCenter); + vBox->addWidget(lbBrightCfg); + vBox->addSpacing(9); + + auto hBox = new HBox(vBox); + hBox->addStretch(); + + radioAuto = new QRadioButton; + radioAuto->setChecked(true); + hBox->addWidget(radioAuto); + hBox->addSpacing(40); + + radioManual = new QRadioButton; + hBox->addWidget(radioManual); + hBox->addSpacing(40); + + radioSchedule = new QRadioButton; + hBox->addWidget(radioSchedule); + hBox->addStretch(); + + fdAdaptToOld = new QCheckBox; + hBox->addWidget(fdAdaptToOld); + + + auto line = new QFrame; + line->setFrameShape(QFrame::HLine); + line->setFrameShadow(QFrame::Sunken); + vBox->addWidget(line); + + auto stack = new QStackedLayout(vBox); + { + auto vBox = new VBox(stack); + + fdBrightTip = new QLabel; + fdBrightTip->setAlignment(Qt::AlignCenter); + fdBrightTip->setWordWrap(true); + vBox->addWidget(fdBrightTip); + + auto hBox = new QHBoxLayout; + hBox->addStretch(); + + lbSensi = new QLabel; + lbSensi->setMinimumWidth(120); + lbSensi->setAlignment(Qt::AlignRight | Qt::AlignVCenter); + hBox->addWidget(lbSensi); + + fdSensi = new QSlider(Qt::Horizontal); + fdSensi->setRange(1, 100); + hBox->addWidget(fdSensi); + + auto lbSensiValue = new QLabel(QString::number(fdSensi->value())+"%"); + lbSensiValue->setMinimumWidth(40); + lbSensiValue->setAlignment(Qt::AlignRight | Qt::AlignVCenter); + connect(fdSensi, &QSlider::valueChanged, lbSensiValue, [lbSensiValue](int value) { + lbSensiValue->setText(QString::number(value)+"%"); + }); + hBox->addWidget(lbSensiValue); + + btnSensiSet = new QPushButton; + btnSensiSet->setMinimumSize(60, 30); + btnSensiSet->setProperty("ssType", "progManageTool"); + connect(btnSensiSet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "SetBrightnessSensitivity"); + json.insert("_type", "SetBrightnessSensitivity"); + json.insert("sensitivity", fdSensi->value()); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("SetBrightnessSensitivity")+" ..."); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, card, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("SetBrightnessSensitivity")) + } + } + }); + hBox->addWidget(btnSensiSet); + + btnSensiGet = new QPushButton; + btnSensiGet->setMinimumSize(60, 30); + btnSensiGet->setProperty("ssType", "progManageTool"); + connect(btnSensiGet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "GetBrightnessSensitivity"); + json.insert("_type", "GetBrightnessSensitivity"); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("GetBrightnessSensitivity")+" ..."); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg] { + Def_CtrlSingleGetReply + waitingDlg->success(); + fdSensi->setValue(json["sensitivity"].toInt()); + }); + } else { + foreach(auto card, *gSelCards) { + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + auto cardId = card->m_strCardId; + connect(reply, &QNetworkReply::finished, this, [reply, cardId] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(err.isEmpty()) err = QString::number(json["sensitivity"].toInt()); + gFdResInfo->append(cardId+" "+tr("GetBrightnessSensitivity")+" "+err); + }); + } + } + }); + hBox->addWidget(btnSensiGet); + + hBox->addStretch(); + vBox->addLayout(hBox); + + hBox = new QHBoxLayout; + hBox->addStretch(); + + lbMinBright = new QLabel; + lbMinBright->setMinimumWidth(120); + lbMinBright->setAlignment(Qt::AlignRight | Qt::AlignVCenter); + hBox->addWidget(lbMinBright); + + fdMinBright = new QSlider(Qt::Horizontal); + fdMinBright->setRange(1, 100); + hBox->addWidget(fdMinBright); + + auto lbMinBrightValue = new QLabel(QString::number(fdMinBright->value())+"%"); + lbMinBrightValue->setMinimumWidth(40); + lbMinBrightValue->setAlignment(Qt::AlignRight | Qt::AlignVCenter); + connect(fdMinBright, &QSlider::valueChanged, lbSensiValue, [lbMinBrightValue](int value) { + lbMinBrightValue->setText(QString::number(value)+"%"); + }); + hBox->addWidget(lbMinBrightValue); + + btnMinBrightSet = new QPushButton; + btnMinBrightSet->setMinimumSize(60, 30); + btnMinBrightSet->setProperty("ssType", "progManageTool"); + connect(btnMinBrightSet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + auto isAdaptToOld = fdAdaptToOld->isChecked(); + QJsonObject json; + json.insert("_id", "SetMinBrightness"); + json.insert("_type", "SetMinBrightness"); + auto brightPercent = fdMinBright->value(); + if(! isAdaptToOld) json.insert("minBrightnessPercentage", brightPercent); + if(gSelCards->count() == 1) { + if(isAdaptToOld) json.insert("brightness", (brightPercent * gSelCards->at(0)->BrightnessLevel + 50) / 100); + auto waitingDlg = new WaitingDlg(this, tr("SetMinBrightness")+" ..."); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + if(isAdaptToOld) json.insert("brightness", (brightPercent * card->BrightnessLevel + 50) / 100); + Def_CtrlSetMulti(tr("SetMinBrightness")); + } + } + }); + hBox->addWidget(btnMinBrightSet); + + btnMinBrightGet = new QPushButton; + btnMinBrightGet->setMinimumSize(60, 30); + btnMinBrightGet->setProperty("ssType", "progManageTool"); + connect(btnMinBrightGet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "GetMinBrightness"); + json.insert("_type", "GetMinBrightness"); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("GetMinBrightness")+" ..."); + Def_CtrlReqPre + auto brightLevel = card->BrightnessLevel; + connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg, brightLevel] { + Def_CtrlSingleGetReply + waitingDlg->success(); + auto value = json["minBrightnessPercentage"].toInt(-1); + if(value==-1) value = qRound(json["brightness"].toInt() * 100.0 / brightLevel); + fdMinBright->setValue(value); + }); + } else { + foreach(auto card, *gSelCards) { + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + auto cardId = card->m_strCardId; + auto brightLevel = card->BrightnessLevel; + connect(reply, &QNetworkReply::finished, this, [reply, cardId, brightLevel] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(err.isEmpty()) { + auto value = json["minBrightnessPercentage"].toInt(-1); + if(value==-1) value = qRound(json["brightness"].toInt() * 100.0 / brightLevel); + err = QString::number(value)+"%"; + } + gFdResInfo->append(cardId+" "+tr("GetMinBrightness")+" "+err); + }); + } + } + }); + hBox->addWidget(btnMinBrightGet); + + hBox->addStretch(); + vBox->addLayout(hBox); + + + line = new QFrame; + line->setFrameShape(QFrame::HLine); + line->setFrameShadow(QFrame::Sunken); + vBox->addWidget(line); + + fdSensiTypeTip = new QLabel; + fdSensiTypeTip->setAlignment(Qt::AlignCenter); + fdSensiTypeTip->setWordWrap(true); + vBox->addWidget(fdSensiTypeTip); + + hBox = new QHBoxLayout; + hBox->addStretch(); + + fdR68 = new QRadioButton("R68/RL3"); + hBox->addWidget(fdR68); + + fdRL2 = new QRadioButton("RL2"); + hBox->addWidget(fdRL2); + + hBox->addSpacing(20); + + btnUpload = new QPushButton; + btnUpload->setMinimumSize(60, 30); + btnUpload->setProperty("ssType", "progManageTool"); + connect(btnUpload, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QString sensorName; + if(fdRL2->isChecked()) sensorName = fdRL2->text(); + else if(fdR68->isChecked()) sensorName = fdR68->text(); + else { + QMessageBox::information(gMainWin, tr("Tip"), tr("NeedSelectSensorTypeTip")); + return; + } + QString xlsxFile = QFileDialog::getOpenFileName(this, tr("Open file dialog"), "/", "brightness files(*.xlsx)"); + if(xlsxFile.isEmpty() || ! QFileInfo::exists(xlsxFile)) return; + QXlsx::Document xlsx(xlsxFile); + auto workbook = xlsx.workbook(); + QXlsx::Worksheet *sheet = 0; + if(workbook->sheetCount() < 2) { + sheet = xlsx.currentWorksheet(); + if(sheet==0) { + QMessageBox::information(gMainWin, tr("Tip"), tr("Not found current worksheet")); + return; + } + } else { + auto names = sensorName.split("/"); + foreach(auto name, names) { + auto idx = xlsx.sheetNames().indexOf(name); + if(idx > -1) { + workbook->setActiveSheet(idx); + sheet = dynamic_cast(workbook->sheet(idx)); + break; + } + } + if(sheet==0) { + QMessageBox::information(gMainWin, tr("Tip"), "Not found sheet "+sensorName); + return; + } + } + QJsonArray values; + for(int j=0; j<255; j++) { + auto val = sheet->read(3, j+3).toString(); + if(val.isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), "Cell is empty at 3, "+QString::number(j+3)); + return; + } + values.append(val); + } + QJsonObject json; + json.insert("_id", "SensorBrightnessTable"); + json.insert("_type", "SensorBrightnessTable"); + json.insert("values", values); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("SensorBrightnessTable")); + Def_CtrlReqPre; + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter; + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("SensorBrightnessTable")); + } + } + }); + hBox->addWidget(btnUpload); + + btnTableGet = new QPushButton(); + btnTableGet->setMinimumSize(60, 30); + btnTableGet->setProperty("ssType", "progManageTool"); + connect(btnTableGet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QString strSensorType; + if(fdRL2->isChecked()) strSensorType = fdRL2->text(); + else if(fdR68->isChecked()) strSensorType = fdR68->text(); + else { + QMessageBox::information(gMainWin, tr("Tip"), tr("NeedSelectSensorTypeTip")); + return; + } + QJsonObject json; + json.insert("_id", "GetSensorBrightnessTable"); + json.insert("_type", "GetSensorBrightnessTable"); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("GetSensorBrightnessTable")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg, card, strSensorType] { + Def_CtrlSingleGetReply + waitingDlg->close(); + QStringList values = json["values"].toVariant().value(); + if(values.isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("no sensorBrightnessTable")); + return; + } + QString tempFile = QCoreApplication::applicationDirPath()+"/bright-template.xlsx"; + QFile tempQFile(tempFile); + if(! tempQFile.exists()) { + QMessageBox::information(gMainWin, tr("Tip"), tempFile+" is not exist"); + return; + } + QString selectFilter = "*.xlsx"; + QString savingFile = QFileDialog::getSaveFileName(this, tr("Save file"), card->m_strCardId + "BrightnessTable.xlsx", "brightness(*.xlsx );", &selectFilter, QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); + if(savingFile.isEmpty()) return; + tempQFile.copy(savingFile); + QXlsx::Document xlsx(savingFile); + xlsx.selectSheet(strSensorType); + for(int m=0; maddWidget(btnTableGet); + + hBox->addStretch(); + vBox->addLayout(hBox); + + + hBox = new QHBoxLayout; + hBox->addStretch(); + + lbCurBright = new QLabel; + hBox->addWidget(lbCurBright); + + fdCurBright = new QLabel; + hBox->addWidget(fdCurBright); + + btnCurBrightGet = new QPushButton; + btnCurBrightGet->setMinimumSize(60, 30); + btnCurBrightGet->setProperty("ssType", "progManageTool"); + connect(btnCurBrightGet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "GetCurrentSensorBrightness"); + json.insert("_type", "GetCurrentSensorBrightness"); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("GetCurrentSensorBrightness")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg, card] { + QJsonDocument json; + QByteArray data; + QString err = checkReplyForJson(reply, &json, &data); + if(! err.isEmpty()) { + waitingDlg->close(); + QMessageBox::critical(gMainWin, tr("Error"), err); + return; + } + waitingDlg->success(); + if(json["is485"].toBool()) fdR68->setChecked(true); + else fdRL2->setChecked(true); + fdCurBright->setText(QString::number(qRound(json["value"].toInt() * 100.0 / card->BrightnessLevel))+"%"); + }); + } else { + foreach(auto card, *gSelCards) { + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + connect(reply, &QNetworkReply::finished, this, [reply, card] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(err.isEmpty()) err = QString::number(qRound(json["value"].toInt() * 100.0 / card->BrightnessLevel))+"%"; + gFdResInfo->append(card->m_strCardId+" "+tr("GetCurrentSensorBrightness")+" "+err); + }); + } + } + }); + hBox->addWidget(btnCurBrightGet); + + hBox->addStretch(); + vBox->addLayout(hBox); + vBox->addStretch(); + } + { + auto vBox = new VBox(stack); + + auto hBox = new QHBoxLayout; + hBox->addStretch(); + + lbFixedBright = new QLabel; + hBox->addWidget(lbFixedBright); + + fdFixedBright = new QSlider(Qt::Horizontal); + fdFixedBright->setRange(1, 100); + hBox->addWidget(fdFixedBright); + + auto lbBrightValue = new QLabel(QString::number(fdFixedBright->value())+"%"); + lbBrightValue->setMinimumWidth(40); + lbBrightValue->setAlignment(Qt::AlignRight | Qt::AlignVCenter); + connect(fdFixedBright, &QSlider::valueChanged, lbBrightValue, [lbBrightValue](int value) { + lbBrightValue->setText(QString::number(value)+"%"); + }); + hBox->addWidget(lbBrightValue); + + hBox->addStretch(); + + vBox->addLayout(hBox); + vBox->addSpacing(20); + + hBox = new QHBoxLayout; + hBox->addStretch(); + + btnFixedSet = new QPushButton; + btnFixedSet->setMinimumSize(60, 30); + btnFixedSet->setProperty("ssType", "progManageTool"); + connect(btnFixedSet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + auto isAdaptToOld = fdAdaptToOld->isChecked(); + QJsonObject json; + json.insert("_id", "SetBrightness"); + json.insert("_type", "SetBrightness"); + auto percent = fdFixedBright->value(); + if(! isAdaptToOld) json.insert("brightnessPercentage", percent); + if(gSelCards->count() == 1) { + if(isAdaptToOld) json.insert("brightness", (percent * gSelCards->at(0)->BrightnessLevel + 50) / 100); + auto waitingDlg = new WaitingDlg(this, tr("SetBrightness")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + if(isAdaptToOld) json.insert("brightness", (percent * card->BrightnessLevel + 50) / 100); + Def_CtrlSetMulti(tr("SetBrightness")) + } + } + }); + hBox->addWidget(btnFixedSet); + + btnFixedGet = new QPushButton; + btnFixedGet->setMinimumSize(60, 30); + btnFixedGet->setProperty("ssType", "progManageTool"); + connect(btnFixedGet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "GetBrightness"); + json.insert("_type", "GetBrightness"); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("GetBrightness")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg, card] { + QJsonDocument json; + QByteArray data; + QString err = checkReplyForJson(reply, &json, &data); + if(! err.isEmpty()) { + waitingDlg->close(); + QMessageBox::critical(gMainWin, tr("Error"), err); + return; + } + waitingDlg->success(); + card->bright = json["brightnessPercentage"].toInt(-1); + if(card->bright==-1) card->bright = qRound(json["brightness"].toInt() * 100.0 / card->BrightnessLevel); + fdFixedBright->setValue(card->bright); + }); + } else { + foreach(auto card, *gSelCards) { + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + connect(reply, &QNetworkReply::finished, this, [reply, card] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(err.isEmpty()) { + auto value = json["brightnessPercentage"].toInt(-1); + if(value==-1) value = qRound(json["brightness"].toInt() * 100.0 / card->BrightnessLevel); + err = QString::number(value)+"%"; + } + gFdResInfo->append(card->m_strCardId+" "+tr("Brightness")+" "+err); + }); + } + } + }); + hBox->addWidget(btnFixedGet); + + hBox->addStretch(); + + vBox->addLayout(hBox); + vBox->addStretch(); + } + { + auto hBox = new HBox(stack); + hBox->addStretch(); + auto vBox = new VBox(hBox); + hBox->addStretch(); + + hBox = new HBox(vBox); + + fdScheTip = new QLabel; + fdScheTip->setWordWrap(true); + hBox->addWidget(fdScheTip); + + + hBox = new HBox(vBox); + + btnScheAdd = new QPushButton; + btnScheAdd->setMinimumSize(60, 30); + btnScheAdd->setProperty("ssType", "progManageTool"); + connect(btnScheAdd, &QPushButton::clicked, this, [this] { + int row = tableSche->rowCount(); + tableSche->insertRow(row); + + auto cellWgt = new QWidget; + auto hBox = new QHBoxLayout(cellWgt); + + auto slider = new QSlider(Qt::Horizontal); + slider->setRange(1, 100); + hBox->addWidget(slider); + + auto lb = new QLabel(QString::number(slider->value())+"%"); + connect(slider, &QSlider::valueChanged, lb, [lb](int value) { + lb->setText(QString::number(value)+"%"); + }); + hBox->addWidget(lb); + + tableSche->setCellWidget(row, "bright", cellWgt); + + auto timeEdit = new QTimeEdit(QTime(0, 0)); + timeEdit->setDisplayFormat("HH:mm"); + timeEdit->setAlignment(Qt::AlignCenter); + tableSche->setCellWidget(row, "start", timeEdit); + + timeEdit = new QTimeEdit(QTime(1, 0)); + timeEdit->setDisplayFormat("HH:mm"); + timeEdit->setAlignment(Qt::AlignCenter); + tableSche->setCellWidget(row, "end", timeEdit); + }); + hBox->addWidget(btnScheAdd); + + btnScheDel = new QPushButton; + btnScheDel->setMinimumSize(60, 30); + btnScheDel->setProperty("ssType", "progManageTool"); + connect(btnScheDel, &QPushButton::clicked, this, [this] { + auto selected = tableSche->selectedRanges(); + if(! selected.isEmpty()) tableSche->model()->removeRows(selected[0].topRow(), selected[0].rowCount()); + }); + hBox->addWidget(btnScheDel); + + btnScheClear = new QPushButton; + btnScheClear->setMinimumSize(60, 30); + btnScheClear->setProperty("ssType", "progManageTool"); + connect(btnScheClear, &QPushButton::clicked, this, [this] {tableSche->setRowCount(0);}); + hBox->addWidget(btnScheClear); + + hBox->addStretch(); + + lbDefBright = new QLabel; + lbDefBright->setAlignment(Qt::AlignRight | Qt::AlignVCenter); + lbDefBright->setMinimumWidth(120); + hBox->addWidget(lbDefBright); + + fdDefBright = new QSlider(Qt::Horizontal); + fdDefBright->setRange(0, 100); + fdDefBright->setValue(100); + fdDefBright->setMinimumWidth(120); + hBox->addWidget(fdDefBright); + + auto lbDefBrightValue = new QLabel(QString::number(fdDefBright->value())+"%"); + lbDefBrightValue->setMinimumWidth(40); + lbDefBrightValue->setAlignment(Qt::AlignRight | Qt::AlignVCenter); + connect(fdDefBright, &QSlider::valueChanged, lbDefBrightValue, [lbDefBrightValue](int value) { + lbDefBrightValue->setText(QString::number(value)+"%"); + }); + hBox->addWidget(lbDefBrightValue); + + hBox->addStretch(); + + btnScheImport = new QPushButton; + btnScheImport->setMinimumSize(QSize(60, 30)); + btnScheImport->setProperty("ssType", "progManageTool"); + connect(btnScheImport, &QPushButton::clicked, this, [this] { + auto dir = QSettings().value("CtrlScheduleDir").toString(); + if(dir.isEmpty()) dir = "/"; + QString scheFile = QFileDialog::getOpenFileName(this, tr("Import File"), dir, tr("BrightnessSchedule (*.bjs)")); + if(scheFile.isEmpty()) return; + QFile scheQFile(scheFile); + if(! scheQFile.open(QIODevice::ReadOnly)) return; + auto data = scheQFile.readAll(); + scheQFile.close(); + auto json = QJsonDocument::fromJson(data); + tableSche->setRowCount(0); + fdDefBright->setValue(json["defaultBrightness"].toInt()); + auto jsitems = json["items"].toArray(); + foreach(auto jsitem, jsitems) { + auto schedule = jsitem["schedules"][0]; + int row = tableSche->rowCount(); + tableSche->insertRow(row); + + auto cellWgt = new QWidget; + auto hBox = new QHBoxLayout(cellWgt); + + auto slider = new QSlider(Qt::Horizontal); + slider->setRange(1, 100); + slider->setValue(jsitem["brightness"].toInt()); + hBox->addWidget(slider); + + auto lb = new QLabel(QString::number(slider->value())+"%"); + connect(slider, &QSlider::valueChanged, lb, [lb](int value) { + lb->setText(QString::number(value)+"%"); + }); + hBox->addWidget(lb); + tableSche->setCellWidget(row, "bright", cellWgt); + + auto timeEdit = new QTimeEdit(QTime::fromString(schedule["startTime"].toString(), "HH:mm")); + timeEdit->setDisplayFormat("HH:mm"); + timeEdit->setAlignment(Qt::AlignCenter); + tableSche->setCellWidget(row, "start", timeEdit); + + timeEdit = new QTimeEdit(QTime::fromString(schedule["endTime"].toString(), "HH:mm")); + timeEdit->setDisplayFormat("HH:mm"); + timeEdit->setAlignment(Qt::AlignCenter); + tableSche->setCellWidget(row, "end", timeEdit); + } + }); + hBox->addWidget(btnScheImport); + + btnScheExport = new QPushButton; + btnScheExport->setMinimumSize(QSize(60, 30)); + btnScheExport->setProperty("ssType", "progManageTool"); + connect(btnScheExport, &QPushButton::clicked, this, [this] { + QSettings settings; + auto dir = settings.value("CtrlScheduleDir").toString(); + if(dir.isEmpty()) dir = "/"; + QString scheFile = QFileDialog::getSaveFileName(this, tr("Save File"), dir, tr("BrightnessSchedule (*.bjs)")); + if(scheFile.isEmpty()) return; + settings.setValue("CtrlScheduleDir", QFileInfo(scheFile).absolutePath()); + QFile scheQFile(scheFile); + if(! scheQFile.open(QIODevice::WriteOnly)) return; + QJsonArray items; + for(int i=0; irowCount(); i++) items.append(QJsonObject{ + {"brightness", static_cast(tableSche->cellWidget(i, "bright")->layout()->itemAt(0)->widget())->value()}, + {"schedules", QJsonArray{QJsonObject{ + {"startTime", static_cast(tableSche->cellWidget(i, "start"))->text()}, + {"endTime", static_cast(tableSche->cellWidget(i, "end"))->text()} + }}} + }); + scheQFile.write(QJsonDocument(QJsonObject{{"defaultBrightness", fdDefBright->value()}, {"items", items}}).toJson()); + scheQFile.close(); + }); + hBox->addWidget(btnScheExport); + + + tableSche = new Table({ + {"bright", "", 300}, + {"start", "", 100}, + {"end", "", 100} + }); + tableSche->setDefs(); + tableSche->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); + vBox->addWidget(tableSche); + + hBox = new HBox(vBox); + hBox->addStretch(); + + btnScheSet = new QPushButton; + btnScheSet->setMinimumSize(QSize(60, 30)); + btnScheSet->setProperty("ssType", "progManageTool"); + connect(btnScheSet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + auto isAdaptToOld = fdAdaptToOld->isChecked(); + QJsonObject json; + json.insert("_id", "SetAutoBrightnessTask"); + json.insert("_type", "SetAutoBrightnessTask"); + if(! isAdaptToOld) getScheduleJson(json, 0); + if(gSelCards->count() == 1) { + if(isAdaptToOld) getScheduleJson(json, gSelCards->at(0)->BrightnessLevel); + auto waitingDlg = new WaitingDlg(this, tr("SetAutoBrightnessTask")); + Def_CtrlReqPre; + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + if(isAdaptToOld) getScheduleJson(json, card->BrightnessLevel); + Def_CtrlSetMulti(tr("SetAutoBrightnessTask")) + } + } + }); + hBox->addWidget(btnScheSet); + + hBox->addStretch(); + + btnScheGet = new QPushButton; + btnScheGet->setMinimumSize(QSize(60, 30)); + btnScheGet->setProperty("ssType", "progManageTool"); + connect(btnScheGet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "GetAutoBrightnessTask"); + json.insert("_type", "GetAutoBrightnessTask"); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("GetAutoBrightnessTask")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg, card] { + Def_CtrlSingleGetReply + waitingDlg->success(); + restoreScheduleJson(json, card->BrightnessLevel); + }); + } + }); + hBox->addWidget(btnScheGet); + + hBox->addStretch(); + } + stack->setCurrentIndex(0); + + auto group = new QButtonGroup; + group->addButton(radioAuto, 0); + group->addButton(radioManual, 1); + group->addButton(radioSchedule, 2); + connect(group, &QButtonGroup::idToggled, stack, [=](int idx, bool checked) { + if(checked) stack->setCurrentIndex(idx); + }); + + connect(gDevicePanel, &DevicePanel::sigSelectedDeviceList, this, [this] { + if(isVisible()) init(); + }); + transUi(); +} + +void CtrlBrightPanel::showEvent(QShowEvent *event) { + QWidget::showEvent(event); + init(); +} +void CtrlBrightPanel::init() { + bool isSingle = gSelCards->count()==1; + btnTableGet->setEnabled(isSingle); + btnScheGet->setEnabled(isSingle); + if(! isSingle) return; + auto card = gSelCards->at(0); + + mSensi = -1; + mTask = -1; + + QJsonObject json; + json.insert("_id", "GetAutoBrightnessTask"); + json.insert("_type", "GetAutoBrightnessTask"); + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + connect(reply, &QNetworkReply::finished, this, [this, reply, card] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) return; + mTask = restoreScheduleJson(json, card->BrightnessLevel); + if(mTask) radioSchedule->setChecked(true); + else if(mSensi > 0) radioAuto->setChecked(true); + else if(mSensi == 0) radioManual->setChecked(true); + }); + + json = QJsonObject(); + json.insert("_id", "GetBrightnessSensitivity"); + json.insert("_type", "GetBrightnessSensitivity"); + reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + connect(reply, &QNetworkReply::finished, this, [this, reply] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) return; + mSensi = json["sensitivity"].toInt(); + fdSensi->setValue(mSensi); + if(mTask != 0) return; + if(mSensi > 0) radioAuto->setChecked(true); + else radioManual->setChecked(true); + }); + + json = QJsonObject(); + json.insert("_id", "GetMinBrightness"); + json.insert("_type", "GetMinBrightness"); + reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + connect(reply, &QNetworkReply::finished, this, [this, reply, card] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) return; + auto value = json["minBrightnessPercentage"].toInt(-1); + if(value==-1) value = qRound(json["brightness"].toInt() * 100.0 / card->BrightnessLevel); + fdMinBright->setValue(value); + }); + + json = QJsonObject(); + json.insert("_id", "GetBrightness"); + json.insert("_type", "GetBrightness"); + reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + connect(reply, &QNetworkReply::finished, this, [this, reply, card] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) return; + card->bright = json["brightnessPercentage"].toInt(-1); + if(card->bright==-1) card->bright = qRound(json["brightness"].toInt() * 100.0 / card->BrightnessLevel); + fdFixedBright->setValue(card->bright); + }); +} + +void CtrlBrightPanel::changeEvent(QEvent *event) { + QWidget::changeEvent(event); + if(event->type() == QEvent::LanguageChange) transUi(); +} +void CtrlBrightPanel::transUi() { + lbBrightCfg->setText(tr("Brightness Configuration")); + radioAuto->setText(tr("Auto")); + radioManual->setText(tr("Manual")); + radioSchedule->setText(tr("Schedule")); + fdAdaptToOld->setText(tr("Adapt to Old Devices")); + + fdBrightTip->setText(tr("BrightTip1")); + fdSensiTypeTip->setText(tr("BrightTip2")); + lbSensi->setText(tr("Sensitivity")); + lbMinBright->setText(tr("Minbrightness")); + btnMinBrightSet->setText(tr("Set")); + btnSensiSet->setText(tr("Set")); + btnUpload->setText(tr("Upload")); + btnMinBrightGet->setText(tr("Readback")); + btnSensiGet->setText(tr("Readback")); + btnTableGet->setText(tr("ReadbackTable")); + btnCurBrightGet->setText(tr("Refresh")); + lbCurBright->setText(tr("Cur Brigntness")+": "); + + lbFixedBright->setText(tr("Brightness value")); + btnFixedSet->setText(tr("Set")); + btnFixedGet->setText(tr("Readback")); + + lbDefBright->setText(tr("Default brightness")); + btnScheAdd->setText(tr("Add")); + btnScheClear->setText(tr("Clear")); + btnScheDel->setText(tr("Delete")); + btnScheImport->setText(tr("Import")); + btnScheExport->setText(tr("Export")); + + tableSche->setHeaderText("bright", tr("BrightnessValue")); + tableSche->setHeaderText("start", tr("Start Time")); + tableSche->setHeaderText("end", tr("End Time")); + + btnScheSet->setText(tr("Apply")); + btnScheGet->setText(tr("Readback")); + fdScheTip->setText(tr("Default brightness tip")); +} + +bool CtrlBrightPanel::restoreScheduleJson(QJsonDocument &json, int max) { + tableSche->setRowCount(0); + auto taskBrightness = json["taskBrightness"]; + auto brightness = json["defaultBrightnessPercentage"].toInt(-1); + if(brightness==-1) brightness = qRound(taskBrightness["defaultBrightness"].toInt() * 100.0 / max); + fdDefBright->setValue(brightness); + auto jsitems = taskBrightness["items"].toArray(); + auto brightnesses = json["brightnessPercentageList"].toArray(); + for(int i=0; irowCount(); + tableSche->insertRow(row); + + auto cellWgt = new QWidget; + auto hBox = new QHBoxLayout(cellWgt); + + auto slider = new QSlider(Qt::Horizontal); + slider->setRange(1, 100); + if(brightnesses.size() > i) slider->setValue(brightnesses[i].toInt()); + else slider->setValue(qRound(jsitems.at(i)["brightness"].toInt() * 100.0 / max)); + hBox->addWidget(slider); + + auto lb = new QLabel(QString::number(slider->value())+"%"); + connect(slider, &QSlider::valueChanged, lb, [lb](int value) { + lb->setText(QString::number(value)+"%"); + }); + hBox->addWidget(lb); + tableSche->setCellWidget(row, "bright", cellWgt); + + auto timeEdit = new QTimeEdit(QTime::fromString(schedule["startTime"].toString(), "HH:mm")); + timeEdit->setDisplayFormat("HH:mm"); + timeEdit->setAlignment(Qt::AlignCenter); + tableSche->setCellWidget(row, "start", timeEdit); + + timeEdit = new QTimeEdit(QTime::fromString(schedule["endTime"].toString(), "HH:mm")); + timeEdit->setDisplayFormat("HH:mm"); + timeEdit->setAlignment(Qt::AlignCenter); + tableSche->setCellWidget(row, "end", timeEdit); + } + return jsitems.count() > 0; +} +void CtrlBrightPanel::getScheduleJson(QJsonObject &json, int max) { + QJsonArray items, brightnesses; + for(int i=0; irowCount(); i++) { + QJsonObject item; + auto brightness = static_cast(tableSche->cellWidget(i, "bright")->layout()->itemAt(0)->widget())->value(); + if(max==0) brightnesses.append(brightness); + else item.insert("brightness", (brightness * max + 50) / 100); + item.insert("schedules", QJsonArray{QJsonObject{ + {"timeType", "Range"}, + {"startTime", static_cast(tableSche->cellWidget(i, "start"))->text()}, + {"endTime", static_cast(tableSche->cellWidget(i, "end"))->text()}, + {"dateType", "All"}, + {"filterType", "None"}, + {"monthFilter", QJsonArray()}, + {"weekFilter", QJsonArray()} + }}); + items.append(item); + } + QJsonObject taskBrightness{ + {"createBy", "alahover"}, + {"name", "TimingBrightness"}, + {"items", items} + }; + if(max==0) { + json.insert("defaultBrightnessPercentage", fdDefBright->value()); + json.insert("brightnessPercentageList", brightnesses); + } else { + auto def = (fdDefBright->value() * max + 50) / 100; + taskBrightness.insert("defaultBrightness", def); + taskBrightness.insert("brightness", def); + } + json.insert("taskBrightness", taskBrightness); +} diff --git a/LedOK/wDevicesManager/ctrlbrightpanel.h b/LedOK/device/ctrlbrightpanel.h similarity index 86% rename from LedOK/wDevicesManager/ctrlbrightpanel.h rename to LedOK/device/ctrlbrightpanel.h index 86f70ed..b2c47ba 100644 --- a/LedOK/wDevicesManager/ctrlbrightpanel.h +++ b/LedOK/device/ctrlbrightpanel.h @@ -1,15 +1,12 @@ #ifndef CTRLBRIGHTPANEL_H #define CTRLBRIGHTPANEL_H -#include "ledcard.h" -#include "base/table.h" -#include +#include "gutil/qgui.h" #include #include #include +#include #include -#include -#include class CtrlBrightPanel : public QWidget { Q_OBJECT @@ -22,12 +19,13 @@ protected: void transUi(); private: - bool restoreScheduleJson(QJsonObject, int = 100); - QJsonObject getScheduleJson(int = 100); + bool restoreScheduleJson(QJsonDocument &, int); + void getScheduleJson(QJsonObject &, int); QLabel *lbBrightCfg; QRadioButton *radioAuto; QRadioButton *radioManual; QRadioButton *radioSchedule; + QCheckBox *fdAdaptToOld; char mSensi{-1}; char mTask{-1}; diff --git a/LedOK/device/ctrlhdmipanel.cpp b/LedOK/device/ctrlhdmipanel.cpp new file mode 100644 index 0000000..cc46580 --- /dev/null +++ b/LedOK/device/ctrlhdmipanel.cpp @@ -0,0 +1,424 @@ +#include "ctrlhdmipanel.h" +#include "gutil/qgui.h" +#include "tools.h" +#include "globaldefine.h" +#include "base/waitingdlg.h" +#include +#include +#include +#include + +CtrlHdmiPanel::CtrlHdmiPanel(QWidget *parent) : QWidget(parent) { + auto vBox = new QVBoxLayout(this); + lbHdmiCfg = new QLabel; + lbHdmiCfg->setAlignment(Qt::AlignCenter); + vBox->addWidget(lbHdmiCfg); + + auto line = new QFrame; + line->setFrameShape(QFrame::HLine); + line->setFrameShadow(QFrame::Sunken); + vBox->addWidget(line); + + auto hBox = new QHBoxLayout(); + hBox->addStretch(); + + fdManual = new QRadioButton; + hBox->addWidget(fdManual); + hBox->addSpacing(40); + + fdSchedule = new QRadioButton; + hBox->addWidget(fdSchedule); + hBox->addStretch(); + + vBox->addLayout(hBox); + + auto stacked = new QStackedLayout; + vBox->addLayout(stacked); + { + auto vBox = new VBox(stacked); + vBox->addSpacing(20); + + auto hBox = new HBox(vBox); + hBox->addStretch(); + + fdAsync = new QRadioButton; + hBox->addWidget(fdAsync); + hBox->addSpacing(20); + fdHdmi = new QRadioButton("HDMI"); + hBox->addWidget(fdHdmi); + hBox->addSpacing(20); + fdHdmi2 = new QRadioButton("HDMI 2"); + hBox->addWidget(fdHdmi2); + hBox->addStretch(); + + auto btnGroup = new QButtonGroup(this); + btnGroup->addButton(fdAsync, 0); + btnGroup->addButton(fdHdmi, 1); + btnGroup->addButton(fdHdmi2, 2); + connect(btnGroup, &QButtonGroup::idToggled, this, [this](int id, bool checked) { + if(! checked) return; + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "SyncSwitch"); + json.insert("_type", "SyncSwitch"); + json.insert("switchOn", (bool)id); + if(id) json.insert("number", id); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, checked ? tr("SyncSwitch") : tr("AnSyncSwitch")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + if(checked){ + Def_CtrlSetMulti(tr("SyncSwitch")) + } else { + Def_CtrlSetMulti(tr("AnSyncSwitch")) + } + } + } + }); + + vBox->addSpacing(20); + + hBox = new HBox(vBox); + hBox->addStretch(); + btnGetSync = new QPushButton; + btnGetSync->setMinimumSize(60, 30); + btnGetSync->setProperty("ssType", "progManageTool"); + connect(btnGetSync, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "IsSync"); + json.insert("_type", "IsSync"); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("IsSync")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg] { + Def_CtrlSingleGetReply + waitingDlg->success(); + auto switchOn = json["switchOn"]; + if(switchOn.isUndefined()) switchOn = json["result"]; + if(! switchOn.toBool()) fdAsync->setChecked(true); + else if(json["number"].toInt()==2) fdHdmi2->setChecked(true); + else fdHdmi->setChecked(true); + }); + } else { + foreach(auto card, *gSelCards) { + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + auto cardId = card->m_strCardId; + connect(reply, &QNetworkReply::finished, this, [reply, cardId] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(err.isEmpty()) { + auto switchOn = json["switchOn"]; + if(switchOn.isUndefined()) switchOn = json["result"]; + if(! switchOn.toBool()) err = tr("Async"); + else { + err = "HDMI"; + auto number = json["number"].toInt(); + if(number) err += " "+QString::number(number); + } + } + gFdResInfo->append(cardId+" "+err); + }); + } + } + }); + hBox->addWidget(btnGetSync); + hBox->addStretch(); + + vBox->addStretch(); + } + { + auto vBox = new VBox(stacked); + auto hBox = new HBox(vBox); + hBox->setSpacing(10); + + tableSche = new Table({ + {"start", "", 100}, + {"end", "", 100}, + {"0", "", 60}, + {"1", "", 60}, + {"2", "", 60}, + {"3", "", 60}, + {"4", "", 60}, + {"5", "", 60}, + {"6", "", 60} + }); + tableSche->setDefs(); + tableSche->setStyleSheet("Table {selection-background-color: #8ce;}"); + + btnScheAdd = new QPushButton; + btnScheAdd->setMinimumSize(QSize(60, 30)); + btnScheAdd->setProperty("ssType", "progManageTool"); + connect(btnScheAdd, &QPushButton::clicked, this, [this] { + int row = tableSche->appendRow(); + auto timeEdit = new QTimeEdit(QTime(0, 0)); + timeEdit->setDisplayFormat("HH:mm"); + timeEdit->setAlignment(Qt::AlignCenter); + tableSche->setCellWidget(row, "start", timeEdit); + + timeEdit = new QTimeEdit(QTime(1, 0)); + timeEdit->setDisplayFormat("HH:mm"); + timeEdit->setAlignment(Qt::AlignCenter); + tableSche->setCellWidget(row, "end", timeEdit); + + for(int i=0; i<7; i++) { + auto fd = new QCheckBox; + fd->setChecked(true); + tableSche->setCellWidget(row, QString::number(i), fd); + } + }); + hBox->addWidget(btnScheAdd); + + btnScheDel = new QPushButton; + btnScheDel->setMinimumSize(QSize(60, 30)); + btnScheDel->setProperty("ssType", "progManageTool"); + connect(btnScheDel, &QPushButton::clicked, this, [this] { + auto selected = tableSche->selectedRanges(); + if(! selected.isEmpty()) tableSche->model()->removeRows(selected[0].topRow(), selected[0].rowCount()); + }); + hBox->addWidget(btnScheDel); + + btnScheClear = new QPushButton; + btnScheClear->setMinimumSize(QSize(60, 30)); + btnScheClear->setProperty("ssType", "progManageTool"); + connect(btnScheClear, &QPushButton::clicked, tableSche, &Table::clearRows); + hBox->addWidget(btnScheClear); + hBox->addStretch(); + + btnScheImport = new QPushButton; + btnScheImport->setMinimumSize(QSize(0, 30)); + btnScheImport->setProperty("ssType", "progManageTool"); + connect(btnScheImport, &QPushButton::clicked, this, [this] { + auto dir = QSettings().value("CtrlScheduleDir").toString(); + if(dir.isEmpty()) dir = "/"; + QString scheFile = QFileDialog::getOpenFileName(this, tr("Import File"), dir, tr("Sync Schedule")+" (*.syncs)"); + if(scheFile.isEmpty()) return; + QFile scheQFile(scheFile); + if(! scheQFile.open(QIODevice::ReadOnly)) return; + auto data = scheQFile.readAll(); + scheQFile.close(); + restoreScheduleJson(QJsonDocument::fromJson(data).object()); + }); + hBox->addWidget(btnScheImport); + + btnScheExport = new QPushButton; + btnScheExport->setMinimumSize(QSize(0, 30)); + btnScheExport->setProperty("ssType", "progManageTool"); + connect(btnScheExport, &QPushButton::clicked, this, [this] { + QSettings settings; + auto dir = settings.value("CtrlScheduleDir").toString(); + if(dir.isEmpty()) dir = "/"; + QString scheFile = QFileDialog::getSaveFileName(this, tr("Save File"), dir, tr("Sync Schedule")+" (*.syncs)"); + if(scheFile.isEmpty()) return; + settings.setValue("CtrlScheduleDir", QFileInfo(scheFile).absolutePath()); + QFile scheQFile(scheFile); + if(! scheQFile.open(QIODevice::WriteOnly)) return; + scheQFile.write(QJsonDocument(getScheduleJson()).toJson()); + scheQFile.close(); + }); + hBox->addWidget(btnScheExport); + + labelSyncScheduleTip = new QLabel; + labelSyncScheduleTip->setWordWrap(true); + vBox->addWidget(labelSyncScheduleTip); + + vBox->addWidget(tableSche); + + hBox = new HBox(vBox); + hBox->addStretch(); + + btnScheSet = new QPushButton; + btnScheSet->setProperty("ssType", "progManageTool"); + btnScheSet->setMinimumSize(QSize(60, 30)); + connect(btnScheSet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "SetTimingHdmiInTask"); + json.insert("_type", "SetTimingHdmiInTask"); + if(gSelCards->count() == 1) { + json.insert("HdmiInTask", getScheduleJson()); + auto waitingDlg = new WaitingDlg(this, tr("SetTimingHdmiInTask")); + Def_CtrlReqPre; + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + json.insert("HdmiInTask", getScheduleJson()); + Def_CtrlSetMulti(tr("SetTimingHdmiInTask")) + } + } + }); + hBox->addWidget(btnScheSet); + hBox->addStretch(); + + btnScheGet = new QPushButton; + btnScheGet->setMinimumSize(QSize(0, 30)); + btnScheGet->setProperty("ssType", "progManageTool"); + connect(btnScheGet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "GetTimingHdmiInTask"); + json.insert("_type", "GetTimingHdmiInTask"); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("GetTimingHdmiInTask")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg] { + Def_CtrlSingleGetReply + waitingDlg->success(); + restoreScheduleJson(json["creenTask"].toObject()); + }); + } + }); + hBox->addWidget(btnScheGet); + + hBox->addStretch(); + } + + auto m_buttonGroup = new QButtonGroup; + m_buttonGroup->addButton(fdManual, 0); + m_buttonGroup->addButton(fdSchedule, 1); + connect(m_buttonGroup,SIGNAL(buttonClicked(int)),stacked,SLOT(setCurrentIndex(int))); + fdManual->setChecked(true); + stacked->setCurrentIndex(0); + + connect(gDevicePanel, &DevicePanel::sigSelectedDeviceList, this, [this] { + if(isVisible()) init(); + }); + transUi(); +} + +void CtrlHdmiPanel::showEvent(QShowEvent *event) { + QWidget::showEvent(event); + init(); +} + +void CtrlHdmiPanel::init() { + bool isSingle = gSelCards->count()==1; + btnScheGet->setEnabled(isSingle); + if(! isSingle) { + fdHdmi2->setVisible(true); + return; + } + auto card = gSelCards->at(0); + fdHdmi2->setVisible(card->m_strCardId.startsWith("m8s", Qt::CaseInsensitive)); + + QJsonObject json; + json.insert("_id", "IsSync"); + json.insert("_type", "IsSync"); + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + connect(reply, &QNetworkReply::finished, this, [this, reply] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) return; + auto switchOn = json["switchOn"]; + if(switchOn.isUndefined()) switchOn = json["result"]; + if(! switchOn.toBool()) fdAsync->setChecked(true); + else if(json["number"].toInt()==2) fdHdmi2->setChecked(true); + else fdHdmi->setChecked(true); + }); +} +void CtrlHdmiPanel::changeEvent(QEvent *event) { + QWidget::changeEvent(event); + if(event->type() == QEvent::LanguageChange) transUi(); +} +void CtrlHdmiPanel::transUi() { + lbHdmiCfg->setText(tr("HDMI Configuration")); + fdManual->setText(tr("Manual")); + fdSchedule->setText(tr("Schedule")); + + fdAsync->setText(tr("Async")); + btnGetSync->setText(tr("Readback")); + + tableSche->setHeaderText("start", tr("Start Time")); + tableSche->setHeaderText("end", tr("End Time")); + tableSche->setHeaderText("0", tr("SUN")); + tableSche->setHeaderText("1", tr("MON")); + tableSche->setHeaderText("2", tr("TUE")); + tableSche->setHeaderText("3", tr("WED")); + tableSche->setHeaderText("4", tr("THU")); + tableSche->setHeaderText("5", tr("FRI")); + tableSche->setHeaderText("6", tr("SAT")); + + btnScheAdd->setText(tr("Add")); + btnScheSet->setText(tr("Apply")); + btnScheClear->setText(tr("Clear")); + btnScheDel->setText(tr("Delete")); + btnScheImport->setText(tr("Import")); + btnScheExport->setText(tr("Export")); + labelSyncScheduleTip->setText(tr("By default, the asynchronous content is played, and the synchronous signal content is played in the fixed time period")); + btnScheSet->setText(tr("Apply")); + btnScheGet->setText(tr("Readback")); +} + +void CtrlHdmiPanel::restoreScheduleJson(QJsonObject oTaskSync) { + tableSche->setRowCount(0); + auto oSchedules = oTaskSync["schedules"].toArray(); + foreach(auto oSchedule, oSchedules) { + int row = tableSche->rowCount(); + tableSche->insertRow(row); + + auto timeEdit = new QTimeEdit(QTime::fromString(oSchedule["startTime"].toString()+":00")); + timeEdit->setDisplayFormat("HH:mm"); + timeEdit->setAlignment(Qt::AlignCenter); + tableSche->setCellWidget(row, "start", timeEdit); + + timeEdit = new QTimeEdit(QTime::fromString(oSchedule["endTime"].toString()+":00")); + timeEdit->setDisplayFormat("HH:mm"); + timeEdit->setAlignment(Qt::AlignCenter); + tableSche->setCellWidget(row, "end", timeEdit); + + if(oSchedule["filterType"].toString()=="None") for(int i=0; i<7; i++) { + auto fd = new QCheckBox; + fd->setChecked(true); + tableSche->setCellWidget(row, QString::number(i), fd); + } else if(oSchedule["filterType"].toString()=="Week") { + auto weekFilter = oSchedule["weekFilter"].toArray(); + for(int i=0; i<7; i++) { + auto fd = new QCheckBox; + if(weekFilter.contains(i)) fd->setChecked(true); + tableSche->setCellWidget(row, QString::number(i), fd); + } + } + } +} +QJsonObject CtrlHdmiPanel::getScheduleJson() { + QJsonArray schedules; + for(int i=0; irowCount(); i++) { + QJsonObject schedule; + schedule["timeType"] = "Range"; + schedule["startTime"] = static_cast(tableSche->cellWidget(i, "start"))->text(); + schedule["endTime"] = static_cast(tableSche->cellWidget(i, "end"))->text(); + schedule["dateType"] = "All"; + schedule["monthFilter"] = QJsonArray(); + QJsonArray weekFilter; + for(int d=0; d<7; d++) if(static_cast(tableSche->cellWidget(i, QString::number(d)))->isChecked()) weekFilter.append(d); + if(weekFilter.size()>=7) { + schedule["filterType"] = "None"; + weekFilter = QJsonArray(); + } else schedule["filterType"] = "Week"; + schedule["weekFilter"] = weekFilter; + schedules.append(schedule); + } + return QJsonObject{ + {"createBy", "alahover"}, + {"name", "TimingScreen"}, + {"schedules", schedules} + }; +} diff --git a/LedOK/device/ctrlhdmipanel.h b/LedOK/device/ctrlhdmipanel.h new file mode 100644 index 0000000..b70a007 --- /dev/null +++ b/LedOK/device/ctrlhdmipanel.h @@ -0,0 +1,38 @@ +#ifndef CTRLHDMIPANEL_H +#define CTRLHDMIPANEL_H + +#include "base/switchcontrol.h" +#include "gutil/qgui.h" +#include +#include +#include + +class CtrlHdmiPanel : public QWidget { + Q_OBJECT +public: + explicit CtrlHdmiPanel(QWidget *parent = nullptr); + void restoreScheduleJson(QJsonObject oTaskSync); + QJsonObject getScheduleJson(); +protected: + void showEvent(QShowEvent *event) override; + void init(); + void changeEvent(QEvent *) override; + void transUi(); + +private: + QLabel *lbHdmiCfg; + QRadioButton *fdManual, *fdSchedule, *fdAsync, *fdHdmi, *fdHdmi2; + QPushButton *btnGetSync; + + Table *tableSche; + QPushButton *btnScheAdd; + QPushButton *btnScheDel; + QPushButton *btnScheClear; + QPushButton *btnScheImport; + QPushButton *btnScheExport; + QLabel *labelSyncScheduleTip; + QPushButton *btnScheSet; + QPushButton *btnScheGet; +}; + +#endif // CTRLHDMIPANEL_H diff --git a/LedOK/device/ctrlnetworkpanel.cpp b/LedOK/device/ctrlnetworkpanel.cpp new file mode 100644 index 0000000..5602eda --- /dev/null +++ b/LedOK/device/ctrlnetworkpanel.cpp @@ -0,0 +1,1021 @@ +#include "ctrlnetworkpanel.h" +#include "base/waitingdlg.h" +#include "globaldefine.h" +#include "tools.h" +#include "gutil/qgui.h" +#include +#include +#include +#include + +CtrlNetworkPanel::CtrlNetworkPanel(QWidget *parent) : QWidget(parent) { + auto vBox = new VBox(this); + + lbLanCfg = new QLabel; + QFont font = lbLanCfg->font(); + font.setPointSize(12); + lbLanCfg->setFont(font); + lbLanCfg->setAlignment(Qt::AlignCenter); + vBox->addWidget(lbLanCfg); + + auto hBox = new HBox(vBox); + hBox->addStretch(); + + fdDhcp = new QRadioButton; + fdDhcp->setChecked(true); + hBox->addWidget(fdDhcp, 0, Qt::AlignTop); + + hBox->addSpacing(30); + + auto vBoxSpecifyIp = new VBox(hBox); + vBoxSpecifyIp->setContentsMargins(0, 0, 0, 0); + + fdSpecifyIp = new QRadioButton; + vBoxSpecifyIp->addWidget(fdSpecifyIp, 0, Qt::AlignCenter); + + auto grp = new QButtonGroup(this); + grp->addButton(fdDhcp); + grp->addButton(fdSpecifyIp); + + gBoxSpecifyIp = new QGroupBox; + gBoxSpecifyIp->setMaximumWidth(340); + gBoxSpecifyIp->setVisible(false); + connect(fdSpecifyIp, &QRadioButton::toggled, gBoxSpecifyIp, &QWidget::setVisible); + { + auto vvv = new VBox(gBoxSpecifyIp); + auto hhh = new HBox(vvv); + + labelIpAddress = new QLabel; + hhh->addWidget(labelIpAddress); + + fdIP = new QIPLineEdit; + fdIP->setFixedWidth(160); + hhh->addWidget(fdIP); + + hhh = new HBox(vvv); + + labelMaskAddress = new QLabel; + hhh->addWidget(labelMaskAddress); + + fdMask = new QIPLineEdit; + fdMask->setFixedWidth(160); + hhh->addWidget(fdMask); + + hhh = new HBox(vvv); + + labelGateway = new QLabel; + hhh->addWidget(labelGateway); + + fdGateWay = new QIPLineEdit; + fdGateWay->setFixedWidth(160); + hhh->addWidget(fdGateWay); + + hhh = new HBox(vvv); + + labelDnsAddress = new QLabel; + hhh->addWidget(labelDnsAddress); + + fdDns = new QIPLineEdit; + fdDns->setFixedWidth(160); + hhh->addWidget(fdDns); + } + vBoxSpecifyIp->addWidget(gBoxSpecifyIp); + + hBox->addStretch(); + + hBox = new HBox(vBox); + hBox->addStretch(); + + btnLanSet = new QPushButton; + btnLanSet->setMinimumSize(QSize(60, 30)); + btnLanSet->setProperty("ssType", "progManageTool"); + connect(btnLanSet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QString ip = fdIP->text(); + QString mask = fdMask->text(); + QString gateWay = fdGateWay->text(); + QString dns = fdDns->text(); + if(fdDhcp->isChecked()) { + if(ip=="...") ip="0.255.255.255"; + if(mask=="...") mask="0.255.255.255"; + if(gateWay=="...") gateWay="0.255.255.255"; + if(dns=="...") dns="0.255.255.255"; + } else { + if(ip=="...") { + QMessageBox::warning(gMainWin, tr("Attention"), tr("Please input IP address!")); + fdIP->setFocus(); + return; + } + if(!isTextValid(ip)) { + QMessageBox::warning(gMainWin, tr("Attention"), tr("Your IP Address is Invalid!")+"["+ip+"]"); + fdIP->setFocus(); + return; + } + if(mask=="...") { + QMessageBox::warning(gMainWin, tr("Attention"), tr("Please input Mask address!")); + fdMask->setFocus(); + return; + } + if(!isTextValid(mask)) { + QMessageBox::warning(gMainWin, tr("Attention"), tr("Your Mask Address is Invalid!")); + fdMask->setFocus(); + return; + } + if(gateWay=="...") { + QMessageBox::warning(gMainWin, tr("Attention"), tr("Please input Gateway address!")); + fdGateWay->setFocus(); + return; + } + if(!isTextValid(gateWay)) { + QMessageBox::warning(gMainWin, tr("Attention"), tr("Your Gateway Address is Invalid!")); + fdGateWay->setFocus(); + return; + } + if(dns=="...") { + QMessageBox::warning(gMainWin, tr("Attention"), tr("Please input DNS address!")); + fdDns->setFocus(); + return; + } + if (!isTextValid(dns)) { + QMessageBox::warning(gMainWin, tr("Attention"), tr("Your DNS Address is Invalid!")); + fdDns->setFocus(); + return; + } + } + QJsonObject json; + json.insert("_id", "SetEthernet"); + json.insert("_type", "SetEthernet"); + json.insert("dhcp", fdDhcp->isChecked()); + json.insert("ip", ip); + json.insert("netMask", mask); + json.insert("gateWay", gateWay); + json.insert("dns", dns); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("SetEthernet")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("SetEthernet")) + } + } + }); + hBox->addWidget(btnLanSet); + + hBox->addSpacing(50); + + btnLanGet = new QPushButton; + btnLanGet->setMinimumSize(QSize(60, 30)); + btnLanGet->setProperty("ssType", "progManageTool"); + connect(btnLanGet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "GetEthernet"); + json.insert("_type", "GetEthernet"); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("GetEthernet")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg] { + Def_CtrlSingleGetReply + waitingDlg->success(); + if(json["dhcp"].toBool()) { + fdDhcp->setChecked(true); + gBoxSpecifyIp->setVisible(false); + } else { + fdSpecifyIp->setChecked(true); + gBoxSpecifyIp->setVisible(true); + } + fdIP->setText(json["ipAddr"].toString()); + fdMask->setText(json["netMask"].toString()); + fdGateWay->setText(json["gateWay"].toString()); + fdDns->setText(json["dnsAddr"].toString()); + }); + } else { + foreach(auto card, *gSelCards) { + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + auto cardId = card->m_strCardId; + connect(reply, &QNetworkReply::finished, this, [reply, cardId] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(err.isEmpty()) err = json["dhcp"].toBool() ? tr("DHCP IP") : tr("STATIC IP"); + gFdResInfo->append(cardId+" "+tr("GetEthernet")+" "+err); + gFdResInfo->append(" IP: "+json["ipAddr"].toString()); + gFdResInfo->append(" Mask: "+json["netMask"].toString()); + gFdResInfo->append(" GateWay: "+json["gateWay"].toString()); + gFdResInfo->append(" Dns: "+json["dnsAddr"].toString()); + }); + } + } + }); + hBox->addWidget(btnLanGet); + + hBox->addStretch(); + + auto line = new QFrame; + line->setFrameShape(QFrame::HLine); + line->setFrameShadow(QFrame::Sunken); + vBox->addWidget(line); + + label_5 = new QLabel; + label_5->setFont(font); + label_5->setAlignment(Qt::AlignCenter); + vBox->addWidget(label_5); + + hBox = new HBox(vBox); + hBox->addStretch(); + + auto stackedWifi = new QStackedLayout; + fdIsWifi = new QRadioButton; + connect(fdIsWifi, &QRadioButton::toggled, this, [stackedWifi](bool checked) { + stackedWifi->setCurrentIndex(checked ? 0 : 1); + }); + hBox->addWidget(fdIsWifi); + hBox->addSpacing(50); + + fdIsHotspot = new QRadioButton; + hBox->addWidget(fdIsHotspot); + hBox->addStretch(); + + vBox->addLayout(stackedWifi); + { + auto vvv = new VBox(stackedWifi); + hBox = new HBox(vvv); + + lbWifiName = new QLabel; + lbWifiName->setMinimumWidth(80); + hBox->addWidget(lbWifiName); + + fdWifiName = new QComboBox; + fdWifiName->setEditable(true); + fdWifiName->setMinimumWidth(200); + fdWifiName->setSizeAdjustPolicy(QComboBox::AdjustToContents); + hBox->addWidget(fdWifiName); + + btnScan = new QPushButton; + btnScan->setMinimumWidth(60); + btnScan->setProperty("ssType", "progManageTool"); + connect(btnScan, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "GetWifiList"); + json.insert("_type", "GetWifiList"); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("GetWifiList")+" ..."); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg] { + Def_CtrlSingleGetReply + waitingDlg->success(); + auto wifis = json["wifiList"].toArray(); + auto cur = fdWifiName->currentText(); + fdWifiName->clear(); + foreach(auto wifi, wifis) fdWifiName->addItem(QIcon(":/res/signal-"+QString::number((wifi["signal"].toInt()+19)/20)+".png"), wifi["ssid"].toString()); + if(! cur.isEmpty()) fdWifiName->setCurrentText(cur); + }); + } + }); + hBox->addWidget(btnScan); + hBox->addStretch(); + + hBox = new HBox(vvv); + + lbWifiPassword = new QLabel; + lbWifiPassword->setMinimumWidth(80); + hBox->addWidget(lbWifiPassword); + + fdWifiPassword = new QLineEdit; + fdWifiPassword->setFixedWidth(200); + fdWifiPassword->setEchoMode(QLineEdit::PasswordEchoOnEdit); + hBox->addWidget(fdWifiPassword); + hBox->addStretch(); + + vvv->addStretch(); + + vvv = new VBox(stackedWifi); + hBox = new HBox(vvv); + + lbHotspotName = new QLabel; + lbHotspotName->setMinimumWidth(80); + hBox->addWidget(lbHotspotName); + + fdHotspotName = new QLineEdit; + fdHotspotName->setFixedWidth(200); + hBox->addWidget(fdHotspotName); + hBox->addStretch(); + + hBox = new HBox(vvv); + + lbHotspotPassword = new QLabel; + lbHotspotPassword->setMinimumWidth(80); + hBox->addWidget(lbHotspotPassword); + + fdHotspotPassword = new QLineEdit; + fdHotspotPassword->setEchoMode(QLineEdit::PasswordEchoOnEdit); + fdHotspotPassword->setFixedWidth(200); + hBox->addWidget(fdHotspotPassword); + hBox->addStretch(); + + vvv->addStretch(); + } + fdIsWifi->setChecked(true); + + hBox = new HBox(vBox); + hBox->addStretch(); + + btnWiFiSet = new QPushButton; + btnWiFiSet->setMinimumSize(QSize(60, 30)); + btnWiFiSet->setProperty("ssType", "progManageTool"); + connect(btnWiFiSet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + if(fdIsWifi->isChecked()) { + QJsonObject json; + json.insert("_id", "ConfigurationWiFi"); + json.insert("_type", "ConfigurationWiFi"); + json.insert("ssid", fdWifiName->currentText()); + json.insert("password", fdWifiPassword->text()); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("ConfigurationWiFi")+" ..."); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("ConfigurationWiFi")) + } + } + } else if(fdIsHotspot->isChecked()) { + QJsonObject json; + json.insert("_id", "ConfigurationHotSpot"); + json.insert("_type", "ConfigurationHotSpot"); + json.insert("apName", fdHotspotName->text()); + json.insert("password", fdHotspotPassword->text()); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("ConfigurationHotSpot")+" ..."); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("ConfigurationHotSpot")) + } + } + } + }); + hBox->addWidget(btnWiFiSet); + hBox->addSpacing(50); + + btnWiFiGet = new QPushButton; + btnWiFiGet->setMinimumSize(QSize(60, 30)); + btnWiFiGet->setProperty("ssType", "progManageTool"); + connect(btnWiFiGet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "IsPortableHotSpot"); + json.insert("_type", "IsPortableHotSpot"); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("IsPortableHotSpot")+" ..."); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg] { + Def_CtrlSingleGetReply + waitingDlg->success(); + fdWifiName->setCurrentText(json["wifi"].toString()); + auto hotSpots = json["hotSpots"].toString(); + fdHotspotName->setText(hotSpots); + if(hotSpots.isEmpty()) fdIsWifi->setChecked(true); + else fdIsHotspot->setChecked(true); + }); + } else { + foreach(auto card, *gSelCards) { + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + auto cardId = card->m_strCardId; + connect(reply, &QNetworkReply::finished, this, [reply, cardId] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(err.isEmpty()) { + err = tr("success"); + auto wifi = json["wifi"].toString(); + if(! wifi.isEmpty()) err += " "+tr("WifiName")+":"+wifi; + auto hotSpots = json["hotSpots"].toString(); + if(! hotSpots.isEmpty()) err += " "+tr("ApName")+":"+hotSpots; + } + gFdResInfo->append(cardId+" "+tr("IsPortableHotSpot")+" "+err); + }); + } + } + }); + hBox->addWidget(btnWiFiGet); + + hBox->addStretch(); + + + line_3 = new QFrame; + line_3->setFrameShape(QFrame::HLine); + line_3->setFrameShadow(QFrame::Sunken); + + vBox->addWidget(line_3); + + lbCellularConfig = new QLabel; + lbCellularConfig->setFont(font); + + vBox->addWidget(lbCellularConfig, 0, Qt::AlignHCenter); + + hBox = new HBox(vBox); + + fdEnableCellular = new QCheckBox; + fdEnableCellular->setChecked(true); + connect(fdEnableCellular, &QCheckBox::toggled, this, [=](bool checked) { + groupApn->setEnabled(checked); + fdMcc->setEnabled(checked); + fdCarrierName->setEnabled(checked); + + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "SetSwitchSimData"); + json.insert("_type", "SetSwitchSimData"); + json.insert("enable", checked); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("SetSwitchSimData")+" ..."); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("SetSwitchSimData")) + } + } + }); + hBox->addWidget(fdEnableCellular); + + btnSIMStatusGet = new QPushButton; + btnSIMStatusGet->setMinimumHeight(30); + btnSIMStatusGet->setProperty("ssType", "progManageTool"); + connect(btnSIMStatusGet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "GetSIMStatus"); + json.insert("_type", "GetSIMStatus"); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("GetSIMStatus")+" ..."); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg] { + Def_CtrlSingleGetReply + waitingDlg->close(); + QString str4GStatus = tr("状态:"); + auto state = json["state"].toInt(); + if(state<2) str4GStatus += tr("未知"); + else if(state==2) str4GStatus += tr("锁定状态,需要用户的PIN码解锁"); + else if(state==3) str4GStatus += tr("锁定状态,需要用户的PUK码解锁"); + else if(state==4) str4GStatus += tr("锁定状态,需要网络的PIN码解锁"); + else if(state==5) str4GStatus += tr("就绪"); + auto imsi = json["imsi"].toString(); + if(imsi.isEmpty()) str4GStatus += "\n"+tr("no checked sim card"); + else { + str4GStatus += "\nIMSI: "+imsi+"\n"; + fdMcc->setCurrentText(imsi.left(3)); + str4GStatus += tr("国家码:") + json["countryCode"].toString() + "(" + imsi.left(3) + ")\n"; + str4GStatus += tr("号码:") + json["phoneNumber"].toString() + "\n"; + str4GStatus += tr("用户:") + json["user"].toString() + "\n"; + str4GStatus += tr("信号:"); + switch(json["serviceState"].toInt()) { + case 0: str4GStatus+=tr("信号正常")+"\r\n"; break; + case 1: str4GStatus+=tr("不在服务区")+"\r\n"; break; + case 2: str4GStatus+=tr("仅限紧急呼叫")+"\r\n"; break; + case 3: str4GStatus+=tr("射频已经关闭")+"\r\n"; break; + } + str4GStatus += tr("网络:"); + switch(json["networkType"].toInt()) { + case 0: str4GStatus+=tr("网络类型未知")+"\r\n"; break; + case 1: str4GStatus+=tr("GPRS网络")+"\r\n"; break; + case 2: str4GStatus+=tr("EDGE网络")+"\r\n"; break; + case 3: str4GStatus+=tr("UMTS网络")+"\r\n"; break; + case 4: str4GStatus+=tr("CDMA网络,IS95A 或 IS95B.")+"\r\n"; break; + case 5: str4GStatus+=tr("EVDO网络, revision 0.")+"\r\n"; break; + case 6: str4GStatus+=tr("EVDO网络, revision A.")+"\r\n"; break; + case 7: str4GStatus+=tr("1xRTT网络")+"\r\n"; break; + case 8: str4GStatus+=tr("HSDPA网络")+"\r\n"; break; + case 9: str4GStatus+=tr("HSUPA网络")+"\r\n"; break; + case 10: str4GStatus+=tr("HSPA网络")+"\r\n"; break; + } + str4GStatus += tr("漫游:") + (json["roaming"].toBool() ? tr("Yes") : tr("No")) + "\n"; + str4GStatus += tr("数据连接状态:"); + switch(json["dataState"].toInt()) { + case 0: str4GStatus+=tr("断开")+"\r\n"; break; + case 1: str4GStatus+=tr("正在连接")+"\r\n"; break; + case 2: str4GStatus+=tr("已连接")+"\r\n"; break; + case 3: str4GStatus+=tr("暂停")+"\r\n"; break; + } + str4GStatus += tr("数据活动休眠状态:"); + switch(json["dataActivity"].toInt()) { + case 0: str4GStatus+=tr("活动,但无数据发送和接收")+"\r\n"; break; + case 1: str4GStatus+=tr("活动,正在接收数据")+"\r\n"; break; + case 2: str4GStatus+=tr("活动,正在发送数据")+"\r\n"; break; + case 3: str4GStatus+=tr("活动,正在接收和发送数据")+"\r\n"; break; + case 4: str4GStatus+=tr("休眠状态")+"\r\n"; break; + } + str4GStatus += tr("信号强度:") + QString::number(json["signalStrength"].toInt())+"\n"; + } + QMessageBox::information(gMainWin, tr("Tip"), str4GStatus); + }); + } + }); + hBox->addWidget(btnSIMStatusGet); + hBox->addStretch(); + + groupApn = new QGroupBox; + vBox->addWidget(groupApn); + auto vvv = new VBox(groupApn); + + lbCheckStatusTip = new QLabel(groupApn); + lbCheckStatusTip->setWordWrap(true); + vvv->addWidget(lbCheckStatusTip); + + hBox = new HBox(vvv); + + label_2 = new QLabel(groupApn); + hBox->addWidget(label_2); + + fdMcc = new QComboBox; + fdMcc->setMinimumWidth(80); + fdMcc->setEditable(true); + connect(fdMcc, (void(QComboBox::*)(int))&QComboBox::currentIndexChanged, this, [=](int index) { + if(index < 1) return; + fdCarrierName->clear(); + fdCarrierName->addItem(""); + auto apnInfos = fdMcc->itemData(index).toJsonArray(); + foreach(auto apnInfo, apnInfos) fdCarrierName->addItem(apnInfo["carrier"].toString(), apnInfo); + }); + hBox->addWidget(fdMcc); + + hBox->addWidget(new QLabel("->")); + + label_3 = new QLabel(groupApn); + hBox->addWidget(label_3); + + fdCarrierName = new QComboBox; + fdCarrierName->setMinimumSize(QSize(200, 0)); + fdCarrierName->setEditable(true); + connect(fdCarrierName, (void(QComboBox::*)(int))&QComboBox::currentIndexChanged, this, [=](int index) { + if(index < 1) return; + auto json = fdCarrierName->itemData(index).toJsonObject(); + fdCus_Name->setText(json["carrier"].toString()); + fdCus_apn->setText(json["apn"].toString()); + fdCus_User->setText(json["user"].toString()); + fdCus_pwd->setText(json["password"].toString()); + fdCus_type->setText(json["type"].toString()); + fdCus_server->setText(json["server"].toString()); + fdCus_proxy->setText(json["proxy"].toString()); + fdCus_port->setText(json["port"].toString()); + fdCus_mmsc->setText(json["mmsc"].toString()); + fdCus_mmsProxy->setText(json["mmsproxy"].toString()); + fdCus_mmsPort->setText(json["mmsport"].toString()); + }); + hBox->addWidget(fdCarrierName); + + hBox->addStretch(); + + hBox = new HBox(vvv); + hBox->addStretch(); + + auto grid = new QGridLayout(); + hBox->addLayout(grid); + + auto label = new QLabel("APN"); + label->setAlignment((Qt::Alignment)AlignRight); + grid->addWidget(label, 0, 0); + grid->addWidget(lbCus_Name = new QLabel, 1, 0); + lbCus_Name->setAlignment((Qt::Alignment)AlignRight); + grid->addWidget(lbCus_User = new QLabel, 2, 0); + lbCus_User->setAlignment((Qt::Alignment)AlignRight); + grid->addWidget(lbCus_pwd = new QLabel, 3, 0); + lbCus_pwd->setAlignment((Qt::Alignment)AlignRight); + grid->addWidget(lbCus_type = new QLabel, 4, 0); + lbCus_type->setAlignment((Qt::Alignment)AlignRight); + grid->addWidget(lbCus_server = new QLabel, 5, 0); + lbCus_server->setAlignment((Qt::Alignment)AlignRight); + grid->addWidget(lbCus_port = new QLabel, 0, 2); + lbCus_port->setMinimumWidth(80); + lbCus_port->setAlignment((Qt::Alignment)AlignRight); + grid->addWidget(lbCus_proxy = new QLabel, 1, 2); + lbCus_proxy->setAlignment((Qt::Alignment)AlignRight); + grid->addWidget(label = new QLabel("mmsc"), 2, 2); + label->setAlignment((Qt::Alignment)AlignRight); + grid->addWidget(lbCus_mmsPort = new QLabel, 3, 2); + lbCus_mmsPort->setAlignment((Qt::Alignment)AlignRight); + grid->addWidget(lbCus_mmsProxy = new QLabel, 4, 2); + lbCus_mmsProxy->setAlignment((Qt::Alignment)AlignRight); + + fdCus_apn = new QLineEdit; + fdCus_Name = new QLineEdit; + fdCus_User = new QLineEdit; + fdCus_pwd = new QLineEdit; + fdCus_type = new QLineEdit; + fdCus_server = new QLineEdit; + fdCus_port = new QLineEdit; + fdCus_proxy = new QLineEdit; + fdCus_mmsc = new QLineEdit; + fdCus_mmsPort = new QLineEdit; + fdCus_mmsProxy = new QLineEdit; + + fdCus_apn->setMinimumWidth(260); + fdCus_port->setMinimumWidth(260); + grid->addWidget(fdCus_apn, 0, 1); + grid->addWidget(fdCus_Name, 1, 1); + grid->addWidget(fdCus_User, 2, 1); + grid->addWidget(fdCus_pwd, 3, 1); + grid->addWidget(fdCus_type, 4, 1); + grid->addWidget(fdCus_server, 5, 1); + grid->addWidget(fdCus_port, 0, 3); + grid->addWidget(fdCus_proxy, 1, 3); + grid->addWidget(fdCus_mmsc, 2, 3); + grid->addWidget(fdCus_mmsPort, 3, 3); + grid->addWidget(fdCus_mmsProxy, 4, 3); + + auto hhhh = new HBox; + btnAPNCusSet = new QPushButton; + btnAPNCusSet->setMinimumSize(QSize(60, 30)); + btnAPNCusSet->setProperty("ssType", "progManageTool"); + connect(btnAPNCusSet, &QPushButton::clicked, this, [=] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "SetAPN"); + json.insert("_type", "SetAPN"); + json.insert("carrier", fdCus_Name->text()); + json.insert("apn", fdCus_apn->text()); + json.insert("user", fdCus_User->text()); + json.insert("password", fdCus_pwd->text()); + json.insert("type", fdCus_type->text()); + json.insert("server", fdCus_server->text()); + json.insert("proxy", fdCus_proxy->text()); + json.insert("port", fdCus_port->text()); + json.insert("mmsc", fdCus_mmsc->text()); + json.insert("mmsproxy", fdCus_mmsProxy->text()); + json.insert("mmsport", fdCus_mmsPort->text()); + + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("SetAPN")+" ..."); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [=] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("SetAPN")) + } + } + }); + hhhh->addWidget(btnAPNCusSet); + hhhh->addStretch(); + + btnAPNCusGet = new QPushButton; + btnAPNCusGet->setMinimumSize(QSize(60, 30)); + btnAPNCusGet->setProperty("ssType", "progManageTool"); + connect(btnAPNCusGet, &QPushButton::clicked, this, [=] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "GetCurrentAPN"); + json.insert("_type", "GetCurrentAPN"); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("GetCurrentAPN")+" ..."); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [=] { + Def_CtrlSingleGetReply + waitingDlg->success(); + fdCus_Name->setText(json["carrier"].toString()); + fdCus_apn->setText(json["apn"].toString()); + fdCus_User->setText(json["user"].toString()); + fdCus_pwd->setText(json["password"].toString()); + fdCus_type->setText(json["type"].toString()); + fdCus_server->setText(json["server"].toString()); + fdCus_proxy->setText(json["proxy"].toString()); + fdCus_port->setText(json["port"].toString()); + fdCus_mmsc->setText(json["mmsc"].toString()); + fdCus_mmsProxy->setText(json["mmsproxy"].toString()); + fdCus_mmsPort->setText(json["mmsport"].toString()); + }); + } else { + foreach(auto card, *gSelCards) { + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + auto cardId = card->m_strCardId; + connect(reply, &QNetworkReply::finished, this, [reply, cardId] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(err.isEmpty()) { + err = json["apn"].toString(); + auto user = json["user"].toString(); + if(! user.isEmpty()) err += ", User:"+user+", Password:"+json["password"].toString(); + } + gFdResInfo->append(cardId+" "+tr("GetCurrentAPN")+" "+err); + }); + } + } + }); + hhhh->addWidget(btnAPNCusGet); + + grid->addLayout(hhhh, 5, 3); + + hBox->addStretch(); + + + vBox->addSpacing(20); + + hBox = new HBox(vBox); + hBox->setContentsMargins(-1, 0, 10, -1); + label_10 = new QLabel; + + hBox->addWidget(label_10); + + fdFightModel = new SwitchControl; + fdFightModel->setMinimumSize(QSize(80, 35)); + fdFightModel->setSliderColor(QColor(0, 0, 0),QColor(0, 160, 230)); + fdFightModel->setBgColor(QColor(200,200,200),QColor(0,200,0)); + fdFightModel->setTextColor(QColor(100,100,100),QColor(0, 160, 230)); + fdFightModel->setText(tr("OFF"), tr("ON")); + connect(fdFightModel, &SwitchControl::checkedChanged, this, [=](bool checked) { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "ContrFlightMode"); + json.insert("_type", "ContrFlightMode"); + json.insert("state", checked); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("ContrFlightMode")+" ..."); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("ContrFlightMode")) + } + } + }); + hBox->addWidget(fdFightModel); + + btnFlightModelGet = new QPushButton; + btnFlightModelGet->setMinimumSize(QSize(0, 30)); + btnFlightModelGet->setProperty("ssType", "progManageTool"); + connect(btnFlightModelGet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "GetFlightModeState"); + json.insert("_type", "GetFlightModeState"); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("GetFlightModeState")+" ..."); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg] { + Def_CtrlSingleGetReply + waitingDlg->success(); + fdFightModel->setCheckedStatus(json["result"].toBool()); + fdFightModel->update(); + }); + } else { + foreach(auto card, *gSelCards) { + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + auto cardId = card->m_strCardId; + connect(reply, &QNetworkReply::finished, this, [reply, cardId] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(err.isEmpty()) err = json["result"].toBool() ? "true" : "false"; + gFdResInfo->append(cardId+" "+tr("GetFlightModeState")+" "+err); + }); + } + } + }); + hBox->addWidget(btnFlightModelGet); + hBox->addStretch(); + + vBox->addStretch(); + + connect(gDevicePanel, &DevicePanel::sigSelectedDeviceList, this, [this] { + if(isVisible()) init(); + }); + transUi(); +} + +void CtrlNetworkPanel::showEvent(QShowEvent *event) { + QWidget::showEvent(event); + init(); +} +void CtrlNetworkPanel::init() { + bool isSingle = gSelCards->count()==1; + btnScan->setEnabled(isSingle); + + if(! isSingle) return; + auto card = gSelCards->at(0); + + QJsonObject json; + json.insert("_id", "GetEthernet"); + json.insert("_type", "GetEthernet"); + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + connect(reply, &QNetworkReply::finished, this, [this, reply] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) return; + + if(json["dhcp"].toBool()) { + fdDhcp->setChecked(true); + gBoxSpecifyIp->setVisible(false); + } else { + fdSpecifyIp->setChecked(true); + gBoxSpecifyIp->setVisible(true); + } + fdIP->setText(json["ipAddr"].toString()); + fdGateWay->setText(json["gateWay"].toString()); + fdMask->setText(json["netMask"].toString()); + fdDns->setText(json["dnsAddr"].toString()); + }); + + json = QJsonObject(); + json.insert("_id", "GetWifiList"); + json.insert("_type", "GetWifiList"); + reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + connect(reply, &QNetworkReply::finished, this, [=] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) return; + auto wifis = json["wifiList"].toArray(); + fdWifiName->clear(); + foreach(auto wifi, wifis) fdWifiName->addItem(QIcon(":/res/signal-"+QString::number((wifi["signal"].toInt()+19)/20)+".png"), wifi["ssid"].toString()); + { + QJsonObject json; + json.insert("_id", "IsPortableHotSpot"); + json.insert("_type", "IsPortableHotSpot"); + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + connect(reply, &QNetworkReply::finished, this, [this, reply] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) return; + auto wifi = json["wifi"].toString(); + fdWifiName->setCurrentText(wifi); + auto hotSpots = json["hotSpots"].toString(); + fdHotspotName->setText(hotSpots); + if(hotSpots.isEmpty()) fdIsWifi->setChecked(true); + else fdIsHotspot->setChecked(true); + }); + } + }); + + json = QJsonObject(); + json.insert("_id", "GetSwitchSimData"); + json.insert("_type", "GetSwitchSimData"); + reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + connect(reply, &QNetworkReply::finished, this, [=] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) return; + bool b = json["enable"].toBool(); + fdEnableCellular->setChecked(b); + fdMcc->setEnabled(b); + fdCarrierName->setEnabled(b); + }); + + json = QJsonObject(); + json.insert("_id", "GetAPNList"); + json.insert("_type", "GetAPNList"); + reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + connect(reply, &QNetworkReply::finished, this, [=] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) return; + fdMcc->clear(); + fdMcc->addItem(""); + auto apns = json["apns"].toArray(); + foreach(auto apn, apns) { + QString mcc = apn["mcc"].toString(); + for(int i=0; icount(); i++) if(mcc==fdMcc->itemText(i)) { + auto var = fdMcc->itemData(i); + fdMcc->setItemData(i, QVariant()); + ((QJsonArray *)var.data())->append(apn); + fdMcc->setItemData(i, var); + goto end; + } + fdMcc->addItem(mcc, QJsonArray{apn}); + end:; + } + }); + + getCurrentAPN(card->m_strCardIp); + + json = QJsonObject(); + json.insert("_id", "GetFlightModeState"); + json.insert("_type", "GetFlightModeState"); + reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + connect(reply, &QNetworkReply::finished, this, [=] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) return; + fdFightModel->setCheckedStatus(json["result"].toBool()); + fdFightModel->update(); + }); +} + +void CtrlNetworkPanel::changeEvent(QEvent *event) { + QWidget::changeEvent(event); + if(event->type() == QEvent::LanguageChange) transUi(); +} +void CtrlNetworkPanel::transUi() { + lbLanCfg->setText(tr("Wire Enther(RJ45) Configuration")); + fdDhcp->setText(tr("DHCP")); + fdSpecifyIp->setText(tr("Specify IP")); + lbHotspotName->setText(tr("AP name")); + labelGateway->setText(tr("Gateway")); + lbWifiName->setText(tr("WiFi name")); + labelIpAddress->setText(tr("IP Address")); + lbHotspotPassword->setText(tr("Password")); + labelDnsAddress->setText(tr("DNS Address")); + labelMaskAddress->setText(tr("Subnet mask")); + lbWifiPassword->setText(tr("Password")); + btnScan->setText(tr("Scan")); + btnWiFiSet->setText(tr("Set")); + btnLanSet->setText(tr("Set")); + btnWiFiGet->setText(tr("Readback")); + btnLanGet->setText(tr("Readback")); + fdIsWifi->setText(tr("WiFi Mode")); + fdIsHotspot->setText(tr("Ap Mode")); + label_5->setText(tr("WIFI Configuration")); + fdHotspotPassword->setPlaceholderText(tr("Input password")); + fdWifiPassword->setPlaceholderText(tr("Input password")); + fdHotspotName->setPlaceholderText(tr("Input ap name")); + lbCellularConfig->setText(tr("Cellular Config")); + lbCheckStatusTip->setText(tr("Through the check status button")); + fdEnableCellular->setText(tr("Enable Cellular Data")); + + groupApn->setTitle(tr("Set APN Info")); + label_2->setText(tr("Country ID(mcc):")); + label_3->setText(tr("Carrier Name")); + fdCus_apn->setPlaceholderText(tr("APN(Required)")); + btnFlightModelGet->setText(tr("Readback")); + btnSIMStatusGet->setText(tr("Get cellular network status information")); + label_10->setText(tr("Flight Mode")); + + lbCus_Name->setText(tr("Carrier Name")); + lbCus_User->setText(tr("User")); + lbCus_pwd->setText(tr("Password")); + lbCus_type->setText(tr("Type")); + lbCus_server->setText(tr("Server")); + lbCus_port->setText(tr("Port")); + lbCus_proxy->setText(tr("Proxy")); + lbCus_mmsPort->setText(tr("MMS Port")); + lbCus_mmsProxy->setText(tr("MMS Proxy")); + btnAPNCusSet->setText(tr("Set")); + btnAPNCusGet->setText(tr("Readback")); +} + +void CtrlNetworkPanel::getCurrentAPN(QString &ip) { + QJsonObject json; + json.insert("_id", "GetCurrentAPN"); + json.insert("_type", "GetCurrentAPN"); + auto reply = Tools::netManager().post(reqForJson("http://"+ip+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + connect(reply, &QNetworkReply::finished, this, [=] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) return; + fdCus_Name->setText(json["carrier"].toString()); + fdCus_apn->setText(json["apn"].toString()); + fdCus_User->setText(json["user"].toString()); + fdCus_pwd->setText(json["password"].toString()); + fdCus_type->setText(json["type"].toString()); + fdCus_server->setText(json["server"].toString()); + fdCus_proxy->setText(json["proxy"].toString()); + fdCus_port->setText(json["port"].toString()); + fdCus_mmsc->setText(json["mmsc"].toString()); + fdCus_mmsProxy->setText(json["mmsproxy"].toString()); + fdCus_mmsPort->setText(json["mmsport"].toString()); + }); +} diff --git a/LedOK/device/ctrlnetworkpanel.h b/LedOK/device/ctrlnetworkpanel.h new file mode 100644 index 0000000..315e31b --- /dev/null +++ b/LedOK/device/ctrlnetworkpanel.h @@ -0,0 +1,88 @@ +#ifndef CTRLNETWORKPANEL_H +#define CTRLNETWORKPANEL_H + +#include +#include +#include +#include "base/qiplineedit.h" +#include "base/switchcontrol.h" +#include +#include +#include +#include +#include + +struct ApnInfo { + QString apn; + QString carrier; + QString mcc; + QString mmsc; + QString mmsport; + QString mmsproxy; + QString mnc; + QString password; + QString port; + QString proxy; + QString server; + QString type; + QString user; +}; +class CtrlNetworkPanel : public QWidget { + Q_OBJECT +public: + explicit CtrlNetworkPanel(QWidget *parent = nullptr); + void getCurrentAPN(QString &); +protected: + void showEvent(QShowEvent *event) override; + void init(); + void changeEvent(QEvent *) override; + void transUi(); + +private: + QLabel *lbLanCfg; + QRadioButton *fdDhcp, *fdSpecifyIp; + QGroupBox *gBoxSpecifyIp; + QLabel *labelIpAddress; + QIPLineEdit *fdIP; + QLabel *labelMaskAddress; + QIPLineEdit *fdGateWay; + QLabel *labelGateway; + QIPLineEdit *fdMask; + QLabel *labelDnsAddress; + QIPLineEdit *fdDns; + QPushButton *btnLanSet; + QPushButton *btnLanGet; + QLabel *label_5; + QLabel *lbWifiName; + QLabel *lbWifiPassword; + + QRadioButton *fdIsWifi, *fdIsHotspot; + QComboBox *fdWifiName; + QLineEdit *fdWifiPassword; + QPushButton *btnScan; + QPushButton *btnWiFiSet; + QPushButton *btnWiFiGet; + QLabel *lbHotspotName; + QLabel *lbHotspotPassword; + QLineEdit *fdHotspotName; + QLineEdit *fdHotspotPassword; + QFrame *line_3; + QLabel *lbCellularConfig; + QCheckBox *fdEnableCellular; + QPushButton *btnSIMStatusGet; + QGroupBox *groupApn; + QLabel *lbCheckStatusTip; + QLabel *label_2; + QComboBox *fdMcc; + QLabel *label_3; + QComboBox *fdCarrierName; + QPushButton *btnAPNCusSet, *btnAPNCusGet; + QLabel *label_10; + SwitchControl *fdFightModel; + QPushButton *btnFlightModelGet; + + QLabel *lbCus_Name, *lbCus_User, *lbCus_pwd, *lbCus_mmsPort, *lbCus_mmsProxy, *lbCus_port, *lbCus_proxy, *lbCus_server, *lbCus_type; + QLineEdit *fdCus_apn, *fdCus_Name, *fdCus_User, *fdCus_pwd, *fdCus_type, *fdCus_server, *fdCus_port, *fdCus_proxy, *fdCus_mmsc, *fdCus_mmsPort, *fdCus_mmsProxy; +}; + +#endif // CTRLNETWORKPANEL_H diff --git a/LedOK/device/ctrlpwdpanel.cpp b/LedOK/device/ctrlpwdpanel.cpp new file mode 100644 index 0000000..6ea7bff --- /dev/null +++ b/LedOK/device/ctrlpwdpanel.cpp @@ -0,0 +1,253 @@ +#include "ctrlpwdpanel.h" +#include "gutil/qgui.h" +#include "base/waitingdlg.h" +#include "QFileDialog" +#include +#include +#include +#include "tools.h" + +CtrlPwdPanel::CtrlPwdPanel(QWidget *parent) : QWidget(parent) { + auto vBox = new VBox(this); + lbPwdConfig = new QLabel; + lbPwdConfig->setAlignment(Qt::AlignCenter); + vBox->addWidget(lbPwdConfig); + vBox->addSpacing(20); + + auto grid = new Grid(vBox); + grid->setColumnStretch(0, 1); + grid->setColumnStretch(3, 1); + + lbOldPwd = new QLabel; + grid->addWidget(lbOldPwd, 0, 1); + + lbNewPwd = new QLabel; + grid->addWidget(lbNewPwd, 1, 1); + + lbPwdAgain = new QLabel; + grid->addWidget(lbPwdAgain, 2, 1); + + fdOldPwd = new QLineEdit; + fdOldPwd->setFixedSize(160, 30); + fdOldPwd->setEchoMode(QLineEdit::PasswordEchoOnEdit); + grid->addWidget(fdOldPwd, 0, 2); + + fdNewPwd = new QLineEdit; + fdNewPwd->setFixedSize(160, 30); + fdNewPwd->setEchoMode(QLineEdit::PasswordEchoOnEdit); + grid->addWidget(fdNewPwd, 1, 2); + + fdPwdAgain = new QLineEdit; + fdPwdAgain->setFixedSize(160, 30); + fdPwdAgain->setEchoMode(QLineEdit::PasswordEchoOnEdit); + grid->addWidget(fdPwdAgain, 2, 2); + + vBox->addSpacing(20); + + auto hBox = new HBox(vBox); + hBox->addStretch(); + + btnPwdSet = new QPushButton; + btnPwdSet->setMinimumSize(60, 30); + btnPwdSet->setProperty("ssType", "progManageTool"); + connect(btnPwdSet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + if(fdOldPwd->isVisible() && fdOldPwd->text().isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("InputOriginalPasswordTip")); + return; + } + if(fdNewPwd->text().isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("InputNewPasswordTip")); + return; + } + if(fdPwdAgain->text().isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("InputRepeatPasswordTip")); + return; + } + if(fdNewPwd->text() != fdPwdAgain->text()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("InputRepeatPasswordNotSameTip")); + return; + } + auto res = QMessageBox::information(gMainWin, tr("Tip Info"), tr("After setting the password, please remember the password and record it. If you forget the password, the device will be unable to operate. Are you sure you want to continue with this operation?"), QMessageBox::Ok, QMessageBox::Cancel); + if(res != QMessageBox::Ok) return; + QJsonObject json; + json.insert("_id", "SetControllerPassword"); + json.insert("_type", "SetControllerPassword"); + json.insert("pwd", fdOldPwd->text()); + json.insert("newPwd", fdNewPwd->text()); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("SetControllerPassword")+" ..."); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, card, [=] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) { + waitingDlg->close(); + QMessageBox::critical(gMainWin, tr("Error"), err); + return; + } + if(json["result"].toInt()) { + waitingDlg->close(); + QMessageBox::critical(gMainWin, tr("Tip"), tr("OriginalPasswordErrorTip")); + return; + } + waitingDlg->success(); + lbOldPwd->show(); + fdOldPwd->show(); + btnPwdClear->show(); + btnPwdSet->setText(tr("Modify password")); + card->bPassword = true; + fdNewPwd->clear(); + fdPwdAgain->clear(); + fdOldPwd->clear(); + }); + } else { + foreach(auto card, *gSelCards) { + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + connect(reply, &QNetworkReply::finished, card, [=] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(err.isEmpty()) { + if(json["result"].toInt()) err = tr("OriginalPasswordErrorTip"); + else { + err = tr("Success"); + lbOldPwd->show(); + fdOldPwd->show(); + btnPwdClear->show(); + btnPwdSet->setText(tr("Modify password")); + card->bPassword = true; + } + } + gFdResInfo->append(card->m_strCardId+" "+tr("SetControllerPassword")+" "+err); + }); + } + } + }); + hBox->addWidget(btnPwdSet); + + btnPwdClear = new QPushButton; + btnPwdClear->setMinimumSize(60, 30); + btnPwdClear->setProperty("ssType", "progManageTool"); + connect(btnPwdClear, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + if(fdOldPwd->isVisible() && fdOldPwd->text().isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("InputOriginalPasswordTip")); + return; + } + QJsonObject json; + json.insert("_id", "SetControllerPassword"); + json.insert("_type", "SetControllerPassword"); + json.insert("pwd", fdOldPwd->text()); + json.insert("newPwd",""); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("SetControllerPassword")+" ..."); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, card, [=] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) { + waitingDlg->close(); + QMessageBox::critical(gMainWin, tr("Error"), err); + return; + } + if(json["result"].toInt()) { + waitingDlg->close(); + QMessageBox::critical(gMainWin, tr("Tip"), tr("OriginalPasswordErrorTip")); + return; + } + waitingDlg->success(); + lbOldPwd->hide(); + fdOldPwd->hide(); + btnPwdClear->hide(); + btnPwdSet->setText(tr("Set encryption")); + card->bPassword = false; + fdNewPwd->clear(); + fdPwdAgain->clear(); + fdOldPwd->clear(); + }); + } else { + foreach(auto card, *gSelCards) { + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + connect(reply, &QNetworkReply::finished, card, [=] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(err.isEmpty()) { + if(json["result"].toInt()) err = tr("OriginalPasswordErrorTip"); + else { + err = tr("Success"); + lbOldPwd->hide(); + fdOldPwd->hide(); + btnPwdClear->hide(); + btnPwdSet->setText(tr("Set encryption")); + card->bPassword = false; + } + } + gFdResInfo->append(card->m_strCardId+" "+tr("SetControllerPassword")+" "+err); + }); + } + } + }); + hBox->addWidget(btnPwdClear); + hBox->addStretch(); + + vBox->addStretch(); + + connect(gDevicePanel, &DevicePanel::sigSelectedDeviceList, this, [this] { + if(isVisible()) init(); + }); + transUi(); +} + +void CtrlPwdPanel::showEvent(QShowEvent *event) { + QWidget::showEvent(event); + init(); +} +void CtrlPwdPanel::init() { + bool isSingle = gSelCards->count()==1; + if(! isSingle) return; + auto card = gSelCards->at(0); + + QJsonObject json; + json.insert("_id", "HasControllerPassword"); + json.insert("_type", "HasControllerPassword"); + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + connect(reply, &QNetworkReply::finished, card, [=] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) return; + if(json["result"].toBool()) { + lbOldPwd->show(); + fdOldPwd->show(); + btnPwdClear->show(); + btnPwdSet->setText(tr("Modify password")); + card->bPassword = true; + } else { + lbOldPwd->hide(); + fdOldPwd->hide(); + btnPwdClear->hide(); + btnPwdSet->setText(tr("Set encryption")); + card->bPassword = false; + } + }); +} +void CtrlPwdPanel::changeEvent(QEvent *event) { + QWidget::changeEvent(event); + if(event->type() == QEvent::LanguageChange) transUi(); +} +void CtrlPwdPanel::transUi() { + lbPwdConfig->setText(tr("Set Password")); + lbOldPwd->setText(tr("Original password")); + lbNewPwd->setText(tr("New password")); + lbPwdAgain->setText(tr("Enter again")); + fdOldPwd->setPlaceholderText(tr("original password")); + fdNewPwd->setPlaceholderText(tr("New password")); + fdPwdAgain->setPlaceholderText(tr("Repeat new password")); + btnPwdSet->setText(tr("Set encryption")); + btnPwdClear->setText(tr("Cancel encryption")); +} diff --git a/LedOK/device/ctrlpwdpanel.h b/LedOK/device/ctrlpwdpanel.h new file mode 100644 index 0000000..d6055b4 --- /dev/null +++ b/LedOK/device/ctrlpwdpanel.h @@ -0,0 +1,30 @@ +#ifndef CTRLPWDPANEL_H +#define CTRLPWDPANEL_H + +#include +#include +#include + +class CtrlPwdPanel : public QWidget { + Q_OBJECT +public: + explicit CtrlPwdPanel(QWidget *parent = nullptr); +protected: + void showEvent(QShowEvent *event) override; + void init(); + void changeEvent(QEvent *) override; + void transUi(); + +private: + QLabel *lbPwdConfig; + QLabel *lbOldPwd; + QLabel *lbNewPwd; + QLabel *lbPwdAgain; + QLineEdit *fdOldPwd; + QLineEdit *fdNewPwd; + QLineEdit *fdPwdAgain; + QPushButton *btnPwdSet; + QPushButton *btnPwdClear; +}; + +#endif // CTRLPWDPANEL_H diff --git a/LedOK/wDevicesManager/ctrlverifyclockpanel.cpp b/LedOK/device/ctrlverifyclockpanel.cpp similarity index 89% rename from LedOK/wDevicesManager/ctrlverifyclockpanel.cpp rename to LedOK/device/ctrlverifyclockpanel.cpp index d99f529..49f74b5 100644 --- a/LedOK/wDevicesManager/ctrlverifyclockpanel.cpp +++ b/LedOK/device/ctrlverifyclockpanel.cpp @@ -1,925 +1,893 @@ -#include "ctrlverifyclockpanel.h" -#include "base/waitingdlg.h" -#include "globaldefine.h" -#include "gqt.h" -#include "tools.h" -#include -#include -#include - -CtrlVerifyClockPanel::CtrlVerifyClockPanel(QWidget *parent) : QWidget(parent) { - auto vBox = new VBox(this); - auto hBox = new HBox(vBox); - hBox->setContentsMargins(-1, 0, -1, -1); - - label = new QLabel; - hBox->addWidget(label); - - fdTimezone = new QComboBox; - fdTimezone->setMinimumWidth(200); - fdTimezone->addItem("Africa/Brazzaville");//西部非洲标准时间 (布拉扎维) - fdTimezone->addItem("Africa/Cairo");//东欧标准时间 (开罗) - fdTimezone->addItem("Africa/Casablanca");//卡萨布兰卡 - fdTimezone->addItem("Africa/Harare");//中部非洲标准时间 (哈拉雷) - fdTimezone->addItem("Africa/Nairobi");//东部非洲标准时间 (内罗毕) - fdTimezone->addItem("Africa/Windhoek");//温得和克 - fdTimezone->addItem("America/Anchorage");//>安克雷奇 - fdTimezone->addItem("America/Argentina/Buenos_Aires");//布宜诺斯艾利斯 - fdTimezone->addItem("America/Barbados");//>大西洋时间 (巴巴多斯) - fdTimezone->addItem("America/Bogota");//>哥伦比亚时间 (波哥大) - fdTimezone->addItem("America/Caracas");//>委内瑞拉时间 (加拉加斯) - fdTimezone->addItem("America/Chicago");//>美国中部时间 (芝加哥) - fdTimezone->addItem("America/Chihuahua");//>奇瓦瓦 - fdTimezone->addItem("America/Costa_Rica");//>美国中部时间 (哥斯达黎加) - fdTimezone->addItem("America/Denver");//>美国山区时间 (丹佛) - fdTimezone->addItem("America/Godthab");//戈特霍布 - fdTimezone->addItem("America/Los_Angeles");//>美国太平洋时间 (洛杉矶) - fdTimezone->addItem("America/Manaus");//亚马逊标准时间 (马瑙斯) - fdTimezone->addItem("America/Mexico_City");//>美国中部时间 (墨西哥城) - fdTimezone->addItem("America/Montevideo");//乌拉圭时间 (蒙得维的亚) - fdTimezone->addItem("America/New_York");//>美国东部时间 (纽约) - fdTimezone->addItem("America/Phoenix");//>美国山区时间 (凤凰城) - fdTimezone->addItem("America/Regina");//>美国中部时间 (里贾纳) - fdTimezone->addItem("America/Santiago");//圣地亚哥 - fdTimezone->addItem("America/Sao_Paulo");//圣保罗 - fdTimezone->addItem("America/St_Johns");//纽芬兰时间 (圣约翰) - fdTimezone->addItem("America/Tijuana");//>美国太平洋时间 (提华纳) - fdTimezone->addItem("Asia/Almaty");//阿拉木图 - fdTimezone->addItem("Asia/Amman");//东欧标准时间 (安曼) - fdTimezone->addItem("Asia/Baghdad");//巴格达 - fdTimezone->addItem("Asia/Baku");//巴库 - fdTimezone->addItem("Asia/Bangkok");//曼谷 - fdTimezone->addItem("Asia/Beirut");//东欧标准时间 (贝鲁特) - fdTimezone->addItem("Asia/Calcutta");//加尔各答 - fdTimezone->addItem("Asia/Colombo");//科伦坡 - fdTimezone->addItem("Asia/Dubai");//迪拜 - fdTimezone->addItem("Asia/Hong_Kong");//香港时间 (香港) - fdTimezone->addItem("Asia/Irkutsk");//伊尔库茨克时间 (伊尔库茨克) - fdTimezone->addItem("Asia/Jerusalem");//以色列时间 (耶路撒冷) - fdTimezone->addItem("Asia/Kabul");//阿富汗时间 (喀布尔) - fdTimezone->addItem("Asia/Karachi");//卡拉奇 - fdTimezone->addItem("Asia/Katmandu");//尼泊尔时间 (加德满都) - fdTimezone->addItem("Asia/Krasnoyarsk");//克拉斯诺亚尔斯克 - fdTimezone->addItem("Asia/Kuala_Lumpur");//吉隆坡 - fdTimezone->addItem("Asia/Kuwait");//科威特 - fdTimezone->addItem("Asia/Magadan");//马加丹时间 (马加丹) - fdTimezone->addItem("Asia/Oral");//乌拉尔 - fdTimezone->addItem("Asia/Rangoon");//缅甸时间 (仰光) - fdTimezone->addItem("Asia/Seoul");//首尔 - fdTimezone->addItem("Asia/Shanghai");//中国标准时间 (北京) - fdTimezone->addItem("Asia/Taipei");//台北时间 (台北) - fdTimezone->addItem("Asia/Tbilisi");//第比利斯 - fdTimezone->addItem("Asia/Tehran");//伊朗标准时间 (德黑兰) - fdTimezone->addItem("Asia/Tokyo");//日本时间 (东京) - fdTimezone->addItem("Asia/Vladivostok");//海参崴时间 (符拉迪沃斯托克) - fdTimezone->addItem("Asia/Yakutsk");//雅库茨克时间 (雅库茨克) - fdTimezone->addItem("Asia/Yekaterinburg");//叶卡捷林堡 - fdTimezone->addItem("Asia/Yerevan");//埃里温 - fdTimezone->addItem("Atlantic/Azores");//亚述尔群岛 - fdTimezone->addItem("Atlantic/Cape_Verde");//佛得角 - fdTimezone->addItem("Atlantic/South_Georgia");//南乔治亚 - fdTimezone->addItem("Australia/Adelaide");//阿德莱德 - fdTimezone->addItem("Australia/Brisbane");//布里斯班 - fdTimezone->addItem("Australia/Darwin");//达尔文 - fdTimezone->addItem("Australia/Hobart");//霍巴特 - fdTimezone->addItem("Australia/Perth");//佩思 - fdTimezone->addItem("Australia/Sydney");//悉尼 - fdTimezone->addItem("Europe/Amsterdam");//中欧标准时间 (阿姆斯特丹) - fdTimezone->addItem("Europe/Athens");//东欧标准时间 (雅典) - fdTimezone->addItem("Europe/Belgrade");//中欧标准时间 (贝尔格莱德) - fdTimezone->addItem("Europe/Brussels");//中欧标准时间 (布鲁塞尔) - fdTimezone->addItem("Europe/Helsinki");//东欧标准时间 (赫尔辛基) - fdTimezone->addItem("Europe/London");//格林尼治标准时间 (伦敦) - fdTimezone->addItem("Europe/Minsk");//明斯克 - fdTimezone->addItem("Europe/Moscow");//莫斯科 - fdTimezone->addItem("Europe/Sarajevo");//中欧标准时间 (萨拉热窝) - fdTimezone->addItem("Pacific/Auckland");//奥克兰 - fdTimezone->addItem("Pacific/Fiji");//斐济 - fdTimezone->addItem("Pacific/Guam");//关岛 - fdTimezone->addItem("Pacific/Honolulu"); - fdTimezone->addItem("Pacific/Majuro"); - fdTimezone->addItem("Pacific/Midway"); - fdTimezone->addItem("Pacific/Tongatapu");//东加塔布 - hBox->addWidget(fdTimezone); - - fdTimeZoneSet = new QPushButton; - connect(fdTimeZoneSet, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - QJsonObject json; - json.insert("_id", "SetTimezone"); - json.insert("_type", "SetTimezone"); - json.insert("timezone", fdTimezone->currentText()); - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, tr("SetTimezone")); - Def_CtrlReqPre - connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { - Def_CtrlSetReqAfter - }); - } else { - foreach(auto card, *gSelCards) { - Def_CtrlSetMulti(tr("SetTimezone")) - } - } - }); - hBox->addWidget(fdTimeZoneSet); - hBox->addSpacing(20); - - lbLang = new QLabel; - hBox->addWidget(lbLang); - - fdIsEn = new QRadioButton; - hBox->addWidget(fdIsEn); - - fdIsCn = new QRadioButton; - hBox->addWidget(fdIsCn); - - btnLangSet = new QPushButton; - connect(btnLangSet, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - QJsonObject json; - json.insert("_id", "SetLanguage"); - json.insert("_type", "SetLanguage"); - json.insert("language", fdIsCn->isChecked() ? 1 : 0); - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, "设置语言"); - Def_CtrlReqPre - connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { - Def_CtrlSetReqAfter - }); - } else { - foreach(auto card, *gSelCards) { - Def_CtrlSetMulti("设置语言") - } - } - }); - hBox->addWidget(btnLangSet); - - btnLangGet = new QPushButton; - connect(btnLangGet, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - QJsonObject json; - json.insert("_id", "GetLanguage"); - json.insert("_type", "GetLanguage"); - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, "获取语言"); - Def_CtrlReqPre - connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg] { - Def_CtrlSingleGetReply - waitingDlg->success(); - if(json["language"].toInt()==1) fdIsCn->setChecked(true); - else fdIsEn->setChecked(true); - }); - } else { - foreach(auto card, *gSelCards) { - auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); - connect(reply, &QNetworkReply::finished, this, [reply, card] { - QJsonDocument json; - QString err = checkReplyForJson(reply, &json); - if(err.isEmpty()) err = json["language"].toInt()==1 ? "中文" : "英文"; - gFdResInfo->append(card->m_strCardId+" 获取语言 "+err); - }); - } - } - }); - hBox->addWidget(btnLangGet); - hBox->addStretch(); - - - labelVerifyClockConfiguration = new QLabel; - labelVerifyClockConfiguration->setAlignment(Qt::AlignCenter); - vBox->addWidget(labelVerifyClockConfiguration); - - auto line = new QFrame; - line->setFrameShape(QFrame::HLine); - line->setFrameShadow(QFrame::Sunken); - vBox->addWidget(line); - - hBox = new HBox(vBox); - auto vvv = new VBox(hBox); - - btnSyncTime = new QPushButton(tr("Verify to Computer time")); - btnSyncTime->setMinimumSize(QSize(60, 30)); - connect(btnSyncTime, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - QJsonObject json; - json.insert("_id", "SyncTime"); - json.insert("_type", "SyncTime"); - json.insert("time", QDateTime::currentDateTime().toMSecsSinceEpoch()); - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, tr("SyncTime")); - Def_CtrlReqPre - connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { - Def_CtrlSetReqAfter - }); - } else { - foreach(auto card, *gSelCards) { - Def_CtrlSetMulti(tr("SyncTime")) - } - } - }); - vvv->addWidget(btnSyncTime); - - groupBox_5 = new QGroupBox; - vvv->addWidget(groupBox_5); - - auto vvvv = new QVBoxLayout(groupBox_5); - vvvv->addStretch(); - - btnDateGet = new QPushButton; - btnDateGet->setMinimumSize(QSize(0, 30)); - connect(btnDateGet, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - QJsonObject json; - json.insert("_id", "GetControllerDate"); - json.insert("_type", "GetControllerDate"); - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, tr("GetControllerDate")); - Def_CtrlReqPre - connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg] { - Def_CtrlSingleGetReply - waitingDlg->success(); - labelCurTime->setText(json["date"].toString()); - }); - } else { - foreach(auto card, *gSelCards) { - auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); - connect(reply, &QNetworkReply::finished, this, [reply, card] { - QJsonDocument json; - QString err = checkReplyForJson(reply, &json); - if(err.isEmpty()) err = json["date"].toString(); - gFdResInfo->append(card->m_strCardId+" "+tr("GetControllerDate")+" "+err); - }); - } - } - }); - vvvv->addWidget(btnDateGet); - - labelCurTime = new QLabel; - vvvv->addWidget(labelCurTime); - vvvv->addStretch(); - - - hBox->addSpacing(20); - - - groupBox = new QGroupBox; - groupBox->setCheckable(true); - vvv = new VBox(groupBox); - vvv->setSpacing(3); - - auto hhh = new HBox(vvv); - fdIsLora = new QRadioButton("Lora"); - hhh->addWidget(fdIsLora); - fdIsGPS = new QRadioButton("GPS"); - hhh->addWidget(fdIsGPS); - fdIsNTP = new QRadioButton("NTP"); - hhh->addWidget(fdIsNTP); - fdIsLan = new QRadioButton; - hhh->addWidget(fdIsLan); - - horizontalLayout_5 = new QHBoxLayout(); - horizontalLayout_5->setContentsMargins(0, 0, 0, 0); - - labelSyncTimeInterval = new QLabel(groupBox); - horizontalLayout_5->addWidget(labelSyncTimeInterval); - - lineEdit_3 = new QLineEdit(groupBox); - lineEdit_3->setMinimumSize(QSize(160, 30)); - lineEdit_3->setMaximumSize(QSize(160, 16777215)); - lineEdit_3->setStyleSheet(QString::fromUtf8("background-color: #FFFFFF;")); - - horizontalLayout_5->addWidget(lineEdit_3); - - labelmintime = new QLabel(groupBox); - - horizontalLayout_5->addWidget(labelmintime); - - - vvv->addLayout(horizontalLayout_5); - - horizontalLayout_9 = new QHBoxLayout(); - horizontalLayout_9->setContentsMargins(-1, 0, -1, -1); - labelIdCode = new QLabel(groupBox); - - horizontalLayout_9->addWidget(labelIdCode); - - lineEditIdCode = new QLineEdit(groupBox); - lineEditIdCode->setMinimumSize(QSize(0, 30)); - lineEditIdCode->setStyleSheet(QString::fromUtf8("background-color: #FFFFFF;")); - - horizontalLayout_9->addWidget(lineEditIdCode); - - vvv->addLayout(horizontalLayout_9); - - horizontalLayout_10 = new QHBoxLayout(); - horizontalLayout_10->setContentsMargins(-1, 0, -1, -1); - labelTimeOffset = new QLabel(groupBox); - - horizontalLayout_10->addWidget(labelTimeOffset); - - lineEditTimeOffset = new QLineEdit(groupBox); - lineEditTimeOffset->setMinimumSize(QSize(0, 30)); - lineEditTimeOffset->setStyleSheet(QString::fromUtf8("background-color: #FFFFFF;")); - - horizontalLayout_10->addWidget(lineEditTimeOffset); - - - vvv->addLayout(horizontalLayout_10); - - horizontalLayout_13 = new QHBoxLayout(); - horizontalLayout_13->setContentsMargins(-1, 0, -1, -1); - checkBoxBrightness = new QCheckBox(groupBox); - - horizontalLayout_13->addWidget(checkBoxBrightness); - - checkBoxVolume = new QCheckBox(groupBox); - - horizontalLayout_13->addWidget(checkBoxVolume); - - checkBoxScreenSwitch = new QCheckBox(groupBox); - - horizontalLayout_13->addWidget(checkBoxScreenSwitch); - - - vvv->addLayout(horizontalLayout_13); - - horizontalLayout_7 = new QHBoxLayout(); - horizontalLayout_7->setContentsMargins(-1, 0, -1, -1); - pushButtonSetSync = new QPushButton(groupBox); - pushButtonSetSync->setMinimumSize(QSize(60, 30)); - connect(pushButtonSetSync, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - QJsonObject json; - json.insert("_id", "SetingSyncMethod"); - json.insert("_type", "SetingSyncMethod"); - json.insert("ntpServer", labelNtpServerAddress->text()); - json.insert("delaySync", lineEditTimeOffset->text().toInt()); - json.insert("identificationCode",lineEditIdCode->text()); - json.insert("brightness", checkBoxBrightness->isChecked() ? "serial" : "none"); - json.insert("volume", checkBoxVolume->isChecked() ? "serial" : "none"); - json.insert("screenSwitch", checkBoxScreenSwitch->isChecked() ? "serial" : "none"); - if(fdIsLora->isChecked()) json.insert("time", "serial"); - else if(fdIsNTP->isChecked()) { - json.insert("time", "ntp"); - json.insert("checkNtpTime", lineEdit_3->text().toInt()); - } else if(fdIsGPS->isChecked()) json.insert("time", "gps"); - else if(fdIsLan->isChecked()) json.insert("time", "Lan"); - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, tr("SetingSyncMethod")); - Def_CtrlReqPre - connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { - Def_CtrlSetReqAfter - }); - } else { - foreach(auto card, *gSelCards) { - Def_CtrlSetMulti(tr("SetingSyncMethod")) - } - } - }); - horizontalLayout_7->addWidget(pushButtonSetSync); - - fdSyncGet = new QPushButton; - fdSyncGet->setMinimumSize(QSize(60, 30)); - connect(fdSyncGet, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - QJsonObject json; - json.insert("_id", "GetingSyncMethod"); - json.insert("_type", "GetingSyncMethod"); - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, tr("GetingSyncMethod")); - Def_CtrlReqPre - connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg] { - Def_CtrlSingleGetReply - waitingDlg->success(); - dealGetSync(json); - }); - } else { - foreach(auto card, *gSelCards) { - auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); - connect(reply, &QNetworkReply::finished, this, [reply, card] { - QJsonDocument json; - QByteArray data; - QString err = checkReplyForJson(reply, &json, &data); - if(err.isEmpty()) { - QString strOtherSyncItem = tr("screenSwitch") + ":" + (json["screenSwitch"].toBool() ? tr("YES") : tr("NO")) - + " " + tr("volume") + ":" + (json["volume"].toBool() ? tr("YES") : tr("NO")) - + " " + tr("brightness") + ":" + (json["brightness"].toBool() ? tr("YES") : tr("NO")); - QString lastSynchronousTime = QDateTime::fromMSecsSinceEpoch(json["lastSynchronousTime"].toDouble()).toString("yyyy-MM-dd HH:mm:ss"); - QString time = json["time"].toString(); - QString lower = time.toLower(); - if(lower=="serial") { - err = "Lora\n "+tr("identificationCode")+": "+json["identificationCode"].toString()+"\n " - +tr("delaySync")+": "+QString::number(json["delaySync"].toInt())+tr("msec")+"\n " - +tr("OtherSyncItem")+": "+strOtherSyncItem+"\n " - +tr("lastSynchronousTime")+": "+lastSynchronousTime; - } else if(lower=="ntp") { - err = time+"\n "+tr("checkNtpTime")+": "+QString::number(json["checkNtpTime"].toInt())+"\n " - +tr("OtherSyncItem")+": "+strOtherSyncItem+"\n " - +tr("lastSynchronousTime")+": "+lastSynchronousTime; - } else if(lower=="gps") { - err = time+"\n "+tr("OtherSyncItem")+": "+strOtherSyncItem+"\n "+tr("lastSynchronousTime")+": "+lastSynchronousTime; - } else if(lower=="lan") { - err = tr("LAN")+"\n "+tr("identificationCode")+": "+json["identificationCode"].toString()+"\n " - +tr("delaySync")+": "+QString::number(json["delaySync"].toInt())+tr("msec")+"\n " - +tr("OtherSyncItem")+": "+strOtherSyncItem+"\n " - +tr("lastSynchronousTime")+": "+lastSynchronousTime; - } else { - err = time+"\n "+data; - } - } - gFdResInfo->append(card->m_strCardId+" "+tr("GetingSyncMethod")+" "+err); - }); - } - } - }); - horizontalLayout_7->addWidget(fdSyncGet); - - vvv->addLayout(horizontalLayout_7); - vvv->addStretch(); - - groupBox_4 = new QGroupBox(groupBox); - groupBox_4->setMinimumSize(QSize(0, 20)); - horizontalLayout_11 = new QHBoxLayout(groupBox_4); - horizontalLayout_11->setSpacing(6); - horizontalLayout_11->setContentsMargins(0, 0, 0, 0); - radioButton_4 = new QRadioButton(groupBox_4); - - buttonGroup_2 = new QButtonGroup(this); - buttonGroup_2->addButton(radioButton_4); - radioButton_4->setChecked(true); - - horizontalLayout_11->addWidget(radioButton_4, 0, Qt::AlignHCenter); - - radioButton_5 = new QRadioButton(groupBox_4); - buttonGroup_2->addButton(radioButton_5); - - horizontalLayout_11->addWidget(radioButton_5, 0, Qt::AlignHCenter); - - - vvv->addWidget(groupBox_4); - - horizontalLayout_12 = new QHBoxLayout(); - horizontalLayout_12->setContentsMargins(-1, 0, -1, -1); - btnLoraMasterSet = new QPushButton(groupBox); - btnLoraMasterSet->setMinimumSize(QSize(0, 30)); - connect(btnLoraMasterSet, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - QJsonObject json; - json.insert("_id", "MasterSlaveSwitch"); - json.insert("_type", "MasterSlaveSwitch"); - bool isMaster = buttonGroup_2->checkedId()==0; - json.insert("master", isMaster); - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, isMaster ? tr("MasterSwitch ") : tr("SlaveSwitch ")); - Def_CtrlReqPre - connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { - Def_CtrlSetReqAfter - }); - } else { - foreach(auto card, *gSelCards) { - auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); - connect(reply, &QNetworkReply::finished, this, [reply, card, isMaster] { - QString err = checkReplyForJson(reply); - gFdResInfo->append(card->m_strCardId+" "+(isMaster ? tr("MasterSwitch ") : tr("SlaveSwitch "))+" "+(err.isEmpty()?QCoreApplication::translate("Def","Success"):err)); - }); - } - } - }); - horizontalLayout_12->addWidget(btnLoraMasterSet); - - btnLoraMasterGet = new QPushButton(groupBox); - btnLoraMasterGet->setMinimumSize(QSize(0, 30)); - connect(btnLoraMasterGet, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - QJsonObject json; - json.insert("_id", "IsMasterSlave"); - json.insert("_type", "IsMasterSlave"); - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, tr("IsMasterSlave")); - Def_CtrlReqPre - connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg] { - Def_CtrlSingleGetReply - waitingDlg->success(); - bool isMaster = json["result"].toBool(); - radioButton_4->setChecked(isMaster); - radioButton_5->setChecked(! isMaster); - }); - } else { - foreach(auto card, *gSelCards) { - auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); - connect(reply, &QNetworkReply::finished, this, [reply, card] { - QJsonDocument json; - QString err = checkReplyForJson(reply, &json); - if(err.isEmpty()) err = json["result"].toBool() ? tr("Master") : tr("Slave"); - gFdResInfo->append(card->m_strCardId+" "+tr("Lora identity")+" "+err); - }); - } - } - }); - horizontalLayout_12->addWidget(btnLoraMasterGet); - - vvv->addLayout(horizontalLayout_12); - - hBox->addWidget(groupBox); - - hBox->addSpacing(20); - - groupNTP = new QGroupBox; - vvv = new VBox(groupNTP); - - hhh = new HBox(vvv); - labelNtpServerAddress = new QLabel(groupNTP); - hhh->addWidget(labelNtpServerAddress); - - fdNtpServer = new QLineEdit(groupNTP); - fdNtpServer->setMinimumSize(QSize(160, 30)); - fdNtpServer->setMaximumSize(QSize(160, 16777215)); - fdNtpServer->setStyleSheet(QString::fromUtf8("background-color: #FFFFFF;")); - hhh->addWidget(fdNtpServer); - hhh->addStretch(); - - vvv->addSpacing(20); - - hhh = new HBox(vvv); - btnNtpSet = new QPushButton; - btnNtpSet->setMinimumSize(QSize(60, 30)); - connect(btnNtpSet, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - QJsonObject json; - json.insert("_id", "SetNtpServer"); - json.insert("_type", "SetNtpServer"); - json.insert("ntpServer", fdNtpServer->text()); - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, tr("SetNtpServer")); - Def_CtrlReqPre - connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { - Def_CtrlSetReqAfter - }); - } else { - foreach(auto card, *gSelCards) { - Def_CtrlSetMulti(tr("SetNtpServer")) - } - } - }); - hhh->addWidget(btnNtpSet); - - btnNtpGet = new QPushButton; - btnNtpGet->setMinimumSize(QSize(60, 30)); - connect(btnNtpGet, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - QJsonObject json; - json.insert("_id", "GetNtpServer"); - json.insert("_type", "GetNtpServer"); - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, tr("GetNtpServer")); - Def_CtrlReqPre - connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg] { - Def_CtrlSingleGetReply - waitingDlg->success(); - fdNtpServer->setText(json["ntpServer"].toString()); - }); - } else { - foreach(auto card, *gSelCards) { - auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); - connect(reply, &QNetworkReply::finished, this, [reply, card] { - QJsonDocument json; - QString err = checkReplyForJson(reply, &json); - if(err.isEmpty()) err = json["ntpServer"].toString(); - gFdResInfo->append(card->m_strCardId+" "+tr("GetNtpServer")+" "+err); - }); - } - } - }); - hhh->addWidget(btnNtpGet); - - vvv->addStretch(); - - hBox->addWidget(groupNTP); - hBox->addStretch(); - - vBox->addStretch(); - - label->setText(tr("TimeZone")); - lbLang->setText(tr("Language:")); - fdIsEn->setText(tr("English")); - fdIsCn->setText(tr("\344\270\255\346\226\207")); - labelVerifyClockConfiguration->setText(tr("Verify Clock Configuration")); - groupBox_5->setTitle(tr("Cur time of controller")); - groupBox->setTitle(tr("Enable Synchronous playing")); - fdIsLan->setText(tr("LAN")); - labelSyncTimeInterval->setText(tr("Sync time interval")); - lineEdit_3->setPlaceholderText(tr("Sync time interval")); - labelmintime->setText(tr("(min/time)")); - labelIdCode->setText(tr("Sync identificationCode")); - lineEditIdCode->setPlaceholderText(tr("identification code")); - labelTimeOffset->setText(tr("Time offset(msec)")); - checkBoxBrightness->setText(tr("Brightness")); - checkBoxVolume->setText(tr("Volume")); - checkBoxScreenSwitch->setText(tr("Screen on/off")); - radioButton_4->setText(tr("Slave")); - radioButton_5->setText(tr("Master ")); - groupNTP->setTitle(tr("NTP Server")); - labelNtpServerAddress->setText(tr("NTP Server address")); - fdNtpServer->setPlaceholderText(tr("NTP Server address")); - - btnNtpSet->setProperty("ssType", "progManageTool"); - pushButtonSetSync->setProperty("ssType", "progManageTool"); - btnSyncTime->setProperty("ssType", "progManageTool"); - fdSyncGet->setProperty("ssType", "progManageTool"); - btnNtpGet->setProperty("ssType", "progManageTool"); - - btnLoraMasterSet->setProperty("ssType", "progManageTool"); - btnLoraMasterGet->setProperty("ssType", "progManageTool"); - btnDateGet->setProperty("ssType", "progManageTool"); - fdTimeZoneSet->setProperty("ssType", "progManageTool"); - buttonGroup_2->setId(radioButton_4, 0); - buttonGroup_2->setId(radioButton_5, 1); - - fdIsLora->setChecked(true); - labelIdCode->setVisible(true); - lineEditIdCode->setVisible(true); - labelTimeOffset->setVisible(true); - lineEditTimeOffset->setVisible(true); - lineEdit_3->setVisible(false); - labelSyncTimeInterval->setVisible(false); - labelmintime->setVisible(false); - - //按钮事件绑定 - connect(fdIsGPS,SIGNAL(clicked()),this,SLOT(OnRadioButton())); - connect(fdIsLora,SIGNAL(clicked()),this,SLOT(OnRadioButton2())); - connect(fdIsNTP,SIGNAL(clicked()),this,SLOT(OnRadioButton3())); - connect(fdIsLan,SIGNAL(clicked()),this,SLOT(OnRadioButton6())); - - //MARCO_DEFINE_CONTROL_FUNC2(parent->parent(),parent) - - connect(gDevicePanel, &DevicePanel::sigSelectedDeviceList, this, [this] { - if(isVisible()) init(); - }); - transUi(); -} - -void CtrlVerifyClockPanel::showEvent(QShowEvent *event) { - QWidget::showEvent(event); - init(); -} -void CtrlVerifyClockPanel::init() { - bool isSingle = gSelCards->count()==1; - if(! isSingle) return; - auto card = gSelCards->at(0); - - QJsonObject json; - json.insert("_id", "GetingSyncMethod"); - json.insert("_type", "GetingSyncMethod"); - auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); - connect(reply, &QNetworkReply::finished, this, [this, reply] { - QJsonDocument json; - QString err = checkReplyForJson(reply, &json); - if(! err.isEmpty()) { - QMessageBox::critical(gMainWin, tr("Error"), err); - return; - } - dealGetSync(json); - }); - - json = QJsonObject(); - json.insert("_id", "GetTimezone"); - json.insert("_type", "GetTimezone"); - reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); - connect(reply, &QNetworkReply::finished, this, [this, reply] { - QJsonDocument json; - QString err = checkReplyForJson(reply, &json); - if(! err.isEmpty()) { - QMessageBox::critical(gMainWin, tr("Error"), err); - return; - } - fdTimezone->setCurrentText(json["timezone"].toString()); - }); - - json = QJsonObject(); - json.insert("_id", "GetLanguage"); - json.insert("_type", "GetLanguage"); - reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); - connect(reply, &QNetworkReply::finished, this, [this, reply] { - QJsonDocument json; - QString err = checkReplyForJson(reply, &json); - if(! err.isEmpty()) { - QMessageBox::critical(gMainWin, tr("Error"), err); - return; - } - if(json["language"].toInt()==1) fdIsCn->setChecked(true); - else fdIsEn->setChecked(true); - }); -} -void CtrlVerifyClockPanel::changeEvent(QEvent *event) { - QWidget::changeEvent(event); - if(event->type() == QEvent::LanguageChange) transUi(); -} -void CtrlVerifyClockPanel::transUi() { - labelNtpServerAddress->setText(tr("NTP Server address")); - labelTimeOffset->setText(tr("Time offset(msec)")); - labelVerifyClockConfiguration->setText(tr("Verify clock configuration")); - lbLang->setText(tr("Language:")); - btnNtpSet->setText(tr("Set")); - pushButtonSetSync->setText(tr("Set")); - btnLangSet->setText(tr("Set")); - btnSyncTime->setText(tr("Verify to Computer time")); - fdTimeZoneSet->setText(tr("Set")); - btnLoraMasterSet->setText(tr("Set")); - btnLangGet->setText(tr("Readback")); - btnLoraMasterGet->setText(tr("Readback")); - btnNtpGet->setText(tr("Readback")); - fdSyncGet->setText(tr("Readback")); - btnDateGet->setText(tr("Readback")); - groupNTP->setTitle(tr("NTP Server")); - groupBox->setTitle(tr("Enable Synchronous playing")); - radioButton_4->setText(tr("Master")); - radioButton_5->setText(tr("Slave")); - labelSyncTimeInterval->setText(tr("Sync time interval")); - labelIdCode->setText(tr("Identification Code")); - checkBoxBrightness->setText(tr("Brightness")); - checkBoxVolume->setText(tr("Volume")); - checkBoxScreenSwitch->setText(tr("Screen on/off")); - - groupBox_5->setTitle(tr("Cur time of controller")); - - fdNtpServer->setPlaceholderText(tr("NTP Server address")); - lineEdit_3->setPlaceholderText(tr("Sync time interval")); - lineEditIdCode->setPlaceholderText(tr("identification code")); - label->setText(tr("TimeZone")); -} -void CtrlVerifyClockPanel::dealGetSync(QJsonDocument &json) { - QString strType = json["time"].toString().toLower(); - if(strType=="serial" || strType=="lan") { - if(strType=="serial") fdIsLora->setChecked(true); - else fdIsLan->setChecked(true); - lineEditIdCode->setText(json["identificationCode"].toString()); - lineEditTimeOffset->setText(QString::number(json["delaySync"].toInt())); - labelIdCode->setVisible(true); - lineEditIdCode->setVisible(true); - labelTimeOffset->setVisible(true); - lineEditTimeOffset->setVisible(true); - lineEdit_3->setVisible(false); - labelSyncTimeInterval->setVisible(false); - labelmintime->setVisible(false); - checkBoxScreenSwitch->setChecked(json["screenSwitch"].toString()!="NONE"); - checkBoxVolume->setChecked(json["volume"].toString()!="NONE"); - checkBoxBrightness->setChecked(json["brightness"].toString()!="NONE"); - checkBoxScreenSwitch->setVisible(true); - checkBoxVolume->setVisible(true); - checkBoxBrightness->setVisible(true); - pushButtonSetSync->setVisible(true); - fdSyncGet->setVisible(true); - } else if(strType=="ntp") { - fdIsNTP->setChecked(true); - lineEdit_3->setText(QString::number(json["checkNtpTime"].toInt())); - labelIdCode->setVisible(false); - lineEditIdCode->setVisible(false); - labelTimeOffset->setVisible(false); - lineEditTimeOffset->setVisible(false); - lineEdit_3->setVisible(true); - labelSyncTimeInterval->setVisible(true); - labelmintime->setVisible(true); - groupBox_4->setVisible(false); - radioButton_4->setVisible(false); - radioButton_5->setVisible(false); - btnLoraMasterSet->setVisible(false); - btnLoraMasterGet->setVisible(false); - checkBoxScreenSwitch->setVisible(false); - checkBoxVolume->setVisible(false); - checkBoxBrightness->setVisible(false); - pushButtonSetSync->setVisible(true); - fdSyncGet->setVisible(true); - } else if(strType=="gps") { - fdIsGPS->setChecked(true); - labelIdCode->setVisible(false); - lineEditIdCode->setVisible(false); - labelTimeOffset->setVisible(false); - lineEditTimeOffset->setVisible(false); - labelSyncTimeInterval->setVisible(false); - lineEdit_3->setVisible(false); - labelmintime->setVisible(false); - groupBox_4->setVisible(false); - radioButton_4->setVisible(false); - radioButton_5->setVisible(false); - btnLoraMasterSet->setVisible(false); - btnLoraMasterGet->setVisible(false); - checkBoxScreenSwitch->setVisible(false); - checkBoxVolume->setVisible(false); - checkBoxBrightness->setVisible(false); - pushButtonSetSync->setVisible(true); - fdSyncGet->setVisible(true); - } -} -void CtrlVerifyClockPanel::OnRadioButton()//gps -{ - labelIdCode->setVisible(false); - lineEditIdCode->setVisible(false); - labelTimeOffset->setVisible(false); - lineEditTimeOffset->setVisible(false); - labelSyncTimeInterval->setVisible(false); - lineEdit_3->setVisible(false); - labelmintime->setVisible(false); - groupBox_4->setVisible(false); - radioButton_4->setVisible(false); - radioButton_5->setVisible(false); - btnLoraMasterSet->setVisible(false); - btnLoraMasterGet->setVisible(false); - checkBoxScreenSwitch->setVisible(false); - checkBoxVolume->setVisible(false); - checkBoxBrightness->setVisible(false); - pushButtonSetSync->setVisible(true); - fdSyncGet->setVisible(true); -} -void CtrlVerifyClockPanel::OnRadioButton2()//lora -{ - labelIdCode->setVisible(true); - lineEditIdCode->setVisible(true); - labelTimeOffset->setVisible(true); - lineEditTimeOffset->setVisible(true); - lineEdit_3->setVisible(false); - labelSyncTimeInterval->setVisible(false); - labelmintime->setVisible(false); - groupBox_4->setVisible(true); - radioButton_4->setVisible(true); - radioButton_5->setVisible(true); - btnLoraMasterSet->setVisible(true); - btnLoraMasterGet->setVisible(true); - checkBoxScreenSwitch->setVisible(true); - checkBoxVolume->setVisible(true); - checkBoxBrightness->setVisible(true); - pushButtonSetSync->setVisible(true); - fdSyncGet->setVisible(true); -} - -void CtrlVerifyClockPanel::OnRadioButton3()//ntp -{ - labelIdCode->setVisible(false); - lineEditIdCode->setVisible(false); - labelTimeOffset->setVisible(false); - lineEditTimeOffset->setVisible(false); - lineEdit_3->setVisible(true); - labelSyncTimeInterval->setVisible(true); - labelmintime->setVisible(true); - groupBox_4->setVisible(false); - radioButton_4->setVisible(false); - radioButton_5->setVisible(false); - btnLoraMasterSet->setVisible(false); - btnLoraMasterGet->setVisible(false); - checkBoxScreenSwitch->setVisible(false); - checkBoxVolume->setVisible(false); - checkBoxBrightness->setVisible(false); - pushButtonSetSync->setVisible(true); - fdSyncGet->setVisible(true); -} -void CtrlVerifyClockPanel::OnRadioButton6() { - labelIdCode->setVisible(true); - lineEditIdCode->setVisible(true); - labelTimeOffset->setVisible(true); - lineEditTimeOffset->setVisible(true); - lineEdit_3->setVisible(false); - labelSyncTimeInterval->setVisible(false); - labelmintime->setVisible(false); - groupBox_4->setVisible(true); - radioButton_4->setVisible(true); - radioButton_5->setVisible(true); - btnLoraMasterSet->setVisible(true); - btnLoraMasterGet->setVisible(true); - checkBoxScreenSwitch->setVisible(true); - checkBoxVolume->setVisible(true); - checkBoxBrightness->setVisible(true); - pushButtonSetSync->setVisible(true); - fdSyncGet->setVisible(true); -} +#include "ctrlverifyclockpanel.h" +#include "base/waitingdlg.h" +#include "globaldefine.h" +#include "gutil/qgui.h" +#include "tools.h" +#include +#include +#include + +CtrlVerifyClockPanel::CtrlVerifyClockPanel(QWidget *parent) : QWidget(parent) { + auto vBox = new VBox(this); + auto hBox = new HBox(vBox); + + label = new QLabel; + hBox->addWidget(label); + + fdTimezone = new QComboBox; + fdTimezone->setMinimumWidth(200); + fdTimezone->addItem("Africa/Brazzaville");//西部非洲标准时间 (布拉扎维) + fdTimezone->addItem("Africa/Cairo");//东欧标准时间 (开罗) + fdTimezone->addItem("Africa/Casablanca");//卡萨布兰卡 + fdTimezone->addItem("Africa/Harare");//中部非洲标准时间 (哈拉雷) + fdTimezone->addItem("Africa/Nairobi");//东部非洲标准时间 (内罗毕) + fdTimezone->addItem("Africa/Windhoek");//温得和克 + fdTimezone->addItem("America/Anchorage");//>安克雷奇 + fdTimezone->addItem("America/Argentina/Buenos_Aires");//布宜诺斯艾利斯 + fdTimezone->addItem("America/Barbados");//>大西洋时间 (巴巴多斯) + fdTimezone->addItem("America/Bogota");//>哥伦比亚时间 (波哥大) + fdTimezone->addItem("America/Caracas");//>委内瑞拉时间 (加拉加斯) + fdTimezone->addItem("America/Chicago");//>美国中部时间 (芝加哥) + fdTimezone->addItem("America/Chihuahua");//>奇瓦瓦 + fdTimezone->addItem("America/Costa_Rica");//>美国中部时间 (哥斯达黎加) + fdTimezone->addItem("America/Denver");//>美国山区时间 (丹佛) + fdTimezone->addItem("America/Godthab");//戈特霍布 + fdTimezone->addItem("America/Los_Angeles");//>美国太平洋时间 (洛杉矶) + fdTimezone->addItem("America/Manaus");//亚马逊标准时间 (马瑙斯) + fdTimezone->addItem("America/Mexico_City");//>美国中部时间 (墨西哥城) + fdTimezone->addItem("America/Montevideo");//乌拉圭时间 (蒙得维的亚) + fdTimezone->addItem("America/New_York");//>美国东部时间 (纽约) + fdTimezone->addItem("America/Phoenix");//>美国山区时间 (凤凰城) + fdTimezone->addItem("America/Regina");//>美国中部时间 (里贾纳) + fdTimezone->addItem("America/Santiago");//圣地亚哥 + fdTimezone->addItem("America/Sao_Paulo");//圣保罗 + fdTimezone->addItem("America/St_Johns");//纽芬兰时间 (圣约翰) + fdTimezone->addItem("America/Tijuana");//>美国太平洋时间 (提华纳) + fdTimezone->addItem("Asia/Almaty");//阿拉木图 + fdTimezone->addItem("Asia/Amman");//东欧标准时间 (安曼) + fdTimezone->addItem("Asia/Baghdad");//巴格达 + fdTimezone->addItem("Asia/Baku");//巴库 + fdTimezone->addItem("Asia/Bangkok");//曼谷 + fdTimezone->addItem("Asia/Beirut");//东欧标准时间 (贝鲁特) + fdTimezone->addItem("Asia/Calcutta");//加尔各答 + fdTimezone->addItem("Asia/Colombo");//科伦坡 + fdTimezone->addItem("Asia/Dubai");//迪拜 + fdTimezone->addItem("Asia/Hong_Kong");//香港时间 (香港) + fdTimezone->addItem("Asia/Irkutsk");//伊尔库茨克时间 (伊尔库茨克) + fdTimezone->addItem("Asia/Jerusalem");//以色列时间 (耶路撒冷) + fdTimezone->addItem("Asia/Kabul");//阿富汗时间 (喀布尔) + fdTimezone->addItem("Asia/Karachi");//卡拉奇 + fdTimezone->addItem("Asia/Katmandu");//尼泊尔时间 (加德满都) + fdTimezone->addItem("Asia/Krasnoyarsk");//克拉斯诺亚尔斯克 + fdTimezone->addItem("Asia/Kuala_Lumpur");//吉隆坡 + fdTimezone->addItem("Asia/Kuwait");//科威特 + fdTimezone->addItem("Asia/Magadan");//马加丹时间 (马加丹) + fdTimezone->addItem("Asia/Oral");//乌拉尔 + fdTimezone->addItem("Asia/Rangoon");//缅甸时间 (仰光) + fdTimezone->addItem("Asia/Seoul");//首尔 + fdTimezone->addItem("Asia/Shanghai");//中国标准时间 (北京) + fdTimezone->addItem("Asia/Taipei");//台北时间 (台北) + fdTimezone->addItem("Asia/Tbilisi");//第比利斯 + fdTimezone->addItem("Asia/Tehran");//伊朗标准时间 (德黑兰) + fdTimezone->addItem("Asia/Tokyo");//日本时间 (东京) + fdTimezone->addItem("Asia/Vladivostok");//海参崴时间 (符拉迪沃斯托克) + fdTimezone->addItem("Asia/Yakutsk");//雅库茨克时间 (雅库茨克) + fdTimezone->addItem("Asia/Yekaterinburg");//叶卡捷林堡 + fdTimezone->addItem("Asia/Yerevan");//埃里温 + fdTimezone->addItem("Atlantic/Azores");//亚述尔群岛 + fdTimezone->addItem("Atlantic/Cape_Verde");//佛得角 + fdTimezone->addItem("Atlantic/South_Georgia");//南乔治亚 + fdTimezone->addItem("Australia/Adelaide");//阿德莱德 + fdTimezone->addItem("Australia/Brisbane");//布里斯班 + fdTimezone->addItem("Australia/Darwin");//达尔文 + fdTimezone->addItem("Australia/Hobart");//霍巴特 + fdTimezone->addItem("Australia/Perth");//佩思 + fdTimezone->addItem("Australia/Sydney");//悉尼 + fdTimezone->addItem("Europe/Amsterdam");//中欧标准时间 (阿姆斯特丹) + fdTimezone->addItem("Europe/Athens");//东欧标准时间 (雅典) + fdTimezone->addItem("Europe/Belgrade");//中欧标准时间 (贝尔格莱德) + fdTimezone->addItem("Europe/Brussels");//中欧标准时间 (布鲁塞尔) + fdTimezone->addItem("Europe/Helsinki");//东欧标准时间 (赫尔辛基) + fdTimezone->addItem("Europe/London");//格林尼治标准时间 (伦敦) + fdTimezone->addItem("Europe/Minsk");//明斯克 + fdTimezone->addItem("Europe/Moscow");//莫斯科 + fdTimezone->addItem("Europe/Sarajevo");//中欧标准时间 (萨拉热窝) + fdTimezone->addItem("Pacific/Auckland");//奥克兰 + fdTimezone->addItem("Pacific/Fiji");//斐济 + fdTimezone->addItem("Pacific/Guam");//关岛 + fdTimezone->addItem("Pacific/Honolulu"); + fdTimezone->addItem("Pacific/Majuro"); + fdTimezone->addItem("Pacific/Midway"); + fdTimezone->addItem("Pacific/Tongatapu");//东加塔布 + hBox->addWidget(fdTimezone); + + fdTimeZoneSet = new QPushButton; + connect(fdTimeZoneSet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "SetTimezone"); + json.insert("_type", "SetTimezone"); + json.insert("timezone", fdTimezone->currentText()); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("SetTimezone")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("SetTimezone")) + } + } + }); + hBox->addWidget(fdTimeZoneSet); + hBox->addSpacing(20); + + lbLang = new QLabel; + hBox->addWidget(lbLang); + + fdIsEn = new QRadioButton("English"); + hBox->addWidget(fdIsEn); + + fdIsCn = new QRadioButton("中文"); + hBox->addWidget(fdIsCn); + + btnLangSet = new QPushButton; + connect(btnLangSet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "SetLanguage"); + json.insert("_type", "SetLanguage"); + json.insert("language", fdIsCn->isChecked() ? 1 : 0); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, "设置语言"); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti("设置语言") + } + } + }); + hBox->addWidget(btnLangSet); + + btnLangGet = new QPushButton; + connect(btnLangGet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "GetLanguage"); + json.insert("_type", "GetLanguage"); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, "获取语言"); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg] { + Def_CtrlSingleGetReply + waitingDlg->success(); + if(json["language"].toInt()==1) fdIsCn->setChecked(true); + else fdIsEn->setChecked(true); + }); + } else { + foreach(auto card, *gSelCards) { + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + auto cardId = card->m_strCardId; + connect(reply, &QNetworkReply::finished, this, [reply, cardId] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(err.isEmpty()) err = json["language"].toInt()==1 ? "中文" : "英文"; + gFdResInfo->append(cardId+" 获取语言 "+err); + }); + } + } + }); + hBox->addWidget(btnLangGet); + hBox->addStretch(); + + + labelVerifyClockConfiguration = new QLabel; + labelVerifyClockConfiguration->setAlignment(Qt::AlignCenter); + vBox->addWidget(labelVerifyClockConfiguration); + + auto line = new QFrame; + line->setFrameShape(QFrame::HLine); + line->setFrameShadow(QFrame::Sunken); + vBox->addWidget(line); + + hBox = new HBox(vBox); + auto vvv = new VBox(hBox); + + btnSyncTime = new QPushButton(tr("Verify to Computer time")); + btnSyncTime->setMinimumSize(QSize(60, 30)); + connect(btnSyncTime, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "SyncTime"); + json.insert("_type", "SyncTime"); + json.insert("time", QDateTime::currentDateTime().toMSecsSinceEpoch()); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("SyncTime")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("SyncTime")) + } + } + }); + vvv->addWidget(btnSyncTime); + + groupBox_5 = new QGroupBox; + vvv->addWidget(groupBox_5); + + auto vvvv = new QVBoxLayout(groupBox_5); + vvvv->addStretch(); + + btnDateGet = new QPushButton; + btnDateGet->setMinimumSize(QSize(0, 30)); + connect(btnDateGet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "GetControllerDate"); + json.insert("_type", "GetControllerDate"); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("GetControllerDate")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg] { + Def_CtrlSingleGetReply + waitingDlg->success(); + labelCurTime->setText(json["date"].toString()); + }); + } else { + foreach(auto card, *gSelCards) { + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + auto cardId = card->m_strCardId; + connect(reply, &QNetworkReply::finished, this, [reply, cardId] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(err.isEmpty()) err = json["date"].toString(); + gFdResInfo->append(cardId+" "+tr("GetControllerDate")+" "+err); + }); + } + } + }); + vvvv->addWidget(btnDateGet); + + labelCurTime = new QLabel; + vvvv->addWidget(labelCurTime); + vvvv->addStretch(); + + + hBox->addSpacing(20); + + + groupBox = new QGroupBox; + groupBox->setCheckable(true); + vvv = new VBox(groupBox); + vvv->setSpacing(3); + + auto hhh = new HBox(vvv); + fdIsLora = new QRadioButton("Lora"); + hhh->addWidget(fdIsLora); + fdIsGPS = new QRadioButton("GPS"); + hhh->addWidget(fdIsGPS); + fdIsNTP = new QRadioButton("NTP"); + hhh->addWidget(fdIsNTP); + fdIsLan = new QRadioButton; + hhh->addWidget(fdIsLan); + + horizontalLayout_5 = new QHBoxLayout(); + horizontalLayout_5->setContentsMargins(0, 0, 0, 0); + + labelSyncTimeInterval = new QLabel(groupBox); + horizontalLayout_5->addWidget(labelSyncTimeInterval); + + lineEdit_3 = new QLineEdit(groupBox); + lineEdit_3->setMinimumSize(QSize(160, 30)); + lineEdit_3->setMaximumSize(QSize(160, 16777215)); + horizontalLayout_5->addWidget(lineEdit_3); + + labelmintime = new QLabel(groupBox); + + horizontalLayout_5->addWidget(labelmintime); + + + vvv->addLayout(horizontalLayout_5); + + horizontalLayout_9 = new QHBoxLayout(); + horizontalLayout_9->setContentsMargins(-1, 0, -1, -1); + labelIdCode = new QLabel(groupBox); + + horizontalLayout_9->addWidget(labelIdCode); + + lineEditIdCode = new QLineEdit(groupBox); + lineEditIdCode->setMinimumSize(QSize(0, 30)); + lineEditIdCode->setStyleSheet(QString::fromUtf8("background-color: #FFFFFF;")); + + horizontalLayout_9->addWidget(lineEditIdCode); + + vvv->addLayout(horizontalLayout_9); + + horizontalLayout_10 = new QHBoxLayout(); + horizontalLayout_10->setContentsMargins(-1, 0, -1, -1); + labelTimeOffset = new QLabel(groupBox); + + horizontalLayout_10->addWidget(labelTimeOffset); + + lineEditTimeOffset = new QLineEdit(groupBox); + lineEditTimeOffset->setMinimumSize(QSize(0, 30)); + lineEditTimeOffset->setStyleSheet(QString::fromUtf8("background-color: #FFFFFF;")); + + horizontalLayout_10->addWidget(lineEditTimeOffset); + + + vvv->addLayout(horizontalLayout_10); + + horizontalLayout_13 = new QHBoxLayout(); + horizontalLayout_13->setContentsMargins(-1, 0, -1, -1); + checkBoxBrightness = new QCheckBox(groupBox); + + horizontalLayout_13->addWidget(checkBoxBrightness); + + checkBoxVolume = new QCheckBox(groupBox); + + horizontalLayout_13->addWidget(checkBoxVolume); + + checkBoxScreenSwitch = new QCheckBox(groupBox); + + horizontalLayout_13->addWidget(checkBoxScreenSwitch); + + + vvv->addLayout(horizontalLayout_13); + + horizontalLayout_7 = new QHBoxLayout(); + horizontalLayout_7->setContentsMargins(-1, 0, -1, -1); + btnSyncSet = new QPushButton(groupBox); + btnSyncSet->setMinimumSize(QSize(60, 30)); + connect(btnSyncSet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "SetingSyncMethod"); + json.insert("_type", "SetingSyncMethod"); + json.insert("ntpServer", labelNtpServerAddress->text()); + json.insert("delaySync", lineEditTimeOffset->text().toInt()); + json.insert("identificationCode",lineEditIdCode->text()); + json.insert("brightness", checkBoxBrightness->isChecked() ? "serial" : "none"); + json.insert("volume", checkBoxVolume->isChecked() ? "serial" : "none"); + json.insert("screenSwitch", checkBoxScreenSwitch->isChecked() ? "serial" : "none"); + if(fdIsLora->isChecked()) json.insert("time", "serial"); + else if(fdIsNTP->isChecked()) { + json.insert("time", "ntp"); + json.insert("checkNtpTime", lineEdit_3->text().toInt()); + } else if(fdIsGPS->isChecked()) json.insert("time", "gps"); + else if(fdIsLan->isChecked()) json.insert("time", "Lan"); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("SetingSyncMethod")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("SetingSyncMethod")) + } + } + }); + horizontalLayout_7->addWidget(btnSyncSet); + + fdSyncGet = new QPushButton; + fdSyncGet->setMinimumSize(QSize(60, 30)); + connect(fdSyncGet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "GetingSyncMethod"); + json.insert("_type", "GetingSyncMethod"); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("GetingSyncMethod")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg] { + Def_CtrlSingleGetReply + waitingDlg->success(); + dealGetSync(json); + }); + } else { + foreach(auto card, *gSelCards) { + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + auto cardId = card->m_strCardId; + connect(reply, &QNetworkReply::finished, this, [reply, cardId] { + QJsonDocument json; + QByteArray data; + QString err = checkReplyForJson(reply, &json, &data); + if(err.isEmpty()) { + QString strOtherSyncItem = tr("screenSwitch") + ":" + (json["screenSwitch"].toBool() ? tr("YES") : tr("NO")) + + " " + tr("volume") + ":" + (json["volume"].toBool() ? tr("YES") : tr("NO")) + + " " + tr("brightness") + ":" + (json["brightness"].toBool() ? tr("YES") : tr("NO")); + QString lastSynchronousTime = QDateTime::fromMSecsSinceEpoch(json["lastSynchronousTime"].toDouble()).toString("yyyy-MM-dd HH:mm:ss"); + QString time = json["time"].toString(); + QString lower = time.toLower(); + if(lower=="serial") { + err = "Lora\n "+tr("identificationCode")+": "+json["identificationCode"].toString()+"\n " + +tr("delaySync")+": "+QString::number(json["delaySync"].toInt())+tr("msec")+"\n " + +tr("OtherSyncItem")+": "+strOtherSyncItem+"\n " + +tr("lastSynchronousTime")+": "+lastSynchronousTime; + } else if(lower=="ntp") { + err = time+"\n "+tr("checkNtpTime")+": "+QString::number(json["checkNtpTime"].toInt())+"\n " + +tr("OtherSyncItem")+": "+strOtherSyncItem+"\n " + +tr("lastSynchronousTime")+": "+lastSynchronousTime; + } else if(lower=="gps") { + err = time+"\n "+tr("OtherSyncItem")+": "+strOtherSyncItem+"\n "+tr("lastSynchronousTime")+": "+lastSynchronousTime; + } else if(lower=="lan") { + err = tr("LAN")+"\n "+tr("identificationCode")+": "+json["identificationCode"].toString()+"\n " + +tr("delaySync")+": "+QString::number(json["delaySync"].toInt())+tr("msec")+"\n " + +tr("OtherSyncItem")+": "+strOtherSyncItem+"\n " + +tr("lastSynchronousTime")+": "+lastSynchronousTime; + } else { + err = time+"\n "+data; + } + } + gFdResInfo->append(cardId+" "+tr("GetingSyncMethod")+" "+err); + }); + } + } + }); + horizontalLayout_7->addWidget(fdSyncGet); + + vvv->addLayout(horizontalLayout_7); + vvv->addStretch(); + + groupBox_4 = new QGroupBox(groupBox); + groupBox_4->setMinimumSize(QSize(0, 20)); + horizontalLayout_11 = new QHBoxLayout(groupBox_4); + horizontalLayout_11->setSpacing(6); + horizontalLayout_11->setContentsMargins(0, 0, 0, 0); + fdMaster = new QRadioButton(groupBox_4); + + buttonGroup_2 = new QButtonGroup(this); + buttonGroup_2->addButton(fdMaster); + fdMaster->setChecked(true); + + horizontalLayout_11->addWidget(fdMaster, 0, Qt::AlignHCenter); + + fdSlave = new QRadioButton(groupBox_4); + buttonGroup_2->addButton(fdSlave); + + horizontalLayout_11->addWidget(fdSlave, 0, Qt::AlignHCenter); + + + vvv->addWidget(groupBox_4); + + horizontalLayout_12 = new QHBoxLayout(); + horizontalLayout_12->setContentsMargins(-1, 0, -1, -1); + btnLoraMasterSet = new QPushButton(groupBox); + btnLoraMasterSet->setMinimumSize(QSize(0, 30)); + connect(btnLoraMasterSet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "MasterSlaveSwitch"); + json.insert("_type", "MasterSlaveSwitch"); + bool isMaster = buttonGroup_2->checkedId()==0; + json.insert("master", isMaster); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, isMaster ? tr("MasterSwitch ") : tr("SlaveSwitch ")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + connect(reply, &QNetworkReply::finished, this, [reply, card, isMaster] { + QString err = checkReplyForJson(reply); + gFdResInfo->append(card->m_strCardId+" "+(isMaster ? tr("MasterSwitch ") : tr("SlaveSwitch "))+" "+(err.isEmpty()?QCoreApplication::translate("Def","Success"):err)); + }); + } + } + }); + horizontalLayout_12->addWidget(btnLoraMasterSet); + + btnLoraMasterGet = new QPushButton(groupBox); + btnLoraMasterGet->setMinimumSize(QSize(0, 30)); + connect(btnLoraMasterGet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "IsMasterSlave"); + json.insert("_type", "IsMasterSlave"); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("IsMasterSlave")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg] { + Def_CtrlSingleGetReply + waitingDlg->success(); + bool isMaster = json["result"].toBool(); + fdMaster->setChecked(isMaster); + fdSlave->setChecked(! isMaster); + }); + } else { + foreach(auto card, *gSelCards) { + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + auto cardId = card->m_strCardId; + connect(reply, &QNetworkReply::finished, this, [reply, cardId] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(err.isEmpty()) err = json["result"].toBool() ? tr("Master") : tr("Slave"); + gFdResInfo->append(cardId+" "+tr("Lora identity")+" "+err); + }); + } + } + }); + horizontalLayout_12->addWidget(btnLoraMasterGet); + + vvv->addLayout(horizontalLayout_12); + + hBox->addWidget(groupBox); + + hBox->addSpacing(20); + + groupNTP = new QGroupBox; + vvv = new VBox(groupNTP); + + hhh = new HBox(vvv); + labelNtpServerAddress = new QLabel(groupNTP); + hhh->addWidget(labelNtpServerAddress); + + fdNtpServer = new QLineEdit(groupNTP); + fdNtpServer->setMinimumSize(QSize(160, 30)); + fdNtpServer->setMaximumSize(QSize(160, 16777215)); + fdNtpServer->setStyleSheet(QString::fromUtf8("background-color: #FFFFFF;")); + hhh->addWidget(fdNtpServer); + hhh->addStretch(); + + vvv->addSpacing(20); + + hhh = new HBox(vvv); + btnNtpSet = new QPushButton; + btnNtpSet->setMinimumSize(QSize(60, 30)); + connect(btnNtpSet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "SetNtpServer"); + json.insert("_type", "SetNtpServer"); + json.insert("ntpServer", fdNtpServer->text()); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("SetNtpServer")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { + Def_CtrlSetReqAfter + }); + } else { + foreach(auto card, *gSelCards) { + Def_CtrlSetMulti(tr("SetNtpServer")) + } + } + }); + hhh->addWidget(btnNtpSet); + + btnNtpGet = new QPushButton; + btnNtpGet->setMinimumSize(QSize(60, 30)); + connect(btnNtpGet, &QPushButton::clicked, this, [this] { + if(gSelCards->isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); + return; + } + QJsonObject json; + json.insert("_id", "GetNtpServer"); + json.insert("_type", "GetNtpServer"); + if(gSelCards->count() == 1) { + auto waitingDlg = new WaitingDlg(this, tr("GetNtpServer")); + Def_CtrlReqPre + connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg] { + Def_CtrlSingleGetReply + waitingDlg->success(); + fdNtpServer->setText(json["ntpServer"].toString()); + }); + } else { + foreach(auto card, *gSelCards) { + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + auto cardId = card->m_strCardId; + connect(reply, &QNetworkReply::finished, this, [reply, cardId] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(err.isEmpty()) err = json["ntpServer"].toString(); + gFdResInfo->append(cardId+" "+tr("GetNtpServer")+" "+err); + }); + } + } + }); + hhh->addWidget(btnNtpGet); + + vvv->addStretch(); + + hBox->addWidget(groupNTP); + hBox->addStretch(); + + vBox->addStretch(); + + btnNtpSet->setProperty("ssType", "progManageTool"); + btnSyncSet->setProperty("ssType", "progManageTool"); + btnSyncTime->setProperty("ssType", "progManageTool"); + fdSyncGet->setProperty("ssType", "progManageTool"); + btnNtpGet->setProperty("ssType", "progManageTool"); + + btnLoraMasterSet->setProperty("ssType", "progManageTool"); + btnLoraMasterGet->setProperty("ssType", "progManageTool"); + btnDateGet->setProperty("ssType", "progManageTool"); + fdTimeZoneSet->setProperty("ssType", "progManageTool"); + buttonGroup_2->setId(fdMaster, 0); + buttonGroup_2->setId(fdSlave, 1); + + fdIsLora->setChecked(true); + labelIdCode->setVisible(true); + lineEditIdCode->setVisible(true); + labelTimeOffset->setVisible(true); + lineEditTimeOffset->setVisible(true); + lineEdit_3->setVisible(false); + labelSyncTimeInterval->setVisible(false); + labelmintime->setVisible(false); + + //按钮事件绑定 + connect(fdIsGPS,SIGNAL(clicked()),this,SLOT(OnRadioButton())); + connect(fdIsLora,SIGNAL(clicked()),this,SLOT(OnRadioButton2())); + connect(fdIsNTP,SIGNAL(clicked()),this,SLOT(OnRadioButton3())); + connect(fdIsLan,SIGNAL(clicked()),this,SLOT(OnRadioButton6())); + + connect(gDevicePanel, &DevicePanel::sigSelectedDeviceList, this, [this] { + if(isVisible()) init(); + }); + transUi(); +} + +void CtrlVerifyClockPanel::showEvent(QShowEvent *event) { + QWidget::showEvent(event); + init(); +} +void CtrlVerifyClockPanel::init() { + bool isSingle = gSelCards->count()==1; + if(! isSingle) return; + auto card = gSelCards->at(0); + + QJsonObject json; + json.insert("_id", "GetingSyncMethod"); + json.insert("_type", "GetingSyncMethod"); + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + connect(reply, &QNetworkReply::finished, this, [this, reply] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) return; + dealGetSync(json); + }); + + json = QJsonObject(); + json.insert("_id", "GetTimezone"); + json.insert("_type", "GetTimezone"); + reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + connect(reply, &QNetworkReply::finished, this, [this, reply] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) return; + fdTimezone->setCurrentText(json["timezone"].toString()); + }); + + json = QJsonObject(); + json.insert("_id", "GetLanguage"); + json.insert("_type", "GetLanguage"); + reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + connect(reply, &QNetworkReply::finished, this, [this, reply] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) return; + if(json["language"].toInt()==1) fdIsCn->setChecked(true); + else fdIsEn->setChecked(true); + }); +} +void CtrlVerifyClockPanel::changeEvent(QEvent *event) { + QWidget::changeEvent(event); + if(event->type() == QEvent::LanguageChange) transUi(); +} +void CtrlVerifyClockPanel::transUi() { + btnDateGet->setText(tr("Readback")); + btnLangGet->setText(tr("Readback")); + btnLangSet->setText(tr("Set")); + btnLoraMasterGet->setText(tr("Readback")); + btnLoraMasterSet->setText(tr("Set")); + btnNtpGet->setText(tr("Readback")); + btnNtpSet->setText(tr("Set")); + btnSyncTime->setText(tr("Verify to Computer time")); + checkBoxBrightness->setText(tr("Brightness")); + checkBoxScreenSwitch->setText(tr("Screen on/off")); + checkBoxVolume->setText(tr("Volume")); + fdIsLan->setText(tr("LAN")); + fdNtpServer->setPlaceholderText(tr("NTP Server address")); + fdSyncGet->setText(tr("Readback")); + fdTimeZoneSet->setText(tr("Set")); + groupBox->setTitle(tr("Enable Synchronous playing")); + groupBox_5->setTitle(tr("Cur time of controller")); + groupNTP->setTitle(tr("NTP Server")); + label->setText(tr("TimeZone")); + labelIdCode->setText(tr("Identification Code")); + labelNtpServerAddress->setText(tr("NTP Server address")); + labelSyncTimeInterval->setText(tr("Sync time interval")); + labelTimeOffset->setText(tr("Time offset(msec)")); + labelVerifyClockConfiguration->setText(tr("Verify Clock Configuration")); + labelmintime->setText(tr("(min/time)")); + lbLang->setText(tr("Language:")); + lineEditIdCode->setPlaceholderText(tr("identification code")); + lineEdit_3->setPlaceholderText(tr("Sync time interval")); + btnSyncSet->setText(tr("Set")); + fdMaster->setText(tr("Master")); + fdSlave->setText(tr("Slave")); +} +void CtrlVerifyClockPanel::dealGetSync(QJsonDocument &json) { + QString strType = json["time"].toString().toLower(); + if(strType=="serial" || strType=="lan") { + if(strType=="serial") fdIsLora->setChecked(true); + else fdIsLan->setChecked(true); + lineEditIdCode->setText(json["identificationCode"].toString()); + lineEditTimeOffset->setText(QString::number(json["delaySync"].toInt())); + labelIdCode->setVisible(true); + lineEditIdCode->setVisible(true); + labelTimeOffset->setVisible(true); + lineEditTimeOffset->setVisible(true); + lineEdit_3->setVisible(false); + labelSyncTimeInterval->setVisible(false); + labelmintime->setVisible(false); + checkBoxScreenSwitch->setChecked(json["screenSwitch"].toString()!="NONE"); + checkBoxVolume->setChecked(json["volume"].toString()!="NONE"); + checkBoxBrightness->setChecked(json["brightness"].toString()!="NONE"); + checkBoxScreenSwitch->setVisible(true); + checkBoxVolume->setVisible(true); + checkBoxBrightness->setVisible(true); + btnSyncSet->setVisible(true); + fdSyncGet->setVisible(true); + } else if(strType=="ntp") { + fdIsNTP->setChecked(true); + lineEdit_3->setText(QString::number(json["checkNtpTime"].toInt())); + labelIdCode->setVisible(false); + lineEditIdCode->setVisible(false); + labelTimeOffset->setVisible(false); + lineEditTimeOffset->setVisible(false); + lineEdit_3->setVisible(true); + labelSyncTimeInterval->setVisible(true); + labelmintime->setVisible(true); + groupBox_4->setVisible(false); + fdMaster->setVisible(false); + fdSlave->setVisible(false); + btnLoraMasterSet->setVisible(false); + btnLoraMasterGet->setVisible(false); + checkBoxScreenSwitch->setVisible(false); + checkBoxVolume->setVisible(false); + checkBoxBrightness->setVisible(false); + btnSyncSet->setVisible(true); + fdSyncGet->setVisible(true); + } else if(strType=="gps") { + fdIsGPS->setChecked(true); + labelIdCode->setVisible(false); + lineEditIdCode->setVisible(false); + labelTimeOffset->setVisible(false); + lineEditTimeOffset->setVisible(false); + labelSyncTimeInterval->setVisible(false); + lineEdit_3->setVisible(false); + labelmintime->setVisible(false); + groupBox_4->setVisible(false); + fdMaster->setVisible(false); + fdSlave->setVisible(false); + btnLoraMasterSet->setVisible(false); + btnLoraMasterGet->setVisible(false); + checkBoxScreenSwitch->setVisible(false); + checkBoxVolume->setVisible(false); + checkBoxBrightness->setVisible(false); + btnSyncSet->setVisible(true); + fdSyncGet->setVisible(true); + } +} +void CtrlVerifyClockPanel::OnRadioButton()//gps +{ + labelIdCode->setVisible(false); + lineEditIdCode->setVisible(false); + labelTimeOffset->setVisible(false); + lineEditTimeOffset->setVisible(false); + labelSyncTimeInterval->setVisible(false); + lineEdit_3->setVisible(false); + labelmintime->setVisible(false); + groupBox_4->setVisible(false); + fdMaster->setVisible(false); + fdSlave->setVisible(false); + btnLoraMasterSet->setVisible(false); + btnLoraMasterGet->setVisible(false); + checkBoxScreenSwitch->setVisible(false); + checkBoxVolume->setVisible(false); + checkBoxBrightness->setVisible(false); + btnSyncSet->setVisible(true); + fdSyncGet->setVisible(true); +} +void CtrlVerifyClockPanel::OnRadioButton2()//lora +{ + labelIdCode->setVisible(true); + lineEditIdCode->setVisible(true); + labelTimeOffset->setVisible(true); + lineEditTimeOffset->setVisible(true); + lineEdit_3->setVisible(false); + labelSyncTimeInterval->setVisible(false); + labelmintime->setVisible(false); + groupBox_4->setVisible(true); + fdMaster->setVisible(true); + fdSlave->setVisible(true); + btnLoraMasterSet->setVisible(true); + btnLoraMasterGet->setVisible(true); + checkBoxScreenSwitch->setVisible(true); + checkBoxVolume->setVisible(true); + checkBoxBrightness->setVisible(true); + btnSyncSet->setVisible(true); + fdSyncGet->setVisible(true); +} + +void CtrlVerifyClockPanel::OnRadioButton3()//ntp +{ + labelIdCode->setVisible(false); + lineEditIdCode->setVisible(false); + labelTimeOffset->setVisible(false); + lineEditTimeOffset->setVisible(false); + lineEdit_3->setVisible(true); + labelSyncTimeInterval->setVisible(true); + labelmintime->setVisible(true); + groupBox_4->setVisible(false); + fdMaster->setVisible(false); + fdSlave->setVisible(false); + btnLoraMasterSet->setVisible(false); + btnLoraMasterGet->setVisible(false); + checkBoxScreenSwitch->setVisible(false); + checkBoxVolume->setVisible(false); + checkBoxBrightness->setVisible(false); + btnSyncSet->setVisible(true); + fdSyncGet->setVisible(true); +} +void CtrlVerifyClockPanel::OnRadioButton6() { + labelIdCode->setVisible(true); + lineEditIdCode->setVisible(true); + labelTimeOffset->setVisible(true); + lineEditTimeOffset->setVisible(true); + lineEdit_3->setVisible(false); + labelSyncTimeInterval->setVisible(false); + labelmintime->setVisible(false); + groupBox_4->setVisible(true); + fdMaster->setVisible(true); + fdSlave->setVisible(true); + btnLoraMasterSet->setVisible(true); + btnLoraMasterGet->setVisible(true); + checkBoxScreenSwitch->setVisible(true); + checkBoxVolume->setVisible(true); + checkBoxBrightness->setVisible(true); + btnSyncSet->setVisible(true); + fdSyncGet->setVisible(true); +} diff --git a/LedOK/wDevicesManager/ctrlverifyclockpanel.h b/LedOK/device/ctrlverifyclockpanel.h similarity index 95% rename from LedOK/wDevicesManager/ctrlverifyclockpanel.h rename to LedOK/device/ctrlverifyclockpanel.h index 3d4f4c5..135b359 100644 --- a/LedOK/wDevicesManager/ctrlverifyclockpanel.h +++ b/LedOK/device/ctrlverifyclockpanel.h @@ -59,12 +59,12 @@ private: QCheckBox *checkBoxVolume; QCheckBox *checkBoxScreenSwitch; QHBoxLayout *horizontalLayout_7; - QPushButton *pushButtonSetSync; + QPushButton *btnSyncSet; QPushButton *fdSyncGet; QGroupBox *groupBox_4; QHBoxLayout *horizontalLayout_11; - QRadioButton *radioButton_4; - QRadioButton *radioButton_5; + QRadioButton *fdMaster; + QRadioButton *fdSlave; QHBoxLayout *horizontalLayout_12; QPushButton *btnLoraMasterSet; QPushButton *btnLoraMasterGet; diff --git a/LedOK/wDevicesManager/ledcard.cpp b/LedOK/device/ledcard.cpp similarity index 97% rename from LedOK/wDevicesManager/ledcard.cpp rename to LedOK/device/ledcard.cpp index 843dc44..f045a4b 100644 --- a/LedOK/wDevicesManager/ledcard.cpp +++ b/LedOK/device/ledcard.cpp @@ -1,48 +1,48 @@ -#include "ledcard.h" - -LedCard::LedCard(QObject *p) : QObject(p) { - -} - -void LedCard::copyLedCardHTTPGetParam(LedCard *p) -{ - m_strCardId = p->m_strCardId; - m_strCardIp = p->m_strCardIp; - if(p->m_strCardRemarkName!="") - m_strCardRemarkName=p->m_strCardRemarkName; - starterversionName = p->starterversionName ; - starterPort = p->starterPort ; - androidVersion = p->androidVersion ; - iHttpGetId = p->iHttpGetId ; - androidHeight = p->androidHeight ; - androidWidth = p->androidWidth ; - lastActive = p->lastActive ; -} -void LedCard::copyLedCardHTTPPostParam(LedCard *p) -{ - strIMEI =p->strIMEI ; - HardVersion =p->HardVersion ; - BrightnessLevel =p->BrightnessLevel ; - ScreenResolution =p->ScreenResolution ; - FirmwareVersion =p->FirmwareVersion ; -} -bool LedCard::CompareHTTPGetParam(LedCard *p) { - //这里只比较httpGet devicelist打算应答 - if(m_strCardIp!=p->m_strCardIp) return false; - if(m_strCardRemarkName!=p->m_strCardRemarkName) return false; - if(starterversionName!=p->starterversionName) return false; - if(androidVersion!=p->androidVersion) return false; - if(androidWidth!=p->androidWidth) return false; - if(androidHeight!=p->androidHeight) return false; - return true; -} -bool LedCard::CompareHTTPPostParam(LedCard *p) -{ - //这里只比较httpGet devicelist打算应答 - if(strIMEI!=p->strIMEI) return false; - if(HardVersion!=p->HardVersion) return false; - if(BrightnessLevel!=p->BrightnessLevel) return false; - if(ScreenResolution!=p->ScreenResolution) return false; - if(FirmwareVersion!=p->FirmwareVersion) return false; - return true; -} +#include "ledcard.h" + +LedCard::LedCard(QObject *p) : QObject(p) { + +} + +void LedCard::copyLedCardHTTPGetParam(LedCard *p) +{ + m_strCardId = p->m_strCardId; + m_strCardIp = p->m_strCardIp; + if(p->m_strCardRemarkName!="") + m_strCardRemarkName=p->m_strCardRemarkName; + starterversionName = p->starterversionName ; + starterPort = p->starterPort ; + androidVersion = p->androidVersion ; + iHttpGetId = p->iHttpGetId ; + androidHeight = p->androidHeight ; + androidWidth = p->androidWidth ; + lastActive = p->lastActive ; +} +void LedCard::copyLedCardHTTPPostParam(LedCard *p) +{ + strIMEI =p->strIMEI ; + HardVersion =p->HardVersion ; + BrightnessLevel =p->BrightnessLevel ; + ScreenResolution =p->ScreenResolution ; + FirmwareVersion =p->FirmwareVersion ; +} +bool LedCard::CompareHTTPGetParam(LedCard *p) { + //这里只比较httpGet devicelist打算应答 + if(m_strCardIp!=p->m_strCardIp) return false; + if(m_strCardRemarkName!=p->m_strCardRemarkName) return false; + if(starterversionName!=p->starterversionName) return false; + if(androidVersion!=p->androidVersion) return false; + if(androidWidth!=p->androidWidth) return false; + if(androidHeight!=p->androidHeight) return false; + return true; +} +bool LedCard::CompareHTTPPostParam(LedCard *p) +{ + //这里只比较httpGet devicelist打算应答 + if(strIMEI!=p->strIMEI) return false; + if(HardVersion!=p->HardVersion) return false; + if(BrightnessLevel!=p->BrightnessLevel) return false; + if(ScreenResolution!=p->ScreenResolution) return false; + if(FirmwareVersion!=p->FirmwareVersion) return false; + return true; +} diff --git a/LedOK/wDevicesManager/ledcard.h b/LedOK/device/ledcard.h similarity index 91% rename from LedOK/wDevicesManager/ledcard.h rename to LedOK/device/ledcard.h index 34074ae..faefbb4 100644 --- a/LedOK/wDevicesManager/ledcard.h +++ b/LedOK/device/ledcard.h @@ -1,58 +1,60 @@ -#ifndef LEDCARD_H -#define LEDCARD_H - -#include - -class LedCard : public QObject { - Q_OBJECT - Q_PROPERTY(QString strCardId MEMBER m_strCardId NOTIFY CardIdChanged) - Q_PROPERTY(QString strCardIp MEMBER m_strCardIp NOTIFY CardIpChanged) - Q_PROPERTY(qint32 iCardWidth MEMBER m_iWidth NOTIFY WidthChanged) - Q_PROPERTY(qint32 iCardHeight MEMBER m_iHeight NOTIFY HeightChanged) - Q_PROPERTY(QString strCardRemarkName MEMBER m_strCardRemarkName NOTIFY CardRemarkNameChanged) - -public: - LedCard(QObject *p = nullptr); -signals: - void CardIdChanged(const QString &); - void CardIpChanged(const QString &); - void WidthChanged(qint32 t); - void HeightChanged(qint32 t); - void CardRemarkNameChanged(const QString &); -public: - //属性 - QString m_strCardId; - QString m_strCardIp; - qint32 m_iWidth = 0; - qint32 m_iHeight = 0; - QString m_strCardRemarkName = ""; - QString starterversionName = ""; - int starterPort = 0; - QString androidVersion = ""; - int iHttpGetId = 0; - int androidHeight = 0; - //int iCardSystemVersion = 0; - int brightness = 255; - int androidWidth = 0; - int lastActive = 0; - QString strIMEI=""; - QString HardVersion="0000"; - int BrightnessLevel=255; - QString ScreenResolution=""; - QString FirmwareVersion=""; - QString strXixunplayerVersion=""; - int strXixunplayerVersionCode=0; - bool bPassword=false; - void copyLedCardHTTPGetParam(LedCard *p); - void copyLedCardHTTPPostParam(LedCard *p); - bool CompareHTTPGetParam(LedCard *p); - bool CompareHTTPPostParam(LedCard *p); - //状态 - bool m_bLockStatus=true; - bool m_bPowerStatus=true; - bool m_bOnLine=true; - - -}; - -#endif // LEDCARD_H +#ifndef LEDCARD_H +#define LEDCARD_H + +#include +#include +class LedCard : public QObject { + Q_OBJECT + Q_PROPERTY(QString strCardId MEMBER m_strCardId NOTIFY CardIdChanged) + Q_PROPERTY(QString strCardIp MEMBER m_strCardIp NOTIFY CardIpChanged) + Q_PROPERTY(qint32 iCardWidth MEMBER m_iWidth NOTIFY WidthChanged) + Q_PROPERTY(qint32 iCardHeight MEMBER m_iHeight NOTIFY HeightChanged) + Q_PROPERTY(QString strCardRemarkName MEMBER m_strCardRemarkName NOTIFY CardRemarkNameChanged) + +public: + LedCard(QObject *p = nullptr); + ~LedCard(){ + qDebug()<<"~~~~LedCard"; + } +signals: + void CardIdChanged(const QString &); + void CardIpChanged(const QString &); + void WidthChanged(qint32 t); + void HeightChanged(qint32 t); + void CardRemarkNameChanged(const QString &); +public: + //属性 + QString m_strCardId; + QString m_strCardIp; + qint32 m_iWidth = 0; + qint32 m_iHeight = 0; + QString m_strCardRemarkName = ""; + QString starterversionName = ""; + int starterPort = 0; + QString androidVersion = ""; + int iHttpGetId = 0; + int androidHeight = 0; + int bright{100}; + int androidWidth = 0; + int lastActive = 0; + QString strIMEI=""; + QString HardVersion="0000"; + int BrightnessLevel=255; + QString ScreenResolution=""; + QString FirmwareVersion=""; + QString strXixunplayerVersion=""; + int strXixunplayerVersionCode=0; + bool bPassword=false; + void copyLedCardHTTPGetParam(LedCard *p); + void copyLedCardHTTPPostParam(LedCard *p); + bool CompareHTTPGetParam(LedCard *p); + bool CompareHTTPPostParam(LedCard *p); + //状态 + bool m_bLockStatus=true; + bool m_bPowerStatus=true; + bool m_bOnLine=true; + + +}; + +#endif // LEDCARD_H diff --git a/LedOK/wDevicesManager/specialdlg - 副本.cpp b/LedOK/device/specialdlg - 副本.cpp similarity index 97% rename from LedOK/wDevicesManager/specialdlg - 副本.cpp rename to LedOK/device/specialdlg - 副本.cpp index 4e5a1e6..8a6fafd 100644 --- a/LedOK/wDevicesManager/specialdlg - 副本.cpp +++ b/LedOK/device/specialdlg - 副本.cpp @@ -1,75 +1,75 @@ -#include "specialdlg.h" -#include "tools.h" -#include "globaldefine.h" -#include "base/waitingdlg.h" -#include "LoUIClass/qiplineedit.h" -#include -#include - -SpecialDlg::SpecialDlg(QWidget *parent) : QDialog(parent) { - resize(300, 100); - setWindowTitle(tr("Specify IP")); - - auto vBox = new QVBoxLayout(this); - vBox->addStretch(); - - auto hBox = new QHBoxLayout(); - hBox->addStretch(); - - auto label = new QLabel(tr("Specify IP")); - label->setAlignment(Qt::AlignCenter); - hBox->addWidget(label); - - auto fdIP = new QIPLineEdit(); - fdIP->setMinimumWidth(160); - hBox->addWidget(fdIP); - - hBox->addStretch(); - - vBox->addLayout(hBox); - vBox->addStretch(); - - hBox = new QHBoxLayout(); - hBox->addStretch(); - - auto bnSearch = new QPushButton(tr("Search")); - hBox->addWidget(bnSearch); - - auto btnCancel = new QPushButton(tr("Cancel")); - connect(btnCancel, &QPushButton::clicked, this, &QDialog::reject); - hBox->addWidget(btnCancel); - - hBox->addStretch(); - - vBox->addLayout(hBox); - - //绑定信号和槽函数 - connect(bnSearch, &QPushButton::clicked, this, [this, fdIP] { - QString strTempIp = fdIP->text(); - if(strTempIp=="...") { - QMessageBox::warning(gMainWin, tr("Attention"), tr("Please input IP address!")); - return; - } else if(! isTextValid(strTempIp)) { - QMessageBox::warning(gMainWin, tr("Attention"), tr("Your IP Address is Invalid!")); - return; - } - auto waitingDlg = new WaitingDlg(gMainWin, tr("Search")+" ..."); - waitingDlg->show(); - auto reply = Tools::netManager().get(reqForJson("http://"+strTempIp+":3000/deviceList?fromDetector=true")); - //在该ip的3000端口get方法deviceList,可以一次性获取到局域网中设备列表的详细信息 - connect(reply, &QNetworkReply::finished, this, [reply, this, waitingDlg] { - QJsonDocument json; - QString err = parseReplyJson(reply); - if(! err.isEmpty()) { - waitingDlg->close(); - QMessageBox::critical(gMainWin, tr("Error"), err); - return; - } - waitingDlg->success(); - close(); - QStringList keys = json.object().keys(); - qDebug()<<"json size"<parseInfo(json[key].toObject(), ""); - }); - }); -} +#include "specialdlg.h" +#include "tools.h" +#include "globaldefine.h" +#include "base/waitingdlg.h" +#include "LoUIClass/qiplineedit.h" +#include +#include + +SpecialDlg::SpecialDlg(QWidget *parent) : QDialog(parent) { + resize(300, 100); + setWindowTitle(tr("Specify IP")); + + auto vBox = new QVBoxLayout(this); + vBox->addStretch(); + + auto hBox = new QHBoxLayout(); + hBox->addStretch(); + + auto label = new QLabel(tr("Specify IP")); + label->setAlignment(Qt::AlignCenter); + hBox->addWidget(label); + + auto fdIP = new QIPLineEdit(); + fdIP->setMinimumWidth(160); + hBox->addWidget(fdIP); + + hBox->addStretch(); + + vBox->addLayout(hBox); + vBox->addStretch(); + + hBox = new QHBoxLayout(); + hBox->addStretch(); + + auto bnSearch = new QPushButton(tr("Search")); + hBox->addWidget(bnSearch); + + auto btnCancel = new QPushButton(tr("Cancel")); + connect(btnCancel, &QPushButton::clicked, this, &QDialog::reject); + hBox->addWidget(btnCancel); + + hBox->addStretch(); + + vBox->addLayout(hBox); + + //绑定信号和槽函数 + connect(bnSearch, &QPushButton::clicked, this, [this, fdIP] { + QString strTempIp = fdIP->text(); + if(strTempIp=="...") { + QMessageBox::warning(gMainWin, tr("Attention"), tr("Please input IP address!")); + return; + } else if(! isTextValid(strTempIp)) { + QMessageBox::warning(gMainWin, tr("Attention"), tr("Your IP Address is Invalid!")); + return; + } + auto waitingDlg = new WaitingDlg(gMainWin, tr("Search")+" ..."); + waitingDlg->show(); + auto reply = Tools::netManager().get(reqForJson("http://"+strTempIp+":3000/deviceList?fromDetector=true")); + //在该ip的3000端口get方法deviceList,可以一次性获取到局域网中设备列表的详细信息 + connect(reply, &QNetworkReply::finished, this, [reply, this, waitingDlg] { + QJsonDocument json; + QString err = parseReplyJson(reply); + if(! err.isEmpty()) { + waitingDlg->close(); + QMessageBox::critical(gMainWin, tr("Error"), err); + return; + } + waitingDlg->success(); + close(); + QStringList keys = json.object().keys(); + qDebug()<<"json size"<parseInfo(json[key].toObject(), ""); + }); + }); +} diff --git a/LedOK/wDevicesManager/specialdlg - 副本.h b/LedOK/device/specialdlg - 副本.h similarity index 93% rename from LedOK/wDevicesManager/specialdlg - 副本.h rename to LedOK/device/specialdlg - 副本.h index cdafa95..ed8804c 100644 --- a/LedOK/wDevicesManager/specialdlg - 副本.h +++ b/LedOK/device/specialdlg - 副本.h @@ -1,12 +1,12 @@ -#ifndef SPECIALDLG_H -#define SPECIALDLG_H - -#include - -class SpecialDlg : public QDialog { - Q_OBJECT -public: - explicit SpecialDlg(QWidget *); -}; - -#endif // SPECIALDLG_H +#ifndef SPECIALDLG_H +#define SPECIALDLG_H + +#include + +class SpecialDlg : public QDialog { + Q_OBJECT +public: + explicit SpecialDlg(QWidget *); +}; + +#endif // SPECIALDLG_H diff --git a/LedOK/device/upgradeapkdialog.cpp b/LedOK/device/upgradeapkdialog.cpp new file mode 100644 index 0000000..6b85be9 --- /dev/null +++ b/LedOK/device/upgradeapkdialog.cpp @@ -0,0 +1,647 @@ +#include "upgradeapkdialog.h" +#include "gutil/qcore.h" +#include "gutil/qgui.h" +#include "gutil/qnetwork.h" +#include "base/waitingdlg.h" +#include "tools.h" +#include +#include +#include +#include +#include +#include +#include +#include + +UpgradeApkDialog::UpgradeApkDialog(QWidget *parent) : QDialog(parent) { + resize(1280, 720); + setWindowFlag(Qt::WindowMaximizeButtonHint); + setWindowState(Qt::WindowMaximized); + + setWindowTitle(tr("Update APK")); + + auto vBox = new VBox(this); + auto hBox = new HBox(vBox); + + auto btnSelectOnlineApk = new QPushButton(tr("Select Online APK")); + btnSelectOnlineApk->setMinimumSize(QSize(100, 30)); + btnSelectOnlineApk->setProperty("ssType", "progManageTool"); + hBox->addWidget(btnSelectOnlineApk); + + auto btnSelectApk = new QPushButton(tr("Select apk")); + btnSelectApk->setMinimumSize(QSize(100, 30)); + btnSelectApk->setProperty("ssType", "progManageTool"); + hBox->addWidget(btnSelectApk); + + auto btnSelectFpga = new QPushButton(tr("Select Fpga")); + btnSelectFpga->setMinimumSize(QSize(100, 30)); + btnSelectFpga->setProperty("ssType", "progManageTool"); + hBox->addWidget(btnSelectFpga); + + auto fdFileName = new QLabel; + fdFileName->setMinimumSize(200, 30); + fdFileName->setStyleSheet("background-color: #fff;"); + hBox->addWidget(fdFileName); + + connect(btnSelectApk, &QPushButton::clicked, this, [=] { + filePath = QFileDialog::getOpenFileName(this, "Open file", QString(), "apk package (*.apk *.zip)"); + if(filePath.isEmpty()) return; + fileId = ""; + fdFileName->setText(QFileInfo(filePath).fileName()); + }); + connect(btnSelectFpga, &QPushButton::clicked, this, [=] { + filePath = QFileDialog::getOpenFileName(this, "Open File", QString(), "rpd package (*.rpd)"); + if(filePath.isEmpty()) return; + fileId = ""; + fdFileName->setText(QFileInfo(filePath).fileName()); + }); + connect(btnSelectOnlineApk, &QPushButton::clicked, this, [=] { + NetReq req("https://www.ledokcloud.com/aips4/screen/upgrade/getGeneric?type=0&page=1&limit=10"); + req.setRawHeader("token","e183653f716cb150ebf3b4f8a83c95e7"); + auto reply = req.timeout(60000).post(""); + connect(reply, &QNetworkReply::finished, this, [=] { + QJsonDocument json; + auto err = errStrWithData(reply, &json); + if(! err.isEmpty()) { + QMessageBox::critical(this, "Error", err); + return; + } + if(json["code"].toInt()) { + QMessageBox::critical(this, "Error", json["msg"].toString()); + return; + } + auto files = json["page"]["list"].toArray(); + if(files.isEmpty()) { + QMessageBox::critical(this, "Error", tr("No Files")); + return; + } + QDialog dlg(this); + dlg.setWindowFlag(Qt::WindowContextHelpButtonHint, false); + dlg.setWindowTitle(tr("Select Online APK")); + dlg.resize(800, 500); + + auto vBox = new VBox(&dlg); + vBox->setContentsMargins(0,0,0,0); + + auto table = new Table{ + {"name", tr("Name"), 200, QHeaderView::Stretch}, + {"size", tr("Size"), 80}, + {"createTime", tr("Create Time"), 150} + }; + table->setDefs(); + table->setSelectionMode(QAbstractItemView::SingleSelection); + foreach(auto file, files) { + auto rr = table->appendRow(); + table->setText(rr, "name", file["fileName"].toString()+"."+file["suffix"].toString()); + table->setText(rr, "size", byteSizeStr(file["fileSize"].toInt()))->setTextAlignment(AlignRight); + table->setText(rr, "createTime", file["createTime"].toString()); + table->setData(rr, 0, file["fileId"].toString()); + } + connect(table, &Table::cellDoubleClicked, &dlg, [=, &dlg](int row) { + fdFileName->setText(table->text(row, "name")); + fileId = table->data(row, 0).toString(); + filePath = ""; + dlg.accept(); + }); + vBox->addWidget(table); + + auto hBox = new HBox(vBox); + hBox->addStretch(); + + auto btnOk = new QPushButton("确定"); + btnOk->setMinimumWidth(80); + connect(btnOk, &QPushButton::clicked, &dlg, [=, &dlg] { + auto sels = table->selectedRanges(); + if(sels.isEmpty()) { + QMessageBox::warning(&dlg, "Warning", "请选择文件"); + return; + } + auto row = sels[0].topRow(); + fdFileName->setText(table->text(row, "name")); + fileId = table->data(row, 0).toString(); + filePath = ""; + dlg.accept(); + }); + hBox->addWidget(btnOk); + hBox->addStretch(); + + auto btnClose = new QPushButton("关闭"); + btnClose->setMinimumWidth(80); + connect(btnClose, &QPushButton::clicked, &dlg, &QDialog::reject); + hBox->addWidget(btnClose); + hBox->addStretch(); + + dlg.exec(); + }); + }); + + auto btnUpgread = new QPushButton(tr("Upgrade")); + btnUpgread->setMinimumSize(QSize(80, 30)); + btnUpgread->setProperty("ssType", "progManageTool"); + connect(btnUpgread, &QPushButton::clicked, this, [=] { + auto fileName = fdFileName->text(); + if(fileName.length() < 3) return; + int cnt = table->topLevelItemCount(); + QList items; + for(int i=0; itopLevelItem(i)->checkState(0) == Qt::Checked) { + auto item = static_cast(table->topLevelItem(i)); + if(item->isUpdating) { + QMessageBox::information(this, tr("Tip"), tr("Is upgrading now. Please wait")); + return; + } + if(item->mCard->bPassword && item->mCard->m_bLockStatus && item->m_lockFlag) { + item->setResult(tr("This screen is encrypted"), Qt::red); + return; + } + items.append(item); + } + if(items.isEmpty()) { + QMessageBox::information(this, tr("Tip"), tr("NoSelectedController")); + return; + } + QByteArray fileData; + if(! filePath.isEmpty()) { + QFile file(filePath); + if(! file.exists()) return; + if(! file.open(QIODevice::ReadOnly)) return; + fileData = file.readAll(); + file.close(); + } else if(! fileId.isEmpty()) { + auto waitingDlg = new WaitingDlg(this, tr("Downloading Online File")+" ..."); + waitingDlg->show(); + auto reply = NetReq("https://www.ledokcloud.com/aips4/sys/file/download/"+fileId).timeout(120000).get(); + QEventLoop loop; + connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); + connect(reply, &QNetworkReply::downloadProgress, waitingDlg, [=](qint64 bytesReceived, qint64 bytesTotal) { + waitingDlg->fdText->setText(tr("Downloading Online File")+" "+QString::number(bytesReceived*100/bytesTotal)+" %"); + }); + loop.exec(QEventLoop::ExcludeUserInputEvents); + waitingDlg->close(); + auto err = errStr(reply); + fileData = reply->readAll(); + if(! err.isEmpty()) { + if(! fileData.isEmpty()) err += "\n"+fileData; + QMessageBox::critical(this, tr("Error"), err); + return; + } + if(fileData.isEmpty()) { + QMessageBox::critical(this, tr("Error"), tr("Online file is empty")); + return; + } + } + auto nameBytes = fileName.toUtf8(); + auto Boundary = "----QtLedOK_.oOo._"+QUuid::createUuid().toByteArray(QUuid::WithoutBraces); + QByteArray data; + data.append("--").append(Boundary).append("\r\nContent-Disposition: form-data; name=\"username\"\r\n\r\n10005\r\n"); + data.append("--").append(Boundary).append("\r\nContent-Disposition: form-data; name=\"").append(nameBytes).append("\"; filename=\"").append(nameBytes).append("\"\r\n\r\n").append(fileData).append("\r\n"); + data.append("--").append(Boundary).append("--\r\n"); + bool isApk = ! fileName.endsWith(".rpd", Qt::CaseInsensitive); + foreach(auto item, items) { + item->setResult(tr("Uploading")+" ..."); + item->mProgress->setValue(0); + item->isUpdating = true; + NetReq req("http://"+item->mCard->m_strCardIp+":2016/upload?type="+(isApk ? "software":"hardware")); + auto reply = req.timeout(120000).type("multipart/form-data; boundary="+Boundary).post(data); + connect(reply, &QNetworkReply::uploadProgress, item, [item](qint64 bytesSent, qint64 bytesTotal) { + if(bytesTotal<=0) return; + item->mProgress->setValue(bytesSent*100/bytesTotal); + }); + connect(reply, &QNetworkReply::finished, item, [=] { + QString err = errStrWithData(reply); + if(! err.isEmpty()) { + item->setResult(tr("Upload error")+": "+err, Qt::red); + item->isUpdating = false; + return; + } + item->mProgress->setValue(100); + item->setResult(tr("Installing")+" ..."); + QJsonObject json; + if(isApk) { + json.insert("_id", "UpgradeSoftware"); + json.insert("_type", "UpgradeSoftware"); + json.insert("fileName", fileName); + json.insert("isCustom", true); + } else { + json.insert("_id", "SynchronousHardwareVersion"); + json.insert("_type", "SynchronousHardwareVersion"); + } + auto reply = NetReq("http://"+item->mCard->m_strCardIp+":2016/settings").timeout(120000).post(json); + connect(reply, &QNetworkReply::finished, item, [=] { + item->isUpdating = false; + QString err = errStrWithData(reply); + if(! err.isEmpty()) { + item->setResult(tr("Install error")+": "+err, Qt::red); + return; + } + item->setResult(tr("Install success"), Qt::darkGreen); + if(isApk) item->OnCheckSoftVersions(); + else item->OnCheckFpgaVersions(); + }); + }); + } + }); + hBox->addWidget(btnUpgread); + hBox->addStretch(); + + hBox->addWidget(new QLabel("APK:")); + + auto fdApk = new QComboBox; + fdApk->setMinimumWidth(200); + fdApk->setEditable(true); + fdApk->addItem("com.xixun.xixunplayer"); + fdApk->addItem("com.xixun.joey.cardsystem"); + fdApk->addItem("com.xixun.joey.systemcore"); + fdApk->addItem("net.sysolution.taxiapp"); + fdApk->addItem("net.sysolution.starter"); + fdApk->addItem("com.xixun.display"); + fdApk->addItem("com.xixun.xy.conn"); + fdApk->addItem("com.xixun.xy.update"); + fdApk->addItem("net.sysolution.basicapp"); + hBox->addWidget(fdApk); + + auto btnUninstall = new QPushButton(tr("Uninstall")); + btnUninstall->setMinimumSize(80, 30); + btnUninstall->setProperty("ssType", "progManageTool"); + connect(btnUninstall, &QPushButton::clicked, this, [this, fdApk] { + auto strApkName = fdApk->currentText(); + if(strApkName.isEmpty()) { + QMessageBox::information(gMainWin, tr("Tip"), "APK is Empty"); + return; + } + if(! strApkName.endsWith(".xixunplayer") && ! strApkName.endsWith(".taxiapp") && QMessageBox::warning(gMainWin, tr("Reminder"), tr("Reminder: Uninstalling this program may cause the device to offline, cannot be found, lost configs and have a black screen. Please uninstall with caution!")+"\n"+tr("Do you want to continue?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes) return; + int cnt = table->topLevelItemCount(); + for(int i=0; itopLevelItem(i)->checkState(0) == Qt::Checked) { + auto item = static_cast(table->topLevelItem(i)); + item->setResult(tr("Uninstalling")+" ..."); + QJsonObject json; + json.insert("_id", "UninstallSoftware"); + json.insert("_type", "UninstallSoftware"); + json.insert("packageName", strApkName); + auto reply = NetReq("http://"+item->mCard->m_strCardIp+":2016/settings").timeout(120000).post(json); + connect(reply, &QNetworkReply::finished, this, [reply, item, strApkName] { + QString err = errStrWithData(reply); + if(! err.isEmpty()) { + item->setResult(tr("Uninstall error")+": "+err, Qt::red); + return; + } + item->setResult(tr("Uninstall success"), Qt::darkGreen); + }); + } + }); + hBox->addWidget(btnUninstall); + + auto btnCheck = new QPushButton(tr("check running state")); + btnCheck->setMinimumSize(QSize(140, 30)); + btnCheck->setProperty("ssType", "progManageTool"); + connect(btnCheck, &QPushButton::clicked, this, [this, fdApk] { + QString strApkName = fdApk->currentText(); + int cnt = table->topLevelItemCount(); + for(int i=0; itopLevelItem(i)->checkState(0) == Qt::Checked) { + auto item = static_cast(table->topLevelItem(i)); + item->setResult(tr("Check apk running status")); + QJsonObject json; + json.insert("_id", "IsSoftwareRunning"); + json.insert("_type", "IsSoftwareRunning"); + json.insert("packageName", strApkName); + auto reply = NetReq("http://"+item->mCard->m_strCardIp+":2016/settings").timeout(120000).post(json); + connect(reply, &QNetworkReply::finished, this, [reply, item, strApkName] { + QJsonDocument json; + QString err = errStrWithData(reply, &json); + if(! err.isEmpty()) { + item->setResult(tr("Check error")+": "+err, Qt::red); + return; + } + if(json["running"].toBool()) item->setResult(tr("Running"), Qt::darkGreen); + else item->setResult(tr("Not running"), Qt::red); + }); + } + }); + hBox->addWidget(btnCheck); + + + hBox = new HBox(vBox); + auto label = new QLabel; + hBox->addWidget(label); + + hBox->addStretch(); + + auto btnRefresh = new QPushButton(tr("Refresh")); + btnRefresh->setMinimumSize(QSize(0, 30)); + btnRefresh->setProperty("ssType", "progManageTool"); + connect(btnRefresh, &QPushButton::clicked, this, [this, label] { + table->clear(); + table->onCheckAll(false); + int iCount = gDevicePanel->mLedCards.count(); + for(int i=0;imLedCards.at(i)); + label->setText(tr("All")+":"+QString::number(iCount)); + }); + hBox->addWidget(btnRefresh); + + auto txtSearch = new QLineEdit(); + txtSearch->setClearButtonEnabled(true); + txtSearch->setMaximumWidth(200); + txtSearch->addAction(new QAction(QIcon(":/res/program/bnSearch.png"), ""), QLineEdit::LeadingPosition); + connect(txtSearch,SIGNAL(textChanged(const QString &)),this,SLOT(FilterProgram(const QString &))); + hBox->addWidget(txtSearch); + + + table = new LoQTreeWidget(); + table->setProperty("ssType", "topList"); + vBox->addWidget(table); + + hBox = new HBox(vBox); + hBox->addStretch(); + + auto pushButtonCancel = new QPushButton(tr("Cancel")); + pushButtonCancel->setMinimumSize(QSize(0, 30)); + pushButtonCancel->setProperty("ssType", "progManageTool"); + connect(pushButtonCancel, &QPushButton::clicked, this, &UpgradeApkDialog::reject); + hBox->addWidget(pushButtonCancel); + + + m_headerItem = new QTreeWidgetItem(); + for(int i=1; isetTextAlignment(i, Qt::AlignCenter); + m_headerItem->setText(Upgrade_Check, ""); + m_headerItem->setText(Upgrade_SCREEN_ID, tr("Screen ID")); + m_headerItem->setText(Upgrade_ONLINE, tr("Online")); + m_headerItem->setText(Upgrade_SCREEN_IP, tr("Screen IP")); + m_headerItem->setText(Upgrade_ENCRYPT, tr("Security")); + m_headerItem->setText(Upgrade_REMARK_NAME, tr("Remark Name")); + m_headerItem->setText(Upgrade_PROGRESS, tr("Progress")); + m_headerItem->setText(Upgrade_Remark, tr("State")); + m_headerItem->setText(Upgrade_XIXUNPLAYER_VERSION, tr("xixunplayer")); + m_headerItem->setText(Upgrade_CARDSYSTEM_VERSION, tr("cardsystem")); + m_headerItem->setText(Upgrade_STARTER_VERSION, tr("starter")); + m_headerItem->setText(Upgrade_TAXIAPP_VERSION, tr("taxiapp")); + m_headerItem->setText(Upgrade_DISPLAYER_VERSION, tr("displayer")); + m_headerItem->setText(Upgrade_FPAG_VERSION, tr("FPGA")); + m_headerItem->setText(Upgrade_CONNECTION_VERSION, tr("connection")); + m_headerItem->setText(Upgrade_UPDATE_VERSION, tr("update")); + + table->setHeaderItem(m_headerItem); + table->header()->setSectionResizeMode(Upgrade_Check, QHeaderView::Fixed); + table->setColumnWidth(Upgrade_Check, 40); + table->header()->setSectionResizeMode(Upgrade_SCREEN_ID, QHeaderView::ResizeToContents); + table->header()->setSectionResizeMode(Upgrade_ONLINE, QHeaderView::Fixed); + table->setColumnWidth(Upgrade_ONLINE, 40); + table->header()->setSectionResizeMode(Upgrade_SCREEN_IP, QHeaderView::ResizeToContents); + table->header()->setSectionResizeMode(Upgrade_ENCRYPT, QHeaderView::Fixed); + table->setColumnWidth(Upgrade_ENCRYPT, 40); + table->header()->setSectionResizeMode(Upgrade_PROGRESS, QHeaderView::Fixed); + table->setColumnWidth(Upgrade_PROGRESS, 100); + table->header()->setSectionResizeMode(Upgrade_XIXUNPLAYER_VERSION, QHeaderView::ResizeToContents); + table->header()->setSectionResizeMode(Upgrade_CARDSYSTEM_VERSION, QHeaderView::ResizeToContents); + table->header()->setSectionResizeMode(Upgrade_STARTER_VERSION, QHeaderView::ResizeToContents); + table->header()->setSectionResizeMode(Upgrade_TAXIAPP_VERSION, QHeaderView::ResizeToContents); + table->header()->setSectionResizeMode(Upgrade_DISPLAYER_VERSION, QHeaderView::ResizeToContents); + table->header()->setSectionResizeMode(Upgrade_FPAG_VERSION, QHeaderView::Fixed); + table->setColumnWidth(Upgrade_FPAG_VERSION, 100); + table->header()->setSectionResizeMode(Upgrade_Remark, QHeaderView::Stretch); + table->header()->setSectionResizeMode(Upgrade_REMARK_NAME, QHeaderView::ResizeToContents); + table->header()->setSectionResizeMode(Upgrade_CONNECTION_VERSION, QHeaderView::ResizeToContents); + table->header()->setSectionResizeMode(Upgrade_UPDATE_VERSION, QHeaderView::ResizeToContents); + + int iCount = gDevicePanel->mLedCards.count(); + for(int i=0; imLedCards.at(i)); + label->setText(tr("All")+":"+QString::number(iCount)); +} + +void UpgradeApkDialog::onAddLedCard(LedCard *card) { + int iExistFlg=0; + int cnt = table->topLevelItemCount(); + for(int i=0; i(table->topLevelItem(i))->mCard->m_strCardId; + if(strTempCardId == card->m_strCardId) { + iExistFlg=1; + static_cast(table->topLevelItem(i))->SetItemParam(card); + break; + } + } + if(iExistFlg==0) new wUpgradeApkItem(card, table, this); +} + +void UpgradeApkDialog::keyPressEvent(QKeyEvent *ev) { + if(ev->key() == Qt::Key_F3) { + QMessageBox::warning(this, "Tip", tr("The encrypted control card can be upgraded directly")); + int cnt = table->topLevelItemCount(); + for(int i=0; i(table->topLevelItem(i))->m_lockFlag = false; + } +} +void UpgradeApkDialog::FilterProgram(const QString &strtemp) +{ + if (strtemp.isEmpty()) //显示全部 + { + for (int i = 0; i< table->topLevelItemCount(); ++i) + { + QTreeWidgetItem* topItem = table->topLevelItem(i); + table->setRowHidden(i,table->indexFromItem(topItem->parent()),false); + } + } + else + { + QList resultList = table->findItems(strtemp, Qt::MatchContains,Upgrade_SCREEN_ID); //搜索结果 + if (resultList.size() > 0) + { + //QMessageBox::warning(this, "Export", QString(resultList.size())); + for (int i = 0; i< table->topLevelItemCount(); ++i) + { + QTreeWidgetItem* topItem = table->topLevelItem(i); + if (resultList.contains(topItem)) + table->setRowHidden(i,table->indexFromItem(topItem->parent()),false); //显示匹配的结果 + else + table->setRowHidden(i,table->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 + } + } + else { + + QList resultList6 = table->findItems(strtemp, Qt::MatchContains,Upgrade_REMARK_NAME); //搜索结果 + if (resultList6.size() > 0) + { + //QMessageBox::warning(this, "Export", QString(resultList.size())); + for (int i = 0; i< table->topLevelItemCount(); ++i) + { + QTreeWidgetItem* topItem = table->topLevelItem(i); + if (resultList6.contains(topItem)) + table->setRowHidden(i,table->indexFromItem(topItem->parent()),false); //显示匹配的结果 + else + table->setRowHidden(i,table->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 + } + } + else { + + + //QMessageBox::warning(this, "Export", "FilterProgram"); + QList resultList1 = table->findItems(strtemp, Qt::MatchContains,Upgrade_XIXUNPLAYER_VERSION); //搜索结果 + if (resultList1.size() > 0) + { + //QMessageBox::warning(this, "Export", QString(resultList.size())); + for (int i = 0; i< table->topLevelItemCount(); ++i) + { + QTreeWidgetItem* topItem = table->topLevelItem(i); + if (resultList1.contains(topItem)) + table->setRowHidden(i,table->indexFromItem(topItem->parent()),false); //显示匹配的结果 + else + table->setRowHidden(i,table->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 + } + } + else { + QList resultList2 = table->findItems(strtemp, Qt::MatchContains,Upgrade_SCREEN_IP); //搜索结果 + if (resultList2.size() > 0) + { + //QMessageBox::warning(this, "Export", QString(resultList.size())); + for (int i = 0; i< table->topLevelItemCount(); ++i) + { + QTreeWidgetItem* topItem = table->topLevelItem(i); + if (resultList2.contains(topItem)) + table->setRowHidden(i,table->indexFromItem(topItem->parent()),false); //显示匹配的结果 + else + table->setRowHidden(i,table->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 + } + } + else { + QList resultList2 = table->findItems(strtemp, Qt::MatchContains,Upgrade_XIXUNPLAYER_VERSION); //搜索结果 + if (resultList2.size() > 0) + { + //QMessageBox::warning(this, "Export", QString(resultList.size())); + for (int i = 0; i< table->topLevelItemCount(); ++i) + { + QTreeWidgetItem* topItem = table->topLevelItem(i); + if (resultList2.contains(topItem)) + table->setRowHidden(i,table->indexFromItem(topItem->parent()),false); //显示匹配的结果 + else + table->setRowHidden(i,table->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 + } + } + else { + QList resultList2 = table->findItems(strtemp, Qt::MatchContains,Upgrade_CARDSYSTEM_VERSION); //搜索结果 + if (resultList2.size() > 0) + { + //QMessageBox::warning(this, "Export", QString(resultList.size())); + for (int i = 0; i< table->topLevelItemCount(); ++i) + { + QTreeWidgetItem* topItem = table->topLevelItem(i); + if (resultList2.contains(topItem)) + table->setRowHidden(i,table->indexFromItem(topItem->parent()),false); //显示匹配的结果 + else + table->setRowHidden(i,table->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 + } + } + else { + QList resultList2 = table->findItems(strtemp, Qt::MatchContains,Upgrade_TAXIAPP_VERSION); //搜索结果 + if (resultList2.size() > 0) + { + //QMessageBox::warning(this, "Export", QString(resultList.size())); + for (int i = 0; i< table->topLevelItemCount(); ++i) + { + QTreeWidgetItem* topItem = table->topLevelItem(i); + if (resultList2.contains(topItem)) + table->setRowHidden(i,table->indexFromItem(topItem->parent()),false); //显示匹配的结果 + else + table->setRowHidden(i,table->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 + } + } + else { + QList resultList2 = table->findItems(strtemp, Qt::MatchContains,Upgrade_DISPLAYER_VERSION); //搜索结果 + if (resultList2.size() > 0) + { + //QMessageBox::warning(this, "Export", QString(resultList.size())); + for (int i = 0; i< table->topLevelItemCount(); ++i) + { + QTreeWidgetItem* topItem = table->topLevelItem(i); + if (resultList2.contains(topItem)) + table->setRowHidden(i,table->indexFromItem(topItem->parent()),false); //显示匹配的结果 + else + table->setRowHidden(i,table->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 + } + } + else { + QList resultList2 = table->findItems(strtemp, Qt::MatchContains,Upgrade_STARTER_VERSION); //搜索结果 + if (resultList2.size() > 0) + { + //QMessageBox::warning(this, "Export", QString(resultList.size())); + for (int i = 0; i< table->topLevelItemCount(); ++i) + { + QTreeWidgetItem* topItem = table->topLevelItem(i); + if (resultList2.contains(topItem)) + table->setRowHidden(i,table->indexFromItem(topItem->parent()),false); //显示匹配的结果 + else + table->setRowHidden(i,table->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 + } + } + else { + QList resultList2 = table->findItems(strtemp, Qt::MatchContains,Upgrade_CONNECTION_VERSION); //搜索结果 + if (resultList2.size() > 0) + { + //QMessageBox::warning(this, "Export", QString(resultList.size())); + for (int i = 0; i< table->topLevelItemCount(); ++i) + { + QTreeWidgetItem* topItem = table->topLevelItem(i); + if (resultList2.contains(topItem)) + table->setRowHidden(i,table->indexFromItem(topItem->parent()),false); //显示匹配的结果 + else + table->setRowHidden(i,table->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 + } + } + else { + QList resultList2 = table->findItems(strtemp, Qt::MatchContains,Upgrade_UPDATE_VERSION); //搜索结果 + if (resultList2.size() > 0) + { + //QMessageBox::warning(this, "Export", QString(resultList.size())); + for (int i = 0; i< table->topLevelItemCount(); ++i) + { + QTreeWidgetItem* topItem = table->topLevelItem(i); + if (resultList2.contains(topItem)) + table->setRowHidden(i,table->indexFromItem(topItem->parent()),false); //显示匹配的结果 + else + table->setRowHidden(i,table->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 + } + } + else { + QList resultList2 = table->findItems(strtemp, Qt::MatchContains,Upgrade_FPAG_VERSION); //搜索结果 + if (resultList2.size() > 0) + { + //QMessageBox::warning(this, "Export", QString(resultList.size())); + for (int i = 0; i< table->topLevelItemCount(); ++i) + { + QTreeWidgetItem* topItem = table->topLevelItem(i); + if (resultList2.contains(topItem)) + table->setRowHidden(i,table->indexFromItem(topItem->parent()),false); //显示匹配的结果 + else + table->setRowHidden(i,table->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 + } + } + else { + QList resultList2 = table->findItems(strtemp, Qt::MatchContains,Upgrade_Remark); //搜索结果 + if (resultList2.size() > 0) + { + //QMessageBox::warning(this, "Export", QString(resultList.size())); + for (int i = 0; i< table->topLevelItemCount(); ++i) + { + QTreeWidgetItem* topItem = table->topLevelItem(i); + if (resultList2.contains(topItem)) + table->setRowHidden(i,table->indexFromItem(topItem->parent()),false); //显示匹配的结果 + else + table->setRowHidden(i,table->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 + } + } + else { + for (int i = 0; i< table->topLevelItemCount(); ++i) + { + QTreeWidgetItem* topItem = table->topLevelItem(i); + table->setRowHidden(i,table->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } +} diff --git a/LedOK/wDevicesManager/upgradeapkdialog.h b/LedOK/device/upgradeapkdialog.h similarity index 85% rename from LedOK/wDevicesManager/upgradeapkdialog.h rename to LedOK/device/upgradeapkdialog.h index 0ac855b..d5363c3 100644 --- a/LedOK/wDevicesManager/upgradeapkdialog.h +++ b/LedOK/device/upgradeapkdialog.h @@ -1,25 +1,25 @@ -#ifndef UPGRADEAPKDIALOG_H -#define UPGRADEAPKDIALOG_H - -#include -#include -#include "wupgradeapkitem.h" - -class UpgradeApkDialog : public QDialog { - Q_OBJECT -public: - explicit UpgradeApkDialog(QWidget *parent = nullptr); -protected: - virtual void keyPressEvent(QKeyEvent *ev); -protected slots: - void FilterProgram(const QString &strtemp); - -private: - void onAddLedCard(LedCard *p); - - LoQTreeWidget *wDevicePublishList; - QTreeWidgetItem *m_headerItem=nullptr; - QString m_strUrl=""; -}; - -#endif // UpgradeApkDialog_H +#ifndef UPGRADEAPKDIALOG_H +#define UPGRADEAPKDIALOG_H + +#include +#include +#include "wupgradeapkitem.h" + +class UpgradeApkDialog : public QDialog { + Q_OBJECT +public: + explicit UpgradeApkDialog(QWidget *parent = nullptr); + QString filePath, fileId; +protected: + virtual void keyPressEvent(QKeyEvent *ev); +protected slots: + void FilterProgram(const QString &strtemp); + +private: + void onAddLedCard(LedCard *p); + + LoQTreeWidget *table; + QTreeWidgetItem *m_headerItem=nullptr; +}; + +#endif // UpgradeApkDialog_H diff --git a/LedOK/device/wupgradeapkitem.cpp b/LedOK/device/wupgradeapkitem.cpp new file mode 100644 index 0000000..4291ab0 --- /dev/null +++ b/LedOK/device/wupgradeapkitem.cpp @@ -0,0 +1,138 @@ +#include "wupgradeapkitem.h" +#include "tools.h" +#include "base/x_uimsgboxok.h" +#include "passwordindlg.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +wUpgradeApkItem::wUpgradeApkItem(LedCard *pLedCard, LoQTreeWidget *parent, QWidget *pWnd) : QObject(parent), QTreeWidgetItem(UserType), m_parent(parent) { + m_pWnd=pWnd; + mCard=pLedCard; + setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); + setCheckState(0, Qt::Unchecked); + m_parent->addTopLevelItem(this); + m_ImageOnline = new QLabel(); + m_parent->setItemWidget(this, Upgrade_ONLINE, m_ImageOnline); + m_ImageOnline->setAlignment(Qt::AlignCenter); + for(int i=1; isetAlignment(Qt::AlignCenter); + mProgress->setStyleSheet("margin-top:8px; margin-bottom:8px; "); + m_parent->setItemWidget(this, Upgrade_PROGRESS, mProgress); + OnCheckSoftVersions(); + OnCheckFpgaVersions(); +} + +void wUpgradeApkItem::OnCheckFpgaVersions() { + QJsonObject json; + json.insert("_id", "CheckHardwareVersions"); + json.insert("_type", "CheckHardwareVersions"); + auto reply = Tools::netManager().post(reqForJson("http://"+mCard->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + connect(reply, &QNetworkReply::finished, this, [reply, this] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) { + return; + } + QString strBuf; + auto vers = json["versions"].toArray(); + for(int i=0; im_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + connect(reply, &QNetworkReply::finished, this, [reply, this] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) { + return; + } + auto apps = json["apps"].toArray(); + foreach(QJsonValue app, apps) { + QString packageName = app["packageName"].toString(); + QString verName = app["versionName"].toString(); + if(packageName=="com.xixun.xixunplayer") setData(Upgrade_XIXUNPLAYER_VERSION, 0, verName); + else if(packageName=="com.xixun.joey.cardsystem") setData(Upgrade_CARDSYSTEM_VERSION, 0, verName); + else if(packageName=="net.sysolution.starter") setData(Upgrade_STARTER_VERSION, 0, verName); + else if(packageName=="net.sysolution.taxiapp") setData(Upgrade_TAXIAPP_VERSION, 0, verName); + else if(packageName=="com.xixun.display") setData(Upgrade_DISPLAYER_VERSION, 0, verName); + else if(packageName=="com.xixun.xy.conn") setData(Upgrade_CONNECTION_VERSION, 0, verName); + else if(packageName=="com.xixun.xy.update") setData(Upgrade_UPDATE_VERSION, 0, verName); + } + }); +} +void wUpgradeApkItem::onVerifyLockPassword() { + bool ok; + auto pwd = QInputDialog::getText(gMainWin, tr("Input password"), tr("Input password"), QLineEdit::Password, QString(), &ok); + if(! ok) return; + QJsonObject json; + json.insert("_id", "VerifyPassword"); + json.insert("_type", "VerifyPassword"); + json.insert("pwd", pwd); + auto reply = Tools::netManager().post(reqForJson("http://"+mCard->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + connect(reply, &QNetworkReply::finished, this, [reply, this] { + QJsonDocument json; + QString err = checkReplyForJson(reply, &json); + if(! err.isEmpty()) { + QMessageBox::critical(gMainWin, tr("Error"), err); + return; + } + if(json["result"].toBool()) mCard->m_bLockStatus = false; + else { + mCard->m_bLockStatus = true; + QMessageBox::critical(gMainWin, tr("Tip Info"), tr("password is wrong")); + } + SetPasswordItem(mCard); + }); +} +void wUpgradeApkItem::SetPasswordItem(LedCard *p){ + if(p->bPassword) {//加过密 + if(m_bnLock==nullptr){ + m_bnLock = new QPushButton(m_pWnd); + m_bnLock->setStyleSheet("background-color:transparent;"); + m_bnLock->setStyleSheet("margin-left:12px; margin-right:12px;margin-top:12px; margin-bottom:12px;"); + m_parent->setItemWidget(this, Upgrade_ENCRYPT, m_bnLock); + connect(m_bnLock, SIGNAL(clicked()), this, SLOT(onVerifyLockPassword())); + } + if(p->m_bLockStatus) m_bnLock->setIcon(QIcon(":/res/device/Lock.png")); //如果已经验证通过密码显示绿色图标 + else m_bnLock->setIcon(QIcon(":/res/device/UnLock.png")); //如果没有验证显示蓝色锁图标 + m_parent->setItemWidget(this, Upgrade_ENCRYPT, m_bnLock); + } +} +void wUpgradeApkItem::setResult(QString tip, QColor color) { + setText(Upgrade_Remark, tip); + setToolTip(Upgrade_Remark, tip); + setForeground(Upgrade_Remark, color); +} +void wUpgradeApkItem::SetItemParam(LedCard *p) { + setData(Upgrade_SCREEN_ID, 0, p->m_strCardId); + setData(Upgrade_SCREEN_IP, 0, p->m_strCardIp); + mCard->m_strCardId = p->m_strCardId; + mCard->m_strCardIp = p->m_strCardIp; + mCard->m_bOnLine = p->m_bOnLine; + if(mCard->m_bOnLine) m_ImageOnline->setPixmap(QPixmap(mCard->m_bOnLine ? ":/res/device/O_Online.png" : ":/res/device/O_Offline.png")); + SetPasswordItem(mCard); + setData(Upgrade_REMARK_NAME, 0, p->m_strCardRemarkName); + OnCheckSoftVersions(); + OnCheckFpgaVersions(); +} diff --git a/LedOK/device/wupgradeapkitem.h b/LedOK/device/wupgradeapkitem.h new file mode 100644 index 0000000..9e8d71f --- /dev/null +++ b/LedOK/device/wupgradeapkitem.h @@ -0,0 +1,68 @@ +#ifndef WUPGRADEAPKITEM_H +#define WUPGRADEAPKITEM_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class wUpgradeApkItem : public QObject, public QTreeWidgetItem { + Q_OBJECT +public: + explicit wUpgradeApkItem(LedCard *pLedCard, LoQTreeWidget *parent = nullptr,QWidget *pWnd=nullptr); + void SetItemParam(LedCard *p); + void setResult(QString, QColor cr = Qt::blue); + + LedCard *mCard = nullptr; + bool isUpdating{false}; + bool m_lockFlag=true; + QLabel *m_ImageOnline=nullptr; + LoQTreeWidget *m_parent = nullptr; + QWidget *m_pWnd=nullptr; + QProgressBar *mProgress=nullptr; + QPushButton *m_bnLock = nullptr; +signals: + void sigUpgradeSuccess(); + void sigUpgradeFail(); + +public slots: + void onVerifyLockPassword(); + void OnCheckSoftVersions(); + void OnCheckFpgaVersions(); + +private: + void SetPasswordItem(LedCard *p); + void postFileTask(const QString& strUrl, const QString& strFilePath);//需要的数据 +}; +enum ENUM_DEVICE_PUBLISH_HEADERITEM +{ + Upgrade_Check=0, + Upgrade_SCREEN_ID, + Upgrade_ONLINE, + Upgrade_SCREEN_IP, + Upgrade_ENCRYPT, + Upgrade_REMARK_NAME, + Upgrade_PROGRESS, + Upgrade_Remark, + Upgrade_XIXUNPLAYER_VERSION, + Upgrade_CARDSYSTEM_VERSION, + Upgrade_STARTER_VERSION, + Upgrade_TAXIAPP_VERSION, + Upgrade_DISPLAYER_VERSION, + Upgrade_FPAG_VERSION, + Upgrade_CONNECTION_VERSION, + Upgrade_UPDATE_VERSION, + Upgrade_END, +}; + + +#endif // WPROGRAMPUBLISHITEM_H diff --git a/LedOK/devicectrlpanel.cpp b/LedOK/devicectrlpanel.cpp index f166eeb..413e4b4 100644 --- a/LedOK/devicectrlpanel.cpp +++ b/LedOK/devicectrlpanel.cpp @@ -1,146 +1,143 @@ -#include "devicectrlpanel.h" -#include "devicepanel.h" -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -QTextEdit *gFdResInfo; - -DeviceCtrlPanel::DeviceCtrlPanel(DevicePanel *parent) : QWidget(parent), mDevWgt(parent) { - auto vBox = new QVBoxLayout(this); - vBox->setContentsMargins(0,0,0,0); - vBox->setSpacing(0); - - auto hBox = new QHBoxLayout; - hBox->setSpacing(2); - - mBtnGrp = new QButtonGroup(this); - for(int i=0; isizePolicy(); - policy.setHorizontalPolicy(QSizePolicy::Preferred); - btn->setSizePolicy(policy); - btn->setIconSize(QSize(48, 48)); - btn->setCheckable(true); - btn->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); - btn->setProperty("ss", "CtrlTab"); - hBox->addWidget(btn); - mBtnGrp->addButton(btn, i); - } - mBtnGrp->button(Setting_Bright)->setIcon(QIcon(":/res/bnBrightnessAdjustMent_s.png")); - mBtnGrp->button(Setting_PowerControl)->setIcon(QIcon(":/res/bnPowerControl_s.png")); - mBtnGrp->button(Setting_NetCfg)->setIcon(QIcon(":/res/bnNetConfig_s.png")); - mBtnGrp->button(Setting_VerifyClock)->setIcon(QIcon(":/res/bnVerifyClock_s.png")); - mBtnGrp->button(Setting_Encrypt)->setIcon(QIcon(":/res/encrypt.png")); - mBtnGrp->button(Setting_HDMI)->setIcon(QIcon(":/res/Hdmi.png")); - mBtnGrp->button(Setting_Volume)->setIcon(QIcon(":/res/volume.png")); - mBtnGrp->button(Setting_Advanced)->setIcon(QIcon(":/res/AdvParam.png")); - mBtnGrp->button(Setting_Test)->setIcon(QIcon(":/res/test.png")); - - connect(mBtnGrp, &QButtonGroup::idToggled, this, [this](int index, bool checked) { - if(!checked || index==curIndex) return; - curIndex = index; - if(wgts[index]==0) { - if(index==Setting_Bright) wgts[index] = new CtrlBrightPanel(this); - else if(index==Setting_PowerControl) wgts[index] = new ControlPowerWidget(this,m_pLedlist); - else if(index==Setting_NetCfg) wgts[index] = new ControlNetConfigWidget(this,m_pLedlist); - else if(index==Setting_VerifyClock) wgts[index] = new CtrlVerifyClockPanel(this); - else if(index==Setting_Encrypt) wgts[index] = new ControlEncryptWidget(this,m_pLedlist); - else if(index==Setting_HDMI) wgts[index] = new ControlHdmiWidget(this,m_pLedlist); - else if(index==Setting_Volume) wgts[index] = new ControlVolumeWidget(this,m_pLedlist); - else if(index==Setting_Advanced) wgts[index] = new CtrlAdvancedPanel(this,m_pLedlist); - else if(index==Setting_Test) wgts[index] = new ControlTestWidget(this,m_pLedlist); - } - scrollArea->takeWidget(); - scrollArea->setWidget(wgts[index]); - emit sigSwitchIndexChanged(curIndex); - }); - vBox->addLayout(hBox); - - auto line = new QFrame; - line->setFrameShape(QFrame::HLine); - line->setFrameShadow(QFrame::Sunken); - vBox->addWidget(line); - - hBox = new QHBoxLayout(); - - scrollArea = new QScrollArea(); - scrollArea->setWidgetResizable(true); - hBox->addWidget(scrollArea); - - auto vBox2 = new QVBoxLayout(); - - fdInfo = new QTextEdit(); - gFdResInfo = fdInfo; - fdInfo->setReadOnly(true); - fdInfo->setMaximumWidth(360); - vBox2->addWidget(fdInfo); - - btnClear = new QPushButton(tr("Clear")); - btnClear->setMinimumHeight(30); - btnClear->setProperty("ssType", "progManageTool"); - connect(btnClear, &QPushButton::clicked, fdInfo, &QTextEdit::clear); - vBox2->addWidget(btnClear); - - hBox->addLayout(vBox2); - - vBox->addLayout(hBox); - - connect(mDevWgt, &DevicePanel::sigSelectedDeviceList, this, [this](QList *list) { - m_pLedlist = list; - if(m_pLedlist==nullptr) return; - if(m_pLedlist->count()<=1) { - if(m_pLedlist->count()==1) { - m_pLedCard=list->at(0); - mDevWgt->fdCardNumInfo->setText(tr("single screen operation")+"->"+tr("Current Screen")+":"+m_pLedCard->m_strCardId); - } else mDevWgt->fdCardNumInfo->setText(tr("Current Screen")+": "+tr("none")); - fdInfo->hide(); - btnClear->hide(); - } else { - QString strSelectNum = QString::number(m_pLedlist->count()); - mDevWgt->fdCardNumInfo->setText(tr("Multi screen operation")+"->"+tr("selected num")+":"+strSelectNum); - fdInfo->clear(); - fdInfo->show(); - btnClear->show(); - } - }); - - transUi(); - - mBtnGrp->button(0)->setChecked(true); -} - -void DeviceCtrlPanel::changeEvent(QEvent *event) { - QWidget::changeEvent(event); - if(event->type() == QEvent::LanguageChange) transUi(); -} -void DeviceCtrlPanel::transUi() { - mBtnGrp->button(Setting_Bright)->setText(tr("Brightness Adjustment")); - mBtnGrp->button(Setting_PowerControl)->setText(tr("Power Control")); - mBtnGrp->button(Setting_NetCfg)->setText(tr("Net Config")); - mBtnGrp->button(Setting_VerifyClock)->setText(tr("Time Synchronization")); - mBtnGrp->button(Setting_HDMI)->setText(tr("Video source")); - mBtnGrp->button(Setting_Encrypt)->setText(tr("Encrypt")); - mBtnGrp->button(Setting_Advanced)->setText(tr("Advanced parameters")); - mBtnGrp->button(Setting_Volume)->setText(tr("Volume Adjustment")); - mBtnGrp->button(Setting_Test)->setText(tr("Test")); - - if(m_pLedCard!=nullptr) mDevWgt->fdCardNumInfo->setText(tr("single screen operation")+" -> "+tr("Current Screen:")+m_pLedCard->m_strCardId); - else mDevWgt->fdCardNumInfo->setText(tr("Current Screen")+": "+tr("none")); - btnClear->setText(tr("Clear")); -} - -void DeviceCtrlPanel::OnOutputInfo(QString strInfo) { - if(isVisible() && fdInfo->isVisible()) fdInfo->append(strInfo); -} +#include "devicectrlpanel.h" +#include "devicepanel.h" +#include "tools.h" +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QTextEdit *gFdResInfo; + +DeviceCtrlPanel::DeviceCtrlPanel(DevicePanel *parent) : QWidget(parent), mDevWgt(parent) { + auto vBox = new QVBoxLayout(this); + vBox->setContentsMargins(0,0,0,0); + vBox->setSpacing(0); + + auto hBox = new QHBoxLayout; + hBox->setSpacing(2); + + mBtnGrp = new QButtonGroup(this); + for(int i=0; isizePolicy(); + policy.setHorizontalPolicy(QSizePolicy::Preferred); + btn->setSizePolicy(policy); + btn->setIconSize(QSize(48, 48)); + btn->setCheckable(true); + btn->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); + btn->setProperty("ss", "CtrlTab"); + hBox->addWidget(btn); + mBtnGrp->addButton(btn, i); + } + mBtnGrp->button(Setting_Bright)->setIcon(QIcon(":/res/bnBrightnessAdjustMent_s.png")); + mBtnGrp->button(Setting_PowerControl)->setIcon(QIcon(":/res/bnPowerControl_s.png")); + mBtnGrp->button(Setting_NetCfg)->setIcon(QIcon(":/res/bnNetConfig_s.png")); + mBtnGrp->button(Setting_VerifyClock)->setIcon(QIcon(":/res/bnVerifyClock_s.png")); + mBtnGrp->button(Setting_Encrypt)->setIcon(QIcon(":/res/encrypt.png")); + mBtnGrp->button(Setting_HDMI)->setIcon(QIcon(":/res/Hdmi.png")); + mBtnGrp->button(Setting_Volume)->setIcon(QIcon(":/res/volume.png")); + mBtnGrp->button(Setting_Advanced)->setIcon(QIcon(":/res/AdvParam.png")); + mBtnGrp->button(Setting_Test)->setIcon(QIcon(":/res/test.png")); + + connect(mBtnGrp, &QButtonGroup::idToggled, this, [this](int index, bool checked) { + if(!checked || index==curIndex) return; + curIndex = index; + if(wgts[index]==0) { + if(index==Setting_Bright) wgts[index] = new CtrlBrightPanel(this); + else if(index==Setting_PowerControl) wgts[index] = new ControlPowerWidget(this, gSelCards); + else if(index==Setting_NetCfg) wgts[index] = new CtrlNetworkPanel(this); + else if(index==Setting_VerifyClock) wgts[index] = new CtrlVerifyClockPanel(this); + else if(index==Setting_Encrypt) wgts[index] = new CtrlPwdPanel(this); + else if(index==Setting_HDMI) wgts[index] = new CtrlHdmiPanel(this); + else if(index==Setting_Volume) wgts[index] = new ControlVolumeWidget(this, gSelCards); + else if(index==Setting_Advanced) wgts[index] = new CtrlAdvancedPanel(this); + else if(index==Setting_Test) wgts[index] = new ControlTestWidget(this, gSelCards); + } + scrollArea->takeWidget(); + scrollArea->setWidget(wgts[index]); + emit sigSwitchIndexChanged(curIndex); + }); + vBox->addLayout(hBox); + + auto line = new QFrame; + line->setFrameShape(QFrame::HLine); + line->setFrameShadow(QFrame::Sunken); + vBox->addWidget(line); + + hBox = new QHBoxLayout(); + + scrollArea = new QScrollArea(); + scrollArea->setWidgetResizable(true); + hBox->addWidget(scrollArea); + + auto vBox2 = new QVBoxLayout(); + + fdInfo = new QTextEdit(); + gFdResInfo = fdInfo; + fdInfo->setReadOnly(true); + fdInfo->setMaximumWidth(360); + vBox2->addWidget(fdInfo); + + btnClear = new QPushButton(tr("Clear")); + btnClear->setMinimumHeight(30); + btnClear->setProperty("ssType", "progManageTool"); + connect(btnClear, &QPushButton::clicked, fdInfo, &QTextEdit::clear); + vBox2->addWidget(btnClear); + + hBox->addLayout(vBox2); + + vBox->addLayout(hBox); + + connect(mDevWgt, &DevicePanel::sigSelectedDeviceList, this, [this]() { + if(gSelCards->count() < 2) { + if(gSelCards->count()==1) mDevWgt->fdCardNumInfo->setText(tr("Current Screen")+": "+gSelCards->at(0)->m_strCardId); + else mDevWgt->fdCardNumInfo->setText(tr("Current Screen")+": "+tr("none")); + fdInfo->hide(); + btnClear->hide(); + } else { + mDevWgt->fdCardNumInfo->setText(tr("Multi screen operation")+". "+tr("selected num")+": "+QString::number(gSelCards->count())); + fdInfo->clear(); + fdInfo->show(); + btnClear->show(); + } + }); + + transUi(); + + mBtnGrp->button(0)->setChecked(true); +} + +void DeviceCtrlPanel::changeEvent(QEvent *event) { + QWidget::changeEvent(event); + if(event->type() == QEvent::LanguageChange) transUi(); +} +void DeviceCtrlPanel::transUi() { + mBtnGrp->button(Setting_Bright)->setText(tr("Brightness Adjustment")); + mBtnGrp->button(Setting_PowerControl)->setText(tr("Power Control")); + mBtnGrp->button(Setting_NetCfg)->setText(tr("Net Config")); + mBtnGrp->button(Setting_VerifyClock)->setText(tr("Time Sync")); + mBtnGrp->button(Setting_HDMI)->setText(tr("Video source")); + mBtnGrp->button(Setting_Encrypt)->setText(tr("Password")); + mBtnGrp->button(Setting_Advanced)->setText(tr("Advanced")); + mBtnGrp->button(Setting_Volume)->setText(tr("Volume Adj.")); + mBtnGrp->button(Setting_Test)->setText(tr("Test")); + + if(gSelCards->count() < 1) mDevWgt->fdCardNumInfo->setText(tr("Current Screen")+": "+tr("none")); + else if(gSelCards->count()==1) mDevWgt->fdCardNumInfo->setText(tr("Current Screen")+": "+gSelCards->at(0)->m_strCardId); + else mDevWgt->fdCardNumInfo->setText(tr("Multi screen operation")+". "+tr("selected num")+": "+QString::number(gSelCards->count())); + btnClear->setText(tr("Clear")); +} + +void DeviceCtrlPanel::OnOutputInfo(QString strInfo) { + if(isVisible() && fdInfo->isVisible()) fdInfo->append(strInfo); +} diff --git a/LedOK/devicectrlpanel.h b/LedOK/devicectrlpanel.h index a283fbb..60b7a57 100644 --- a/LedOK/devicectrlpanel.h +++ b/LedOK/devicectrlpanel.h @@ -2,7 +2,7 @@ #define DEVICECTRLPANEL_H #include "globaldefine.h" -#include "wDevicesManager/ledcard.h" +#include "device/ledcard.h" #include #include #include @@ -32,8 +32,6 @@ private: QPushButton *btnClear; QWidget *wgts[Setting_End]{}; int curIndex{-1}; - QList *m_pLedlist{0}; - LedCard *m_pLedCard{0}; }; diff --git a/LedOK/deviceitem.cpp b/LedOK/deviceitem.cpp index fef651a..57bcc95 100644 --- a/LedOK/deviceitem.cpp +++ b/LedOK/deviceitem.cpp @@ -11,7 +11,6 @@ #include #include #include -#include "base/updaterdialog.h" #include #include "base/pixbmpshowdialog.h" #include @@ -21,7 +20,7 @@ DeviceItem::DeviceItem(LedCard *pLedCard, LoQTreeWidget *parent,QWidget *pWnd) : QObject(parent), QTreeWidgetItem(UserType), m_parent(parent){ m_pWnd=pWnd; - m_pLedCard=pLedCard; + mCard=pLedCard; pHpptClient = new HpptClient(this); setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); setCheckState(0, Qt::Unchecked); @@ -33,24 +32,24 @@ DeviceItem::DeviceItem(LedCard *pLedCard, LoQTreeWidget *parent,QWidget *pWnd) : m_bnCardDetailInfo->setStyleSheet(R"rrr( QPushButton { border-radius: 4px; - image: url(:/res/DeviceManager/bnDetail.png); + image: url(:/res/device/bnDetail.png); } -QPushButton:hover{background-color: #cccccc;} +QPushButton:hover{background-color: #ccc;} )rrr"); connect(m_bnCardDetailInfo, &QPushButton::clicked, this, [this]{ QString strTip=""; - strTip.append(tr("cur brightness:")).append(QString::number(m_pLedCard->brightness)).append("\r\n"); + strTip.append(tr("cur brightness:")).append(QString::number(mCard->bright)).append("\r\n"); //strTip.append("cardsystem apk version:"+QString::number(m_LedCard.iCardSystemVersion)+"\r\n"); //strTip.append("device apk:"+m_LedCard.starterversionName+"\r\n"); - strTip.append(tr("android version:")).append(m_pLedCard->androidVersion).append("\r\n"); + strTip.append(tr("android version:")).append(mCard->androidVersion).append("\r\n"); //strTip.append(tr("android width:")+QString::number(m_LedCard.androidWidth)+"\r\n"); //strTip.append(tr("android height:")+QString::number(m_LedCard.androidHeight)+"\r\n"); - strTip.append(tr("IMEI:")).append(m_pLedCard->strIMEI).append("\r\n"); - strTip.append(tr("HardWard Version:")).append(m_pLedCard->HardVersion).append("\r\n"); - strTip.append(tr("MAX Brightness level:")).append(QString::number(m_pLedCard->BrightnessLevel)).append("\r\n"); - strTip.append(tr("Android OS Resolution:")).append(m_pLedCard->ScreenResolution).append("\r\n"); - strTip.append(tr("Firmware Version:")).append(m_pLedCard->FirmwareVersion).append("\r\n"); - strTip.append(tr("Player Version:")).append(m_pLedCard->strXixunplayerVersion).append("\r\n"); + strTip.append(tr("IMEI:")).append(mCard->strIMEI).append("\r\n"); + strTip.append(tr("HardWard Version:")).append(mCard->HardVersion).append("\r\n"); + strTip.append(tr("MAX Brightness level:")).append(QString::number(mCard->BrightnessLevel)).append("\r\n"); + strTip.append(tr("Android OS Resolution:")).append(mCard->ScreenResolution).append("\r\n"); + strTip.append(tr("Firmware Version:")).append(mCard->FirmwareVersion).append("\r\n"); + strTip.append(tr("Player Version:")).append(mCard->strXixunplayerVersion).append("\r\n"); QMessageBox::information(gMainWin, tr("Detail Info"), strTip); }); @@ -60,24 +59,24 @@ QPushButton:hover{background-color: #cccccc;} m_bnReadbackPic->setStyleSheet(R"rrr( QPushButton { border-radius: 4px; - image: url(:/res/DeviceManager/deviceReadbackPic.png); + image: url(:/res/device/deviceReadbackPic.png); } -QPushButton:hover{background-color: #cccccc;} +QPushButton:hover{background-color: #ccc;} )rrr"); connect(m_bnReadbackPic, SIGNAL(clicked()), this, SLOT(onReadbackPic())); m_ImageOnline = new QLabel(); - m_pLedCard->m_bOnLine=true; - m_ImageOnline->setPixmap(QPixmap(":/res/DeviceManager/O_Online.png")); - setData(DeviceTable_ID, 0, m_pLedCard->m_strCardId); - setData(DeviceTable_IP, 0, m_pLedCard->m_strCardIp); - setData(DeviceTable_ScreenSize, 0, QString("%1 x %2").arg(m_pLedCard->m_iWidth).arg(m_pLedCard->m_iHeight)); + mCard->m_bOnLine=true; + m_ImageOnline->setPixmap(QPixmap(":/res/device/O_Online.png")); + setData(DeviceTable_ID, 0, mCard->m_strCardId); + setData(DeviceTable_IP, 0, mCard->m_strCardIp); + setData(DeviceTable_ScreenSize, 0, QString("%1 x %2").arg(mCard->m_iWidth).arg(mCard->m_iHeight)); m_parent->setItemWidget(this, DeviceTable_Info, m_bnCardDetailInfo); m_parent->setItemWidget(this, DeviceTable_Screenshot, m_bnReadbackPic); m_parent->setItemWidget(this, DeviceTable_Online, m_ImageOnline); m_ImageOnline->setAlignment(Qt::AlignCenter); - SetPasswordItem(m_pLedCard); + SetPasswordItem(mCard); for(int i=1; i10) { //下线 - m_pLedCard->m_bOnLine=false; - m_ImageOnline->setPixmap(QPixmap(":/res/DeviceManager/O_Offline.png")); + mCard->m_bOnLine=false; + m_ImageOnline->setPixmap(QPixmap(":/res/device/O_Offline.png")); } else { //在线 - m_pLedCard->m_bOnLine=true; - m_ImageOnline->setPixmap(QPixmap(":/res/DeviceManager/O_Online.png")); + mCard->m_bOnLine=true; + m_ImageOnline->setPixmap(QPixmap(":/res/device/O_Online.png")); } }); mHeartbeatTimer.start(60000); @@ -157,7 +156,7 @@ void DeviceItem::OnControlTcpSend(int iProgramIndex) { QTcpSocket *send = new QTcpSocket(); connect(send, SIGNAL(connected()), this, SLOT(connect_sucessful())); connect(send, SIGNAL(error(QAbstractSocket::SocketError)),this, SLOT(show_error(QAbstractSocket::SocketError))); - send->connectToHost(QHostAddress(m_pLedCard->m_strCardIp),31299); + send->connectToHost(QHostAddress(mCard->m_strCardIp),31299); ST_ANSY_PROGRAM_PACKET tempStreadPakcet; tempStreadPakcet.SyncHead[0]=0x7e; @@ -175,8 +174,8 @@ void DeviceItem::OnControlTcpSend(int iProgramIndex) { QByteArray databuf = QByteArray(reinterpret_cast(&tempStreadPakcet), iLenPacket); if(!send->waitForConnected(10000)) //等待连接返回 { - qDebug()<m_strCardIp<<"Connect timeout "; - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("Connect")+":"+tr("timeout")); + qDebug()<m_strCardIp<<"Connect timeout "; + emit sigOutputInfo(mCard->m_strCardId+":"+tr("receive")+"<-"+tr("Connect")+":"+tr("timeout")); send->close(); delete send; return ; @@ -186,7 +185,7 @@ void DeviceItem::OnControlTcpSend(int iProgramIndex) { { send->read(send->bytesAvailable()); qDebug()<<"recv anycast success ack"; - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("Anycast")+":"+tr("success")); + emit sigOutputInfo(mCard->m_strCardId+":"+tr("receive")+"<-"+tr("Anycast")+":"+tr("success")); } send->close(); delete send; @@ -197,23 +196,12 @@ void DeviceItem::HttpPostByTypeJsonObject(QJsonObject json) QJsonDocument doc; doc.setObject(json); QByteArray post_loginArray = doc.toJson(QJsonDocument::Compact); - m_strUrl="http://"+m_pLedCard->m_strCardIp+":2016/settings"; - if(m_pLedCard->m_strCardId.left(2)!="M8"&&m_pLedCard->m_strCardId.left(2)!="m8") + m_strUrl="http://"+mCard->m_strCardIp+":2016/settings"; + if(mCard->m_strCardId.left(2)!="M8" && mCard->m_strCardId.left(2)!="m8") { - if(json["_type"]=="GetAllScreenSizeM80"||json["_type"]=="SetSpecialResolution"||json["_type"]=="GetSpecialResolution"||json["_type"]=="CleanDisplayScreenSize") - { - // pHpptClient->httpPost(m_strUrl,post_loginArray); - - } - else { - pHpptClient->httpPost(m_strUrl,post_loginArray); - } - } - else - { - - pHpptClient->httpPost(m_strUrl,post_loginArray); + if(json["_type"]!="GetAllScreenSizeM80") pHpptClient->httpPost(m_strUrl,post_loginArray); } + else pHpptClient->httpPost(m_strUrl,post_loginArray); } void DeviceItem::HttpGetLedCardWidthHeight() { @@ -230,7 +218,7 @@ void DeviceItem::HttpGetLedCardRemarkName(){ } void DeviceItem::refreshLable(){ - if(m_pLedCard->m_bPowerStatus){ + if(mCard->m_bPowerStatus){ this->setForeground(DeviceTable_Power, Qt::green); setData(DeviceTable_Power, 0, tr("on")); } else { @@ -267,10 +255,10 @@ void DeviceItem::onReadbackPic() { } void DeviceItem::SetPasswordItem(LedCard *p){ if(p->bPassword) {//加过密 - if(p->m_bLockStatus) m_bnLock->setIcon(QIcon(":/res/DeviceManager/Lock.png")); //如果已经验证通过密码显示绿色图标 - else m_bnLock->setIcon(QIcon(":/res/DeviceManager/UnLock.png")); //如果没有验证显示蓝色锁图标 + if(p->m_bLockStatus) m_bnLock->setIcon(QIcon(":/res/device/Lock.png")); //如果已经验证通过密码显示绿色图标 + else m_bnLock->setIcon(QIcon(":/res/device/UnLock.png")); //如果没有验证显示蓝色锁图标 m_parent->setItemWidget(this, DeviceTable_Password, m_bnLock); - } else m_bnLock->setIcon(QIcon(":/res/DeviceManager/Transparent.png")); //显示空白 + } else m_bnLock->setIcon(QIcon()); //显示空白 } //获取到httpPost的应答,如果参数变化需要出发修改控件item的内容 void DeviceItem::OnProHttpResponse(QString url, QString postMD5, QByteArray data) { @@ -295,38 +283,35 @@ void DeviceItem::OnProHttpResponse(QString url, QString postMD5, QByteArray data QString strType=jsonObject["_type"].toString(); if(jsonObject["success"].toBool()==true) { - //alahover 20200521 qDebug()<m_strCardId +"---------"+ strType; if(strType=="GetScreenSize" ) { - if(m_pLedCard->m_iWidth!=jsonObject["width"].toInt()||m_pLedCard->m_iHeight!=jsonObject["height"].toInt()) + if(mCard->m_iWidth!=jsonObject["width"].toInt()||mCard->m_iHeight!=jsonObject["height"].toInt()) { - m_pLedCard->m_iWidth=jsonObject["width"].toInt(); - m_pLedCard->m_iHeight=jsonObject["height"].toInt(); + mCard->m_iWidth=jsonObject["width"].toInt(); + mCard->m_iHeight=jsonObject["height"].toInt(); } - setData(DeviceTable_ScreenSize, 0, QString("%1 x %2").arg(m_pLedCard->m_iWidth).arg(m_pLedCard->m_iHeight)); + setData(DeviceTable_ScreenSize, 0, QString("%1 x %2").arg(mCard->m_iWidth).arg(mCard->m_iHeight)); } else if(strType=="GetCardAlias" ) { - m_pLedCard->m_strCardRemarkName = QString::fromUtf8(QByteArray::fromBase64(jsonObject["alias"].toString().toLatin1())); - setData(DeviceTable_Remark,0,m_pLedCard->m_strCardRemarkName); + mCard->m_strCardRemarkName = QString::fromUtf8(QByteArray::fromBase64(jsonObject["alias"].toString().toLatin1())); + setData(DeviceTable_Remark,0,mCard->m_strCardRemarkName); } else if(strType=="GetCardName") { m_HeartbeatCount=0; - m_pLedCard->m_bOnLine=true; - m_ImageOnline->setPixmap(QPixmap(":/res/DeviceManager/O_Online.png")); + mCard->m_bOnLine=true; + m_ImageOnline->setPixmap(QPixmap(":/res/device/O_Online.png")); } else if(strType=="GetBuildInformation" ) { - m_pLedCard->strIMEI=jsonObject["IMEI"].toString(); - m_pLedCard->HardVersion=jsonObject["HardVersion"].toString(); - m_pLedCard->BrightnessLevel=jsonObject["BrightnessLevel"].toInt(); - m_pLedCard->ScreenResolution=jsonObject["ScreenResolution"].toString(); - m_pLedCard->FirmwareVersion=jsonObject["FirmwareVersion"].toString(); - //if(m_pLedCard->CompareHTTPPostParam()==false) - + mCard->strIMEI=jsonObject["IMEI"].toString(); + mCard->HardVersion=jsonObject["HardVersion"].toString(); + mCard->BrightnessLevel=jsonObject["BrightnessLevel"].toInt(); + mCard->ScreenResolution=jsonObject["ScreenResolution"].toString(); + mCard->FirmwareVersion=jsonObject["FirmwareVersion"].toString(); } else if(strType=="CheckSoftVersions" ) { @@ -335,42 +320,36 @@ void DeviceItem::OnProHttpResponse(QString url, QString postMD5, QByteArray data QJsonObject oApp = value.toObject(); if(oApp["packageName"].toString().contains("xixunplayer")) { - m_pLedCard->strXixunplayerVersion=oApp["versionName"].toString(); - m_pLedCard->strXixunplayerVersionCode=oApp["versionCode"].toInt(); + mCard->strXixunplayerVersion=oApp["versionName"].toString(); + mCard->strXixunplayerVersionCode=oApp["versionCode"].toInt(); } } } else if(strType == "HasControllerPassword") { - //if(m_pLedCard->bPassword!=jsonObject["result"].toBool()) { - m_pLedCard->bPassword=jsonObject["result"].toBool(); - SetPasswordItem(m_pLedCard); + mCard->bPassword=jsonObject["result"].toBool(); + SetPasswordItem(mCard); } } - else if(strType == "SetScreenOn") - { - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("SetScreenOn")+":"+tr("success")); - } else if(strType == "AliIotSetting") { - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("AliIotSetting")+":"+tr("success")); + emit sigOutputInfo(mCard->m_strCardId+":"+tr("receive")+"<-"+tr("AliIotSetting")+":"+tr("success")); } else if(strType == "IsScreenOn") { - //if(m_pLedCard->m_bPowerStatus!=jsonObject["on"].toBool()) { - m_pLedCard->m_bPowerStatus=jsonObject["on"].toBool(); - if(m_pLedCard->m_bPowerStatus) { + mCard->m_bPowerStatus=jsonObject["on"].toBool(); + if(mCard->m_bPowerStatus) { this->setForeground(DeviceTable_Power, Qt::green); setData(DeviceTable_Power, 0, tr("on")); - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("GetScreenStatus")+tr("success")+","+tr("Status")+":"+tr("on")); + emit sigOutputInfo(mCard->m_strCardId+":"+tr("receive")+"<-"+tr("GetScreenStatus")+tr("success")+","+tr("Status")+":"+tr("on")); } else { this->setForeground(DeviceTable_Power, Qt::red); setData(DeviceTable_Power, 0, tr("off")); - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("GetScreenStatus")+tr("success")+","+tr("Status")+":"+tr("off")); + emit sigOutputInfo(mCard->m_strCardId+":"+tr("receive")+"<-"+tr("GetScreenStatus")+tr("success")+","+tr("Status")+":"+tr("off")); } } } @@ -380,140 +359,56 @@ void DeviceItem::OnProHttpResponse(QString url, QString postMD5, QByteArray data if(bStatus)//解密成功 { qDebug()<<"解密成功"; - m_pLedCard->m_bLockStatus=false; + mCard->m_bLockStatus=false; } else { qDebug()<<"解密失败"; X_UIMsgBoxOk *mb = new X_UIMsgBoxOk(tr("Tip Info"),tr("password is wrong"), m_pWnd,0); mb->exec(); - m_pLedCard->m_bLockStatus=true; + mCard->m_bLockStatus=true; } - SetPasswordItem(m_pLedCard); + SetPasswordItem(mCard); } else if(strType == "GetBrightness") { - m_pLedCard->brightness = jsonObject["brightness"].toInt(); - QString bright = QString::number(m_pLedCard->brightness); - setData(DeviceTable_Brightness, 0, QString::number(m_pLedCard->brightness*100/m_pLedCard->BrightnessLevel)+"% ("+bright+")"); - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("GetBrightness")+tr("success")+","+tr("brightness")+"="+bright); - } - else if(strType == "SetBrightness") - { - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("SetBrightness")+":"+tr("success")); - } - else if(strType == "SetBrightnessSensitivity") - { - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("SetBrightnessSensitivity")+tr("success")); - } - else if(strType == "SetMinBrightness") - { - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("SetMinBrightness")+":"+tr("success")); - } - else if(strType == "GetBrightnessSensitivity") - { - int iTemp=jsonObject["sensitivity"].toInt(); - QString strSensitivity=QString::number(iTemp); - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("GetBrightnessSensitivity")+tr("success")+","+tr("sensitivity")+"="+strSensitivity); - } - else if(strType == "GetMinBrightness") - { - int iTemp=jsonObject["brightness"].toInt(); - QString strMinBrightness=QString::number(iTemp); - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("GetMinBrightness")+tr("success")+","+tr("brightness")+"="+strMinBrightness); - } - else if(strType == "SensorBrightnessTable") - { - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("SetSensorBrightnessTable")+":"+tr("success")); - } - else if(strType == "SetSwitchWiFi") - { - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("SetSwitchWiFi")+":"+tr("success")); - } - else if(strType == "ConfigurationWiFi") - { - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("ConfigurationWiFi")+":"+tr("success")); - } - else if(strType == "ConfigurationHotSpot") - { - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("ConfigurationHotSpot")+":"+tr("success")); - } - else if(strType == "GetSwitchWiFi") - { - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("GetSwitchWiFi")+":"+tr("success")); + mCard->bright = jsonObject["brightnessPercentage"].toInt(-1); + if(mCard->bright==-1) mCard->bright = qRound(jsonObject["brightness"].toInt() * 100.0 / mCard->BrightnessLevel); + QString bright = QString::number(mCard->bright); + setData(DeviceTable_Brightness, 0, QString::number(mCard->bright)+"%"); + emit sigOutputInfo(mCard->m_strCardId+":"+tr("receive")+"<-"+tr("GetBrightness")+tr("success")+","+tr("brightness")+"="+bright+"%"); } else if(strType == "SetAutoBrightnessTask") { - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("SetAutoBrightnessTask")+":"+tr("success")); + emit sigOutputInfo(mCard->m_strCardId+":"+tr("receive")+"<-"+tr("SetAutoBrightnessTask")+":"+tr("success")); } else if(strType == "SetAutoVolumeTask") { - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("SetAutoVolumeTask")+":"+tr("success")); + emit sigOutputInfo(mCard->m_strCardId+":"+tr("receive")+"<-"+tr("SetAutoVolumeTask")+":"+tr("success")); } else if(strType == "SetVolume") { - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("SetVolume")+":"+tr("success")); + emit sigOutputInfo(mCard->m_strCardId+":"+tr("receive")+"<-"+tr("SetVolume")+":"+tr("success")); } else if(strType == "GetVolume") { int itempVolume=jsonObject["volume"].toInt(); QString strCurVolume=QString::number(itempVolume); - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("GetVolume")+":"+tr("success")+","+tr("volume")+"="+strCurVolume); + emit sigOutputInfo(mCard->m_strCardId+":"+tr("receive")+"<-"+tr("GetVolume")+":"+tr("success")+","+tr("volume")+"="+strCurVolume); } else if(strType == "SetTimingScreenTask") { - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("SetTimingScreenTask")+":"+tr("success")); - } - else if(strType == "SetHighForBusy") - { - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("SetHighForBusy")+":"+tr("success")); - } - else if(strType == "GetStateForBusy") - { - if(jsonObject["result"].toInt()==0) - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("GetStateForBusy")+":"+tr("Service:Low Out of service:High")); - else - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("GetStateForBusy")+":"+tr("Service:High Out of service:Low")); - } - else if(strType =="UpgradeSoftware") - { - qDebug()<<"slotUploadFinished success ack"; - MACRO_ASKTIME_STOP - MACRO_POSTING_DLG_UNLOCK - - } - else if(strType == "IsPortableHotSpot") - { - QString strWifi=jsonObject["wifi"].toString(); - if(!strWifi.isEmpty()) - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("IsPortableHotSpot")+":"+tr("success")+","+tr("WifiName")+":"+strWifi); - QString strAp=jsonObject["hotSpots"].toString(); - if(!strAp.isEmpty()) - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("IsPortableHotSpot")+":"+tr("success")+","+tr("ApName")+":"+strAp); - if(strWifi.isEmpty()&&strAp.isEmpty()) - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("IsPortableHotSpot")+":"+tr("success")); + emit sigOutputInfo(mCard->m_strCardId+":"+tr("receive")+"<-"+tr("SetTimingScreenTask")+":"+tr("success")); } else if(strType == "TestScreen") { - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("TestScreen")+":"+tr("success")); + emit sigOutputInfo(mCard->m_strCardId+":"+tr("receive")+"<-"+tr("TestScreen")+":"+tr("success")); } else if(strType == "SetOnlineAddr") { - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("SetOnlineAddr")+":"+tr("success")); + emit sigOutputInfo(mCard->m_strCardId+":"+tr("receive")+"<-"+tr("SetOnlineAddr")+":"+tr("success")); } else if(strType == "SetRealtimeServer") { - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("SetRealtimeServer")+":"+tr("success")); - } - else if(strType == "GetOnlineAddr") - { - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("GetOnlineAddr")+":"+jsonObject["server"].toString()+" ID:"+jsonObject["companuID"].toString()); - } - else if(strType == "GetRealtimeServer") - { - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("GetRealtimeServer")+":"+jsonObject["server"].toString()); - } - else if(strType == "DelPrograms") - { - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("DelPrograms")+":"+tr("success")); + emit sigOutputInfo(mCard->m_strCardId+":"+tr("receive")+"<-"+tr("SetRealtimeServer")+":"+tr("success")); } else if(strType == "GetCurrentSensorBrightness") { @@ -529,33 +424,7 @@ void DeviceItem::OnProHttpResponse(QString url, QString postMD5, QByteArray data int iTempValue=jsonObject["value"].toInt(); QString strSensorValue=QString::number(iTempValue); - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("GetCurrentSensorBrightness")+":"+strSensorType+","+tr("Cur brightness")+":"+strSensorValue); - } - else if(strType == "SetSpecialResolution") - { - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("SetSpecialResolution")+":"+tr("success")); - } - else if(strType == "GetSpecialResolution") - { - QString strTotalResolution = jsonObject["totalResolution"].toString(); - QString strCurDisplayResolution = jsonObject["displayResolution"].toString(); - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("GetSpecialResolution")+":"+tr("totalResolution")+"["+strTotalResolution+"],"+tr("strCurDisplayResolution")+"["+strCurDisplayResolution+"]"); - } - else if(strType == "CleanDisplayScreenSize") - { - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("CleanDisplayScreenSize")+":"+tr("success")); - } - else if(strType == "SetMinBrightness") - { - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("SetMinBrightness")+":"+tr("success")); - } - else if(strType == "SetMaxBrightness") - { - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("SetMaxBrightness")+":"+tr("success")); - } - else if(strType == "GetMaxBrightness") - { - emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("GetMaxBrightness")+":"+QString::number(jsonObject["brightness"].toInt())); + emit sigOutputInfo(mCard->m_strCardId+":"+tr("receive")+"<-"+tr("GetCurrentSensorBrightness")+":"+strSensorType+","+tr("Cur brightness")+":"+strSensorValue); } else if(strType == "GetScreenshotFull") { MACRO_ASKTIME_STOP MACRO_POSTING_DLG_UNLOCK @@ -570,18 +439,10 @@ void DeviceItem::OnProHttpResponse(QString url, QString postMD5, QByteArray data //imageresult.loadFromData(Ret_bytearray); PixbmpShowDialog *dlg=new PixbmpShowDialog(m_pWnd); dlg->m_PixMap.loadFromData(Ret_bytearray); - dlg->ResizeByPixmap(m_pLedCard->m_iWidth,m_pLedCard->m_iHeight); + dlg->ResizeByPixmap(mCard->m_iWidth,mCard->m_iHeight); dlg->exec(); } - } else {//失败应答,打印失败和错误信息 - if(strType == "UpgradeSoftware") { - qDebug()<<"slotUploadFinished failed ack"; - MACRO_ASKTIME_STOP - MACRO_POSTING_DLG_UNLOCK - } - emit sigOutputInfo(m_pLedCard->m_strCardId+"<-"+strType+":failed,error:"+jsonObject["error"].toString()); } - } } QPixmap DeviceItem::Base64_To_Image(QByteArray bytearray,QString SavePath) @@ -600,17 +461,6 @@ QPixmap DeviceItem::Base64_To_Image(QByteArray bytearray,QString SavePath) return imageresult; } -void DeviceItem::slotUploadProgress(qint64 A,qint64 B) -{ - if(B!=0) - { - QString strbaifenbi=tr("Uploadding")+":"+QString("%1%").arg(A*100/B); - emit sigSetTipTextContent(strbaifenbi); - m_pGetAskTimer->stop(); - m_pGetAskTimer->start(50000); - } -} - void DeviceItem::DeletePostingDlg() { if(m_PostingDlg!=nullptr) diff --git a/LedOK/deviceitem.h b/LedOK/deviceitem.h index 714aa01..9a66b43 100644 --- a/LedOK/deviceitem.h +++ b/LedOK/deviceitem.h @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include #include @@ -44,11 +44,10 @@ public: void HttpGetLedCardRemarkName(); QPixmap Base64_To_Image(QByteArray bytearray,QString SavePath); - LedCard *m_pLedCard{0}; + LedCard *mCard{0}; QTimer mHeartbeatTimer; signals: void sigOutputInfo(QString); - void sigSetTipTextContent(QString); public slots: void DeletePostingDlg(); @@ -57,7 +56,6 @@ public slots: protected slots: void onReadbackPic(); void onVerifyLockPassword(); - void slotUploadProgress(qint64 A,qint64 B); private: int m_intIndexFlagOfInfoOrControl=0; void SetPasswordItem(LedCard *p); diff --git a/LedOK/devicepanel.cpp b/LedOK/devicepanel.cpp index 800bd77..b52934c 100644 --- a/LedOK/devicepanel.cpp +++ b/LedOK/devicepanel.cpp @@ -1,7 +1,7 @@ #include "devicepanel.h" #include "devicectrlpanel.h" #include "tools.h" -#include "gqt.h" +#include "gutil/qgui.h" #include #include #include @@ -31,7 +31,7 @@ DevicePanel::DevicePanel(QSettings &settings, QWidget *parent) : QWidget(parent) hBox->setSpacing(2); auto label = new QLabel(); - label->setPixmap({":/res/DeviceManager/DeviceNum_All.png"}); + label->setPixmap({":/res/device/DeviceNum_All.png"}); label->setScaledContents(true); label->setFixedSize(33, 24); hBox->addWidget(label); @@ -46,9 +46,16 @@ DevicePanel::DevicePanel(QSettings &settings, QWidget *parent) : QWidget(parent) auto fdSearch = new QLineEdit(); fdSearch->setClearButtonEnabled(true); fdSearch->setFixedSize(220, 30); - fdSearch->addAction(new QAction(QIcon(":/res/ProgramManager/bnSearch.png"), QString()), QLineEdit::LeadingPosition); + fdSearch->addAction(new QAction(QIcon(":/res/program/bnSearch.png"), QString()), QLineEdit::LeadingPosition); fdSearch->setStyleSheet("border: 1px solid #aaaaaa;"); - connect(fdSearch, &QLineEdit::textChanged, this, &DevicePanel::FilterProgram); + connect(fdSearch, &QLineEdit::textChanged, this, [this](const QString &search) { + auto cnt = mDeviceTable->topLevelItemCount(); + if(search.isEmpty()) for(int i=0; itopLevelItem(i)->setHidden(false); + else for(int i=0; itopLevelItem(i); + item->setHidden(! (item->text(DeviceTable_ID).contains(search) || item->text(DeviceTable_Remark).contains(search) || item->text(DeviceTable_IP).contains(search))); + } + }); hBox->addWidget(fdSearch); hBox->addSpacing(10); @@ -80,7 +87,7 @@ QComboBox { } QComboBox:hover {background-color: #08b;} QComboBox::drop-down {width: 25px;} -QComboBox::down-arrow {image: url(:/res/DeviceManager/FlashArrow.png);} +QComboBox::down-arrow {image: url(:/res/device/FlashArrow.png);} QComboBox QAbstractItemView::item { height: 28px; color: #fff; @@ -91,7 +98,7 @@ QComboBox QAbstractItemView::item:selected {background-color: #09c;} btnRefresh = new QPushButton(tr("Refresh"), areaFlash); btnRefresh->setGeometry(0, 0, 75, areaFlash->height()); connect(btnRefresh, &QPushButton::clicked, this, [this] { - LedCardList.clear(); + mLedCards.clear(); mDeviceTable->onCheckAll(false); mDeviceTable->clear(); nDeviceNum->setText("0"); @@ -137,12 +144,12 @@ QPushButton:hover {background-color: #08b;} parseInfo(document.object(), addr); } else { auto bytes = gram.data(); - STREAM_PACKET *pStreamPacket = (STREAM_PACKET *)bytes.data(); + auto packet = (Packet *)bytes.data(); LedCard *pLedCard = new LedCard(this);//alahover 没有释放 - pLedCard->m_strCardId = pStreamPacket->ucSerialCode; + pLedCard->m_strCardId = packet->serialCode; pLedCard->m_strCardIp = addr; - for(int i=0;im_strCardId==pLedCard->m_strCardId ) {//如果已经存在在列表中 - auto pOldLedCard = LedCardList.at(i);//获取到旧的对象指针 + for(int i=0;im_strCardId==pLedCard->m_strCardId ) {//如果已经存在在列表中 + auto pOldLedCard = mLedCards.at(i);//获取到旧的对象指针 pOldLedCard->m_bOnLine = true; if(pOldLedCard->CompareHTTPGetParam(pLedCard)==false) {//如果ip地址变化了 pOldLedCard->copyLedCardHTTPGetParam(pLedCard); @@ -154,7 +161,7 @@ QPushButton:hover {background-color: #08b;} delete pLedCard; return; } - LedCardList.append(pLedCard); + mLedCards.append(pLedCard); addLedCard(pLedCard);//发送信号到界面 } } @@ -164,7 +171,7 @@ QPushButton:hover {background-color: #08b;} for(int i=1; isetTextAlignment(i, Qt::AlignCenter); mDeviceTable->setHeaderItem(m_headerItem); mDeviceTable->header()->setSectionResizeMode(DeviceTable_Check, QHeaderView::Fixed); - mDeviceTable->setColumnWidth(DeviceTable_Check, 48); + mDeviceTable->setColumnWidth(DeviceTable_Check, 36); mDeviceTable->header()->setSectionResizeMode(DeviceTable_Online, QHeaderView::Fixed); mDeviceTable->setColumnWidth(DeviceTable_Online, 48); mDeviceTable->header()->setSectionResizeMode(DeviceTable_ID, QHeaderView::Stretch); @@ -188,7 +195,6 @@ QPushButton:hover {background-color: #08b;} mDeviceTable->hideColumn(0); mDeviceTable->fdIsSelAll->hide(); - specifyIPDlg = new QDialog(this); specifyIPDlg->setWindowTitle(tr("Specify IP")); @@ -246,30 +252,28 @@ DevicePanel::~DevicePanel() { } void DevicePanel::sendGetInfo() { - QByteArray data = QJsonDocument({{"action", "getInfo"}}).toJson(QJsonDocument::Compact); -// if(mUdpSocket.writeDatagram(data, QHostAddress("255.255.255.255"), 22222) != data.length()) { -// qDebug() << "getInfo writeDatagram to 255.255.255.255 Failed"; -// } + const QByteArray data = QJsonDocument({{"action", "getInfo"}}).toJson(QJsonDocument::Compact); + uchar ccc[]{0x7E, 0x7E, 0x7E, 0x90, 0x42, 0x72, 0x6F, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x21, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1C, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x9F}; + if(mUdpSocket.writeDatagram(data, QHostAddress("255.255.255.255"), 22222) != data.length()) qDebug() << "getInfo write to 255.255.255.255 failed"; + if(mUdpSocket.writeDatagram((char *)ccc, sizeof(ccc), QHostAddress("255.255.255.255"), 31296) != sizeof(ccc)) qDebug() << "getInfo write to 255.255.255.255 failed"; QList networkinterfaces = QNetworkInterface::allInterfaces(); foreach(QNetworkInterface face, networkinterfaces) { auto flags = face.flags(); bool can = (flags & QNetworkInterface::IsRunning) && (flags & QNetworkInterface::CanBroadcast) && ! (flags & QNetworkInterface::IsLoopBack); if(! can) continue; - qDebug() << face; auto addrEntries = face.addressEntries(); foreach(QNetworkAddressEntry addrEntry, addrEntries) { auto ip = addrEntry.ip(); if(ip.protocol()!=QAbstractSocket::IPv4Protocol) continue; auto broadcast = addrEntry.broadcast(); - if(mUdpSocket.writeDatagram(data, broadcast, 22222) != data.length()) qDebug() << "getInfo writeDatagram Failed." << ip.toString() << "->" << broadcast.toString(); + if(mUdpSocket.writeDatagram(data, broadcast, 22222) != data.length()) qDebug() << "getInfo write failed." << ip.toString() << "->" << broadcast.toString(); } } auto ipstr = fdIP->toPlainText(); if(! ipstr.isEmpty()) { auto ips = ipstr.split("\n", Qt::SkipEmptyParts); - foreach(auto ip, ips) { - if(gDevicePanel->mUdpSocket.writeDatagram(data, QHostAddress(ip), 22222) != data.length()) qDebug() << "Specify IP write Failed." << ip; - } + foreach(auto ip, ips) if(mUdpSocket.writeDatagram(data, QHostAddress(ip), 22222) != data.length()) qDebug() << "getInfo specify IP write failed." << ip; } } @@ -308,82 +312,21 @@ void DevicePanel::transUi() { bnSpecifyIP->setItemText(0,tr("Specify IP")); label_3->setText(tr("All")); - m_headerItem->setData(DeviceTable_Check, 0, ""); - m_headerItem->setData(DeviceTable_Online, 0, tr("Online")); - m_headerItem->setData(DeviceTable_ID, 0, tr("Screen ID")); - m_headerItem->setData(DeviceTable_IP, 0, tr("Screen IP")); - m_headerItem->setData(DeviceTable_ScreenSize, 0, tr("Screen Size")); - m_headerItem->setData(DeviceTable_Remark, 0, tr("Remark Name")); - m_headerItem->setData(DeviceTable_Screenshot, 0, tr("readback pic")); - m_headerItem->setData(DeviceTable_Brightness, 0, tr("Cur Brightness")); - m_headerItem->setData(DeviceTable_Power, 0, tr("Power Status")); - m_headerItem->setData(DeviceTable_Password, 0, tr("Security")); - m_headerItem->setData(DeviceTable_Info, 0, tr("More Info")); + m_headerItem->setText(DeviceTable_Online, tr("Online")); + m_headerItem->setText(DeviceTable_ID, tr("Screen ID")); + m_headerItem->setText(DeviceTable_IP, tr("Screen IP")); + m_headerItem->setText(DeviceTable_ScreenSize, tr("Screen Size")); + m_headerItem->setText(DeviceTable_Remark, tr("Remark Name")); + m_headerItem->setText(DeviceTable_Screenshot, tr("readback pic")); + m_headerItem->setText(DeviceTable_Brightness, tr("Cur Brightness")); + m_headerItem->setText(DeviceTable_Power, tr("Power Status")); + m_headerItem->setText(DeviceTable_Password, tr("Security")); + m_headerItem->setText(DeviceTable_Info, tr("More Info")); auto cnt = mDeviceTable->topLevelItemCount(); for(int i=0; i(mDeviceTable->topLevelItem(i))->refreshLable(); } -void DevicePanel::FilterProgram(const QString &strtemp){ - if (strtemp.isEmpty()) //显示全部 - { - for (int i = 0; i< mDeviceTable->topLevelItemCount(); ++i){ - QTreeWidgetItem* topItem = mDeviceTable->topLevelItem(i); - mDeviceTable->setRowHidden(i,mDeviceTable->indexFromItem(topItem->parent()),false); - } - } - else - { - QList resultList = mDeviceTable->findItems(strtemp, Qt::MatchContains,DeviceTable_ID); //搜索结果 - if (resultList.size() > 0) - { - for (int i = 0; i< mDeviceTable->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = mDeviceTable->topLevelItem(i); - if (resultList.contains(topItem)) - mDeviceTable->setRowHidden(i,mDeviceTable->indexFromItem(topItem->parent()),false); //显示匹配的结果 - else - mDeviceTable->setRowHidden(i,mDeviceTable->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - else { - QList resultList1 = mDeviceTable->findItems(strtemp, Qt::MatchContains,DeviceTable_Remark); //搜索结果 - if (resultList1.size() > 0) - { - for (int i = 0; i< mDeviceTable->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = mDeviceTable->topLevelItem(i); - if (resultList1.contains(topItem)) - mDeviceTable->setRowHidden(i,mDeviceTable->indexFromItem(topItem->parent()),false); //显示匹配的结果 - else - mDeviceTable->setRowHidden(i,mDeviceTable->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - else { - QList resultList2 = mDeviceTable->findItems(strtemp, Qt::MatchContains,DeviceTable_IP); //搜索结果 - if (resultList2.size() > 0) - { - for (int i = 0; i< mDeviceTable->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = mDeviceTable->topLevelItem(i); - if (resultList2.contains(topItem)) - mDeviceTable->setRowHidden(i,mDeviceTable->indexFromItem(topItem->parent()),false); //显示匹配的结果 - else - mDeviceTable->setRowHidden(i,mDeviceTable->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - else { - for (int i = 0; i< mDeviceTable->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = mDeviceTable->topLevelItem(i); - mDeviceTable->setRowHidden(i,mDeviceTable->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - } - } - } -} - void DevicePanel::OnControlTcpSend(int iProgramIndex){ int cnt = mDeviceTable->topLevelItemCount(); for(int i=0; itopLevelItem(i)->checkState(0) == Qt::Checked) static_cast(mDeviceTable->topLevelItem(i))->OnControlTcpSend(iProgramIndex); @@ -394,7 +337,7 @@ void DevicePanel::OnControlSendJson(QJsonObject &json,QString strFanYi){ for(int i=0; itopLevelItem(i)->checkState(0) == Qt::Checked) { DeviceItem *item = static_cast(mDeviceTable->topLevelItem(i)); item->HttpPostByTypeJsonObject(json); - QString strCardId=item->m_pLedCard->m_strCardId; + QString strCardId=item->mCard->m_strCardId; mDeviceCtrlPanel->OnOutputInfo(strCardId+":"+tr("send")+"->"+strFanYi); } } @@ -405,7 +348,7 @@ int DevicePanel::GetSelectDeviceNum() { mSelCards.clear(); for(int i=0; itopLevelItem(i)->checkState(0) == Qt::Checked) { iSelectCount++; - mSelCards.append(static_cast(mDeviceTable->topLevelItem(i))->m_pLedCard); + mSelCards.append(static_cast(mDeviceTable->topLevelItem(i))->mCard); } return iSelectCount; } @@ -420,28 +363,35 @@ void DevicePanel::onCheckStateChanged(int f){ emit sigSelectedDeviceList(&mSelCards); } } -void DevicePanel::addLedCard(LedCard *p){ +void DevicePanel::addLedCard(LedCard *card) { int cnt = mDeviceTable->topLevelItemCount(); for(int i=0; i(mDeviceTable->topLevelItem(i)); - if(item->m_pLedCard->m_strCardId != p->m_strCardId) continue; - item->setData(DeviceTable_ID, 0, p->m_strCardId); - item->setData(DeviceTable_IP, 0, p->m_strCardIp); - item->setData(DeviceTable_ScreenSize, 0, QString("%1 x %2").arg(p->m_iWidth).arg(p->m_iHeight)); + if(item->mCard->m_strCardId != card->m_strCardId) continue; + item->setData(DeviceTable_ID, 0, card->m_strCardId); + item->setData(DeviceTable_IP, 0, card->m_strCardIp); + item->setData(DeviceTable_ScreenSize, 0, QString("%1 x %2").arg(card->m_iWidth).arg(card->m_iHeight)); return; } - new DeviceItem(p, mDeviceTable, this); + new DeviceItem(card, mDeviceTable, this); nDeviceNum->setText(QString::number(mDeviceTable->topLevelItemCount())); + + QJsonObject json; + json.insert("_id", "SyncTime"); + json.insert("_type", "SyncTime"); + json.insert("time", QDateTime::currentDateTime().toMSecsSinceEpoch()); + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); + connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater); } void DevicePanel::clearUdpHeartbeat(LedCard *p) { int cnt = mDeviceTable->topLevelItemCount(); for(int i=0; i(mDeviceTable->topLevelItem(i)); - if(item->m_pLedCard->m_strCardId != p->m_strCardId) continue; + if(item->mCard->m_strCardId != p->m_strCardId) continue; item->m_HeartbeatCount = 0; if(item->m_ImageOnline) { - item->m_pLedCard->m_bOnLine = true; - item->m_ImageOnline->setPixmap(QPixmap(":/res/DeviceManager/O_Online.png")); + item->mCard->m_bOnLine = true; + item->m_ImageOnline->setPixmap(QPixmap(":/res/device/O_Online.png")); } return; } @@ -465,8 +415,8 @@ void DevicePanel::parseInfo(const QJsonObject &subObj, const QString &strIp) { pLedCard->androidWidth=subObj["androidWidth"].toInt(); pLedCard->lastActive=subObj["lastActive"].toInt(); - for(int i=0;im_strCardId==pLedCard->m_strCardId ) { //如果已经存在在列表中 - auto pOldLedCard = LedCardList.at(i);//获取到旧的对象指针 + for(int i=0;im_strCardId==pLedCard->m_strCardId ) { //如果已经存在在列表中 + auto pOldLedCard = mLedCards.at(i);//获取到旧的对象指针 pOldLedCard->m_bOnLine = true; if(! pOldLedCard->CompareHTTPGetParam(pLedCard)) {//如果ip地址变化了 pOldLedCard->copyLedCardHTTPGetParam(pLedCard); @@ -478,7 +428,7 @@ void DevicePanel::parseInfo(const QJsonObject &subObj, const QString &strIp) { delete pLedCard; return; } - LedCardList.append(pLedCard); + mLedCards.append(pLedCard); addLedCard(pLedCard);//发送信号到界面 } @@ -486,7 +436,7 @@ STREAM_PACKET LedOkMakeStreamPacket(int iComType,int iLen,unsigned char *ucBuf,Q STREAM_PACKET Temp; memset(&Temp, 0, sizeof(STREAM_PACKET)); if(iLen>2048) return Temp; - memset(Temp.SyncHead,STREAM_SYNC_HEAD,STREAM_SYNC_HEAD_NUM); + memset(Temp.SyncHead, 0x7e, 3); memset(Temp.ucSerialCode,0x00,20); char* ch; QByteArray ba = str.toLatin1(); // must @@ -521,11 +471,10 @@ void DevicePanel::RestoreLedCardIpByUdpCmd() { if(strGateway.length()<=20) memcpy(stTempIp.cDns,strGateway.toLatin1().data(),strGateway.length()); STREAM_PACKET tempStreadPacket = LedOkMakeStreamPacket(COMMAND_ONLY_RESET_CARD_IP, 80, (unsigned char *)&stTempIp,"Broadcast!"); - int iLenPacket=tempStreadPacket.iLength+sizeof(int)+STREAM_SYNC_HEAD_NUM*sizeof(unsigned char)+sizeof(char)+20*sizeof(char)+sizeof(char);/////除正文外的协议结构大小; + int iLenPacket=tempStreadPacket.iLength+sizeof(int)+3*sizeof(unsigned char)+sizeof(char)+20*sizeof(char)+sizeof(char);/////除正文外的协议结构大小; QUdpSocket *tempUdpSocket = new QUdpSocket(this); if(!tempUdpSocket->bind(entry.ip())) break; tempUdpSocket->writeDatagram((char *)&tempStreadPacket,iLenPacket,broadcastAddress, 31296); - } } } diff --git a/LedOK/devicepanel.h b/LedOK/devicepanel.h index 85417ec..b7faf99 100644 --- a/LedOK/devicepanel.h +++ b/LedOK/devicepanel.h @@ -32,7 +32,7 @@ public: void clearUdpHeartbeat(LedCard *); void parseInfo(const QJsonObject &subObj,const QString &strIp); void RestoreLedCardIpByUdpCmd(); - QList LedCardList; + QList mLedCards; protected: void changeEvent(QEvent *) override; void transUi(); @@ -40,7 +40,6 @@ public slots: void ShowDevicesInfoOrControlWidget(int index); protected slots: void onCheckStateChanged(int f); - void FilterProgram(const QString &strtemp); void OnControlSendJson(QJsonObject &json,QString strFanYi); void OnControlTcpSend(int iProgramIndex); diff --git a/LedOK/ffplayer.cpp b/LedOK/ffplayer.cpp index 37b2abc..51df954 100644 --- a/LedOK/ffplayer.cpp +++ b/LedOK/ffplayer.cpp @@ -1,642 +1,648 @@ -#include "ffplayer.h" -#include -#include -#if(QT_VERSION_MAJOR > 5) - #include -#endif -#include -#include - -using namespace std; - -AVFmt::AVFmt(QByteArray url) { - fmt_ctx = avformat_alloc_context(); - int res = avformat_open_input(&fmt_ctx, url.constData(), nullptr, nullptr); - if(res < 0) { - err = "Open input fail: "+errStr(res); - return; - } - res = avformat_find_stream_info(fmt_ctx, nullptr); - if(res < 0) { - err = "Find stream info fail: "+errStr(res); - return; - } - start = fmt_ctx->start_time; - qInfo() << "Fmt Start" << start << "Dur" << fmt_ctx->duration; - for(uint ss=0; ssnb_streams; ss++) if(fmt_ctx->streams[ss]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {vi.idx = ss; break;} - for(uint ss=0; ssnb_streams; ss++) if(fmt_ctx->streams[ss]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {au.idx = ss; break;} - if(vi.idx == -1) qWarning()<<"Didn't find a Video Stream"; - else { - auto viStream = fmt_ctx->streams[vi.idx]; - auto decoder = avcodec_find_decoder(viStream->codecpar->codec_id); - if(decoder==0) { - vi.idx = -1; - qInfo()<<"Couldn't found Video Decoder"; - } else { - vi.ctx = avcodec_alloc_context3(decoder); - avcodec_parameters_to_context(vi.ctx, viStream->codecpar); - vi.ctx->thread_count = 0; - if(avcodec_open2(vi.ctx, decoder, nullptr) < 0) { - vi.idx = -1; - qInfo()<<"Couldn't open Video Codec Ctx"; - } else { - sws_ctx = sws_getContext(vi.ctx->width, vi.ctx->height, vi.ctx->pix_fmt, vi.ctx->width, vi.ctx->height, AV_PIX_FMT_RGB32, SWS_FAST_BILINEAR, 0, 0, 0); - if(vi.ctx->color_primaries==AVCOL_PRI_BT2020) { - res = sws_setColorspaceDetails(sws_ctx, sws_getCoefficients(SWS_CS_BT2020), 0, sws_getCoefficients(SWS_CS_DEFAULT), 0, -0x2200, 0x1c000, 0x18000); //0x12800, 0x40000 - qInfo()<<"sws_setColorspaceDetails"<time_base.num * 1000000; - vi.time_den = viStream->time_base.den; - vi.start = viStream->start_time * vi.time_num / vi.time_den; - qInfo()<<"Video Idx" << vi.idx << "Start" << vi.start << "Dur" << viStream->duration * vi.time_num / vi.time_den; - } - } - } - if(au.idx == -1) qInfo()<<"Couldn't find a Audio Stream"; - else { - auto auStream = fmt_ctx->streams[au.idx]; -#if(QT_VERSION_MAJOR > 5) - QAudioDevice audioDevice = QMediaDevices::defaultAudioOutput(); -#else - QAudioDeviceInfo audioDevice = QAudioDeviceInfo::defaultOutputDevice(); -#endif - if(audioDevice.isNull()) { - au.idx = -1; - qInfo()<<"Couldn't find a Audio Device"; - } else { - AVCodecParameters *codecpar = auStream->codecpar; - AVSampleFormat packed_sample_fmt = av_get_packed_sample_fmt((AVSampleFormat)codecpar->format); - qInfo()<<"audio codecpar:"; - qInfo()<<" sample_rate"<sample_rate; - qInfo()<<" frame_size"<frame_size; - qInfo()<<" sample_fmt"<format); - qInfo()<<" bits per coded/raw sample"<bits_per_coded_sample<bits_per_raw_sample; - - sample_rate = codecpar->sample_rate; - QAudioFormat audioFmt; - audioFmt.setSampleRate(sample_rate); - audioFmt.setChannelCount(2); -#if(QT_VERSION_MAJOR > 5) - if(packed_sample_fmt==AV_SAMPLE_FMT_FLT) audioFmt.setSampleFormat(QAudioFormat::Float); - else if(packed_sample_fmt==AV_SAMPLE_FMT_S16) audioFmt.setSampleFormat(QAudioFormat::Int16); - else if(packed_sample_fmt==AV_SAMPLE_FMT_S32) audioFmt.setSampleFormat(QAudioFormat::Int32); - else if(packed_sample_fmt==AV_SAMPLE_FMT_S64) { - packed_sample_fmt = AV_SAMPLE_FMT_S32; - audioFmt.setSampleFormat(QAudioFormat::Int32); - } else if(packed_sample_fmt==AV_SAMPLE_FMT_DBL) { - packed_sample_fmt = AV_SAMPLE_FMT_FLT; - audioFmt.setSampleFormat(QAudioFormat::Float); - } else { - packed_sample_fmt = AV_SAMPLE_FMT_S16; - audioFmt.setSampleFormat(QAudioFormat::Int16); - } -#else - audioFmt.setCodec("audio/pcm"); - audioFmt.setByteOrder(QAudioFormat::LittleEndian); - if(packed_sample_fmt==AV_SAMPLE_FMT_FLT) { - audioFmt.setSampleType(QAudioFormat::Float); - audioFmt.setSampleSize(32); - } else if(packed_sample_fmt==AV_SAMPLE_FMT_S16) { - audioFmt.setSampleType(QAudioFormat::SignedInt); - audioFmt.setSampleSize(16); - } else if(packed_sample_fmt==AV_SAMPLE_FMT_S32) { - audioFmt.setSampleType(QAudioFormat::SignedInt); - audioFmt.setSampleSize(32); - } else if(packed_sample_fmt==AV_SAMPLE_FMT_S64) { - packed_sample_fmt = AV_SAMPLE_FMT_S32; - audioFmt.setSampleType(QAudioFormat::SignedInt); - audioFmt.setSampleSize(32); - } else if(packed_sample_fmt==AV_SAMPLE_FMT_DBL) { - packed_sample_fmt = AV_SAMPLE_FMT_FLT; - audioFmt.setSampleType(QAudioFormat::Float); - audioFmt.setSampleSize(32); - } else { - packed_sample_fmt = AV_SAMPLE_FMT_S16; - audioFmt.setSampleType(QAudioFormat::SignedInt); - audioFmt.setSampleSize(16); - } -#endif - sink = new QAudioSink(audioDevice, audioFmt); - sinkWriter = sink->start(); - if(sinkWriter==nullptr) { - au.idx = -1; - qCritical()<<"Couldn't Start Audio Output"<error(); - } else { - const AVCodec *decoder = avcodec_find_decoder(codecpar->codec_id); - if(decoder==nullptr) { - au.idx = -1; - qWarning()<<"Couldn't found Audio Decoder"; - } else { - au.ctx = avcodec_alloc_context3(decoder); - avcodec_parameters_to_context(au.ctx, codecpar); - if(avcodec_open2(au.ctx, decoder, nullptr) < 0) { - au.idx = -1; - qWarning()<<"Couldn't open aCodecCtx"; - } else { - out_ch_layout.order = AV_CHANNEL_ORDER_NATIVE; - out_ch_layout.nb_channels = 2; - out_ch_layout.u.mask = AV_CH_LAYOUT_STEREO; - swr_alloc_set_opts2(&swr_ctx, - &out_ch_layout, packed_sample_fmt, audioFmt.sampleRate(), - &au.ctx->ch_layout, au.ctx->sample_fmt, au.ctx->sample_rate, 0, nullptr); - if(swr_init(swr_ctx) < 0) { - au.idx = -1; - qCritical()<<"Couldn't init swrCtx"; - } else { - pcm_sample_size = audioFmt.bytesPerFrame(); - au.time_num = auStream->time_base.num * 1000000; - au.time_den = auStream->time_base.den; - au.start = auStream->start_time * au.time_num / au.time_den; - qInfo()<<"Audio Idx" << au.idx << "Start" << au.start<< "Dur" << auStream->duration * au.time_num / au.time_den; - buf_size = sink->bytesFree(); - qInfo()<<"Audio buffer size"< -1) au.thd = new thread(&AVFmt::mainAuDecode, this); - if(vi.idx > -1) vi.thd = new thread(&AVFmt::mainViDecode, this); -} -AVFmt::~AVFmt() { - if(read_thd!=nullptr) { - acts.lockAddNtf(new Act{0, nullptr, 'Q'}); - read_thd->join(); - delete read_thd; - qInfo() << "~ read thread"; - } - if(au.thd!=nullptr) { - au.thd->join(); - delete au.thd; - qInfo() << "~ au thread"; - } - if(vi.thd!=nullptr) { - vi.thd->join(); - delete vi.thd; - qInfo() << "~ vi thread"; - } - av_packet_free(&packet); - avformat_close_input(&fmt_ctx); - sws_freeContext(sws_ctx); - swr_free(&swr_ctx); - qInfo() << "~ AVContext"; -} - -void AVFmt::mainRead() { - int wait = 0; - int res = 0; - while(true) { - auto act = wait==0 ? acts.lockPoll() : acts.take(wait); - while(act!=nullptr) { - if(act->act=='S') { - if(au.idx!=-1) { - unique_lock lock(au.pkts.mtx); - au.pkts.delAll(); - au.pkts.add(new Packet{0, 0, 'R'}); - lock.unlock(); - au.pkts.cv.notify_all(); - } - if(vi.idx!=-1) { - unique_lock lock(vi.pkts.mtx); - vi.pkts.delAll(); - vi.pkts.add(new Packet{0, 0, 'R'}); - lock.unlock(); - vi.pkts.cv.notify_all(); - } - av_seek_frame(fmt_ctx, -1, act->arg, AVSEEK_FLAG_BACKWARD); - } else if(act->act=='Q') { - if(au.idx!=-1) { - unique_lock lock(au.pkts.mtx); - au.pkts.delAll(); - au.pkts.add(new Packet{0, 0, 'Q'}); - lock.unlock(); - au.pkts.cv.notify_all(); - } - if(vi.idx!=-1) { - unique_lock lock(vi.pkts.mtx); - vi.pkts.delAll(); - vi.pkts.add(new Packet{0, 0, 'Q'}); - lock.unlock(); - vi.pkts.cv.notify_all(); - } - delete act; - return; - } - delete act; - act = acts.lockPoll(); - } - if(res < 0) {wait = 500; continue;} - if(vi.pkts.size > 120 || au.pkts.size > 200) {wait = 100; continue;} - res = av_read_frame(fmt_ctx, packet); - if(res < 0) { - if(au.idx > -1) au.pkts.lockAddNtf(new Packet{0, 0, 0}); - if(vi.idx > -1) vi.pkts.lockAddNtf(new Packet{0, 0, 0}); - if(res!=AVERROR_EOF) { - qCritical()<<"Read Packet fail:"<stream_index == vi.idx) { - vi.pkts.lockAddNtf(new Packet{packet, 0, 0}); - packet = av_packet_alloc(); - } else if(packet->stream_index == au.idx) { - au.pkts.lockAddNtf(new Packet{packet, 0, 0}); - packet = av_packet_alloc(); - } - wait = 0; - } -} -void AVFmt::mainViDecode() { - while(true) { - if(vi_frms.size >= 7) { - unique_lock lock(vi.pkts.mtx); - if(vi.pkts.first && vi.pkts.first->act=='Q') return; - vi.pkts.cv.wait_for(lock, chrono::milliseconds(20)); - continue; - } - auto pkt = vi.pkts.take(); - if(pkt->act=='R') { - avcodec_flush_buffers(vi.ctx); - vi.deLoop = 0; - vi.stop = false; - } else if(pkt->act=='Q') { - delete pkt; - return; - } else if(!vi.stop) { - int res = avcodec_send_packet(vi.ctx, pkt->pkt); - if(res == AVERROR_EOF) goto end; - if(res < 0) qCritical()<<"Video send packet fail:"<width, vi.ctx->height, QImage::Format_ARGB32); - uint8_t *dst[4]{img.bits()}; - int dstStride[4]{(int)img.bytesPerLine()}; - sws_scale(sws_ctx, vi.frm->data, vi.frm->linesize, 0, vi.ctx->height, dst, dstStride); - { - lock_guard lock(vi_frms.mtx); - if(vi.stop) goto end; - viLmt = (vi.frm->best_effort_timestamp + vi.frm->pkt_duration) * vi.time_num / vi.time_den; - vi_frms.add(new Img{img, vi.frm->best_effort_timestamp * vi.time_num / vi.time_den, viLmt, vi.deLoop, 0}); - } - } - if(pkt->pkt==0) { - avcodec_flush_buffers(vi.ctx); - vi.deLoop++; - } - } - end: - delete pkt; - } -} -void AVFmt::mainAuDecode() { - while(true) { - if(au_frms.size >= 9) { - unique_lock lock(au.pkts.mtx); - if(au.pkts.first && au.pkts.first->act=='Q') return; - au.pkts.cv.wait_for(lock, chrono::milliseconds(20)); - continue; - } - auto pkt = au.pkts.take(); - if(pkt->act=='R') { - avcodec_flush_buffers(au.ctx); - au.deLoop = 0; - au.stop = false; - } else if(pkt->act=='Q') { - delete pkt; - return; - } else if(!au.stop) { - int res = avcodec_send_packet(au.ctx, pkt->pkt); - if(res == AVERROR_EOF) goto end; - if(res < 0) qCritical()<<"Audio send packet fail:"<nb_samples<=0) continue; - auto pcm = new uint8_t[au.frm->nb_samples * pcm_sample_size]; - int samp_cnt = swr_convert(swr_ctx, &pcm, au.frm->nb_samples, (const uint8_t **)&au.frm->data, au.frm->nb_samples); - if(samp_cnt<=0) { - delete [] pcm; - qWarning()<<"swr convert fail:"< lock(au_frms.mtx); - if(au.stop) { - delete [] pcm; - goto end; - } - au_frms.add(new Pcm{pcm, samp_cnt * pcm_sample_size, au.frm->best_effort_timestamp * au.time_num / au.time_den, (au.frm->best_effort_timestamp + au.frm->pkt_duration) * au.time_num / au.time_den, au.deLoop, 0}); - } - } - if(pkt->pkt==0) { - avcodec_flush_buffers(au.ctx); - au.deLoop++; - } - } - end: - delete pkt; - } -} - -void AVFmt::checkAndUpd(FFPlayer *player, qint64 now_epoch) { - if(vi.isNull()) { - playAudio(au_frms.lockGet(), player, now_epoch); - return; - } - if(au.isNull()) { - player->hasImg = false; - auto viFrm = vi_frms.lockGet(); - if(viFrm==0) return; - if(start_epoch==0) { - if(vi.start > viFrm->st) { - vi.start = viFrm->st; - if(start > viFrm->st) start = viFrm->st; - } - start_epoch = now_epoch - start + 12500; - return; - } - qint64 cur = now_epoch - start_epoch; - checkFrm: - if(viFrm->loop!=playLoop) { - playLoop = viFrm->loop; - start_epoch = now_epoch - start + 12500; - qInfo()<<"Restart"; - return; - } - if(viFrm->et < cur - 8334) { - if(viFrm->next) { - qWarning() << "Drop video frame. st-cur" << (viFrm->st - cur)/1000 << "st" << viFrm->st/1000 << "cur" << cur/1000 << "Video Only"; - viFrm = vi_frms.lockDelGetNext(); - goto checkFrm; - } - qInfo() << "Video Adjust Start. st-cur" << (viFrm->st - cur)/1000 << "st" << viFrm->st/1000 << "cur" << cur/1000 << "Video Only"; - cur = viFrm->st; - start_epoch = now_epoch - cur; - } - if(viFrm->st > cur) return; - player->img = viFrm->img; - player->hasImg = true; - player->viCurTime = viFrm->st; - delete vi_frms.lockPoll(); - return; - } - player->hasImg = false; - auto auFrm = au_frms.lockGet(); - auto viFrm = vi_frms.lockGet(); - if(start_epoch==0) { - if(viFrm==0) { - if(vi.start < start+500000) return; - } else if(vi.start > viFrm->st) { - vi.start = viFrm->st; - if(start > viFrm->st) start = viFrm->st; - } - if(auFrm==0) { - if(au.start < start+500000) return; - } else if(au.start > auFrm->st) { - au.start = auFrm->st; - if(start > auFrm->st) start = auFrm->st; - } - start_epoch = now_epoch - (start - 12500); - playAudio(auFrm, player, now_epoch, vi.pkts.lockGet()==0 ? INT64_MAX : viLmt); - return; - } - if(viFrm==0) { - if(vi.pkts.lockGet()==0) playAudio(auFrm, player, now_epoch); - return; - } - if(viFrm->loop!=playLoop) { - playAudio(auFrm, player, now_epoch); - return; - } - qint64 cur = now_epoch - start_epoch; - if(auFrm && auFrm->st < cur && auFrm->loop==playLoop) { - qInfo() << "Audio Adjust Start. st-cur" << (auFrm->st - cur)/1000 << "st" << auFrm->st/1000 << "cur" << cur/1000; - cur = auFrm->st; - start_epoch = now_epoch - cur; - } - qint64 curPre = cur - 8334; - while(viFrm->et < curPre && viFrm->next && viFrm->next->loop==playLoop) { - qWarning() << "Drop video frame. st-cur" << (viFrm->st - cur)/1000 << "st" << viFrm->st/1000 << "cur" << cur/1000; - viFrm = vi_frms.lockDelGetNext(); - } - auto bytesFree = sink->bytesFree(); - bool isIdle = bytesFree==buf_size || sink->state()==QAudio::IdleState; - if(viFrm->et < curPre) { - if(isIdle) { - qInfo() << "Video Adjust Start. st-cur" << (viFrm->st - cur)/1000 << "st" << viFrm->st/1000 << "cur" << cur/1000; - cur = viFrm->st; - start_epoch = now_epoch - cur; - } else qInfo() << "Video et < cur. st-cur" << (viFrm->st - cur)/1000 << "st" << viFrm->st/1000 << "cur" << cur/1000; - } - if(auFrm && bytesFree >= auFrm->size && auFrm->loop==playLoop) whiteAudio(auFrm, player, isIdle, cur, vi.deLoop!=playLoop || vi.pkts.lockGet()==0 ? INT64_MAX : viLmt); - if(viFrm->st > cur) return; - player->img = viFrm->img; - player->hasImg = true; - player->viCurTime = viFrm->st; - delete vi_frms.lockPoll(); -} -void AVFmt::playAudio(Pcm *auFrm, FFPlayer *player, qint64 now_epoch, qint64 lmt) { - if(auFrm==0) return; - auto bytesFree = sink->bytesFree(); - if(bytesFree < auFrm->size) return; - bool isIdle = bytesFree==buf_size || sink->state()==QAudio::IdleState; - qint64 cur = now_epoch - start_epoch; - if(start_epoch==0) { - if(au.start > auFrm->st) { - au.start = auFrm->st; - if(start > auFrm->st) start = auFrm->st; - } - cur = start - 12500; - start_epoch = now_epoch - cur; - } else if(auFrm->loop!=playLoop) { - if(! isIdle) return; - playLoop = auFrm->loop; - cur = start - 12500; - start_epoch = now_epoch - cur; - qInfo()<<"Restart"; - } - if(auFrm->st < cur) { - qInfo() << "Audio Adjust Start. st-cur" << (auFrm->st - cur)/1000 << "st" << auFrm->st/1000 << "cur" << cur/1000 << "isIdle" << isIdle; - cur = auFrm->st; - start_epoch = now_epoch - cur; - } - whiteAudio(auFrm, player, isIdle, cur, lmt); - return; -} -void AVFmt::whiteAudio(Pcm *auFrm, FFPlayer *player, bool isIdle, qint64 cur, qint64 lmt) { - if(auFrm->st >= lmt) return; - if(isIdle) { - auto delay = auFrm->st - cur; - if(delay > 50000) return; - else if(delay > 999) { - auto size = (delay * sample_rate / 1000000) * pcm_sample_size; - char *data = new char[size](); - sinkWriter->write(data, size); - delete [] data; - } - } - do { - sinkWriter->write((char*)auFrm->data, auFrm->size); - player->auCurTime = auFrm->st; - auFrm = au_frms.lockDelGetNext(); - } while(auFrm && auFrm->data && sink->bytesFree() >= auFrm->size && auFrm->st < lmt); -} - -FFPlayer::FFPlayer() { - thread = new QThread(); - moveToThread(thread); - connect(thread, &QThread::finished, thread, &QThread::deleteLater); - connect(thread, &QThread::finished, this, &FFPlayer::deleteLater); - connect(this, &FFPlayer::emQuit, this, &FFPlayer::onQuit); - connect(this, &FFPlayer::emOpen, this, &FFPlayer::onOpen); - connect(this, &FFPlayer::emClose, this, &FFPlayer::onClose); - connect(this, &FFPlayer::emPlay, this, &FFPlayer::onPlay); - connect(this, &FFPlayer::emPause, this, &FFPlayer::onPause); - connect(this, &FFPlayer::emStop, this, &FFPlayer::onStop); - connect(this, &FFPlayer::emVol, this, &FFPlayer::onVol); - thread->start(); -} -FFPlayer::~FFPlayer() { - qInfo()<<"~ FFPlayer"; -} - -void FFPlayer::onQuit() { - onClose(); - thread->quit(); -} -void FFPlayer::onOpen(QByteArray url) { - onClose(); - ctx = new AVFmt(url); - if(mVol!=1.0 && ctx->sink) ctx->sink->setVolume(mVol); - if(ctx->err.isEmpty()) status = Paused; - else { - qCritical()<err; - emit emError(ctx->err); - delete ctx; - ctx = 0; - } -} -void FFPlayer::onClose() { - status = Closed; - if(audioDaemonTimerId!=0) { - killTimer(audioDaemonTimerId); - audioDaemonTimerId = 0; - } - if(ctx==0) return; - if(ctx->sink) { - ctx->sink->stop(); - delete ctx->sink; - } - delete ctx; - ctx = 0; - emit emUpd(QImage()); -} - -void FFPlayer::onPlay() { - if(ctx==0) return; - status = Playing; - ctx->sink->resume(); - startAudioDaemon(); -} -void FFPlayer::onPause() { - if(ctx==0) return; - status = Paused; - ctx->sink->suspend(); -} -void FFPlayer::onStop() { - if(audioDaemonTimerId!=0) { - killTimer(audioDaemonTimerId); - audioDaemonTimerId = 0; - } - if(ctx==0) return; - if(ctx->sink) { - ctx->sink->stop(); - ctx->sinkWriter = ctx->sink->start(); - } - lock_guard lock(ctx->acts.mtx); - ctx->vi.stop = true; - ctx->au.stop = true; - status = Paused; - ctx->start_epoch = 0; - ctx->playLoop = 0; - ctx->au_frms.lockDelAll(); - ctx->vi_frms.lockDelAll(); - img = QImage(); - ctx->acts.add(new Act{0, 0, 'S'}); - ctx->acts.cv.notify_all(); -} -void FFPlayer::onVol(qreal vol) { - mVol = vol; - if(ctx && ctx->sink) ctx->sink->setVolume(vol); -} - -void FFPlayer::updFrame() { - if(ctx==0) return; - if(status!=Playing) { - if(img.isNull()) { - lock_guard lock(ctx->vi_frms.mtx); - viSize = ctx->vi_frms.size; - auSize = ctx->au_frms.size; - if(ctx->vi_frms.first==0) return; - img = ctx->vi_frms.first->img; - emit emUpd(img); - } - return; - } - auto now_epoch = chrono::duration_cast(chrono::steady_clock::now().time_since_epoch()).count(); - dur = now_epoch - last_epoch; - last_epoch = now_epoch; - if(dur>100000) return; - if(dur<4000) { - qWarning()<<"FFPlayer UpdFrame Fail: dur"<checkAndUpd(this, now_epoch); - viSize = ctx->vi_frms.size; - auSize = ctx->au_frms.size; - if(hasImg) emit emUpd(img); - startAudioDaemon(); - -} -void FFPlayer::timerEvent(QTimerEvent *event) { - if(event->timerId()!=audioDaemonTimerId) return; - if(ctx==0 || status!=Playing) { - if(audioDaemonTimerId!=0) { - killTimer(audioDaemonTimerId); - audioDaemonTimerId = 0; - } - return; - } - auto now_epoch = chrono::duration_cast(chrono::steady_clock::now().time_since_epoch()).count(); - auto dur = now_epoch - last_epoch; - if(dur<=40000 && ! ctx->vi.isNull()) return; - ctx->checkAndUpd(this, now_epoch); - viSize = ctx->vi_frms.size; - auSize = ctx->au_frms.size; - if(hasImg) emit emUpd(img); -} +#include "ffplayer.h" +#include +#include +#if(QT_VERSION_MAJOR > 5) + #include +#endif +#include +#include + +using namespace std; + +AVFmt::AVFmt(QByteArray url) { + fmt_ctx = avformat_alloc_context(); + int res = avformat_open_input(&fmt_ctx, url.constData(), 0, 0); + if(res < 0) { + err = "Open input fail: "+errStr(res); + return; + } + res = avformat_find_stream_info(fmt_ctx, 0); + if(res < 0) { + err = "Find stream info fail: "+errStr(res); + return; + } + start = fmt_ctx->start_time; + qInfo() << "Fmt Start" << start << "Dur" << fmt_ctx->duration; + for(uint ss=0; ssnb_streams; ss++) if(fmt_ctx->streams[ss]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {vi.idx = ss; break;} + for(uint ss=0; ssnb_streams; ss++) if(fmt_ctx->streams[ss]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {au.idx = ss; break;} + if(vi.idx == -1) qWarning()<<"Didn't find a Video Stream"; + else { + auto viStream = fmt_ctx->streams[vi.idx]; + auto decoder = avcodec_find_decoder(viStream->codecpar->codec_id); + if(decoder==0) { + vi.idx = -1; + qCritical()<<"avcodec_find_decoder fail"; + } else { + vi.ctx = avcodec_alloc_context3(decoder); + avcodec_parameters_to_context(vi.ctx, viStream->codecpar); + vi.ctx->thread_count = 0; + if((res = avcodec_open2(vi.ctx, decoder, 0)) < 0) { + vi.idx = -1; + qCritical()<<"avcodec_open2 fail:"<width*4+63)/64*64; + dstStride[3] = dstStride[0] * vi.ctx->height; + sws_ctx = sws_getContext(vi.ctx->width, vi.ctx->height, vi.ctx->pix_fmt, vi.ctx->width, vi.ctx->height, AV_PIX_FMT_RGB32, SWS_FAST_BILINEAR, 0, 0, 0); + if(vi.ctx->color_primaries==AVCOL_PRI_BT2020) { + res = sws_setColorspaceDetails(sws_ctx, sws_getCoefficients(SWS_CS_BT2020), 0, sws_getCoefficients(SWS_CS_DEFAULT), 0, -0x2200, 0x1c000, 0x18000); //0x12800, 0x40000 + if(res < 0) qInfo()<<"sws_setColorspaceDetails fail:"<time_base.num * 1000000; + vi.time_den = viStream->time_base.den; + vi.start = viStream->start_time * vi.time_num / vi.time_den; + frmDur = viStream->r_frame_rate.den * 1000000 / viStream->r_frame_rate.num; + qInfo()<<"Video idx" << vi.idx << "Start" << vi.start << "dur" << viStream->duration * vi.time_num / vi.time_den << "frame dur" << frmDur; + if(frmDur <= 0) frmDur = 16666; + } + } + } + if(au.idx == -1) qInfo()<<"Couldn't find a Audio Stream"; + else { + auto auStream = fmt_ctx->streams[au.idx]; +#if(QT_VERSION_MAJOR > 5) + QAudioDevice audioDevice = QMediaDevices::defaultAudioOutput(); +#else + QAudioDeviceInfo audioDevice = QAudioDeviceInfo::defaultOutputDevice(); +#endif + if(audioDevice.isNull()) { + au.idx = -1; + qInfo()<<"Couldn't find a Audio Device"; + } else { + AVCodecParameters *codecpar = auStream->codecpar; + AVSampleFormat packed_sample_fmt = av_get_packed_sample_fmt((AVSampleFormat)codecpar->format); + qInfo()<<"audio codecpar:"; + qInfo()<<" sample_rate"<sample_rate; + qInfo()<<" frame_size"<frame_size; + qInfo()<<" sample_fmt"<format); + qInfo()<<" bits per coded/raw sample"<bits_per_coded_sample<bits_per_raw_sample; + + sample_rate = codecpar->sample_rate; + QAudioFormat audioFmt; + audioFmt.setSampleRate(sample_rate); + audioFmt.setChannelCount(2); +#if(QT_VERSION_MAJOR > 5) + if(packed_sample_fmt==AV_SAMPLE_FMT_FLT) audioFmt.setSampleFormat(QAudioFormat::Float); + else if(packed_sample_fmt==AV_SAMPLE_FMT_S16) audioFmt.setSampleFormat(QAudioFormat::Int16); + else if(packed_sample_fmt==AV_SAMPLE_FMT_S32) audioFmt.setSampleFormat(QAudioFormat::Int32); + else if(packed_sample_fmt==AV_SAMPLE_FMT_S64) { + packed_sample_fmt = AV_SAMPLE_FMT_S32; + audioFmt.setSampleFormat(QAudioFormat::Int32); + } else if(packed_sample_fmt==AV_SAMPLE_FMT_DBL) { + packed_sample_fmt = AV_SAMPLE_FMT_FLT; + audioFmt.setSampleFormat(QAudioFormat::Float); + } else { + packed_sample_fmt = AV_SAMPLE_FMT_S16; + audioFmt.setSampleFormat(QAudioFormat::Int16); + } +#else + audioFmt.setCodec("audio/pcm"); + audioFmt.setByteOrder(QAudioFormat::LittleEndian); + if(packed_sample_fmt==AV_SAMPLE_FMT_FLT) { + audioFmt.setSampleType(QAudioFormat::Float); + audioFmt.setSampleSize(32); + } else if(packed_sample_fmt==AV_SAMPLE_FMT_S16) { + audioFmt.setSampleType(QAudioFormat::SignedInt); + audioFmt.setSampleSize(16); + } else if(packed_sample_fmt==AV_SAMPLE_FMT_S32) { + audioFmt.setSampleType(QAudioFormat::SignedInt); + audioFmt.setSampleSize(32); + } else if(packed_sample_fmt==AV_SAMPLE_FMT_S64) { + packed_sample_fmt = AV_SAMPLE_FMT_S32; + audioFmt.setSampleType(QAudioFormat::SignedInt); + audioFmt.setSampleSize(32); + } else if(packed_sample_fmt==AV_SAMPLE_FMT_DBL) { + packed_sample_fmt = AV_SAMPLE_FMT_FLT; + audioFmt.setSampleType(QAudioFormat::Float); + audioFmt.setSampleSize(32); + } else { + packed_sample_fmt = AV_SAMPLE_FMT_S16; + audioFmt.setSampleType(QAudioFormat::SignedInt); + audioFmt.setSampleSize(16); + } +#endif + sink = new QAudioSink(audioDevice, audioFmt); + sinkWriter = sink->start(); + if(sinkWriter==nullptr) { + au.idx = -1; + qCritical()<<"Couldn't Start Audio Output"<error(); + } else { + const AVCodec *decoder = avcodec_find_decoder(codecpar->codec_id); + if(decoder==nullptr) { + au.idx = -1; + qWarning()<<"Couldn't found Audio Decoder"; + } else { + au.ctx = avcodec_alloc_context3(decoder); + avcodec_parameters_to_context(au.ctx, codecpar); + if(avcodec_open2(au.ctx, decoder, nullptr) < 0) { + au.idx = -1; + qWarning()<<"Couldn't open aCodecCtx"; + } else { + #if(QT_VERSION_MAJOR < 6) + out_ch_layout.order = AV_CHANNEL_ORDER_NATIVE; + out_ch_layout.nb_channels = 2; + out_ch_layout.u.mask = AV_CH_LAYOUT_STEREO; + #endif + swr_alloc_set_opts2(&swr_ctx, + &out_ch_layout, packed_sample_fmt, audioFmt.sampleRate(), + &au.ctx->ch_layout, au.ctx->sample_fmt, au.ctx->sample_rate, 0, nullptr); + if(swr_init(swr_ctx) < 0) { + au.idx = -1; + qCritical()<<"Couldn't init swrCtx"; + } else { + pcm_sample_size = audioFmt.bytesPerFrame(); + au.time_num = auStream->time_base.num * 1000000; + au.time_den = auStream->time_base.den; + au.start = auStream->start_time * au.time_num / au.time_den; + qInfo()<<"Audio Idx" << au.idx << "Start" << au.start<< "Dur" << auStream->duration * au.time_num / au.time_den; + buf_size = sink->bytesFree(); + qInfo()<<"Audio buffer size"< -1) au.thd = new thread(&AVFmt::mainAuDecode, this); + if(vi.idx > -1) vi.thd = new thread(&AVFmt::mainViDecode, this); +} +AVFmt::~AVFmt() { + if(read_thd!=nullptr) { + acts.lockAddNtf(new Act{0, nullptr, 'Q'}); + read_thd->join(); + delete read_thd; + qInfo() << "~ read thread"; + } + if(au.thd!=nullptr) { + au.thd->join(); + delete au.thd; + qInfo() << "~ au thread"; + } + if(vi.thd!=nullptr) { + vi.thd->join(); + delete vi.thd; + qInfo() << "~ vi thread"; + } + av_packet_free(&packet); + avformat_close_input(&fmt_ctx); + sws_freeContext(sws_ctx); + swr_free(&swr_ctx); + qInfo() << "~ AVContext"; +} + +void AVFmt::mainRead() { + int wait = 0; + int res = 0; + while(true) { + auto act = wait==0 ? acts.lockPoll() : acts.take(wait); + while(act!=nullptr) { + if(act->act=='S') { + if(au.idx!=-1) { + unique_lock lock(au.pkts.mtx); + au.pkts.delAll(); + au.pkts.add(new Packet{0, 0, 'R'}); + lock.unlock(); + au.pkts.cv.notify_all(); + } + if(vi.idx!=-1) { + unique_lock lock(vi.pkts.mtx); + vi.pkts.delAll(); + vi.pkts.add(new Packet{0, 0, 'R'}); + lock.unlock(); + vi.pkts.cv.notify_all(); + } + av_seek_frame(fmt_ctx, -1, act->arg, act->arg==0 ? AVSEEK_FLAG_FRAME : AVSEEK_FLAG_BACKWARD); + } else if(act->act=='Q') { + if(au.idx!=-1) { + unique_lock lock(au.pkts.mtx); + au.pkts.delAll(); + au.pkts.add(new Packet{0, 0, 'Q'}); + lock.unlock(); + au.pkts.cv.notify_all(); + } + if(vi.idx!=-1) { + unique_lock lock(vi.pkts.mtx); + vi.pkts.delAll(); + vi.pkts.add(new Packet{0, 0, 'Q'}); + lock.unlock(); + vi.pkts.cv.notify_all(); + } + delete act; + return; + } + delete act; + act = acts.lockPoll(); + } + if(res < 0) {wait = 500; continue;} + if(vi.pkts.size > 120 || au.pkts.size > 200) {wait = 100; continue;} + res = av_read_frame(fmt_ctx, packet); + if(res < 0) { + if(au.idx > -1) au.pkts.lockAddNtf(new Packet{0, 0, 0}); + if(vi.idx > -1) vi.pkts.lockAddNtf(new Packet{0, 0, 0}); + if(res!=AVERROR_EOF) { + qCritical()<<"Read Packet fail:"<stream_index == vi.idx) { + vi.pkts.lockAddNtf(new Packet{packet, 0, 0}); + packet = av_packet_alloc(); + } else if(packet->stream_index == au.idx) { + au.pkts.lockAddNtf(new Packet{packet, 0, 0}); + packet = av_packet_alloc(); + } + wait = 0; + } +} +static void imgCleanupHandler(void *info) { + delete [] (uchar*)info; +} +void AVFmt::mainViDecode() { + uint8_t *dst[4]{0}; + while(true) { + if(vi_frms.size >= 7) { + unique_lock lock(vi.pkts.mtx); + if(vi.pkts.first && vi.pkts.first->act=='Q') return; + vi.pkts.cv.wait_for(lock, chrono::milliseconds(20)); + continue; + } + auto pkt = vi.pkts.take(); + if(pkt->act=='R') { + avcodec_flush_buffers(vi.ctx); + vi.deLoop = 0; + vi.stop = false; + } else if(pkt->act=='Q') { + delete pkt; + return; + } else if(!vi.stop) { + int res = avcodec_send_packet(vi.ctx, pkt->pkt); + if(res == AVERROR_EOF) goto end; + if(res < 0) qCritical()<<"Video send packet fail:"<data, vi.frm->linesize, 0, vi.ctx->height, dst, dstStride); + QImage img(dst[0], vi.ctx->width, vi.ctx->height, dstStride[0], QImage::Format_ARGB32, imgCleanupHandler, dst[0]); + { + lock_guard lock(vi_frms.mtx); + if(vi.stop) goto end; + if(vi.frm->pkt_duration) viLmt = (vi.frm->best_effort_timestamp + vi.frm->pkt_duration) * vi.time_num / vi.time_den; + else viLmt = vi.frm->best_effort_timestamp * vi.time_num / vi.time_den + frmDur; + vi_frms.add(new Img{img, vi.frm->best_effort_timestamp * vi.time_num / vi.time_den, viLmt, vi.deLoop, 0}); + } + } + if(pkt->pkt==0) { + avcodec_flush_buffers(vi.ctx); + vi.deLoop++; + } + } + end: + delete pkt; + } +} +void AVFmt::mainAuDecode() { + while(true) { + if(au_frms.size >= 9) { + unique_lock lock(au.pkts.mtx); + if(au.pkts.first && au.pkts.first->act=='Q') return; + au.pkts.cv.wait_for(lock, chrono::milliseconds(20)); + continue; + } + auto pkt = au.pkts.take(); + if(pkt->act=='R') { + avcodec_flush_buffers(au.ctx); + au.deLoop = 0; + au.stop = false; + } else if(pkt->act=='Q') { + delete pkt; + return; + } else if(!au.stop) { + int res = avcodec_send_packet(au.ctx, pkt->pkt); + if(res == AVERROR_EOF) goto end; + if(res < 0) qCritical()<<"Audio send packet fail:"<nb_samples<=0) continue; + auto pcm = new uint8_t[au.frm->nb_samples * pcm_sample_size]; + int samp_cnt = swr_convert(swr_ctx, &pcm, au.frm->nb_samples, (const uint8_t **)&au.frm->data, au.frm->nb_samples); + if(samp_cnt<=0) { + delete [] pcm; + qWarning()<<"swr convert fail:"< lock(au_frms.mtx); + if(au.stop) { + delete [] pcm; + goto end; + } + au_frms.add(new Pcm{pcm, samp_cnt * pcm_sample_size, au.frm->best_effort_timestamp * au.time_num / au.time_den, (au.frm->best_effort_timestamp + au.frm->pkt_duration) * au.time_num / au.time_den, au.deLoop, 0}); + } + } + if(pkt->pkt==0) { + avcodec_flush_buffers(au.ctx); + au.deLoop++; + } + } + end: + delete pkt; + } +} + +void AVFmt::checkAndUpd(FFPlayer *player, qint64 now_epoch) { + if(vi.isNull()) { + playAudio(au_frms.lockGet(), player, now_epoch); + return; + } + if(au.isNull()) { + player->hasImg = false; + auto viFrm = vi_frms.lockGet(); + if(viFrm==0) return; + if(start_epoch==0) { + if(vi.start > viFrm->st) { + vi.start = viFrm->st; + if(start > viFrm->st) start = viFrm->st; + } + start_epoch = now_epoch - start + 12500; + return; + } + qint64 cur = now_epoch - start_epoch; + checkFrm: + if(viFrm->loop!=playLoop) { + playLoop = viFrm->loop; + start_epoch = now_epoch - start + 12500; + qInfo()<<"Restart"; + return; + } + if(viFrm->et < cur - 8334) { + if(viFrm->next) { + qWarning() << "Drop video frame. st-cur" << (viFrm->st - cur)/1000 << "st" << viFrm->st/1000 << "cur" << cur/1000 << "Video Only"; + viFrm = vi_frms.lockDelGetNext(); + goto checkFrm; + } + qInfo() << "Video Adjust Start. st-cur" << (viFrm->st - cur)/1000 << "st" << viFrm->st/1000 << "cur" << cur/1000 << "Video Only"; + cur = viFrm->st; + start_epoch = now_epoch - cur; + } + if(viFrm->st > cur) return; + player->img = viFrm->img; + player->hasImg = true; + player->viCurTime = viFrm->st; + delete vi_frms.lockPoll(); + return; + } + player->hasImg = false; + auto auFrm = au_frms.lockGet(); + auto viFrm = vi_frms.lockGet(); + if(start_epoch==0) { + if(viFrm==0) { + if(vi.start < start+500000) return; + } else if(vi.start > viFrm->st) { + vi.start = viFrm->st; + if(start > viFrm->st) start = viFrm->st; + } + if(auFrm==0) { + if(au.start < start+500000) return; + } else if(au.start > auFrm->st) { + au.start = auFrm->st; + if(start > auFrm->st) start = auFrm->st; + } + start_epoch = now_epoch - (start - 12500); + playAudio(auFrm, player, now_epoch, vi.pkts.lockGet()==0 ? INT64_MAX : viLmt); + return; + } + if(viFrm==0) { + if(vi.pkts.lockGet()==0) playAudio(auFrm, player, now_epoch); + return; + } + if(viFrm->loop!=playLoop) { + playAudio(auFrm, player, now_epoch); + return; + } + qint64 cur = now_epoch - start_epoch; + if(auFrm && auFrm->st < cur && auFrm->loop==playLoop) { + qInfo() << "Audio Adjust Start. st-cur" << (auFrm->st - cur)/1000 << "st" << auFrm->st/1000 << "cur" << cur/1000; + cur = auFrm->st; + start_epoch = now_epoch - cur; + } + qint64 curPre = cur - 8334; + while(viFrm->et < curPre && viFrm->next && viFrm->next->loop==playLoop) { + qWarning() << "Drop video frame. st-cur" << (viFrm->st - cur)/1000 << "st" << viFrm->st/1000 << "cur" << cur/1000; + viFrm = vi_frms.lockDelGetNext(); + } + auto bytesFree = sink->bytesFree(); + bool isIdle = bytesFree==buf_size || sink->state()==QAudio::IdleState; + if(viFrm->et < curPre) { + if(isIdle) { + qInfo() << "Video Adjust Start. st-cur" << (viFrm->st - cur)/1000 << "st" << viFrm->st/1000 << "cur" << cur/1000; + cur = viFrm->st; + start_epoch = now_epoch - cur; + } else qInfo() << "Video et < cur. st-cur" << (viFrm->st - cur)/1000 << "st" << viFrm->st/1000 << "cur" << cur/1000; + } + if(auFrm && bytesFree >= auFrm->size && auFrm->loop==playLoop) whiteAudio(auFrm, player, isIdle, cur, vi.deLoop!=playLoop || vi.pkts.lockGet()==0 ? INT64_MAX : viLmt); + if(viFrm->st > cur) return; + player->img = viFrm->img; + player->hasImg = true; + player->viCurTime = viFrm->st; + delete vi_frms.lockPoll(); +} +void AVFmt::playAudio(Pcm *auFrm, FFPlayer *player, qint64 now_epoch, qint64 lmt) { + if(auFrm==0) return; + auto bytesFree = sink->bytesFree(); + if(bytesFree < auFrm->size) return; + bool isIdle = bytesFree==buf_size || sink->state()==QAudio::IdleState; + qint64 cur = now_epoch - start_epoch; + if(start_epoch==0) { + if(au.start > auFrm->st) { + au.start = auFrm->st; + if(start > auFrm->st) start = auFrm->st; + } + cur = start - 12500; + start_epoch = now_epoch - cur; + } else if(auFrm->loop!=playLoop) { + if(! isIdle) return; + playLoop = auFrm->loop; + cur = start - 12500; + start_epoch = now_epoch - cur; + qInfo()<<"Restart"; + } + if(auFrm->st < cur) { + qInfo() << "Audio Adjust Start. st-cur" << (auFrm->st - cur)/1000 << "st" << auFrm->st/1000 << "cur" << cur/1000 << "isIdle" << isIdle; + cur = auFrm->st; + start_epoch = now_epoch - cur; + } + whiteAudio(auFrm, player, isIdle, cur, lmt); + return; +} +void AVFmt::whiteAudio(Pcm *auFrm, FFPlayer *player, bool isIdle, qint64 cur, qint64 lmt) { + if(auFrm->st >= lmt) return; + if(isIdle) { + auto delay = auFrm->st - cur; + if(delay > 50000) return; + else if(delay > 999) { + auto size = (delay * sample_rate / 1000000) * pcm_sample_size; + char *data = new char[size](); + sinkWriter->write(data, size); + delete [] data; + } + } + do { + sinkWriter->write((char*)auFrm->data, auFrm->size); + player->auCurTime = auFrm->st; + auFrm = au_frms.lockDelGetNext(); + } while(auFrm && auFrm->data && sink->bytesFree() >= auFrm->size && auFrm->st < lmt); +} + +FFPlayer::FFPlayer() { + thread = new QThread(); + moveToThread(thread); + connect(thread, &QThread::finished, thread, &QThread::deleteLater); + connect(thread, &QThread::finished, this, &FFPlayer::deleteLater); + connect(this, &FFPlayer::emQuit, this, &FFPlayer::onQuit); + connect(this, &FFPlayer::emOpen, this, &FFPlayer::onOpen); + connect(this, &FFPlayer::emClose, this, &FFPlayer::onClose); + connect(this, &FFPlayer::emPlay, this, &FFPlayer::onPlay); + connect(this, &FFPlayer::emPause, this, &FFPlayer::onPause); + connect(this, &FFPlayer::emStop, this, &FFPlayer::onStop); + connect(this, &FFPlayer::emVol, this, &FFPlayer::onVol); + thread->start(); +} +FFPlayer::~FFPlayer() { + qInfo()<<"~ FFPlayer"; +} + +void FFPlayer::onQuit() { + onClose(); + thread->quit(); +} +void FFPlayer::onOpen(QByteArray url) { + onClose(); + ctx = new AVFmt(url); + if(mVol!=1.0 && ctx->sink) ctx->sink->setVolume(mVol); + if(ctx->err.isEmpty()) status = Paused; + else { + qCritical()<err; + emit emError(ctx->err); + delete ctx; + ctx = 0; + } +} +void FFPlayer::onClose() { + status = Closed; + if(audioDaemonTimerId!=0) { + killTimer(audioDaemonTimerId); + audioDaemonTimerId = 0; + } + if(ctx==0) return; + if(ctx->sink) { + ctx->sink->stop(); + delete ctx->sink; + } + delete ctx; + ctx = 0; + emit emUpd(QImage()); +} + +void FFPlayer::onPlay() { + if(ctx==0) return; + status = Playing; + if(ctx->sink) ctx->sink->resume(); + startAudioDaemon(); +} +void FFPlayer::onPause() { + if(ctx==0) return; + status = Paused; + if(ctx->sink) ctx->sink->suspend(); +} +void FFPlayer::onStop() { + if(audioDaemonTimerId!=0) { + killTimer(audioDaemonTimerId); + audioDaemonTimerId = 0; + } + if(ctx==0) return; + if(ctx->sink) { + ctx->sink->stop(); + ctx->sinkWriter = ctx->sink->start(); + } + lock_guard lock(ctx->acts.mtx); + ctx->vi.stop = true; + ctx->au.stop = true; + status = Paused; + ctx->start_epoch = 0; + ctx->playLoop = 0; + ctx->au_frms.lockDelAll(); + ctx->vi_frms.lockDelAll(); + img = QImage(); + ctx->acts.add(new Act{0, 0, 'S'}); + ctx->acts.cv.notify_all(); +} +void FFPlayer::onVol(qreal vol) { + mVol = vol; + if(ctx && ctx->sink) ctx->sink->setVolume(vol); +} + +void FFPlayer::updFrame() { + if(ctx==0) return; + if(status!=Playing) { + if(img.isNull()) { + lock_guard lock(ctx->vi_frms.mtx); + viSize = ctx->vi_frms.size; + auSize = ctx->au_frms.size; + if(ctx->vi_frms.first==0) return; + img = ctx->vi_frms.first->img; + emit emUpd(img); + } + return; + } + auto now_epoch = chrono::duration_cast(chrono::steady_clock::now().time_since_epoch()).count(); + dur = now_epoch - last_epoch; + last_epoch = now_epoch; + if(dur>100000) return; + if(dur<4000) { + qWarning()<<"FFPlayer UpdFrame Fail: dur"<checkAndUpd(this, now_epoch); + viSize = ctx->vi_frms.size; + auSize = ctx->au_frms.size; + if(hasImg) emit emUpd(img); + startAudioDaemon(); + +} +void FFPlayer::timerEvent(QTimerEvent *event) { + if(event->timerId()!=audioDaemonTimerId) return; + if(ctx==0 || status!=Playing) { + if(audioDaemonTimerId!=0) { + killTimer(audioDaemonTimerId); + audioDaemonTimerId = 0; + } + return; + } + auto now_epoch = chrono::duration_cast(chrono::steady_clock::now().time_since_epoch()).count(); + auto dur = now_epoch - last_epoch; + if(dur<=40000 && ! ctx->vi.isNull()) return; + ctx->checkAndUpd(this, now_epoch); + viSize = ctx->vi_frms.size; + auSize = ctx->au_frms.size; + if(hasImg) emit emUpd(img); +} diff --git a/LedOK/ffplayer.h b/LedOK/ffplayer.h index 668a276..b07e0ff 100644 --- a/LedOK/ffplayer.h +++ b/LedOK/ffplayer.h @@ -1,260 +1,265 @@ -#ifndef FFPLAYER_H -#define FFPLAYER_H - -#include -#include -#include -#if(QT_VERSION_MAJOR > 5) - #include -#else - #include - typedef QAudioOutput QAudioSink; - typedef QAudioDeviceInfo QAudioDevice; -#endif -extern "C"{ -#include -#include -#include -#include -} - -template -class Queue { -public: - virtual ~Queue() { - delAll(); - } - void add(T *node) { - if(node==nullptr) { - throw std::invalid_argument("node is null"); - return; - } - if(last!=nullptr) last->next = node; - else first = node; - last = node; - size++; - } - void remove() { - if(first==nullptr) return; - if(first==last) first = last = nullptr; - else first = first->next; - size--; - } - T *poll() { - auto node = first; - remove(); - return node; - } - T *delGetNext() { - delete poll(); - return first; - } - T *removeGetNext() { - remove(); - return first; - } - void delAll() { - while(first!=nullptr) delete poll(); - } - - T *volatile first{0}; - T *volatile last{0}; - volatile int size{0}; -}; - -template -class ConQueue : public Queue { -public: - virtual ~ConQueue() { - std::lock_guard lock(mtx); - this->delAll(); - } - void lockAddNtf(T *node) { - { - std::lock_guard lock(mtx); - this->add(node); - } - cv.notify_one(); - } - void lockRemove() { - std::lock_guard lock(mtx); - this->remove(); - } - T *lockPoll() { - std::lock_guard lock(mtx); - return this->poll(); - } - T *lockGet() { - std::lock_guard lock(mtx); - return this->first; - } - T *lockDelGetNext() { - std::lock_guard lock(mtx); - return this->delGetNext(); - } - T *lockRemoveGetNext() { - std::lock_guard lock(mtx); - return this->removeGetNext(); - } - void lockDelAll() { - std::lock_guard lock(mtx); - this->delAll(); - } - - T *take(int ms = 0) { - std::unique_lock lock(mtx); - if(ms==0) while(this->first==nullptr) cv.wait(lock); - else if(this->first==nullptr) cv.wait_for(lock, std::chrono::milliseconds(ms)); - return this->poll(); - } - std::mutex mtx; - std::condition_variable cv; -}; -struct Act { - qint64 arg; - Act *next; - char act; -}; -struct Packet { - AVPacket *pkt; - Packet *next; - uchar act; - ~Packet() {av_packet_free(&pkt);} -}; -struct Img { - QImage img; - qint64 st; - qint64 et; - uint loop; - Img *next; -}; -struct Pcm { - uint8_t *data; - int size; - qint64 st; - qint64 et; - uint loop; - Pcm *next; - ~Pcm() {if(data!=nullptr) delete [] data;} -}; -class Type { -public: - inline bool isNull(){return idx <= -1;} - int idx{-1}; - int time_num{0}, time_den{0}; - qint64 start{0}; - AVCodecContext *ctx{0}; - std::thread *thd{0}; - std::atomic stop{false}; - AVFrame *frm{av_frame_alloc()}; - ConQueue pkts; - uint deLoop{0}; - ~Type() { - av_frame_free(&frm); - avcodec_free_context(&ctx); - } -}; -class AVFmt { - friend class FFPlayer; -public: - static const char Run{0}, Pause{1}, Quit{2}; - AVFmt(QByteArray url); - ~AVFmt(); - void mainRead(); - void mainViDecode(); - void mainAuDecode(); - bool isLoop{true}; -protected: - void checkAndUpd(FFPlayer *, qint64); - void playAudio(Pcm *, FFPlayer *, qint64, qint64 lmt = INT64_MAX); - void whiteAudio(Pcm *, FFPlayer *, bool, qint64 cur, qint64 lmt = INT64_MAX); - QString errStr(int err) { - if(av_strerror(err, err_str, err_size)==0) return QString::fromUtf8(err_str); - return QString::number(err); - } - - QString err; - const static int err_size{255}; - char err_str[err_size]{}; - - AVFormatContext *fmt_ctx{0}; - std::thread *read_thd{0}; - qint64 start{0}; - Type vi, au; - qint64 viLmt{0}; - - SwsContext *sws_ctx{0}; - SwrContext *swr_ctx{0}; - AVChannelLayout out_ch_layout; - int sample_rate{0}, pcm_sample_size{0}; - QAudioSink *sink{0}; - QIODevice *sinkWriter{0}; - int buf_size{0}; - - ConQueue acts; - AVPacket *packet{av_packet_alloc()}; - ConQueue vi_frms; - ConQueue au_frms; - qint64 start_epoch{0}; - uint playLoop{0}; -}; - -class FFPlayer : public QObject { - friend class AVFmt; - Q_OBJECT -public: - static const char Playing{0}, Paused{1}, Closed{2}; - - explicit FFPlayer(); - ~FFPlayer(); - - inline void open(QByteArray url) { - status = Paused; - emit emOpen(url); - } - inline void close() {emit emClose();} - inline void play() {emit emPlay();} - inline void pause() {emit emPause();} - inline void stop() {emit emStop();} - inline void setVol(qreal vol) {emit emVol(vol);} - inline void quit() {emit emQuit();} - - std::atomic status{Closed}; - QImage img; - qint64 dur{0}; - int viSize{0}, auSize{0}; - qint64 viCurTime{0}, auCurTime{0}; -public slots: - void updFrame(); -signals: - void emOpen(QByteArray url); - void emClose(); - void emPlay(); - void emPause(); - void emStop(); - void emVol(qreal vol); - void emUpd(QImage); - void emError(QString err); - void emQuit(); -protected slots: - void onOpen(QByteArray url); - void onClose(); - void onPlay(); - void onPause(); - void onStop(); - void onVol(qreal vol); - void onQuit(); -protected: - void timerEvent(QTimerEvent *event) override; - void startAudioDaemon() { - if(audioDaemonTimerId==0 && ! ctx->au.isNull()) audioDaemonTimerId = startTimer(20); - } - QThread *thread; - AVFmt *ctx{0}; - qint64 last_epoch{0}; - int audioDaemonTimerId{0}; - bool hasImg{false}; - qreal mVol{1.0}; -}; - -#endif // FFPLAYER_H +#ifndef FFPLAYER_H +#define FFPLAYER_H + +#include +#include +#include +#if(QT_VERSION_MAJOR > 5) + #include +#else + #include + typedef QAudioOutput QAudioSink; + typedef QAudioDeviceInfo QAudioDevice; +#endif +extern "C"{ +#include +#include +#include +#include +} + +template +class Queue { +public: + virtual ~Queue() { + delAll(); + } + void add(T *node) { + if(node==nullptr) { + throw std::invalid_argument("node is null"); + return; + } + if(last!=nullptr) last->next = node; + else first = node; + last = node; + size++; + } + void remove() { + if(first==nullptr) return; + if(first==last) first = last = nullptr; + else first = first->next; + size--; + } + T *poll() { + auto node = first; + remove(); + return node; + } + T *delGetNext() { + delete poll(); + return first; + } + T *removeGetNext() { + remove(); + return first; + } + void delAll() { + while(first!=nullptr) delete poll(); + } + + T *volatile first{0}; + T *volatile last{0}; + volatile int size{0}; +}; + +template +class ConQueue : public Queue { +public: + virtual ~ConQueue() { + std::lock_guard lock(mtx); + this->delAll(); + } + void lockAddNtf(T *node) { + { + std::lock_guard lock(mtx); + this->add(node); + } + cv.notify_one(); + } + void lockRemove() { + std::lock_guard lock(mtx); + this->remove(); + } + T *lockPoll() { + std::lock_guard lock(mtx); + return this->poll(); + } + T *lockGet() { + std::lock_guard lock(mtx); + return this->first; + } + T *lockDelGetNext() { + std::lock_guard lock(mtx); + return this->delGetNext(); + } + T *lockRemoveGetNext() { + std::lock_guard lock(mtx); + return this->removeGetNext(); + } + void lockDelAll() { + std::lock_guard lock(mtx); + this->delAll(); + } + + T *take(int ms = 0) { + std::unique_lock lock(mtx); + if(ms==0) while(this->first==nullptr) cv.wait(lock); + else if(this->first==nullptr) cv.wait_for(lock, std::chrono::milliseconds(ms)); + return this->poll(); + } + std::mutex mtx; + std::condition_variable cv; +}; +struct Act { + qint64 arg; + Act *next; + char act; +}; +struct Packet { + AVPacket *pkt; + Packet *next; + uchar act; + ~Packet() {av_packet_free(&pkt);} +}; +struct Img { + QImage img; + qint64 st; + qint64 et; + uint loop; + Img *next; +}; +struct Pcm { + uint8_t *data; + int size; + qint64 st; + qint64 et; + uint loop; + Pcm *next; + ~Pcm() {if(data!=nullptr) delete [] data;} +}; +class Type { +public: + inline bool isNull(){return idx <= -1;} + int idx{-1}; + int time_num{0}, time_den{0}; + qint64 start{0}; + AVCodecContext *ctx{0}; + std::thread *thd{0}; + std::atomic stop{false}; + AVFrame *frm{av_frame_alloc()}; + ConQueue pkts; + uint deLoop{0}; + ~Type() { + av_frame_free(&frm); + avcodec_free_context(&ctx); + } +}; +class AVFmt { + friend class FFPlayer; +public: + static const char Run{0}, Pause{1}, Quit{2}; + AVFmt(QByteArray url); + ~AVFmt(); + void mainRead(); + void mainViDecode(); + void mainAuDecode(); + bool isLoop{true}; +protected: + void checkAndUpd(FFPlayer *, qint64); + void playAudio(Pcm *, FFPlayer *, qint64, qint64 lmt = INT64_MAX); + void whiteAudio(Pcm *, FFPlayer *, bool, qint64 cur, qint64 lmt = INT64_MAX); + QString errStr(int err) { + if(av_strerror(err, errbuf, AV_ERROR_MAX_STRING_SIZE)==0) return QString::fromUtf8(errbuf); + return QString::number(err); + } + + QString err; + char errbuf[AV_ERROR_MAX_STRING_SIZE]{}; + + AVFormatContext *fmt_ctx{0}; + std::thread *read_thd{0}; + qint64 start{0}; + Type vi, au; + qint64 frmDur{0}; + qint64 viLmt{0}; + + SwsContext *sws_ctx{0}; + int dstStride[4]{0}; + SwrContext *swr_ctx{0}; + AVChannelLayout out_ch_layout + #if(QT_VERSION_MAJOR > 5) + AV_CHANNEL_LAYOUT_STEREO + #endif + ; + int sample_rate{0}, pcm_sample_size{0}; + QAudioSink *sink{0}; + QIODevice *sinkWriter{0}; + int buf_size{0}; + + ConQueue acts; + AVPacket *packet{av_packet_alloc()}; + ConQueue vi_frms; + ConQueue au_frms; + qint64 start_epoch{0}; + uint playLoop{0}; +}; + +class FFPlayer : public QObject { + friend class AVFmt; + Q_OBJECT +public: + static const char Playing{0}, Paused{1}, Closed{2}; + + explicit FFPlayer(); + ~FFPlayer(); + + inline void open(QByteArray url) { + status = Paused; + emit emOpen(url); + } + inline void close() {emit emClose();} + inline void play() {emit emPlay();} + inline void pause() {emit emPause();} + inline void stop() {emit emStop();} + inline void setVol(qreal vol) {emit emVol(vol);} + inline void quit() {emit emQuit();} + + std::atomic status{Closed}; + QImage img; + qint64 dur{0}; + int viSize{0}, auSize{0}; + qint64 viCurTime{0}, auCurTime{0}; +public slots: + void updFrame(); +signals: + void emOpen(QByteArray url); + void emClose(); + void emPlay(); + void emPause(); + void emStop(); + void emVol(qreal vol); + void emUpd(QImage); + void emError(QString err); + void emQuit(); +protected slots: + void onOpen(QByteArray url); + void onClose(); + void onPlay(); + void onPause(); + void onStop(); + void onVol(qreal vol); + void onQuit(); +protected: + void timerEvent(QTimerEvent *event) override; + void startAudioDaemon() { + if(audioDaemonTimerId==0 && ! ctx->au.isNull()) audioDaemonTimerId = startTimer(20); + } + QThread *thread; + AVFmt *ctx{0}; + qint64 last_epoch{0}; + int audioDaemonTimerId{0}; + bool hasImg{false}; + qreal mVol{1.0}; +}; + +#endif // FFPLAYER_H diff --git a/LedOK/globaldefine.cpp b/LedOK/globaldefine.cpp index 8fe70b3..b919666 100644 --- a/LedOK/globaldefine.cpp +++ b/LedOK/globaldefine.cpp @@ -1,169 +1,160 @@ -#include -#include -#include -#include -#include -#include -#include - -bool gVideoCompress = true; -bool gVideoTranscoding = true; -bool gTextAntialiasing = false; -bool gShowLoraScreen = false; -bool gWidthSplit = false; - -QNetworkRequest netReq(const QString &url, int timeout, const QVariant &contentType) { - QNetworkRequest request{url}; - request.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy); - request.setTransferTimeout(timeout); - if(contentType.isValid()) request.setHeader(QNetworkRequest::ContentTypeHeader, contentType); - return request; -} -QString parseReplyJson(QNetworkReply *reply, QJsonDocument *outJson) { - reply->deleteLater(); - auto error = reply->error(); - if(error != QNetworkReply::NoError) { - auto errStr = reply->errorString(); - if(error!=QNetworkReply::InternalServerError || ! errStr.endsWith("replied: Unknown")) { - if(error==QNetworkReply::OperationCanceledError) { - error = QNetworkReply::TimeoutError; - errStr = QCoreApplication::translate("Def","Connection Timeout"); - } - return QString(QMetaEnum::fromType().valueToKey(error))+" ("+QString::number(error)+") "+errStr+"\n"+QCoreApplication::translate("Def","Device replied")+":\n"+reply->readAll(); - } - } - auto status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - if(status != 200) return QString::number(status)+" "+reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString()+"\n"+QCoreApplication::translate("Def","Device replied")+":\n"+reply->readAll(); - if(outJson) { - auto data = reply->readAll(); - QJsonParseError jsonErr; - *outJson = QJsonDocument::fromJson(data, &jsonErr); - if(jsonErr.error != QJsonParseError::NoError) return "Json error: "+jsonErr.errorString()+"\n"+QCoreApplication::translate("Def","Device replied")+":\n"+data; - } - return ""; -} -QString checkReplyForJson(QNetworkReply *reply, QJsonDocument *doc, QByteArray *outData) { - reply->deleteLater(); - auto error = reply->error(); - auto data = reply->readAll(); - if(outData) *outData = data; - if(error != QNetworkReply::NoError) { - auto errStr = reply->errorString(); - if(error!=QNetworkReply::InternalServerError || ! errStr.endsWith("replied: Unknown")) { - if(error==QNetworkReply::OperationCanceledError) { - error = QNetworkReply::TimeoutError; - errStr = QCoreApplication::translate("Def","Connection Timeout"); - } - return QString(QMetaEnum::fromType().valueToKey(error))+" ("+QString::number(error)+") "+errStr+"\n"+QCoreApplication::translate("Def","Device replied")+":\n"+data; - } - } - auto status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - if(status != 200) return QString::number(status)+" - "+reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString()+"\n"+QCoreApplication::translate("Def","Device replied")+":\n"+data; - QJsonParseError jsonErr; - QJsonDocument json = QJsonDocument::fromJson(data, &jsonErr); - if(jsonErr.error != QJsonParseError::NoError) return "Json error: "+jsonErr.errorString()+"\n"+QCoreApplication::translate("Def","Device replied")+":\n"+data; - if(! json["success"].toBool()) return QCoreApplication::translate("Def","Fail")+". "+QCoreApplication::translate("Def","Device replied")+":\n"+data; - if(doc) doc->swap(json); - return ""; -} - -bool isTextValid(const QString &strIP){ - if(! strIP.isEmpty()) { - QRegExp rx2("\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b"); - if (!rx2.exactMatch(strIP)) return false; - } - return true; -} -QString getRandomString(int len) { - static const char table[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; - static const int tableSize = sizeof(table) - 1; - QString str; - str.resize(len); - for(int i=0; ihttpPost(strUrl, QJsonDocument(json).toJson(QJsonDocument::Compact)); -} -bool copyDir(const QString &source, const QString &destination, bool override) -{ - QDir directory(source); - if (!directory.exists()) - { - return false; - } - - - QString srcPath = QDir::toNativeSeparators(source); - if (!srcPath.endsWith(QDir::separator())) - srcPath += QDir::separator(); - QString dstPath = QDir::toNativeSeparators(destination); - if (!dstPath.endsWith(QDir::separator())) - dstPath += QDir::separator(); - - - bool error = false; - QStringList fileNames = directory.entryList(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::Hidden); - for (QStringList::size_type i=0; i != fileNames.size(); ++i) - { - QString fileName = fileNames.at(i); - QString srcFilePath = srcPath + fileName; - QString dstFilePath = dstPath + fileName; - QFileInfo fileInfo(srcFilePath); - if (fileInfo.isFile() || fileInfo.isSymLink()) - { - if (override) - { - QFile::setPermissions(dstFilePath, QFile::WriteOwner); - } - QFile::copy(srcFilePath, dstFilePath); - } - else if (fileInfo.isDir()) - { - QDir dstDir(dstFilePath); - dstDir.mkpath(dstFilePath); - if (!copyDir(srcFilePath, dstFilePath, override)) - { - error = true; - } - } - } - - - return !error; -} -unsigned char GetCheckCodeIn8(unsigned char * pBuffer,unsigned int uiSize) { - unsigned int i=0; - unsigned char ucCheckCode=0; - for (i=0;i +#include +#include +#include +#include +#include +#include + +bool gVideoCompress = true; +bool gVideoTranscoding = true; +bool gTextAntialiasing = false; +bool gShowLoraScreen = false; +bool gWidthSplit = false; + +QNetworkRequest netReq(const QString &url, const QByteArray &contentType, int timeout) { + QNetworkRequest request{url}; + request.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy); + if(timeout) request.setTransferTimeout(timeout); + if(! contentType.isEmpty()) request.setRawHeader("Content-Type", contentType); + return request; +} +QString replyErr(QNetworkReply *reply) { + reply->deleteLater(); + auto error = reply->error(); + if(error != QNetworkReply::NoError) { + auto errStr = reply->errorString(); + if(error!=QNetworkReply::InternalServerError || ! errStr.endsWith("replied: Unknown")) { + if(error==QNetworkReply::OperationCanceledError) { + error = QNetworkReply::TimeoutError; + errStr = QCoreApplication::translate("Def","Connection Timeout"); + } + return QString(QMetaEnum::fromType().valueToKey(error))+" ("+QString::number(error)+") "+errStr; + } + } + auto status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + if(status != 200) return QString::number(status)+" "+reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString(); + return ""; +} +QString checkReply(QNetworkReply *reply, QJsonDocument *outJson) { + auto err = replyErr(reply); + if(! err.isEmpty()) { + auto data = reply->readAll(); + if(! data.isEmpty()) err = err+"\n"+QCoreApplication::translate("Def","Device replied")+": "+data; + return err; + } + if(outJson) { + auto data = reply->readAll(); + QJsonParseError jsonErr; + *outJson = QJsonDocument::fromJson(data, &jsonErr); + if(jsonErr.error != QJsonParseError::NoError) return "Json error: "+jsonErr.errorString()+"\n"+QCoreApplication::translate("Def","Device replied")+": "+data; + } + return ""; +} +QString checkReplyForJson(QNetworkReply *reply, QJsonDocument *outJson, QByteArray *outData) { + auto err = replyErr(reply); + auto data = reply->readAll(); + if(outData) *outData = data; + if(! err.isEmpty()) { + if(! data.isEmpty()) err = err+"\n"+QCoreApplication::translate("Def","Device replied")+": "+data; + return err; + } + QJsonParseError jsonErr; + QJsonDocument json = QJsonDocument::fromJson(data, &jsonErr); + if(jsonErr.error != QJsonParseError::NoError) return "Json error: "+jsonErr.errorString()+"\n"+QCoreApplication::translate("Def","Device replied")+": "+data; + if(! json["success"].toBool()) return QCoreApplication::translate("Def","Fail")+". "+QCoreApplication::translate("Def","Device replied")+": "+data; + if(outJson) outJson->swap(json); + return ""; +} + +bool isTextValid(const QString &strIP){ + if(! strIP.isEmpty()) { + QRegExp rx2("\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b"); + if (!rx2.exactMatch(strIP)) return false; + } + return true; +} +QString getRandomString(int len) { + static const char table[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + static const int tableSize = sizeof(table) - 1; + QString str; + str.resize(len); + for(int i=0; ihttpPost(strUrl, QJsonDocument(json).toJson(QJsonDocument::Compact)); +} +bool copyDir(const QString &source, const QString &destination, bool override) +{ + QDir directory(source); + if (!directory.exists()) + { + return false; + } + + + QString srcPath = QDir::toNativeSeparators(source); + if (!srcPath.endsWith(QDir::separator())) + srcPath += QDir::separator(); + QString dstPath = QDir::toNativeSeparators(destination); + if (!dstPath.endsWith(QDir::separator())) + dstPath += QDir::separator(); + + + bool error = false; + QStringList fileNames = directory.entryList(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::Hidden); + for (QStringList::size_type i=0; i != fileNames.size(); ++i) + { + QString fileName = fileNames.at(i); + QString srcFilePath = srcPath + fileName; + QString dstFilePath = dstPath + fileName; + QFileInfo fileInfo(srcFilePath); + if (fileInfo.isFile() || fileInfo.isSymLink()) + { + if (override) + { + QFile::setPermissions(dstFilePath, QFile::WriteOwner); + } + QFile::copy(srcFilePath, dstFilePath); + } + else if (fileInfo.isDir()) + { + QDir dstDir(dstFilePath); + dstDir.mkpath(dstFilePath); + if (!copyDir(srcFilePath, dstFilePath, override)) + { + error = true; + } + } + } + + + return !error; +} +unsigned char GetCheckCodeIn8(unsigned char * pBuffer,unsigned int uiSize) { + unsigned int i=0; + unsigned char ucCheckCode=0; + for (i=0;i -#define MACRO_FENGEFU "/" -#include -#include -#include -#include - -enum { - MainPage_DeviceManager = 0, - MainPage_ProgManager, - MainPage_Setting, - MainPage_LoraScreen, - MainPage_End, -}; - -enum { - - ENUM_IMPORT_DLG=1, - ENUM_EXPORT_DLG=2, - ENUM_DELETE_DLG=3, - ENUM_SELECT_NETWORK=5, -}; - - -#define STREAM_SYNC_HEAD_NUM 3 -#define STREAM_SYNC_HEAD 0x7e -typedef struct _SYSTIMER -{ - int y; //获取年份 - int m; //获取当前月份 - int d; //获得几号 - int h; //获取当前为几时 - int mm; //获取分钟 - int s; //获取秒 - int w; //获取星期几,注意1为星期天,7为星期六 -}SYSTIMER,*P_SYSTIMER; - -typedef struct _RESTORE_IP -{ - char cNewIp[20]; - char cMask[20]; - char cGateway[20]; - char cDns[20]; -// char cLocalIp[20]; - -}RESTORE_IP,*P_RESTORE_IP; -typedef struct _STREAM_PACKET -{ - unsigned char SyncHead[STREAM_SYNC_HEAD_NUM]; - unsigned char ucCommType; - char ucSerialCode[20]; - unsigned int iLength; - char pDataBuffer[2049]; -}STREAM_PACKET,* P_STREAM_PACKET; -enum _NET_COMMU_TYPE -{ - COMMAND_SAVE_ADVANCE_PARAM_NOT_RESET=0x40, - COMMAND_ONLY_RESET_CARD_IP=0X43, - COMMAND_SET_M31_DOUBLE_HUB=0X44, - COMMAND_CONNECT_COLSE =0x7A, - COMMAND_UPGRADE = 0x80, - COMMAND_SIGNLE_FILE_UPGRADE , - COMMAND_LOOPCHECK , - COMMAND_VERIFY_CLOCK , - COMMAND_SCREEN_OPERATOR,//0x84 - COMMAND_SET_SERIAL_NUM, - NET_COMMU_TYPE_PLAY_IN_LINE , // 网络同步在线播放. - NET_COMMU_TYPE_PREVIEW_IN_LINE, // 网络在线预览. - NET_COMMU_TYPE_UPGRADE_SYSTEM, // 系统升级. - NET_COMMU_TYPE_RECOVER_SYSTEM, // 系统还原到上一次正确的启动. - SCREEN_OPERATOR_COMM_PARAMS_SAVE, // 参数保存. - NET_COMMU_TYPE_COMM_EXIT,//普通退出,不重启 - NET_COMMU_TYPE_AUDIO_PLAY,//0X8C - NET_COMMU_TYPE_IO, - NET_COMMU_TYPE_IO_CHECK, - NET_COMMU_TYPE_LIMITE_TIME, - NET_COMMU_TYPE_SYSTEM_BROADCAST,//0X90 - NET_COMMU_TYPE_REALTIME_INSERT_PLAY, - //NET_COMMU_TYPE_SHANSUO_INSERT_PLAY, - NET_COMMU_TYPE_MODIFY_SERIAL_ID, - NET_COMMU_TYPE_KERNEL_UPGRADE_SYSTEM, - NET_COMMU_TYPE_UPGRADE_FINISHED_EXIT, - NET_COMMU_TYPE_REAL_TIME_INSERT_PLAY_WITH_LIST_EXIT, - NET_COMMU_TYPE_ZNSZ,// 智能设置命令. - NET_COMMU_TYPE_SELECT_PROGRAM_PLAY,// 选节目播放.0x97 - NET_COMMU_TYPE_SELECT_MULI_PROGRAM_PLAY,//98选播多个节目 - NET_COMMU_TYPE_GET_PROGRAM_NAME,//99获取所有节目的名称 - NET_COMMU_TYPE_GET_CUR_PLAY_STATUS,//9a查询当前播放的详细信息 - NET_COMMU_TYPE_POWER_PANEL_ON_OR_OFF,//9b开关大屏幕 - NET_COMMU_TYPE_ADJUST_BRIGHTNESS,//9c调节亮度 - NET_COMMU_TYPE_GET_SYSTEM_STATUS,//9d获取系统状态 - NET_COMMU_TYPE_VERIFY_SIGN,//校验签名9e - NET_COMMU_TYPE_SET_WEB_SERVER_PARAM,//配置web服务器参数 - NET_COMMU_TYPE_GET_WEB_SERVER_PARAM,//a0 - NET_COMMU_TYPE_SET_WIFI_PARAM,//a1配置wifi参数 - NET_COMMU_TYPE_GET_WIFI_PARAM,//a2获取wifi参数 - NET_COMMU_TYPE_SCAN_AP_WIFI_PARAM,//a3获取ap热点的名称 - NET_COMMU_TYPE_GET_ANDROID=0xa4, - NET_COMMU_TYPE_INSTALL_APK=0xa5, - NET_COMMU_TYPE_UNINSTALL_APK=0xa6, - NET_COMMU_TYPE_SET_DNS=0xa7, - NET_COMMU_TYPE_GET_DNS=0xa8, - NET_COMMU_TYPE_SET_PROXY=0xa9, - NET_COMMU_TYPE_GET_PROXY=0xaa, - NET_COMMU_TYPE_SET_ANDROID_COMMUNICATION=0xab, - NET_COMMU_TYPE_GET_ANDROID_COMMUNICATION=0xac, - NET_COMMU_TYPE_GET_SIM_STATUS=0xad, - NET_COMMU_TYPE_GET_APN_PARAM=0xae, - NET_COMMU_TYPE_GET_APK_VERSION=0xaf, - NET_COMMU_TYPE_SET_REALTIME_PARAM=0xb0, - NET_COMMU_TYPE_GET_REALTIME_PARAM=0xb1, - NET_COMMU_TYPE_SET_REALTIME_LINSTEN_PARAM=0xb2, - NET_COMMU_TYPE_GET_REALTIME_LINSTEN_PARAM=0xb3, - NET_COMMU_TYPE_SET_HUAWEI_4G=0xB4, - NET_COMMU_TYPE_GET_HUAWEI_4G=0xB5, - NET_COMMU_TYPE_CLEAR_ANDROID_PROGRAM=0xB6, - NET_COMMU_TYPE_SET_AP_PARAM=0xB7, - NET_COMMU_TYPE_GET_AP_PARAM=0xB8, - GET_REALY_RESOLUTION=0xB9, - GET_REALY_ANDROID_FIRMWARE_INFO=0xBA, - NET_COMMU_TYPE_NUM, - - COMMAND_UPGRADE_ANSWER =0xC0, - COMMAND_SIGNLE_FILE_UPGRADE_ANSWER , - COMMAND_LOOPCHECK_ANSWER , - COMMAND_VERIFY_CLOCK_ANSWER , - COMMAND_SCREEN_OPERATOR_ANSWER, - COMMAND_SET_SERIAL_NUM_ANSWER, - NET_COMMU_TYPE_PLAY_IN_LINE_ANSWER , // 网络同步在线播放. - NET_COMMU_TYPE_PREVIEW_IN_LINE_ANSWER, // 网络在线预览. - NET_COMMU_TYPE_UPGRADE_SYSTEM_ANSWER, // 系统升级. - NET_COMMU_TYPE_RECOVER_SYSTEM_ANSWER, // 系统还原到上一次正确的启动. - SCREEN_OPERATOR_COMM_PARAMS_SAVE_ANSWER, - NET_COMMU_TYPE_COMM_EXIT_ANSWER, - NET_COMMU_TYPE_AUDIO_PLAY_ANSWER,//0XcC - NET_COMMU_TYPE_IO_ANSWER, - NET_COMMU_TYPE_IO_CHECK_ANSWER, - NET_COMMU_TYPE_LIMITE_TIME_ANSWER, - -//// - NET_COMMU_TYPE_SYSTEM_BROADCAST_ANSWER, - NET_COMMU_TYPE_REALTIME_INSERT_PLAY_ANSWER, - NET_COMMU_TYPE_REALTIME_INSERT_PLAY_WITH_GLINT_ANSWER , //带闪烁功能的实时插播 - - NET_COMMU_TYPE_KERNEL_UPGRADE_SYSTEM_ANSWER, - NET_COMMU_TYPE_UPGRADE_FINISHED_EXIT_ANSWER,//0xd4 - NET_COMMU_TYPE_REAL_TIME_INSERT_PLAY_WITH_LIST_EXIT_ANSWER, - NET_COMMU_TYPE_ZNSZ_ANSWER,// 智能设置命令. - NET_COMMU_TYPE_SELECT_PROGRAM_PLAY_ANSWER,//0x97 选节目播放. - NET_COMMU_TYPE_SELECT_MULI_PROGRAM_PLAY_ANSWER, - NET_COMMU_TYPE_GET_PROGRAM_NAME_ANSWER, - NET_COMMU_TYPE_GET_CUR_PLAY_STATUS_ANSWER, - NET_COMMU_TYPE_POWER_PANEL_ON_OR_OFF_ANSWER, - NET_COMMU_TYPE_ADJUST_BRIGHTNESS_ANSWER, - NET_COMMU_TYPE_GET_SYSTEM_STATUS_ANSWER,//获取系统状态 - NET_COMMU_TYPE_NUM_ANSWER, - - - COMMAND_CONNECT_COLSE_ANSWER - -}; -extern bool gVideoCompress; -extern bool gVideoTranscoding; -extern bool gTextAntialiasing; -extern bool gShowLoraScreen; -extern bool gWidthSplit; - -extern bool isTextValid(const QString &strIP); -extern quint64 dirFileSize(const QString &path); -extern bool isFileExist(QString fullFileName); -extern QString getRandomString(int length); -extern void HttpPostByTypeJsonObject(HpptClient *pHpptClient, QString strUrl,QJsonObject json); -extern bool copyDir(const QString &source, const QString &destination, bool override); -extern unsigned char GetCheckCodeIn8(unsigned char * pBuffer,unsigned int uiSize); - -enum _ENUM_CONTRL_WIDGET { - Setting_Bright=0, - Setting_PowerControl, - Setting_NetCfg, - Setting_VerifyClock, - Setting_Encrypt, - Setting_HDMI, - Setting_Volume, - Setting_Advanced, - Setting_Test, - Setting_End, -}; - -QNetworkRequest netReq(const QString &url, int = QNetworkRequest::DefaultTransferTimeoutConstant, const QVariant &contentType = QVariant::Invalid); -inline QNetworkRequest reqForJson(const QString &url) { - return netReq(url, 30000, "application/json"); -} -QString parseReplyJson(QNetworkReply *, QJsonDocument * = 0); -QString checkReplyForJson(QNetworkReply *, QJsonDocument * = 0, QByteArray * = 0); - -#define Def_CtrlReqPre \ - waitingDlg->show();\ - auto card = gSelCards->at(0);\ - auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); - -#define Def_CtrlSetReqAfter \ - QString err = checkReplyForJson(reply);\ - if(! err.isEmpty()) {\ - waitingDlg->close();\ - QMessageBox::critical(gMainWin, tr("Error"), err);\ - return;\ - }\ - waitingDlg->success(); - -#define Def_CtrlSingleGetReply \ - QJsonDocument json;\ - QString err = checkReplyForJson(reply, &json);\ - if(! err.isEmpty()) {\ - waitingDlg->close();\ - QMessageBox::critical(gMainWin, tr("Error"), err);\ - return;\ - } - -#define Def_CtrlSetMulti(tip) \ - auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact));\ - connect(reply, &QNetworkReply::finished, this, [reply, card] {\ - QString err = checkReplyForJson(reply);\ - gFdResInfo->append(card->m_strCardId+" "+tip+" "+(err.isEmpty()?QCoreApplication::translate("Def","Success"):err));\ - }); - -#define DDDef_HttpCheckJsonErr\ - auto error = reply->error();\ - if(error != QNetworkReply::NoError) {\ - auto errStr = reply->errorString();\ - if(error==QNetworkReply::OperationCanceledError) {\ - error = QNetworkReply::TimeoutError;\ - errStr = QCoreApplication::translate("Def","Connection Timeout");\ - }\ - if(waitingDlg) waitingDlg->close();\ - QMessageBox::critical(gMainWin, QCoreApplication::translate("Def","Error"), QString::number(error)+" "+QMetaEnum::fromType().valueToKey(error)+" "+errStr);\ - return;\ - }\ - auto status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();\ - if(status != 200) {\ - if(waitingDlg) waitingDlg->close();\ - QMessageBox::critical(gMainWin, QCoreApplication::translate("Def","Error"), QString::number(status)+" "+reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString());\ - return;\ - }\ - auto resp = reply->readAll();\ - QJsonParseError jsonErr;\ - QJsonDocument json = QJsonDocument::fromJson(resp, &jsonErr);\ - if(jsonErr.error != QJsonParseError::NoError) {\ - if(waitingDlg) waitingDlg->close();\ - QMessageBox::critical(gMainWin, QCoreApplication::translate("Def","Error"), "JsonParseError "+jsonErr.errorString());\ - return;\ - }\ - if(! json["success"].toBool()) {\ - if(waitingDlg) waitingDlg->close();\ - QMessageBox::warning(gMainWin, QCoreApplication::translate("Def","Tip Info"), QCoreApplication::translate("Def","Fail"));\ - return;\ - } - - -#define CHECK_CARD_SELECTED \ - if(m_pLedlist!=nullptr) {\ - if(m_pLedlist->count()==0 || (m_pLedlist->count()==1 && m_pLedCard==nullptr)) {\ - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController"));\ - return;\ - }\ - } - -#define MACRO_DEFINE_TIPDLG_FUCN(TIP,SUCCESS,FAILED) \ - if(m_pLedlist!=nullptr) {\ - if(m_pLedlist->count()<=1) {\ - if(m_pLedCard!=nullptr) {\ - HttpPostByTypeJsonObject(pHpptClient,m_strUrl,json);\ - if(m_PostingDlg==nullptr) {\ - m_PostingDlg = new LoEmptyDialog(this);\ - connect(m_PostingDlg,SIGNAL(sigClose()),this,SLOT(DeletePostingDlg()));\ - connect(m_pGetAskTimer,SIGNAL(timeout()),m_PostingDlg,SLOT(TimerOutUnlock()));\ - m_PostingDlg->lock(TIP,SUCCESS,FAILED);\ - m_pGetAskTimer->start(5000);\ - m_PostingDlg->exec();\ - }\ - }\ - } else emit sigSend(json,TIP);\ - } - -#define MACRO_DEFINE_TIPDLG_ALL_FUCN(READBACK,SUCCESS,FAILED) \ - if(m_pLedCard!=nullptr)\ - {\ - if(m_PostingDlg==nullptr)\ - {\ - m_PostingDlg = new LoEmptyDialog(this);\ - connect(m_PostingDlg,SIGNAL(sigClose()),this,SLOT(DeletePostingDlg()));\ - connect(m_pGetAskTimer,SIGNAL(timeout()),m_PostingDlg,SLOT(TimerOutUnlock()));\ - m_PostingDlg->lock(READBACK+" "+m_pLedCard->m_strCardId,SUCCESS,FAILED);\ - m_pGetAskTimer->start(5000);\ - m_PostingDlg->exec();\ - }\ - }\ - - -#define MARCO_DEFINE_CONTROL_FUNC2(PARENT,PARENT1) \ - pHpptClient = new HpptClient(this);\ - connect(pHpptClient,SIGNAL(httpPostRspReady(QString , QString , QByteArray )),this,SLOT(OnProHttpResponse(QString , QString , QByteArray)));\ - pHpptClientAll = new HpptClient(this);\ - connect(pHpptClientAll,SIGNAL(httpPostRspReady(QString , QString , QByteArray )),this,SLOT(OnProHttpResponseAll(QString , QString , QByteArray)));\ - m_pGetAskTimer=new QTimer(this);\ - connect(PARENT1,SIGNAL(sigSwitchIndexChanged(int)),this,SLOT(OnControlTypeSwitchIndexChanged(int)));\ - connect(PARENT,SIGNAL(sigSelectedDeviceList(QList *)),this,SLOT(onSelectedDeviceList(QList *)));\ - connect(this,SIGNAL(sigSend(QJsonObject &,QString)),PARENT,SLOT(OnControlSendJson(QJsonObject &,QString)));\ - onSelectedDeviceList(list); - -#define MACRO_ASKTIME_STOP \ -if(m_pGetAskTimer && m_pGetAskTimer->isActive()) m_pGetAskTimer->stop(); - -#define MACRO_POSTING_DLG_UNLOCK \ -if(m_PostingDlg && m_PostingDlg->getLockStatus()) m_PostingDlg->unlock(); - -#define MACRO_DEFINE_CONTROL_FUNC3 \ - if(m_pLedlist!=nullptr)\ - {\ - if(m_pLedlist->count()==1)\ - {\ - m_pLedCard=list->at(0);\ - m_strUrl="http://"+m_pLedCard->m_strCardIp+":2016/settings";\ - if(m_oldLedlist!=m_pLedCard&&m_bSelected==true)\ - {\ - m_oldLedlist=m_pLedCard;\ - onReadbackAllThisPage();\ - }\ - }\ - } - -typedef struct _ST_ANSY_PROGRAM_PACKET -{ - unsigned char SyncHead[3]; - unsigned char ucCommType; - int iBaoLiu; - unsigned int iLength; - unsigned char pDataBuffer[20]; -}ST_ANSY_PROGRAM_PACKET,*P_ST_ANSY_PROGRAM_PACKET; - -#endif // GLOBALDEFINE_H +#ifndef GLOBALDEFINE_H +#define GLOBALDEFINE_H +#include +#include +#include +#include +#include + +enum { + MainPage_DeviceManager = 0, + MainPage_ProgManager, + MainPage_Setting, + MainPage_LoraScreen, + MainPage_End, +}; + +struct RESTORE_IP { + char cNewIp[20]; + char cMask[20]; + char cGateway[20]; + char cDns[20]; +}; +struct Packet { + unsigned char SyncHead[3]; + unsigned char ucCommType; + char serialCode[20]; + unsigned int iLength; +}; +struct STREAM_PACKET { + unsigned char SyncHead[3]; + unsigned char ucCommType; + char ucSerialCode[20]; + unsigned int iLength; + char pDataBuffer[2049]; +}; +struct ST_ANSY_PROGRAM_PACKET { + unsigned char SyncHead[3]; + unsigned char ucCommType; + int iBaoLiu; + unsigned int iLength; + unsigned char pDataBuffer[20]; +}; + +enum _NET_COMMU_TYPE { + COMMAND_SAVE_ADVANCE_PARAM_NOT_RESET=0x40, + COMMAND_ONLY_RESET_CARD_IP=0X43, + COMMAND_SET_M31_DOUBLE_HUB=0X44, + COMMAND_CONNECT_COLSE =0x7A, + COMMAND_UPGRADE = 0x80, + COMMAND_SIGNLE_FILE_UPGRADE , + COMMAND_LOOPCHECK , + COMMAND_VERIFY_CLOCK , + COMMAND_SCREEN_OPERATOR,//0x84 + COMMAND_SET_SERIAL_NUM, + NET_COMMU_TYPE_PLAY_IN_LINE , // 网络同步在线播放. + NET_COMMU_TYPE_PREVIEW_IN_LINE, // 网络在线预览. + NET_COMMU_TYPE_UPGRADE_SYSTEM, // 系统升级. + NET_COMMU_TYPE_RECOVER_SYSTEM, // 系统还原到上一次正确的启动. + SCREEN_OPERATOR_COMM_PARAMS_SAVE, // 参数保存. + NET_COMMU_TYPE_COMM_EXIT,//普通退出,不重启 + NET_COMMU_TYPE_AUDIO_PLAY,//0X8C + NET_COMMU_TYPE_IO, + NET_COMMU_TYPE_IO_CHECK, + NET_COMMU_TYPE_LIMITE_TIME, + NET_COMMU_TYPE_SYSTEM_BROADCAST,//0X90 + NET_COMMU_TYPE_REALTIME_INSERT_PLAY, + + NET_COMMU_TYPE_MODIFY_SERIAL_ID, + NET_COMMU_TYPE_KERNEL_UPGRADE_SYSTEM, + NET_COMMU_TYPE_UPGRADE_FINISHED_EXIT, + NET_COMMU_TYPE_REAL_TIME_INSERT_PLAY_WITH_LIST_EXIT, + NET_COMMU_TYPE_ZNSZ,// 智能设置命令. + NET_COMMU_TYPE_SELECT_PROGRAM_PLAY,// 选节目播放.0x97 + NET_COMMU_TYPE_SELECT_MULI_PROGRAM_PLAY,//98选播多个节目 + NET_COMMU_TYPE_GET_PROGRAM_NAME,//99获取所有节目的名称 + NET_COMMU_TYPE_GET_CUR_PLAY_STATUS,//9a查询当前播放的详细信息 + NET_COMMU_TYPE_POWER_PANEL_ON_OR_OFF,//9b开关大屏幕 + NET_COMMU_TYPE_ADJUST_BRIGHTNESS,//9c调节亮度 + NET_COMMU_TYPE_GET_SYSTEM_STATUS,//9d获取系统状态 + NET_COMMU_TYPE_VERIFY_SIGN,//校验签名9e + NET_COMMU_TYPE_SET_WEB_SERVER_PARAM,//配置web服务器参数 + NET_COMMU_TYPE_GET_WEB_SERVER_PARAM,//a0 + NET_COMMU_TYPE_SET_WIFI_PARAM,//a1配置wifi参数 + NET_COMMU_TYPE_GET_WIFI_PARAM,//a2获取wifi参数 + NET_COMMU_TYPE_SCAN_AP_WIFI_PARAM,//a3获取ap热点的名称 + NET_COMMU_TYPE_GET_ANDROID=0xa4, + NET_COMMU_TYPE_INSTALL_APK=0xa5, + NET_COMMU_TYPE_UNINSTALL_APK=0xa6, + NET_COMMU_TYPE_SET_DNS=0xa7, + NET_COMMU_TYPE_GET_DNS=0xa8, + NET_COMMU_TYPE_SET_PROXY=0xa9, + NET_COMMU_TYPE_GET_PROXY=0xaa, + NET_COMMU_TYPE_SET_ANDROID_COMMUNICATION=0xab, + NET_COMMU_TYPE_GET_ANDROID_COMMUNICATION=0xac, + NET_COMMU_TYPE_GET_SIM_STATUS=0xad, + NET_COMMU_TYPE_GET_APN_PARAM=0xae, + NET_COMMU_TYPE_GET_APK_VERSION=0xaf, + NET_COMMU_TYPE_SET_REALTIME_PARAM=0xb0, + NET_COMMU_TYPE_GET_REALTIME_PARAM=0xb1, + NET_COMMU_TYPE_SET_REALTIME_LINSTEN_PARAM=0xb2, + NET_COMMU_TYPE_GET_REALTIME_LINSTEN_PARAM=0xb3, + NET_COMMU_TYPE_SET_HUAWEI_4G=0xB4, + NET_COMMU_TYPE_GET_HUAWEI_4G=0xB5, + NET_COMMU_TYPE_CLEAR_ANDROID_PROGRAM=0xB6, + NET_COMMU_TYPE_SET_AP_PARAM=0xB7, + NET_COMMU_TYPE_GET_AP_PARAM=0xB8, + GET_REALY_RESOLUTION=0xB9, + GET_REALY_ANDROID_FIRMWARE_INFO=0xBA, + NET_COMMU_TYPE_NUM, + + COMMAND_UPGRADE_ANSWER =0xC0, + COMMAND_SIGNLE_FILE_UPGRADE_ANSWER , + COMMAND_LOOPCHECK_ANSWER , + COMMAND_VERIFY_CLOCK_ANSWER , + COMMAND_SCREEN_OPERATOR_ANSWER, + COMMAND_SET_SERIAL_NUM_ANSWER, + NET_COMMU_TYPE_PLAY_IN_LINE_ANSWER , // 网络同步在线播放. + NET_COMMU_TYPE_PREVIEW_IN_LINE_ANSWER, // 网络在线预览. + NET_COMMU_TYPE_UPGRADE_SYSTEM_ANSWER, // 系统升级. + NET_COMMU_TYPE_RECOVER_SYSTEM_ANSWER, // 系统还原到上一次正确的启动. + SCREEN_OPERATOR_COMM_PARAMS_SAVE_ANSWER, + NET_COMMU_TYPE_COMM_EXIT_ANSWER, + NET_COMMU_TYPE_AUDIO_PLAY_ANSWER,//0XcC + NET_COMMU_TYPE_IO_ANSWER, + NET_COMMU_TYPE_IO_CHECK_ANSWER, + NET_COMMU_TYPE_LIMITE_TIME_ANSWER, + + NET_COMMU_TYPE_SYSTEM_BROADCAST_ANSWER, + NET_COMMU_TYPE_REALTIME_INSERT_PLAY_ANSWER, + NET_COMMU_TYPE_REALTIME_INSERT_PLAY_WITH_GLINT_ANSWER , //带闪烁功能的实时插播 + + NET_COMMU_TYPE_KERNEL_UPGRADE_SYSTEM_ANSWER, + NET_COMMU_TYPE_UPGRADE_FINISHED_EXIT_ANSWER,//0xd4 + NET_COMMU_TYPE_REAL_TIME_INSERT_PLAY_WITH_LIST_EXIT_ANSWER, + NET_COMMU_TYPE_ZNSZ_ANSWER,// 智能设置命令. + NET_COMMU_TYPE_SELECT_PROGRAM_PLAY_ANSWER,//0x97 选节目播放. + NET_COMMU_TYPE_SELECT_MULI_PROGRAM_PLAY_ANSWER, + NET_COMMU_TYPE_GET_PROGRAM_NAME_ANSWER, + NET_COMMU_TYPE_GET_CUR_PLAY_STATUS_ANSWER, + NET_COMMU_TYPE_POWER_PANEL_ON_OR_OFF_ANSWER, + NET_COMMU_TYPE_ADJUST_BRIGHTNESS_ANSWER, + NET_COMMU_TYPE_GET_SYSTEM_STATUS_ANSWER,//获取系统状态 + NET_COMMU_TYPE_NUM_ANSWER, + + COMMAND_CONNECT_COLSE_ANSWER +}; + +extern bool gVideoCompress; +extern bool gVideoTranscoding; +extern bool gTextAntialiasing; +extern bool gShowLoraScreen; +extern bool gWidthSplit; + +extern bool isTextValid(const QString &strIP); +extern quint64 dirFileSize(const QString &path); +extern bool isFileExist(QString fullFileName); +extern QString getRandomString(int length); +extern void HttpPostByTypeJsonObject(HpptClient *pHpptClient, QString strUrl,QJsonObject json); +extern bool copyDir(const QString &source, const QString &destination, bool override); +extern unsigned char GetCheckCodeIn8(unsigned char * pBuffer,unsigned int uiSize); + +enum _ENUM_CONTRL_WIDGET { + Setting_Bright=0, + Setting_PowerControl, + Setting_NetCfg, + Setting_VerifyClock, + Setting_Encrypt, + Setting_HDMI, + Setting_Volume, + Setting_Advanced, + Setting_Test, + Setting_End, +}; + +QNetworkRequest netReq(const QString &url, const QByteArray & = QByteArray(), int = QNetworkRequest::DefaultTransferTimeoutConstant); +inline QNetworkRequest reqForJson(const QString &url, int timeout = QNetworkRequest::DefaultTransferTimeoutConstant) { + return netReq(url, "application/json", timeout); +} +QString replyErr(QNetworkReply *); +QString checkReply(QNetworkReply *, QJsonDocument * = 0); +QString checkReplyForJson(QNetworkReply *, QJsonDocument * = 0, QByteArray * = 0); + +#define Def_CtrlReqPre \ + waitingDlg->show();\ + auto card = gSelCards->at(0);\ + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact));\ + connect(waitingDlg, &WaitingDlg::rejected, reply, [reply] {\ + reply->blockSignals(true);\ + reply->abort();\ + reply->blockSignals(false);\ + reply->deleteLater();\ + }); + +#define Def_CtrlSetReqAfter \ + QString err = checkReplyForJson(reply);\ + if(! err.isEmpty()) {\ + waitingDlg->close();\ + QMessageBox::critical(gMainWin, tr("Error"), err);\ + return;\ + }\ + waitingDlg->success(); + +#define Def_CtrlSingleGetReply \ + QJsonDocument json;\ + QString err = checkReplyForJson(reply, &json);\ + if(! err.isEmpty()) {\ + waitingDlg->close();\ + QMessageBox::critical(gMainWin, tr("Error"), err);\ + return;\ + } + +#define Def_CtrlSetMulti(tip) \ + auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact));\ + connect(reply, &QNetworkReply::finished, card, [=] {\ + QString err = checkReplyForJson(reply);\ + gFdResInfo->append(card->m_strCardId+" "+tip+" "+(err.isEmpty()?QCoreApplication::translate("Def","Success"):err));\ + }); + +#define CHECK_CARD_SELECTED \ + if(gSelCards->isEmpty()) {\ + QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController"));\ + return;\ + } + +#define MACRO_DEFINE_TIPDLG_FUCN(TIP,SUCCESS,FAILED) \ + if(gSelCards->count()==1) {\ + HttpPostByTypeJsonObject(pHpptClient, m_strUrl, json);\ + if(m_PostingDlg==nullptr) {\ + m_PostingDlg = new LoEmptyDialog(this);\ + connect(m_PostingDlg,SIGNAL(sigClose()),this,SLOT(DeletePostingDlg()));\ + connect(m_pGetAskTimer,SIGNAL(timeout()),m_PostingDlg,SLOT(TimerOutUnlock()));\ + m_PostingDlg->lock(TIP,SUCCESS,FAILED);\ + m_pGetAskTimer->start(5000);\ + m_PostingDlg->exec();\ + }\ + } else if(gSelCards->count() > 1) emit sigSend(json,TIP); + + +#define MACRO_DEFINE_TIPDLG_ALL_FUCN(READBACK,SUCCESS,FAILED) \ + if(gSelCards->count()==1) {\ + if(m_PostingDlg==nullptr) {\ + m_PostingDlg = new LoEmptyDialog(this);\ + connect(m_PostingDlg,SIGNAL(sigClose()),this,SLOT(DeletePostingDlg()));\ + connect(m_pGetAskTimer,SIGNAL(timeout()),m_PostingDlg,SLOT(TimerOutUnlock()));\ + m_PostingDlg->lock(READBACK+" "+gSelCards->at(0)->m_strCardId,SUCCESS,FAILED);\ + m_pGetAskTimer->start(5000);\ + m_PostingDlg->exec();\ + }\ + }\ + + +#define MARCO_DEFINE_CONTROL_FUNC2(PARENT,PARENT1) \ + pHpptClient = new HpptClient(this);\ + connect(pHpptClient,SIGNAL(httpPostRspReady(QString , QString , QByteArray )),this,SLOT(OnProHttpResponse(QString , QString , QByteArray)));\ + pHpptClientAll = new HpptClient(this);\ + connect(pHpptClientAll,SIGNAL(httpPostRspReady(QString , QString , QByteArray )),this,SLOT(OnProHttpResponseAll(QString , QString , QByteArray)));\ + m_pGetAskTimer=new QTimer(this);\ + connect(PARENT1,SIGNAL(sigSwitchIndexChanged(int)),this,SLOT(OnControlTypeSwitchIndexChanged(int)));\ + connect(PARENT,SIGNAL(sigSelectedDeviceList(QList *)),this,SLOT(onSelectedDeviceList(QList *)));\ + connect(this,SIGNAL(sigSend(QJsonObject &,QString)),PARENT,SLOT(OnControlSendJson(QJsonObject &,QString)));\ + onSelectedDeviceList(list); + +#define MACRO_ASKTIME_STOP \ +if(m_pGetAskTimer && m_pGetAskTimer->isActive()) m_pGetAskTimer->stop(); + +#define MACRO_POSTING_DLG_UNLOCK \ +if(m_PostingDlg && m_PostingDlg->getLockStatus()) m_PostingDlg->unlock(); + +#define MACRO_DEFINE_CONTROL_FUNC3 \ + if(m_pLedlist!=nullptr)\ + {\ + if(m_pLedlist->count()==1)\ + {\ + m_pLedCard=list->at(0);\ + m_strUrl="http://"+m_pLedCard->m_strCardIp+":2016/settings";\ + if(m_oldLedlist!=m_pLedCard&&m_bSelected==true)\ + {\ + m_oldLedlist=m_pLedCard;\ + onReadbackAllThisPage();\ + }\ + }\ + } + +#endif // GLOBALDEFINE_H diff --git a/LedOK/gqt.h b/LedOK/gqt.h index 11bc6c8..c789f1c 100644 --- a/LedOK/gqt.h +++ b/LedOK/gqt.h @@ -1,122 +1,122 @@ -#ifndef GQT_H -#define GQT_H -#include -#include -#include - -inline long long steady_milli() { - return std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); -} -inline long long system_milli() { - return std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); -} -inline long long steady_micro() { - return std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); -} -inline long long system_micro() { - return std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); -} - -template -class Wrp { -public: - T *obj; - Wrp(T *obj = nullptr){ - this->obj = obj; - }; - inline Wrp& operator()(T *obj){ - this->obj = obj; - return *this; - } - inline Wrp& operator()(T *obj, QLayout *layout){ - this->obj = obj; - layout->addWidget(obj); - return *this; - } - inline Wrp& addTo(QLayout *layout){ - layout->addWidget(obj); - return *this; - } - inline Wrp& margin(int a){ - obj->setMargin(a); - return *this; - } - inline Wrp& font(const QFont &font){ - obj->setFont(font); - return *this; - } - inline Wrp& font(int size){ - QFont font = obj->font(); - font.setPointSize(size); - obj->setFont(font); - return *this; - } - - inline Wrp& width(int w){ - obj->setFixedWidth(w); - return *this; - } - inline Wrp& height(int h){ - obj->setFixedHeight(h); - return *this; - } - inline Wrp& padding(int wAdd, int hAdd, int minW = 32, int minH = 16){ - wAdd+=8; - hAdd+=8; - QSize size = obj->fontMetrics().size(Qt::TextShowMnemonic, obj->text()); - int &rwidth = size.rwidth(); - rwidth += wAdd; - if(rwidth < minW) rwidth = minW; - int &rheight = size.rheight(); - rheight += hAdd; - if(rheight < minH) rheight = minH; - obj->setFixedSize(size); - return *this; - } - - inline Wrp& alignC(){ - obj->setAlignment(Qt::AlignCenter); - return *this; - } - inline Wrp& alignR(){ - obj->setAlignment(Qt::AlignRight); - return *this; - } - - inline Wrp& connStart(){ - QObject::connect(obj, &QThread::finished, obj, &QThread::deleteLater); - obj->start(); - return *this; - } -}; - -class VBox : public QBoxLayout { -public: - inline VBox(QWidget *parent=nullptr) : QBoxLayout(TopToBottom, parent) {} - inline VBox(QBoxLayout *parent) : QBoxLayout(TopToBottom) { - parent->addLayout(this); - }; -}; -class HBox : public QBoxLayout { -public: - inline HBox(QWidget *parent=nullptr) : QBoxLayout(LeftToRight, parent) {} - inline HBox(QBoxLayout *parent) : QBoxLayout(LeftToRight) { - parent->addLayout(this); - }; -}; - -template -inline QThread *ThreadStart(Func &&f) { - QThread* thread = QThread::create(f); - QObject::connect(thread, &QThread::finished, thread, &QThread::deleteLater); - thread->start(); - return thread; -} - -inline void select(QComboBox *combo, const QVariant &data) { - int idx = combo->findData(data); - if(idx!=-1) combo->setCurrentIndex(idx); -} - - -#endif +#ifndef GQT_H +#define GQT_H +#include +#include +#include + +inline long long steady_milli() { + return std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); +} +inline long long system_milli() { + return std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); +} +inline long long steady_micro() { + return std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); +} +inline long long system_micro() { + return std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); +} + +template +class Wrp { +public: + T *obj; + Wrp(T *obj = nullptr){ + this->obj = obj; + }; + inline Wrp& operator()(T *obj){ + this->obj = obj; + return *this; + } + inline Wrp& operator()(T *obj, QLayout *layout){ + this->obj = obj; + layout->addWidget(obj); + return *this; + } + inline Wrp& addTo(QLayout *layout){ + layout->addWidget(obj); + return *this; + } + inline Wrp& margin(int a){ + obj->setMargin(a); + return *this; + } + inline Wrp& font(const QFont &font){ + obj->setFont(font); + return *this; + } + inline Wrp& font(int size){ + QFont font = obj->font(); + font.setPointSize(size); + obj->setFont(font); + return *this; + } + + inline Wrp& width(int w){ + obj->setFixedWidth(w); + return *this; + } + inline Wrp& height(int h){ + obj->setFixedHeight(h); + return *this; + } + inline Wrp& padding(int wAdd, int hAdd, int minW = 32, int minH = 16){ + wAdd+=8; + hAdd+=8; + QSize size = obj->fontMetrics().size(Qt::TextShowMnemonic, obj->text()); + int &rwidth = size.rwidth(); + rwidth += wAdd; + if(rwidth < minW) rwidth = minW; + int &rheight = size.rheight(); + rheight += hAdd; + if(rheight < minH) rheight = minH; + obj->setFixedSize(size); + return *this; + } + + inline Wrp& alignC(){ + obj->setAlignment(Qt::AlignCenter); + return *this; + } + inline Wrp& alignR(){ + obj->setAlignment(Qt::AlignRight); + return *this; + } + + inline Wrp& connStart(){ + QObject::connect(obj, &QThread::finished, obj, &QThread::deleteLater); + obj->start(); + return *this; + } +}; + +class VBox : public QBoxLayout { +public: + inline VBox(QWidget *parent=nullptr) : QBoxLayout(TopToBottom, parent) {} + inline VBox(QBoxLayout *parent) : QBoxLayout(TopToBottom) { + parent->addLayout(this); + }; +}; +class HBox : public QBoxLayout { +public: + inline HBox(QWidget *parent=nullptr) : QBoxLayout(LeftToRight, parent) {} + inline HBox(QBoxLayout *parent) : QBoxLayout(LeftToRight) { + parent->addLayout(this); + }; +}; + +template +inline QThread *ThreadStart(Func &&f) { + QThread* thread = QThread::create(f); + QObject::connect(thread, &QThread::finished, thread, &QThread::deleteLater); + thread->start(); + return thread; +} + +inline void select(QComboBox *combo, const QVariant &data) { + int idx = combo->findData(data); + if(idx!=-1) combo->setCurrentIndex(idx); +} + + +#endif diff --git a/LedOK/gutil/qcore.cpp b/LedOK/gutil/qcore.cpp new file mode 100644 index 0000000..4eae95f --- /dev/null +++ b/LedOK/gutil/qcore.cpp @@ -0,0 +1 @@ +#include "qcore.h" diff --git a/LedOK/gutil/qcore.h b/LedOK/gutil/qcore.h new file mode 100644 index 0000000..4d5b6dc --- /dev/null +++ b/LedOK/gutil/qcore.h @@ -0,0 +1,33 @@ +#ifndef QCORE_H +#define QCORE_H +#include + +inline QString byteSizeStr(double size) { + const char *units[]{"B", "KB", "MB", "GB", "TB", "PB"}; + auto i = 0; + for(; size >= 1024 && i < 5; i++) size /= 1024; + return QString::number(size, 'g', 3)+" "+units[i]; +} + +inline long long steady_milli() { + return std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); +} +inline long long system_milli() { + return std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); +} +inline long long steady_micro() { + return std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); +} +inline long long system_micro() { + return std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); +} + +template +inline QThread *ThreadStart(Func &&f) { + QThread* thread = QThread::create(f); + QObject::connect(thread, &QThread::finished, thread, &QThread::deleteLater); + thread->start(); + return thread; +} + +#endif diff --git a/LedOK/gutil/qgui.cpp b/LedOK/gutil/qgui.cpp new file mode 100644 index 0000000..745f9da --- /dev/null +++ b/LedOK/gutil/qgui.cpp @@ -0,0 +1,33 @@ +#include "qgui.h" + +const int AlignRight = Qt::AlignRight | Qt::AlignVCenter; + +Table::Table(std::initializer_list colAttrs, int rows, QWidget *parent) : NumTable{rows, (int)colAttrs.size(), parent} { + int i = 0; + for(typename std::initializer_list::const_iterator it = colAttrs.begin(); it != colAttrs.end(); ++it) { + auto item = horizontalHeaderItem(i); + if(item==0) setHorizontalHeaderItem(i, item = new QTableWidgetItem()); + item->setText(it->text); + item->setData(0x99, it->width); + if(it->width > 0) horizontalHeader()->resizeSection(i, it->width); + if(it->resizeMode > -1) horizontalHeader()->setSectionResizeMode(i, (QHeaderView::ResizeMode)it->resizeMode); + mFieldMap.insert(it->field, i++); + } +} + +int Table::sizeHintForColumn(int column) const { + auto item = horizontalHeaderItem(column); + if(item==0) return QTableWidget::sizeHintForColumn(column); + int width = item->data(0x99).toInt(); + if(width==0) return QTableWidget::sizeHintForColumn(column); + auto header = horizontalHeader(); + if(header->sectionResizeMode(column) != QHeaderView::ResizeToContents) return QTableWidget::sizeHintForColumn(column); + int colCnt = columnCount(); + int remainWidth = header->width(), stretchWidth = width; + for(int cc=0; ccsectionResizeMode(cc) == QHeaderView::ResizeToContents) stretchWidth += item->data(0x99).toInt(); + else remainWidth -= item->data(0x99).toInt(); + } + if(remainWidth<=0) return QTableWidget::sizeHintForColumn(column); + return width * remainWidth / stretchWidth; +} diff --git a/LedOK/gutil/qgui.h b/LedOK/gutil/qgui.h new file mode 100644 index 0000000..4412faa --- /dev/null +++ b/LedOK/gutil/qgui.h @@ -0,0 +1,301 @@ +#ifndef QGUI_H +#define QGUI_H + +#include +#include +#include +#include + +extern const int AlignRight; + +inline int setCurrentData(QComboBox *combo, const QVariant &data) { + auto idx = combo->findData(data); + if(idx>-1) combo->setCurrentIndex(idx); + return idx; +} + +class VBox : public QBoxLayout { +public: + inline VBox(QWidget *parent=nullptr) : QBoxLayout(TopToBottom, parent) {} + inline VBox(QBoxLayout *parent) : QBoxLayout(TopToBottom) { + parent->addLayout(this); + }; + inline VBox(QStackedLayout *parent) : QBoxLayout(TopToBottom) { + setContentsMargins(0,0,0,0); + auto wgt = new QWidget; + wgt->setLayout(this); + parent->addWidget(wgt); + }; +}; +class HBox : public QBoxLayout { +public: + inline HBox(QWidget *parent=nullptr) : QBoxLayout(LeftToRight, parent) {} + inline HBox(QBoxLayout *parent) : QBoxLayout(LeftToRight) { + parent->addLayout(this); + }; + inline HBox(QStackedLayout *parent) : QBoxLayout(LeftToRight) { + setContentsMargins(0,0,0,0); + auto wgt = new QWidget; + wgt->setLayout(this); + parent->addWidget(wgt); + }; +}; +class Grid : public QGridLayout { +public: + inline Grid(QWidget *parent=0) : QGridLayout(parent) {} + inline Grid(QBoxLayout *parent) { + parent->addLayout(this); + }; + inline Grid(QStackedLayout *parent) { + auto wgt = new QWidget; + wgt->setLayout(this); + parent->addWidget(wgt); + }; +}; + +class NumTable : public QTableWidget { + Q_OBJECT +public: + explicit NumTable(QWidget *parent = 0) : QTableWidget{parent} {} + NumTable(int rows, int columns, QWidget *parent = 0) : QTableWidget{rows, columns, parent} {} + + inline auto setNoEdit() { + setEditTriggers(QAbstractItemView::NoEditTriggers); + return this; + } + inline auto setColWidth(int value) { + horizontalHeader()->setDefaultSectionSize(value); + return this; + } + inline auto setRowHeight(int value) { + verticalHeader()->setDefaultSectionSize(value); + return this; + } + + inline auto setHeaderText(int column, QString text) { + auto item = horizontalHeaderItem(column); + if(item==0) setHorizontalHeaderItem(column, item = new QTableWidgetItem()); + item->setText(text); + return item; + } + + inline auto itemValid(int row, int column) { + auto item = QTableWidget::item(row, column); + if(item==0) setItem(row, column, item = new QTableWidgetItem); + return item; + } + inline auto text(int row, int column) { + auto item = QTableWidget::item(row, column); + if(item==0) return QString(); + return item->text(); + } + inline auto setText(int row, int column, const QString &text) { + auto item = QTableWidget::item(row, column); + if(item) item->setText(text); + else setItem(row, column, item = new QTableWidgetItem(text)); + return item; + } + + inline auto data(int row, int col) { + auto item = QTableWidget::item(row, col); + if(item==0) return QVariant(); + return item->data(Qt::UserRole); + } + inline auto setData(int row, int col, const QVariant &value) { + auto item = QTableWidget::item(row, col); + if(item==0) setItem(row, col, item = new QTableWidgetItem); + item->setData(Qt::UserRole, value); + return item; + } +}; + +struct ColAttr { + QString field; + QString text; + int width{0}; + int resizeMode{-1}; +}; +class Table : public NumTable { + Q_OBJECT +public: + explicit Table(QWidget *parent = nullptr) : NumTable{parent} {} + Table(std::initializer_list colAttrs, int rows = 0, QWidget *parent = nullptr); + + inline auto setDefs() { + setSelectionBehavior(QTableWidget::SelectRows); + setEditTriggers(QAbstractItemView::NoEditTriggers); + setAlternatingRowColors(true); + return this; + } + inline auto setColStretch() { + horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); + return this; + } + inline auto setRowStretch() { + verticalHeader()->setSectionResizeMode(QHeaderView::Stretch); + return this; + } + inline auto setColFit() { + horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); + return this; + } + inline auto setRowFit() { + verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); + return this; + } + inline auto setColWidth(int value) { + horizontalHeader()->setDefaultSectionSize(value); + return this; + } + inline auto setRowHeight(int value) { + verticalHeader()->setDefaultSectionSize(value); + return this; + } + + inline auto setHeaderText(QString column, QString text) { + auto col = mFieldMap[column]; + auto item = horizontalHeaderItem(col); + if(item==0) setHorizontalHeaderItem(col, item = new QTableWidgetItem()); + item->setText(text); + return item; + } + + inline auto appendRow() { + auto value = rowCount(); + setRowCount(value + 1); + return value; + } + + inline auto item(int row, QString column) { + auto col = mFieldMap[column]; + return QTableWidget::item(row, col); + } + inline void setItem(int row, QString column, QTableWidgetItem *item) { + auto col = mFieldMap[column]; + QTableWidget::setItem(row, col, item); + } + inline auto text(int row, QString column) { + auto col = mFieldMap[column]; + auto item = QTableWidget::item(row, col); + if(item==0) return QString(); + return item->text(); + } + inline auto setText(int row, QString column, const QString &text) { + auto col = mFieldMap[column]; + auto item = QTableWidget::item(row, col); + if(item) item->setText(text); + else QTableWidget::setItem(row, col, item = new QTableWidgetItem(text)); + return item; + } + + inline auto data(int row, QString column) { + auto col = mFieldMap[column]; + auto item = QTableWidget::item(row, col); + if(item==0) return QVariant(); + return item->data(Qt::UserRole); + } + inline auto setData(int row, QString column, const QVariant &value) { + auto col = mFieldMap[column]; + auto item = QTableWidget::item(row, col); + if(item==0) QTableWidget::setItem(row, col, item = new QTableWidgetItem); + item->setData(Qt::UserRole, value); + return item; + } + + inline auto cellWidget(int row, QString column) { + auto col = mFieldMap[column]; + return QTableWidget::cellWidget(row, col); + } + inline void setCellWidget(int row, QString column, QWidget *widget) { + auto col = mFieldMap[column]; + QTableWidget::setCellWidget(row, col, widget); + } + + QMap mFieldMap; + +public Q_SLOTS: + inline void clearRows() {setRowCount(0);} + +protected: + int sizeHintForColumn(int column) const override; +}; + +class ResizeEmitedWgt : public QWidget { + Q_OBJECT +public: + explicit ResizeEmitedWgt(QWidget* parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags()) : QWidget{parent, f} {} +protected: + void resizeEvent(QResizeEvent *) override {emit resized();} +signals: + void resized(); +}; + + +template +class Wrp { +public: + T *obj; + Wrp(T *obj = nullptr){ + this->obj = obj; + }; + inline Wrp& operator()(T *obj){ + this->obj = obj; + return *this; + } + inline Wrp& operator()(T *obj, QLayout *layout){ + this->obj = obj; + layout->addWidget(obj); + return *this; + } + inline Wrp& addTo(QLayout *layout){ + layout->addWidget(obj); + return *this; + } + inline Wrp& margin(int a){ + obj->setMargin(a); + return *this; + } + inline Wrp& font(const QFont &font){ + obj->setFont(font); + return *this; + } + inline Wrp& font(int size){ + QFont font = obj->font(); + font.setPointSize(size); + obj->setFont(font); + return *this; + } + + inline Wrp& width(int w){ + obj->setFixedWidth(w); + return *this; + } + inline Wrp& height(int h){ + obj->setFixedHeight(h); + return *this; + } + inline Wrp& padding(int wAdd, int hAdd, int minW = 32, int minH = 16){ + wAdd+=8; + hAdd+=8; + QSize size = obj->fontMetrics().size(Qt::TextShowMnemonic, obj->text()); + int &rwidth = size.rwidth(); + rwidth += wAdd; + if(rwidth < minW) rwidth = minW; + int &rheight = size.rheight(); + rheight += hAdd; + if(rheight < minH) rheight = minH; + obj->setFixedSize(size); + return *this; + } + + inline Wrp& alignC(){ + obj->setAlignment(Qt::AlignCenter); + return *this; + } + inline Wrp& alignR(){ + obj->setAlignment(Qt::AlignRight); + return *this; + } +}; + +#endif diff --git a/LedOK/gutil/qnetwork.cpp b/LedOK/gutil/qnetwork.cpp new file mode 100644 index 0000000..4c4a020 --- /dev/null +++ b/LedOK/gutil/qnetwork.cpp @@ -0,0 +1,83 @@ +#include "qnetwork.h" + +#include +#include + +const char *const FormBoundary = "----GangphonQtBoundary_.oOo._"; + +QNetworkAccessManager &netAccess() { + static QNetworkAccessManager access; + return access; +}; + +QString errStr(QNetworkReply *reply) { + reply->deleteLater(); + auto error = reply->error(); + if(error != QNetworkReply::NoError) { + if(error==QNetworkReply::OperationCanceledError) return QString(QMetaEnum::fromType().valueToKey(QNetworkReply::TimeoutError))+" ("+QString::number(QNetworkReply::TimeoutError)+") "+QCoreApplication::translate("Net","Connection Timeout"); + auto errStr = reply->errorString(); + if(error!=QNetworkReply::InternalServerError || ! errStr.endsWith("replied: Unknown")) return QString(QMetaEnum::fromType().valueToKey(error))+" ("+QString::number(error)+") "+errStr; + } + auto status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + if(status != 200) return QString::number(status)+" "+reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString(); + return ""; +} +QString errStrWithData(QNetworkReply *reply, QJsonDocument *outJson) { + auto err = errStr(reply); + if(! err.isEmpty()) { + auto data = reply->readAll(); + if(! data.isEmpty()) err += "\n"+data; + return err; + } + if(outJson) { + auto data = reply->readAll(); + QJsonParseError jsonErr; + *outJson = QJsonDocument::fromJson(data, &jsonErr); + if(jsonErr.error != QJsonParseError::NoError) return "JSON "+QCoreApplication::translate("Net","Error")+": "+data; + } + return ""; +} + + +const char* socketErrKey(int value) { + static auto metaEnum = QMetaEnum::fromType(); + return metaEnum.valueToKey(value); +} + +bool TcpSocket::waitForConnected(int msecs) { + if(state() == ConnectedState) return true; + QEventLoop loop; + connect(this, &QTcpSocket::connected, &loop, &QEventLoop::quit); + return connAndExec(msecs, &loop); +} +bool TcpSocket::waitForDisconnected(int msecs) { + if(state() == UnconnectedState) return true; + QEventLoop loop; + connect(this, &QTcpSocket::disconnected, &loop, &QEventLoop::quit); + return connAndExec(msecs, &loop); +} +bool TcpSocket::waitForBytesWritten(int msecs) { + QEventLoop loop; + connect(this, &QTcpSocket::bytesWritten, &loop, &QEventLoop::quit); + return connAndExec(msecs, &loop); +} +bool TcpSocket::waitForReadyRead(int msecs) { + QEventLoop loop; + connect(this, &QTcpSocket::readyRead, &loop, &QEventLoop::quit); + return connAndExec(msecs, &loop); +} + +bool TcpSocket::connAndExec(int msecs, QEventLoop *loop) { + connect(this, &QTcpSocket::errorOccurred, loop, [loop] { + loop->exit(1); + }); + if(msecs > 0) { + connect(this, &TcpSocket::timeout, loop, &QEventLoop::exit); + if(timerId!=0) killTimer(timerId); + timerId = startTimer(msecs); + } + auto res = loop->exec(); + timerStop(); + if(res==5) setSocketError(SocketTimeoutError); + return res==0; +} diff --git a/LedOK/gutil/qnetwork.h b/LedOK/gutil/qnetwork.h new file mode 100644 index 0000000..8b1fe86 --- /dev/null +++ b/LedOK/gutil/qnetwork.h @@ -0,0 +1,90 @@ +#ifndef QNETWORK_H +#define QNETWORK_H + +#include +#include +#include +#include + +extern const char *const FormBoundary; + +QNetworkAccessManager &netAccess(); + +class NetReq : public QNetworkRequest { +public: + NetReq(); + explicit NetReq(const QString &url) : QNetworkRequest{url}{}; + explicit NetReq(const QUrl &url) : QNetworkRequest{url}{}; + NetReq(const QNetworkRequest &other) : QNetworkRequest{other}{}; + + inline NetReq &type(const QByteArray &value) { + setRawHeader("Content-Type", value); + return *this; + } + inline NetReq &typeJson() { + setRawHeader("Content-Type", "application/json"); + return *this; + } + inline NetReq &timeout(int timeout) { + setTransferTimeout(timeout); + return *this; + } + inline NetReq &v5() { + setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy); + return *this; + } + + inline QNetworkReply *get() { + return netAccess().get(*this); + } + inline QNetworkReply *post(const QByteArray &data) { + return netAccess().post(*this, data); + } + inline QNetworkReply *post(const QJsonObject &json) { + setRawHeader("Content-Type", "application/json"); + return netAccess().post(*this, QJsonDocument{json}.toJson(QJsonDocument::Compact)); + } + inline QNetworkReply *post(const QJsonArray &json) { + setRawHeader("Content-Type", "application/json"); + return netAccess().post(*this, QJsonDocument{json}.toJson(QJsonDocument::Compact)); + } + inline QNetworkReply *post(QHttpMultiPart *multiPart) { + return netAccess().post(*this, multiPart); + } +}; + +QString errStr(QNetworkReply *); +QString errStrWithData(QNetworkReply *, QJsonDocument * = 0); + +const char* socketErrKey(int value); + +class TcpSocket : public QTcpSocket { + Q_OBJECT +public: + explicit TcpSocket(QObject *parent = nullptr) : QTcpSocket{parent} {}; + ~TcpSocket() { + if(timerId!=0) killTimer(timerId); + }; + bool waitForConnected(int msecs = 30000) override; + bool waitForDisconnected(int msecs = 30000) override; + bool waitForBytesWritten(int msecs = 30000) override; + bool waitForReadyRead(int msecs = 30000) override; +protected: + void timerEvent(QTimerEvent *e) override { + if(e->timerId()!=timerId) return; + killTimer(timerId); + timerId = 0; + emit timeout(5); + }; + bool connAndExec(int msecs, QEventLoop *loop); + inline void timerStop() { + if(timerId==0) return; + killTimer(timerId); + timerId = 0; + } + int timerId = 0; +signals: + void timeout(int); +}; + +#endif // QNETWORK_H diff --git a/LedOK/importbninprogramdlg.cpp b/LedOK/importbninprogramdlg.cpp index cdfd725..aa1b8b3 100644 --- a/LedOK/importbninprogramdlg.cpp +++ b/LedOK/importbninprogramdlg.cpp @@ -1,14 +1,14 @@ -#include "importbninprogramdlg.h" -#include "ui_importbninprogramdlg.h" - -ImportBnInProgramDlg::ImportBnInProgramDlg(QWidget *parent) : - LoQDialog(parent), - ui(new Ui::ImportBnInProgramDlg) -{ - ui->setupUi(this); -} - -ImportBnInProgramDlg::~ImportBnInProgramDlg() -{ - delete ui; -} +#include "importbninprogramdlg.h" +#include "ui_importbninprogramdlg.h" + +ImportBnInProgramDlg::ImportBnInProgramDlg(QWidget *parent) : + LoQDialog(parent), + ui(new Ui::ImportBnInProgramDlg) +{ + ui->setupUi(this); +} + +ImportBnInProgramDlg::~ImportBnInProgramDlg() +{ + delete ui; +} diff --git a/LedOK/importbninprogramdlg.h b/LedOK/importbninprogramdlg.h index 40f863a..392994a 100644 --- a/LedOK/importbninprogramdlg.h +++ b/LedOK/importbninprogramdlg.h @@ -1,22 +1,22 @@ -#ifndef IMPORTBNINPROGRAMDLG_H -#define IMPORTBNINPROGRAMDLG_H - -#include - -namespace Ui { -class ImportBnInProgramDlg; -} - -class ImportBnInProgramDlg : public LoQDialog -{ - Q_OBJECT - -public: - explicit ImportBnInProgramDlg(QWidget *parent = nullptr); - ~ImportBnInProgramDlg(); - -private: - Ui::ImportBnInProgramDlg *ui; -}; - -#endif // IMPORTBNINPROGRAMDLG_H +#ifndef IMPORTBNINPROGRAMDLG_H +#define IMPORTBNINPROGRAMDLG_H + +#include + +namespace Ui { +class ImportBnInProgramDlg; +} + +class ImportBnInProgramDlg : public LoQDialog +{ + Q_OBJECT + +public: + explicit ImportBnInProgramDlg(QWidget *parent = nullptr); + ~ImportBnInProgramDlg(); + +private: + Ui::ImportBnInProgramDlg *ui; +}; + +#endif // IMPORTBNINPROGRAMDLG_H diff --git a/LedOK/importbninprogramdlg.ui b/LedOK/importbninprogramdlg.ui index 1194194..51fd2dd 100644 --- a/LedOK/importbninprogramdlg.ui +++ b/LedOK/importbninprogramdlg.ui @@ -1,68 +1,68 @@ - - - ImportBnInProgramDlg - - - - 0 - 0 - 638 - 296 - - - - Dialog - - - - - 10 - 210 - 621 - 32 - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - buttonBox - rejected() - ImportBnInProgramDlg - reject() - - - 316 - 260 - - - 286 - 274 - - - - - buttonBox - accepted() - ImportBnInProgramDlg - accept() - - - 248 - 254 - - - 157 - 274 - - - - - + + + ImportBnInProgramDlg + + + + 0 + 0 + 638 + 296 + + + + Dialog + + + + + 10 + 210 + 621 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + buttonBox + rejected() + ImportBnInProgramDlg + reject() + + + 316 + 260 + + + 286 + 274 + + + + + buttonBox + accepted() + ImportBnInProgramDlg + accept() + + + 248 + 254 + + + 157 + 274 + + + + + diff --git a/LedOK/importprogramdlg.ui b/LedOK/importprogramdlg.ui index eb5f518..cb87e5a 100644 --- a/LedOK/importprogramdlg.ui +++ b/LedOK/importprogramdlg.ui @@ -1,80 +1,80 @@ - - - Dialog - - - Qt::NonModal - - - - 0 - 0 - 320 - 240 - - - - - 320 - 240 - - - - Dialog - - - false - - - - - 10 - 200 - 301 - 32 - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - buttonBox - accepted() - Dialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - Dialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - + + + Dialog + + + Qt::NonModal + + + + 0 + 0 + 320 + 240 + + + + + 320 + 240 + + + + Dialog + + + false + + + + + 10 + 200 + 301 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + buttonBox + accepted() + Dialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + Dialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/LedOK/main.cpp b/LedOK/main.cpp index 77ad255..4497704 100644 --- a/LedOK/main.cpp +++ b/LedOK/main.cpp @@ -1,7 +1,9 @@ #include "mainwindow.h" #include +#include #include #include +#include #ifdef _MSC_VER //MSVC编译器 #include @@ -29,7 +31,7 @@ LONG WINAPI handleException(_EXCEPTION_POINTERS *excep) { #endif QString gFileHome; - +QString css; int main(int argc, char *argv[]) { QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); @@ -38,12 +40,18 @@ int main(int argc, char *argv[]) { QApplication::setOrganizationDomain("www.ledok.cn"); QApplication::setApplicationName("LedOK Express"); QApplication a(argc, argv); - gFileHome = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); + a.setStyle(QStyleFactory::create("Fusion")); + QFile file(":/css.css"); + if(file.exists() && file.open(QFile::ReadOnly)) { + a.setStyleSheet(css = file.readAll()); + file.close(); + } QFont font; font.setFamilies(QStringList{"Arial","Microsoft YaHei UI"}); font.setPixelSize(14); a.setFont(font); + gFileHome = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); QSplashScreen splash(QPixmap(":/res/splash.png")); splash.show(); splash.showMessage(QObject::tr("Setting up the LedOK Express..."), Qt::AlignRight | Qt::AlignTop, Qt::white); diff --git a/LedOK/mainwindow.cpp b/LedOK/mainwindow.cpp index 47835ef..f72e7c4 100644 --- a/LedOK/mainwindow.cpp +++ b/LedOK/mainwindow.cpp @@ -1,10 +1,10 @@ #include "mainwindow.h" #include "base/aboutdlg.h" #include "base/softconfigdialog.h" -#include "base/updaterdialog.h" +#include "gutil/qgui.h" #include "cfg.h" #include "tools.h" -#include "wDevicesManager/upgradeapkdialog.h" +#include "device/upgradeapkdialog.h" #include #include #include @@ -14,6 +14,7 @@ #include #include #include +#include "QSimpleUpdater.h" QWidget *gMainWin; extern QPoint gPlayPos; @@ -46,30 +47,36 @@ protected: }; MainWindow::MainWindow(QWidget *parent) : BaseWin(parent) { + setAttribute(Qt::WA_AlwaysShowToolTips); gMainWin = this; - QMenu *menuLang = new QMenu(); - QAction *actLan = nullptr; - QAction *actCN = new QAction("中文"); + auto menuLang = new QMenu(); + + auto actCN = new QAction("中文"); actCN->setCheckable(true); actCN->setObjectName("zh_CN"); - QAction *actTW = new QAction("中文繁体"); + menuLang->addAction(actCN); + + auto actTW = new QAction("中文繁体"); actTW->setCheckable(true); actTW->setObjectName("zh_TW"); - QAction *actEn = new QAction("English"); + menuLang->addAction(actTW); + + auto actEn = new QAction("English"); actEn->setCheckable(true); actEn->setObjectName("en"); - QAction *actJa = new QAction("日本語"); + menuLang->addAction(actEn); + + auto actJa = new QAction("日本語"); actJa->setCheckable(true); actJa->setObjectName("ja"); - menuLang->addAction(actCN); - menuLang->addAction(actTW); - menuLang->addAction(actEn); menuLang->addAction(actJa); + langGrp = new QActionGroup(menuLang); langGrp->addAction(actCN); langGrp->addAction(actTW); langGrp->addAction(actEn); langGrp->addAction(actJa); + connect(menuLang, &QMenu::triggered, this, [this](QAction* action) { auto lanName = action->objectName(); translator.load("app_"+lanName, ":/i18n"); @@ -77,12 +84,8 @@ MainWindow::MainWindow(QWidget *parent) : BaseWin(parent) { }); QSettings settings; - settings.remove("MainSetting"); - settings.remove("MainWindowMaximized"); - settings.remove("posMainWindow"); - settings.remove("sizeMainWindow"); - settings.remove("DirectlyConnectNetWork"); QString langName = settings.value("Language").toString(); + QAction *actLan = nullptr; if(! langName.isEmpty()) { if(langName.endsWith("CN")) actLan = actCN; else if(langName.endsWith("TW")) actLan = actTW; @@ -105,8 +108,8 @@ MainWindow::MainWindow(QWidget *parent) : BaseWin(parent) { QApplication::installTranslator(&transQt); auto geo = settings.value("MainGeo").toRect(); - if(geo.width()>=800 && geo.height()>=500 && geo.x()>=-600 && geo.x()<=1280 && geo.y()>=-200 && geo.y()<=720) setGeometry(geo); - else resize(1280, 720); + if(geo.width()>=800 && geo.height()>=500 && geo.x()>=-600 && geo.x()<=1280 && geo.y()>=-200 && geo.y()<=800) setGeometry(geo); + else resize(1280, 800); if(settings.value("MainIsMax", false).toBool()) setWindowState(Qt::WindowMaximized); gPlayPos = settings.value("PlayPos").toPoint(); @@ -115,7 +118,6 @@ MainWindow::MainWindow(QWidget *parent) : BaseWin(parent) { icon.load(":/res/Logo.png"); titlePos = QPointF(26, 80); iconPos = QPointF(38, 20); - setStyleSheet(Tools::styleSheet()); auto plt = palette(); plt.setBrush(QPalette::Window, QColor(0xdddddd)); setPalette(plt); @@ -146,33 +148,87 @@ MainWindow::MainWindow(QWidget *parent) : BaseWin(parent) { bn_Setting = new QPushButton(); bn_Setting->setIcon(QIcon(":/res/AppSetting.png")); + bn_Setting->setToolTip(tr("Setting")); + pLayout->addWidget(bn_Setting); pLayout->addWidget(m_wTitle->bn_Minimize); pLayout->addWidget(m_wTitle->bn_Maximize); pLayout->addWidget(m_wTitle->bn_Close); - QMenu *menu_setting = new QMenu(); + auto menu_setting = new QMenu(); act_lang = new QAction(); act_lang->setMenu(menuLang); menu_setting->addAction(act_lang); - act_softconfiguration = new QAction(tr("Software Configuration")); - act_softconfiguration->setObjectName("Software Configuration"); + act_softconfiguration = new QAction(tr("Software Config")); + connect(act_softconfiguration, &QAction::triggered, this, [this] { + SoftConfigDialog dlg(this); + dlg.exec(); + mBtnGrp->button(MainPage_LoraScreen)->setVisible(gShowLoraScreen); + }); menu_setting->addAction(act_softconfiguration); act_update = new QAction(tr("Check for updates")); - act_update->setObjectName("Update"); + connect(act_update, &QAction::triggered, this, [this] { + QDialog dlg(this); + dlg.setWindowFlag(Qt::WindowContextHelpButtonHint, false); + dlg.setWindowTitle(tr("Software Update")); + dlg.resize(500, 400); + + auto vBox = new VBox(&dlg); + + auto label = new QLabel(tr("CurVersion")+": "+APP_VERSION); + auto font = label->font(); + font.setPointSize(14); + label->setFont(font); + vBox->addWidget(label); + + auto fdVerInfo = new QTextEdit; + fdVerInfo->setReadOnly(true); + vBox->addWidget(fdVerInfo); + + auto btnUpdate = new QPushButton(tr("Update")); + btnUpdate->setFixedWidth(80); + connect(btnUpdate, &QPushButton::clicked, this, [] { + QSimpleUpdater::getInstance()->setNotifyOnUpdate(UpdVerUrl, true); + QSimpleUpdater::getInstance()->setNotifyOnFinish(UpdVerUrl, false); + QSimpleUpdater::getInstance()->setMandatoryUpdate(UpdVerUrl, true); + QSimpleUpdater::getInstance()->checkForUpdates(UpdVerUrl); + }); + vBox->addWidget(btnUpdate, 0, Qt::AlignHCenter); + + auto updater = QSimpleUpdater::getInstance(); + connect(updater, &QSimpleUpdater::checkingFinished, fdVerInfo, [fdVerInfo, btnUpdate] { + if(QSimpleUpdater::getInstance()->getUpdateAvailable(UpdVerUrl)) fdVerInfo->setText(tr("LatestVersion:") + QSimpleUpdater::getInstance()->getLatestVersion(UpdVerUrl) + "\n" + tr("Update log:") + "\n" + QSimpleUpdater::getInstance()->getChangelog(UpdVerUrl)); + else { + fdVerInfo->setText(tr("The current version is already the latest version") + "\n\n" + tr("Update log:") + "\n" + QSimpleUpdater::getInstance()->getChangelog(UpdVerUrl)); + btnUpdate->setVisible(false); + } + }); + updater->setModuleVersion(UpdVerUrl, APP_VERSION); + updater->setNotifyOnUpdate(UpdVerUrl, false); + updater->setNotifyOnFinish(UpdVerUrl, false); + updater->checkForUpdates(UpdVerUrl); + dlg.exec(); + }); menu_setting->addAction(act_update); act_updatefirmware = new QAction(tr("firmware manager")); - act_updatefirmware->setObjectName("Update firmware"); + connect(act_updatefirmware, &QAction::triggered, this, [this] { + UpgradeApkDialog dlg(this); + dlg.exec(); + }); menu_setting->addAction(act_updatefirmware); act_help = new QAction(); - act_help->setObjectName("Help"); + connect(act_help, &QAction::triggered, this, [this] { + auto act = langGrp->checkedAction(); + if(act==0) return; + QDesktopServices::openUrl(QUrl::fromLocalFile(QCoreApplication::applicationDirPath()+"/help/"+act->objectName()+".pdf")); + }); menu_setting->addAction(act_help); - auto actInfo = new QAction(tr("Info")); + actInfo = new QAction; connect(actInfo, &QAction::triggered, this, [this] { QMessageBox::information(this, tr("Info"), QString("SupportsSsl: ").append(QSslSocket::supportsSsl()?"true":"false") @@ -182,32 +238,12 @@ MainWindow::MainWindow(QWidget *parent) : BaseWin(parent) { menu_setting->addAction(actInfo); act_about = new QAction(tr("About")); - act_about->setObjectName("About"); - menu_setting->addAction(act_about); - - bn_Setting->setMenu(menu_setting);//按钮上添加下拉菜单 - bn_Setting->setToolTip(tr("Setting")); - - connect(menu_setting, &QMenu::triggered, this, [this](QAction* act) { - if(act->objectName()=="About") { - AboutDlg pDlg(this); - pDlg.exec(); - }else if(act->objectName()=="Help") { - auto act = langGrp->checkedAction(); - if(act==0) return; - QDesktopServices::openUrl(QUrl::fromLocalFile(QCoreApplication::applicationDirPath()+"/help/"+act->objectName()+".pdf")); - } else if(act->objectName()=="Update") { - UpdaterDialog *pDlg=new UpdaterDialog(this); - pDlg->exec(); - } else if(act->objectName()=="Update firmware") { - auto dlg = new UpgradeApkDialog(this); - dlg->showMaximized(); - } else if(act->objectName()=="Software Configuration") { - SoftConfigDialog dlg(this); - dlg.exec(); - mBtnGrp->button(MainPage_LoraScreen)->setVisible(gShowLoraScreen); - } + connect(act_about, &QAction::triggered, this, [this] { + AboutDlg dlg(this); + dlg.exec(); }); + menu_setting->addAction(act_about); + bn_Setting->setMenu(menu_setting);//按钮上添加下拉菜单 QSimpleUpdater *updater = QSimpleUpdater::getInstance(); connect(updater, &QSimpleUpdater::checkingFinished, this, [this]() { @@ -296,6 +332,8 @@ MainWindow::MainWindow(QWidget *parent) : BaseWin(parent) { hBox->addWidget(m_pOneKeyCheckCard); hBox->addStretch(); + //hBox->addWidget(new QLabel("ver: " APP_VERSION ".2")); + vBox->addLayout(hBox); gVideoCompress = settings.value("VideoCompress", true).toBool(); @@ -373,9 +411,7 @@ void MainWindow::test() { qDebug()<<"status"<request(); qDebug()<<"reply url"<url(); - qDebug()<<"req url"<readAll(); qDebug()<<"resp"<fdIP) { auto ipstr = mDevicePanel->fdIP->toPlainText(); if(! ipstr.isEmpty()) settings.setValue("SpecifyIP", ipstr); + else settings.remove("SpecifyIP"); } if(m_pTimerSendResoreIpOneKey!=nullptr) { if(m_pTimerSendResoreIpOneKey->isActive()) m_pTimerSendResoreIpOneKey->stop(); @@ -426,9 +463,10 @@ void MainWindow::transUi() { m_pOneKeyCheckCard->setText(tr("Check card")); act_lang->setText(tr("Language")); act_help->setText(tr("Help")); + actInfo->setText(tr("Info")); act_about->setText(tr("About")); act_update->setText(tr("Check for updates")); act_updatefirmware->setText(tr("firmware manager")); - act_softconfiguration->setText(tr("Software Configuration")); + act_softconfiguration->setText(tr("Software Config")); bn_Setting->setToolTip(tr("Setting")); } diff --git a/LedOK/mainwindow.h b/LedOK/mainwindow.h index 9c1b730..f132861 100644 --- a/LedOK/mainwindow.h +++ b/LedOK/mainwindow.h @@ -8,6 +8,7 @@ #include "mguangyingpinwidget.h" #include "progpanel.h" #include +#include class MainWindow : public BaseWin { Q_OBJECT @@ -23,7 +24,7 @@ private: LoQTitleBar *m_wTitle; QActionGroup *langGrp; QAction *act_lang; - QAction *act_help; + QAction *act_help, *actInfo; QAction *act_update; QAction *act_updatefirmware; QAction *act_softconfiguration; diff --git a/LedOK/mguangyingpinwidget.cpp b/LedOK/mguangyingpinwidget.cpp index 8b2b1a6..bd23d90 100644 --- a/LedOK/mguangyingpinwidget.cpp +++ b/LedOK/mguangyingpinwidget.cpp @@ -1,867 +1,867 @@ -#include -#include "mguangyingpinwidget.h" -#include "ui_mguangyingpinwidget.h" -#include -#include "globaldefine.h" -mGuangYingPinWidget::mGuangYingPinWidget(QWidget *parent) : - QWidget(parent), - ui(new Ui::mGuangYingPinWidget) -{ - setAutoFillBackground(true); - QPalette pal; - pal.setBrush(QPalette::Window, QColor(0xeeeeee)); - setPalette(pal); - - ui->setupUi(this); - ui->pushButton1->setProperty("ssType", "progManageTool"); - ui->pushButton2->setProperty("ssType", "progManageTool"); - ui->pushButton3->setProperty("ssType", "progManageTool"); - ui->pushButton4->setProperty("ssType", "progManageTool"); - ui->pushButton5->setProperty("ssType", "progManageTool"); - ui->pushButton6->setProperty("ssType", "progManageTool"); - ui->pushButton7->setProperty("ssType", "progManageTool"); - ui->pushButton8->setProperty("ssType", "progManageTool"); - ui->pushButton9->setProperty("ssType", "progManageTool"); - ui->pushButton10->setProperty("ssType", "progManageTool"); - ui->pushButton11->setProperty("ssType", "progManageTool"); - ui->pushButton12->setProperty("ssType", "progManageTool"); - ui->pushButton13->setProperty("ssType", "progManageTool"); - ui->pushButton14->setProperty("ssType", "progManageTool"); - ui->pushButton15->setProperty("ssType", "progManageTool"); - ui->pushButton16->setProperty("ssType", "progManageTool"); - ui->pushButton17->setProperty("ssType", "progManageTool"); - ui->pushButton18->setProperty("ssType", "progManageTool"); - ui->pushButton19->setProperty("ssType", "progManageTool"); - ui->pushButton20->setProperty("ssType", "progManageTool"); - - ui->pushButtonSend->setProperty("ssType", "progManageTool"); - ui->pushButtonPrevious->setProperty("ssType", "progManageTool"); - ui->pushButtonPrevious->setIcon(QIcon(":/res/previous.png")); - ui->pushButtonNext->setProperty("ssType", "progManageTool"); - ui->pushButtonNext->setIcon(QIcon(":/res/next.png")); - ui->pushButtonLoop->setProperty("ssType", "progManageTool"); - ui->pushButtonLoop->setIcon(QIcon(":/res/loop.png")); - ui->pushButtonMainOpen->setProperty("ssType", "progManageTool"); - ui->pushButtonAuxOpen->setProperty("ssType", "progManageTool"); - ui->pushButtonBrightnessSet->setProperty("ssType", "progManageTool"); - ui->pushButtonScreenOn->setProperty("ssType", "progManageTool"); - ui->pushButtonScreenOff->setProperty("ssType", "progManageTool"); - ui->pushButtonRefresh->setProperty("ssType", "progManageTool"); - ui->pushButtonClearLog->setProperty("ssType", "progManageTool"); - m_recvNum = 0; - m_sendNum = 0; - sPortThread = new TA_SerialThread; - sPortThread->SearchPort(); - - for(uint8_t i = 0;i < sPortThread->portCnt;i++) - { - ui->comboBox_SPortName->addItem(sPortThread->m_arrSerial[i].portName()); - ui->comboBox_SPortNameAux->addItem(sPortThread->m_arrSerial[i].portName()); - } - - //0:1200 1:2400 2:4800 3:9600 4:19200 5:38400 6:57600 7:115200 - if(ui->comboBox_SPortName->count()>=1) - { - ui->comboBox_SPortBaud->setCurrentIndex(3); - //0:5 1:6 2:7 3:8 - ui->comboBox_SPortDataBit->setCurrentIndex(3); - //0:no p 2:e p 3:o p 4:s p 5:m p - ui->comboBox_SPortOEBit->setCurrentIndex(0); - //0:1 1:2 2:1.5 - ui->comboBox_SPortStopBit->setCurrentIndex(0); - - ui->graphicsView_ComStatus->setStyleSheet("background-color: rgb(255, 0, 0);"); - ui->label_ComStatus->setText(tr("State:Off")); - - ui->comboBox_SPortBaudAux->setCurrentIndex(3); - ui->comboBox_SPortDataBitAux->setCurrentIndex(3); - ui->comboBox_SPortOEBitAux->setCurrentIndex(0); - ui->comboBox_SPortStopBitAux->setCurrentIndex(0); - ui->graphicsView_ComStatusAux->setStyleSheet("background-color: rgb(255, 0, 0);"); - ui->label_ComStatusAux->setText(tr("State:Off")); - if(ui->comboBox_SPortName->count()>1) - { - ui->comboBox_SPortNameAux->setCurrentIndex(1); - } - } - ui->lineEdit_ResendTimes->setValidator(new QIntValidator(1,1000,this)); - ui->lineEdit_DelayMill->setValidator(new QIntValidator(1,1000,this)); - - - connect(ui->pushButtonMainOpen, SIGNAL(clicked(bool)), this, SLOT(MWOnoffPort())); - connect(ui->pushButtonAuxOpen, SIGNAL(clicked(bool)), this, SLOT(MWOnoffPortAux())); - connect(ui->pushButton1, SIGNAL(clicked()), this, SLOT(OnAnsyProgram1())); - connect(ui->pushButton2, SIGNAL(clicked()), this, SLOT(OnAnsyProgram2())); - connect(ui->pushButton3, SIGNAL(clicked()), this, SLOT(OnAnsyProgram3())); - connect(ui->pushButton4, SIGNAL(clicked()), this, SLOT(OnAnsyProgram4())); - connect(ui->pushButton5, SIGNAL(clicked()), this, SLOT(OnAnsyProgram5())); - connect(ui->pushButton6, SIGNAL(clicked()), this, SLOT(OnAnsyProgram6())); - connect(ui->pushButton7, SIGNAL(clicked()), this, SLOT(OnAnsyProgram7())); - connect(ui->pushButton8, SIGNAL(clicked()), this, SLOT(OnAnsyProgram8())); - connect(ui->pushButton9, SIGNAL(clicked()), this, SLOT(OnAnsyProgram9())); - connect(ui->pushButton10, SIGNAL(clicked()), this, SLOT(OnAnsyProgram10())); - connect(ui->pushButton11, SIGNAL(clicked()), this, SLOT(OnAnsyProgram11())); - connect(ui->pushButton12, SIGNAL(clicked()), this, SLOT(OnAnsyProgram12())); - connect(ui->pushButton13, SIGNAL(clicked()), this, SLOT(OnAnsyProgram13())); - connect(ui->pushButton14, SIGNAL(clicked()), this, SLOT(OnAnsyProgram14())); - connect(ui->pushButton15, SIGNAL(clicked()), this, SLOT(OnAnsyProgram15())); - connect(ui->pushButton16, SIGNAL(clicked()), this, SLOT(OnAnsyProgram16())); - connect(ui->pushButton17, SIGNAL(clicked()), this, SLOT(OnAnsyProgram17())); - connect(ui->pushButton18, SIGNAL(clicked()), this, SLOT(OnAnsyProgram18())); - connect(ui->pushButton19, SIGNAL(clicked()), this, SLOT(OnAnsyProgram19())); - connect(ui->pushButton20, SIGNAL(clicked()), this, SLOT(OnAnsyProgram20())); - connect(ui->pushButtonClearLog, SIGNAL(clicked()), this, SLOT(OnClearLog())); - connect(ui->pushButtonSend, SIGNAL(clicked()), this, SLOT(OnAnsyProgramCustom())); - connect(ui->pushButtonNext, SIGNAL(clicked()), this, SLOT(OnAnsyProgramNext())); - connect(ui->pushButtonPrevious, SIGNAL(clicked()), this, SLOT(OnAnsyProgramPrevious())); - connect(ui->pushButtonLoop, SIGNAL(clicked()), this, SLOT(OnAnsyProgramLoop())); - connect(ui->pushButtonBrightnessSet, SIGNAL(clicked()), this, SLOT(OnBrightnessSet())); - connect(ui->pushButtonScreenOn, SIGNAL(clicked()), this, SLOT(OnScreenOn())); - connect(ui->pushButtonScreenOff, SIGNAL(clicked()), this, SLOT(OnScreenOff())); - connect(ui->spinBox_ProgramIndex, SIGNAL(valueChanged(int)), this, SLOT(OnAnsyProgramCustomByChanged(int))); - connect(ui->spinBox_BrightnessValue, SIGNAL(valueChanged(int)), this, SLOT(OnBrightnessSetByChanged(int))); - connect(ui->pushButtonRefresh, SIGNAL(clicked()), this, SLOT(OnRefresh())); -} - -mGuangYingPinWidget::~mGuangYingPinWidget(){ - delete ui; -} - -void mGuangYingPinWidget::changeEvent(QEvent *event) { - QWidget::changeEvent(event); - if(event->type() == QEvent::LanguageChange) transUi(); -} -void mGuangYingPinWidget::transUi() { - ui->pushButtonSend->setText(tr("Send")); - ui->pushButtonMainOpen->setText(tr("Open")); - ui->pushButtonAuxOpen->setText(tr("Open")); - ui->pushButtonBrightnessSet->setText(tr("Set")); - ui->pushButtonScreenOn->setText(tr("Screen On")); - ui->pushButtonScreenOff->setText(tr("Screen Off")); - ui->pushButtonRefresh->setText(tr("Refresh")); - ui->groupBoxMain->setTitle(tr("Main")); - ui->groupBoxAux->setTitle(tr("Auxiliary")); - ui->groupBoxParam->setTitle(tr("Param configuration")); - ui->label_PortName->setText(tr("PortName")); - ui->label_BaudRate->setText(tr("BaudRate")); - ui->label_DataBit->setText(tr("DataBit")); - ui->label_OEBit->setText(tr("OEBit")); - ui->label_StopBit->setText(tr("StopBit")); - ui->label_PortNameAux->setText(tr("PortName")); - ui->label_BaudRateAux->setText(tr("BaudRate")); - ui->label_DataBitAux->setText(tr("DataBit")); - ui->label_OEBitAux->setText(tr("OEBit")); - ui->label_StopBitAux->setText(tr("StopBit")); - - ui->label_ResendTimes->setText(tr("Resend times")); - ui->label_DelayMill->setText(tr("Delay millsecond")); - ui->label_ProgramNum->setText(tr("Program number")); - ui->label_BrightNess->setText(tr("Brightness")); - ui->label_ComStatus->setText(tr("State:Off")); - ui->label_ComStatusAux->setText(tr("State:Off")); - ui->pushButtonClearLog->setText(tr("Clear")); - ui->checkBoxDebug->setText(tr("Debug")); - ui->groupBox_Network->setTitle(tr("Network")); - ui->groupBox_com->setTitle(tr("Com")); -} - -void mGuangYingPinWidget::OnAnsyProgram1(void) -{ - MACRO_ANSY_PROGRAM(1) -} -void mGuangYingPinWidget::OnAnsyProgram2(void) -{ - MACRO_ANSY_PROGRAM(2) - -}void mGuangYingPinWidget::OnAnsyProgram3(void) -{ - MACRO_ANSY_PROGRAM(3) -}void mGuangYingPinWidget::OnAnsyProgram4(void) -{ - MACRO_ANSY_PROGRAM(4) -}void mGuangYingPinWidget::OnAnsyProgram5(void) -{ - MACRO_ANSY_PROGRAM(5) -}void mGuangYingPinWidget::OnAnsyProgram6(void) -{ - MACRO_ANSY_PROGRAM(6) -}void mGuangYingPinWidget::OnAnsyProgram7(void) -{ - MACRO_ANSY_PROGRAM(7) -}void mGuangYingPinWidget::OnAnsyProgram8(void) -{ - MACRO_ANSY_PROGRAM(8) -}void mGuangYingPinWidget::OnAnsyProgram9(void) -{ - MACRO_ANSY_PROGRAM(9) -}void mGuangYingPinWidget::OnAnsyProgram10(void) -{ - MACRO_ANSY_PROGRAM(10) -}void mGuangYingPinWidget::OnAnsyProgram11(void) -{ - MACRO_ANSY_PROGRAM(11) -}void mGuangYingPinWidget::OnAnsyProgram12(void) -{ - MACRO_ANSY_PROGRAM(12) -}void mGuangYingPinWidget::OnAnsyProgram13(void) -{ - MACRO_ANSY_PROGRAM(13) -}void mGuangYingPinWidget::OnAnsyProgram14(void) -{ - MACRO_ANSY_PROGRAM(14) -}void mGuangYingPinWidget::OnAnsyProgram15(void) -{ - MACRO_ANSY_PROGRAM(15) -}void mGuangYingPinWidget::OnAnsyProgram16(void) -{ - MACRO_ANSY_PROGRAM(16) -}void mGuangYingPinWidget::OnAnsyProgram17(void) -{ - MACRO_ANSY_PROGRAM(17) -}void mGuangYingPinWidget::OnAnsyProgram18(void) -{ - MACRO_ANSY_PROGRAM(18) -}void mGuangYingPinWidget::OnAnsyProgram19(void) -{ - MACRO_ANSY_PROGRAM(19) -} -void mGuangYingPinWidget::OnAnsyProgram20(void) -{ - MACRO_ANSY_PROGRAM(20) -} -void mGuangYingPinWidget::OnClearLog(void) -{ - ui->textEditReadBuf->clear(); -} -void mGuangYingPinWidget::OnAnsyProgramCustom(void) -{ - int itemp=ui->spinBox_ProgramIndex->value(); - MACRO_ANSY_PROGRAM(itemp) - - if(ui->checkBoxDebug->isChecked()) - { - ui->textEditReadBuf->append("OnAnsyProgramCustom"); - } -} -void mGuangYingPinWidget::OnAnsyProgramCustomByChanged(int icurIndex) -{ - MACRO_ANSY_PROGRAM(icurIndex) -} -void mGuangYingPinWidget::OnBrightnessSetByChanged(int icurValue) -{ - if(ui->pushButtonMainOpen->text()==tr("Close")) - Set_Brightness_buf_and_send(ui->comboBox_SPortName->currentIndex(),icurValue); - if(ui->pushButtonAuxOpen->text()==tr("Close")) - Set_Brightness_buf_and_send(ui->comboBox_SPortNameAux->currentIndex(),icurValue); - } - -void mGuangYingPinWidget::OnAnsyProgramNext(void) -{ - ui->spinBox_ProgramIndex->setValue(ui->spinBox_ProgramIndex->value()+1); - OnAnsyProgramCustom(); -// int itemp=ui->spinBox_ProgramIndex->value(); -// MACRO_ANSY_PROGRAM(itemp) -// if(ui->pushButtonMainOpen->text()==tr("Close")) -// NextProgram_buf_and_send(ui->comboBox_SPortName->currentIndex()); -// if(ui->pushButtonAuxOpen->text()==tr("Close")) -// NextProgram_buf_and_send(ui->comboBox_SPortNameAux->currentIndex()); - -} -void mGuangYingPinWidget::OnAnsyProgramPrevious(void) -{ - ui->spinBox_ProgramIndex->setValue(ui->spinBox_ProgramIndex->value()-1); - OnAnsyProgramCustom(); -// int itemp=ui->spinBox_ProgramIndex->value(); -// MACRO_ANSY_PROGRAM(itemp) -} -void mGuangYingPinWidget::OnAnsyProgramLoop(void) -{ - MACRO_ANSY_PROGRAM(0) -} -void mGuangYingPinWidget::OnBrightnessSet(void) -{ - if(ui->groupBox_com->isChecked()) - { - if(ui->pushButtonMainOpen->text()==tr("Close")) - Set_Brightness_buf_and_send(ui->comboBox_SPortName->currentIndex(),ui->spinBox_BrightnessValue->value()); - if(ui->pushButtonAuxOpen->text()==tr("Close")) - Set_Brightness_buf_and_send(ui->comboBox_SPortNameAux->currentIndex(),ui->spinBox_BrightnessValue->value()); - } - - if(ui->groupBox_Network->isChecked()) - { - Set_Brightness_buf_and_send_by_udp(ui->spinBox_BrightnessValue->value()); - } -} -void mGuangYingPinWidget::OnScreenOn(void) -{ - if(ui->groupBox_com->isChecked()) - { - if(ui->pushButtonMainOpen->text()==tr("Close")) - Screen_OnOff_buf_and_send(ui->comboBox_SPortName->currentIndex(),0x11); - if(ui->pushButtonAuxOpen->text()==tr("Close")) - Screen_OnOff_buf_and_send(ui->comboBox_SPortNameAux->currentIndex(),0x11); - } - if(ui->groupBox_Network->isChecked()) - { - Screen_OnOff_buf_and_send_by_udp(0x11); - } -} -void mGuangYingPinWidget::OnScreenOff(void) -{ - if(ui->groupBox_com->isChecked()) - { - if(ui->pushButtonMainOpen->text()==tr("Close")) - Screen_OnOff_buf_and_send(ui->comboBox_SPortName->currentIndex(),0x10); - if(ui->pushButtonAuxOpen->text()==tr("Close")) - Screen_OnOff_buf_and_send(ui->comboBox_SPortNameAux->currentIndex(),0x10); - } - if(ui->groupBox_Network->isChecked()) - { - Screen_OnOff_buf_and_send_by_udp(0x10); - - } -} -void mGuangYingPinWidget::OnRefresh() -{ - bool resetAllComboxFlag=true; - if(ui->comboBox_SPortName->count()>0) - resetAllComboxFlag=false; -// ui->comboBox_SPortName->clear(); -// ui->comboBox_SPortNameAux->clear(); - - sPortThread->SearchPort(); -// for (int m=0;mportCnt;m++) { - -// } - - - for(uint8_t i = 0;i < sPortThread->portCnt;i++) - { - bool iHaveFlag=false; - for(int j=0;jcomboBox_SPortName->count();j++) - { - if(ui->comboBox_SPortName->itemText(j)==sPortThread->m_arrSerial[i].portName()) - { - iHaveFlag=true; - break; - } - } - if(iHaveFlag==false) - { - ui->comboBox_SPortName->addItem(sPortThread->m_arrSerial[i].portName()); - } - bool iHaveAuxFlag=false; - for(int jj=0;jjcomboBox_SPortNameAux->count();jj++) - { - if(ui->comboBox_SPortNameAux->itemText(jj)==sPortThread->m_arrSerial[i].portName()) - { - iHaveAuxFlag=true; - break; - } - } - if(iHaveAuxFlag==false) - { - ui->comboBox_SPortNameAux->addItem(sPortThread->m_arrSerial[i].portName()); - if(ui->comboBox_SPortNameAux->count()>1&&ui->pushButtonAuxOpen->text()==tr("Open")) - { - ui->comboBox_SPortNameAux->setCurrentIndex(i); - } - - } -// ui->comboBox_SPortName->addItem(sPortThread->m_arrSerial[i].portName()); -// ui->comboBox_SPortNameAux->addItem(sPortThread->m_arrSerial[i].portName()); - } - - if(resetAllComboxFlag) - { - //0:1200 1:2400 2:4800 3:9600 4:19200 5:38400 6:57600 7:115200 - if(ui->comboBox_SPortName->count()>=1) - { - ui->comboBox_SPortBaud->setCurrentIndex(3); - //0:5 1:6 2:7 3:8 - ui->comboBox_SPortDataBit->setCurrentIndex(3); - //0:no p 2:e p 3:o p 4:s p 5:m p - ui->comboBox_SPortOEBit->setCurrentIndex(0); - //0:1 1:2 2:1.5 - ui->comboBox_SPortStopBit->setCurrentIndex(0); - - ui->graphicsView_ComStatus->setStyleSheet("background-color: rgb(255, 0, 0);"); - ui->label_ComStatus->setText(tr("State:Off")); - - ui->comboBox_SPortBaudAux->setCurrentIndex(3); - ui->comboBox_SPortDataBitAux->setCurrentIndex(3); - ui->comboBox_SPortOEBitAux->setCurrentIndex(0); - ui->comboBox_SPortStopBitAux->setCurrentIndex(0); - ui->graphicsView_ComStatusAux->setStyleSheet("background-color: rgb(255, 0, 0);"); - ui->label_ComStatusAux->setText(tr("State:Off")); - if(ui->comboBox_SPortName->count()>1) - { - ui->comboBox_SPortNameAux->setCurrentIndex(1); - } - } - - } - -} -void mGuangYingPinWidget::MWOnoffPort(void) -{ - uint8_t comIndex = ui->comboBox_SPortName->currentIndex(); - - if(ui->pushButtonMainOpen->text()==tr("Open")) - { - sPortThread->InitPortName(comIndex,ui->comboBox_SPortName->currentText()); - sPortThread->InitPortBaudRate(comIndex,ui->comboBox_SPortBaud->currentText().toInt()); - - //qDebug()<comboBox_SPortDataBit->currentIndex(); - switch(ui->comboBox_SPortDataBit->currentIndex()) - { - case 0: sPortThread->InitPortDataBits(comIndex,QSerialPort::Data5); break;//0:5 - case 1: sPortThread->InitPortDataBits(comIndex,QSerialPort::Data6); break;//1:6 - case 2: sPortThread->InitPortDataBits(comIndex,QSerialPort::Data7); break;//2:7 - case 3: sPortThread->InitPortDataBits(comIndex,QSerialPort::Data8); break;//3:8 - default: break; - } - - switch(ui->comboBox_SPortStopBit->currentIndex()) - { - case 0:sPortThread->InitPortStopBits(comIndex,QSerialPort::OneStop);break; - case 1:sPortThread->InitPortStopBits(comIndex,QSerialPort::TwoStop);break; - case 2:sPortThread->InitPortStopBits(comIndex,QSerialPort::OneAndHalfStop);break; - default: break; - } - - switch(ui->comboBox_SPortOEBit->currentIndex()) - { - case 0:sPortThread->InitPortParity(comIndex,QSerialPort::NoParity);break; - case 1:sPortThread->InitPortParity(comIndex,QSerialPort::EvenParity);break; - case 2:sPortThread->InitPortParity(comIndex,QSerialPort::OddParity);break; - case 3:sPortThread->InitPortParity(comIndex,QSerialPort::SpaceParity);break; - case 4:sPortThread->InitPortParity(comIndex,QSerialPort::MarkParity);break; - default: break; - } - if(sPortThread->OpenPort(comIndex)) - { - connect(&(sPortThread->m_arrSerial[comIndex]), SIGNAL(readyRead()), this, SLOT(MWReadData())); - - //参数设置禁止 - ui->comboBox_SPortName->setEnabled(false); - ui->comboBox_SPortBaud->setEnabled(false); - ui->comboBox_SPortDataBit->setEnabled(false); - ui->comboBox_SPortOEBit->setEnabled(false); - ui->comboBox_SPortStopBit->setEnabled(false); - ui->pushButtonMainOpen->setText(tr("Close")); - //发送设置使能 - ui->graphicsView_ComStatus->setStyleSheet("background-color: rgb(0, 255, 0);"); - ui->label_ComStatus->setText(tr("State:On")); - } - else { - X_UIMsgBoxOk *pDlg=new X_UIMsgBoxOk(tr("Tip"),tr("OpenPort COM failed"),this,1); - pDlg->exec(); - } - - - } - else - { - sPortThread->ClosePort(comIndex); - //参数设置使能 - ui->comboBox_SPortName->setEnabled(true); - ui->comboBox_SPortBaud->setEnabled(true); - ui->comboBox_SPortDataBit->setEnabled(true); - ui->comboBox_SPortOEBit->setEnabled(true); - ui->comboBox_SPortStopBit->setEnabled(true); - ui->pushButtonMainOpen->setText(tr("Open")); - //发送设置禁止 - ui->graphicsView_ComStatus->setStyleSheet("background-color: rgb(255, 0, 0);"); - ui->label_ComStatus->setText(tr("State:Off")); - } -} -void mGuangYingPinWidget::MWOnoffPortAux(void) -{ - uint8_t comIndex = ui->comboBox_SPortNameAux->currentIndex(); - - if(ui->pushButtonAuxOpen->text()==tr("Open")) - { - sPortThread->InitPortName(comIndex,ui->comboBox_SPortNameAux->currentText()); - sPortThread->InitPortBaudRate(comIndex,ui->comboBox_SPortBaudAux->currentText().toInt()); - - //qDebug()<comboBox_SPortDataBit->currentIndex(); - switch(ui->comboBox_SPortDataBitAux->currentIndex()) - { - case 0: sPortThread->InitPortDataBits(comIndex,QSerialPort::Data5); break;//0:5 - case 1: sPortThread->InitPortDataBits(comIndex,QSerialPort::Data6); break;//1:6 - case 2: sPortThread->InitPortDataBits(comIndex,QSerialPort::Data7); break;//2:7 - case 3: sPortThread->InitPortDataBits(comIndex,QSerialPort::Data8); break;//3:8 - default: break; - } - - switch(ui->comboBox_SPortStopBitAux->currentIndex()) - { - case 0:sPortThread->InitPortStopBits(comIndex,QSerialPort::OneStop);break; - case 1:sPortThread->InitPortStopBits(comIndex,QSerialPort::TwoStop);break; - case 2:sPortThread->InitPortStopBits(comIndex,QSerialPort::OneAndHalfStop);break; - default: break; - } - - switch(ui->comboBox_SPortOEBitAux->currentIndex()) - { - case 0:sPortThread->InitPortParity(comIndex,QSerialPort::NoParity);break; - case 1:sPortThread->InitPortParity(comIndex,QSerialPort::EvenParity);break; - case 2:sPortThread->InitPortParity(comIndex,QSerialPort::OddParity);break; - case 3:sPortThread->InitPortParity(comIndex,QSerialPort::SpaceParity);break; - case 4:sPortThread->InitPortParity(comIndex,QSerialPort::MarkParity);break; - default: break; - } - if(sPortThread->OpenPort(comIndex)) - { - connect(&(sPortThread->m_arrSerial[comIndex]), SIGNAL(readyRead()), this, SLOT(MWReadDataAux())); - - //参数设置禁止 - ui->comboBox_SPortNameAux->setEnabled(false); - ui->comboBox_SPortBaudAux->setEnabled(false); - ui->comboBox_SPortDataBitAux->setEnabled(false); - ui->comboBox_SPortOEBitAux->setEnabled(false); - ui->comboBox_SPortStopBitAux->setEnabled(false); - ui->pushButtonAuxOpen->setText(tr("Close")); - //发送设置使能 - ui->graphicsView_ComStatusAux->setStyleSheet("background-color: rgb(0, 255, 0);"); - ui->label_ComStatusAux->setText(tr("State:On")); - - } - else { - X_UIMsgBoxOk *pDlg=new X_UIMsgBoxOk(tr("Tip"),tr("OpenPort COM failed"),this,1); - pDlg->exec(); - - } - - } - else - { - sPortThread->ClosePort(comIndex); - //参数设置使能 - ui->comboBox_SPortNameAux->setEnabled(true); - ui->comboBox_SPortBaudAux->setEnabled(true); - ui->comboBox_SPortDataBitAux->setEnabled(true); - ui->comboBox_SPortOEBitAux->setEnabled(true); - ui->comboBox_SPortStopBitAux->setEnabled(true); - ui->pushButtonAuxOpen->setText(tr("Open")); - //发送设置禁止 - ui->graphicsView_ComStatusAux->setStyleSheet("background-color: rgb(255, 0, 0);"); - ui->label_ComStatusAux->setText(tr("State:Off")); - } -} -void mGuangYingPinWidget::Set_program_buf_and_send(int iComIndex,int iProgramIndex) -{ - unsigned char uctemp[3]={0}; - uctemp[0]=0x30+iProgramIndex; - int m_uiResendTimes=ui->lineEdit_ResendTimes->text().toInt(); - int m_uimillisecond=ui->lineEdit_DelayMill->text().toInt(); - unsigned short iDelayTimes=m_uiResendTimes*m_uimillisecond; - qint64 dwStart; - qint64 dwStop; - dwStart = QDateTime::currentMSecsSinceEpoch(); - dwStop=dwStart; - for(int i=0;i<(int)m_uiResendTimes;i++) - { - int itiaozheng=dwStop-dwStart-m_uimillisecond;//时间发送间隔和参数发送间隔的差异 - if(itiaozheng<0) - itiaozheng=0; - unsigned short itemp=(iDelayTimes-i*m_uimillisecond)-itiaozheng;//补充差异,比如实际用了110毫秒,参数100毫秒,则发送过去的协议数据应该是让控制卡减少延时,所以在延时值上再减去补差 - if(itemp<0) - itemp=0; - dwStart=dwStop; - memcpy(&uctemp[1],(unsigned char *)&itemp,2*sizeof(unsigned char)); - MWSendCmd(iComIndex,0x42,uctemp,3,g_iCountCmd); - - - int itempDelay=0; - if(itiaozheng>0) - itempDelay=m_uimillisecond-itiaozheng; - else - itempDelay=m_uimillisecond; - mymidelay(itempDelay); - dwStop = QDateTime::currentMSecsSinceEpoch(); - if(ui->checkBoxDebug->isChecked()) - { - ui->textEditReadBuf->append("dwStart="+QString::number(dwStart)+",dwStop="+QString::number(dwStop)+",dwStop-dwStart="+QString::number(dwStop-dwStart)+",Delay="+QString::number(itempDelay)+",buf delay value="+QString::number(itemp)+"\r\n"); - } - } - g_iCountCmd++; - -} -void mGuangYingPinWidget::Set_program_buf_and_send_by_udp(int iProgramIndex) -{ - unsigned char uctemp[3]={0}; - uctemp[0]=0x30+iProgramIndex; - int m_uiResendTimes=ui->lineEdit_ResendTimes->text().toInt(); - int m_uimillisecond=ui->lineEdit_DelayMill->text().toInt(); - unsigned short iDelayTimes=m_uiResendTimes*m_uimillisecond; - qint64 dwStart; - qint64 dwStop; - dwStart = QDateTime::currentMSecsSinceEpoch(); - dwStop=dwStart; - for(int i=0;i<(int)m_uiResendTimes;i++) - { - int itiaozheng=dwStop-dwStart-m_uimillisecond;//时间发送间隔和参数发送间隔的差异 - if(itiaozheng<0) - itiaozheng=0; - unsigned short itemp=(iDelayTimes-i*m_uimillisecond)-itiaozheng;//补充差异,比如实际用了110毫秒,参数100毫秒,则发送过去的协议数据应该是让控制卡减少延时,所以在延时值上再减去补差 - if(itemp<0) - itemp=0; - dwStart=dwStop; - memcpy(&uctemp[1],(unsigned char *)&itemp,2*sizeof(unsigned char)); - MWSendCmdByUdp(0x42,uctemp,3,g_iCountCmd); - - - int itempDelay=0; - if(itiaozheng>0) - itempDelay=m_uimillisecond-itiaozheng; - else - itempDelay=m_uimillisecond; - mymidelay(itempDelay); - dwStop = QDateTime::currentMSecsSinceEpoch(); - if(ui->checkBoxDebug->isChecked()) - { - ui->textEditReadBuf->append("dwStart="+QString::number(dwStart)+",dwStop="+QString::number(dwStop)+",dwStop-dwStart="+QString::number(dwStop-dwStart)+",Delay="+QString::number(itempDelay)+",buf delay value="+QString::number(itemp)+"\r\n"); - } - } - g_iCountCmd++; - -} -void mGuangYingPinWidget::Set_Brightness_buf_and_send(int iComIndex,int iBrightnessValue) -{ - unsigned char uctemp[2]={0}; - uctemp[0]=0xF1; - uctemp[1]=iBrightnessValue; - int m_uiResendTimes=ui->lineEdit_ResendTimes->text().toInt(); - int m_uimillisecond=ui->lineEdit_DelayMill->text().toInt(); - for(int i=0;i<(int)m_uiResendTimes;i++) - { - MWSendCmd(iComIndex,0x42,uctemp,2,g_iCountCmd); - if(ui->checkBoxDebug->isChecked()) - { - ui->textEditReadBuf->append("SetBrightNess="+QString::number(iBrightnessValue)); - } - mymidelay(m_uimillisecond); - } -} -void mGuangYingPinWidget::Set_Brightness_buf_and_send_by_udp(int iBrightnessValue) -{ - unsigned char uctemp[2]={0}; - uctemp[0]=0xF1; - uctemp[1]=iBrightnessValue; - int m_uiResendTimes=ui->lineEdit_ResendTimes->text().toInt(); - int m_uimillisecond=ui->lineEdit_DelayMill->text().toInt(); - for(int i=0;i<(int)m_uiResendTimes;i++) - { - MWSendCmdByUdp(0x42,uctemp,2,g_iCountCmd); - if(ui->checkBoxDebug->isChecked()) - { - ui->textEditReadBuf->append("SetBrightNess="+QString::number(iBrightnessValue)); - } - mymidelay(m_uimillisecond); - } -} -void mGuangYingPinWidget::Screen_OnOff_buf_and_send(int iComIndex,int iScreenOnOff) -{ - unsigned char uctemp[3]={0}; - uctemp[0]=iScreenOnOff; - uctemp[1]=0; - uctemp[2]=0; - int m_uiResendTimes=ui->lineEdit_ResendTimes->text().toInt(); - int m_uimillisecond=ui->lineEdit_DelayMill->text().toInt(); - for(int i=0;i<(int)m_uiResendTimes;i++) - { - MWSendCmd(iComIndex,0x42,uctemp,3,g_iCountCmd); - if(ui->checkBoxDebug->isChecked()) - { - if(iScreenOnOff==0x11) - ui->textEditReadBuf->append("Screen On"); - else - ui->textEditReadBuf->append("Screen Off"); - } - mymidelay(m_uimillisecond); - } -} -void mGuangYingPinWidget::Screen_OnOff_buf_and_send_by_udp(int iScreenOnOff) -{ - unsigned char uctemp[3]={0}; - uctemp[0]=iScreenOnOff; - uctemp[1]=0; - uctemp[2]=0; - int m_uiResendTimes=ui->lineEdit_ResendTimes->text().toInt(); - int m_uimillisecond=ui->lineEdit_DelayMill->text().toInt(); - for(int i=0;i<(int)m_uiResendTimes;i++) - { - MWSendCmdByUdp(0x42,uctemp,3,g_iCountCmd); - if(ui->checkBoxDebug->isChecked()) - { - if(iScreenOnOff==0x11) - ui->textEditReadBuf->append("Screen On"); - else - ui->textEditReadBuf->append("Screen Off"); - } - mymidelay(m_uimillisecond); - } -} -void mGuangYingPinWidget::NextProgram_buf_and_send(int iComIndex) -{ - unsigned char uctemp[1]={0}; - uctemp[0]=0xF3; - int m_uiResendTimes=ui->lineEdit_ResendTimes->text().toInt(); - int m_uimillisecond=ui->lineEdit_DelayMill->text().toInt(); - for(int i=0;i<(int)m_uiResendTimes;i++) - { - MWSendCmd(iComIndex,0x42,uctemp,1,g_iCountCmd); - if(ui->checkBoxDebug->isChecked()) - { - ui->textEditReadBuf->append("Next Program"); - } - mymidelay(m_uimillisecond); - } -} -void mGuangYingPinWidget::NextProgram_buf_and_send_by_udp() -{ - unsigned char uctemp[1]={0}; - uctemp[0]=0xF3; - int m_uiResendTimes=ui->lineEdit_ResendTimes->text().toInt(); - int m_uimillisecond=ui->lineEdit_DelayMill->text().toInt(); - for(int i=0;i<(int)m_uiResendTimes;i++) - { - MWSendCmdByUdp(0x42,uctemp,1,g_iCountCmd); - if(ui->checkBoxDebug->isChecked()) - { - ui->textEditReadBuf->append("Next Program"); - } - mymidelay(m_uimillisecond); - } -} -void mGuangYingPinWidget::mymidelay(int imlsec) -{ - qint64 dwStart, dwStop; - dwStart = QDateTime::currentMSecsSinceEpoch(); - do{ - dwStop = QDateTime::currentMSecsSinceEpoch(); - } while(dwStop-imlsec(&tempStreadPakcet), iLenPacket); - //sPortThread->SendDataBuf(iComIndex,databuf); - - - QList networkinterfaces = QNetworkInterface::allInterfaces(); - foreach (QNetworkInterface interfaces, networkinterfaces) //networkinterfaces负责提供主机的IP地址和网络接口的列表 - { - foreach (QNetworkAddressEntry entry, interfaces.addressEntries())//QNetworkAddressEntry存储了一个IP地址,子网掩码和广播地址 - { - QHostAddress broadcastAddress("255.255.255.255"); - entry.setBroadcast(QHostAddress::Broadcast); - QUdpSocket *tempUdpSocket= new QUdpSocket(this); - if(!tempUdpSocket->bind(entry.ip())) - break; - int iSendLength=tempUdpSocket->writeDatagram((char *)&tempStreadPakcet,iLenPacket,broadcastAddress,31296); - if(iSendLength != iLenPacket) { - char *aa=reinterpret_cast(&tempStreadPakcet); - tempUdpSocket->writeDatagram(&aa[iSendLength],iLenPacket-iSendLength,broadcastAddress,31296); - } - delete tempUdpSocket; - } - } - if(ui->checkBoxDebug->isChecked()) { - ui->textEditReadBuf->append("udp:"+tr(databuf.toHex())); - } -} -void mGuangYingPinWidget::MWSendCmd(uint8_t iComIndex,unsigned char cmd,unsigned char *pUcValue,unsigned int iLength,int iCountCmd) -{ - ST_ANSY_PROGRAM_PACKET tempStreadPakcet; - tempStreadPakcet.SyncHead[0]=0x7e; - tempStreadPakcet.SyncHead[1]=0x7e; - tempStreadPakcet.SyncHead[2]=0x55; - tempStreadPakcet.ucCommType=cmd; - tempStreadPakcet.iBaoLiu=iCountCmd; - tempStreadPakcet.iLength=iLength; - memcpy(tempStreadPakcet.pDataBuffer,pUcValue,iLength); - tempStreadPakcet.pDataBuffer[tempStreadPakcet.iLength]=GetCheckCodeIn8(&tempStreadPakcet.ucCommType,tempStreadPakcet.iLength+sizeof(tempStreadPakcet.iBaoLiu)+sizeof(tempStreadPakcet.ucCommType)+sizeof(tempStreadPakcet.iLength)); - int iLenPacket=3*sizeof(unsigned char)+sizeof(char)+sizeof(int)+sizeof(int)+tempStreadPakcet.iLength+sizeof(char);/////除正文外的协议结构大小; - QByteArray databuf = QByteArray(reinterpret_cast(&tempStreadPakcet), iLenPacket); - sPortThread->SendDataBuf(iComIndex,databuf); - if(ui->checkBoxDebug->isChecked()) - { - ui->textEditReadBuf->append("com:"+tr(databuf.toHex())); - } -//sPortThread->SendDataBuf(ui->comboBox_SPortName->currentIndex(),ui->textEdit->toPlainText().toLatin1()); -// m_sendNum += (ui->textEdit->toPlainText().toLatin1()).length(); -// MWRSNumDisplay(); -} - -void mGuangYingPinWidget::MWReadData(void) -{ - QByteArray buf; - buf = sPortThread->GetDataBuf(ui->comboBox_SPortName->currentIndex()); - if(!buf.isEmpty()) - { - QString str = tr(buf.toHex()); - if(ui->checkBoxDebug->isChecked()) - { - ui->textEditReadBuf->moveCursor(QTextCursor::End); - ui->textEditReadBuf->insertPlainText(str); - } - MWRSNumDisplay(); - } - buf.clear(); -} -void mGuangYingPinWidget::MWReadDataAux(void) -{ - QByteArray buf; - buf = sPortThread->GetDataBuf(ui->comboBox_SPortNameAux->currentIndex()); - if(!buf.isEmpty()) - { - QString str = tr(buf.toHex()); - if(ui->checkBoxDebug->isChecked()) - { - ui->textEditReadBuf->moveCursor(QTextCursor::End); - ui->textEditReadBuf->insertPlainText(str); - } - MWRSNumDisplay(); - } - buf.clear(); -} -QString mGuangYingPinWidget::ByteArrayToHexString(QByteArray &ba) -{ - QDataStream out(&ba,QIODevice::ReadWrite); //将str的数据 读到out里面去 - QString buf; - while(!out.atEnd()) - { - qint8 outChar = 0; - out >> outChar; //每次一个字节的填充到 outchar - QString str = QString("%1").arg(outChar&0xFF,2,16,QLatin1Char('0')).toUpper() + QString(" "); //2 字符宽度 - buf += str; - } - return buf; -} -void mGuangYingPinWidget::MWClearRecv(void) -{ -// ui->textBrowser->clear(); -// m_recvNum = 0; -// m_sendNum = 0; -// MWRSNumDisplay(); -} - -void mGuangYingPinWidget::MWRSNumDisplay(void) -{ -// ui->label_RecvNum->setText(tr("已接收:") + QString::number(m_recvNum,10)); -// ui->label_SendNum->setText(tr("已发送:") + QString::number(m_sendNum,10)); -} +#include +#include "mguangyingpinwidget.h" +#include "ui_mguangyingpinwidget.h" +#include +#include "globaldefine.h" +mGuangYingPinWidget::mGuangYingPinWidget(QWidget *parent) : + QWidget(parent), + ui(new Ui::mGuangYingPinWidget) +{ + setAutoFillBackground(true); + QPalette pal; + pal.setBrush(QPalette::Window, QColor(0xeeeeee)); + setPalette(pal); + + ui->setupUi(this); + ui->pushButton1->setProperty("ssType", "progManageTool"); + ui->pushButton2->setProperty("ssType", "progManageTool"); + ui->pushButton3->setProperty("ssType", "progManageTool"); + ui->pushButton4->setProperty("ssType", "progManageTool"); + ui->pushButton5->setProperty("ssType", "progManageTool"); + ui->pushButton6->setProperty("ssType", "progManageTool"); + ui->pushButton7->setProperty("ssType", "progManageTool"); + ui->pushButton8->setProperty("ssType", "progManageTool"); + ui->pushButton9->setProperty("ssType", "progManageTool"); + ui->pushButton10->setProperty("ssType", "progManageTool"); + ui->pushButton11->setProperty("ssType", "progManageTool"); + ui->pushButton12->setProperty("ssType", "progManageTool"); + ui->pushButton13->setProperty("ssType", "progManageTool"); + ui->pushButton14->setProperty("ssType", "progManageTool"); + ui->pushButton15->setProperty("ssType", "progManageTool"); + ui->pushButton16->setProperty("ssType", "progManageTool"); + ui->pushButton17->setProperty("ssType", "progManageTool"); + ui->pushButton18->setProperty("ssType", "progManageTool"); + ui->pushButton19->setProperty("ssType", "progManageTool"); + ui->pushButton20->setProperty("ssType", "progManageTool"); + + ui->pushButtonSend->setProperty("ssType", "progManageTool"); + ui->pushButtonPrevious->setProperty("ssType", "progManageTool"); + ui->pushButtonPrevious->setIcon(QIcon(":/res/previous.png")); + ui->pushButtonNext->setProperty("ssType", "progManageTool"); + ui->pushButtonNext->setIcon(QIcon(":/res/next.png")); + ui->pushButtonLoop->setProperty("ssType", "progManageTool"); + ui->pushButtonLoop->setIcon(QIcon(":/res/loop.png")); + ui->pushButtonMainOpen->setProperty("ssType", "progManageTool"); + ui->pushButtonAuxOpen->setProperty("ssType", "progManageTool"); + ui->pushButtonBrightnessSet->setProperty("ssType", "progManageTool"); + ui->pushButtonScreenOn->setProperty("ssType", "progManageTool"); + ui->pushButtonScreenOff->setProperty("ssType", "progManageTool"); + ui->pushButtonRefresh->setProperty("ssType", "progManageTool"); + ui->pushButtonClearLog->setProperty("ssType", "progManageTool"); + m_recvNum = 0; + m_sendNum = 0; + sPortThread = new TA_SerialThread; + sPortThread->SearchPort(); + + for(uint8_t i = 0;i < sPortThread->portCnt;i++) + { + ui->comboBox_SPortName->addItem(sPortThread->m_arrSerial[i].portName()); + ui->comboBox_SPortNameAux->addItem(sPortThread->m_arrSerial[i].portName()); + } + + //0:1200 1:2400 2:4800 3:9600 4:19200 5:38400 6:57600 7:115200 + if(ui->comboBox_SPortName->count()>=1) + { + ui->comboBox_SPortBaud->setCurrentIndex(3); + //0:5 1:6 2:7 3:8 + ui->comboBox_SPortDataBit->setCurrentIndex(3); + //0:no p 2:e p 3:o p 4:s p 5:m p + ui->comboBox_SPortOEBit->setCurrentIndex(0); + //0:1 1:2 2:1.5 + ui->comboBox_SPortStopBit->setCurrentIndex(0); + + ui->graphicsView_ComStatus->setStyleSheet("background-color: rgb(255, 0, 0);"); + ui->label_ComStatus->setText(tr("State:Off")); + + ui->comboBox_SPortBaudAux->setCurrentIndex(3); + ui->comboBox_SPortDataBitAux->setCurrentIndex(3); + ui->comboBox_SPortOEBitAux->setCurrentIndex(0); + ui->comboBox_SPortStopBitAux->setCurrentIndex(0); + ui->graphicsView_ComStatusAux->setStyleSheet("background-color: rgb(255, 0, 0);"); + ui->label_ComStatusAux->setText(tr("State:Off")); + if(ui->comboBox_SPortName->count()>1) + { + ui->comboBox_SPortNameAux->setCurrentIndex(1); + } + } + ui->lineEdit_ResendTimes->setValidator(new QIntValidator(1,1000,this)); + ui->lineEdit_DelayMill->setValidator(new QIntValidator(1,1000,this)); + + + connect(ui->pushButtonMainOpen, SIGNAL(clicked(bool)), this, SLOT(MWOnoffPort())); + connect(ui->pushButtonAuxOpen, SIGNAL(clicked(bool)), this, SLOT(MWOnoffPortAux())); + connect(ui->pushButton1, SIGNAL(clicked()), this, SLOT(OnAnsyProgram1())); + connect(ui->pushButton2, SIGNAL(clicked()), this, SLOT(OnAnsyProgram2())); + connect(ui->pushButton3, SIGNAL(clicked()), this, SLOT(OnAnsyProgram3())); + connect(ui->pushButton4, SIGNAL(clicked()), this, SLOT(OnAnsyProgram4())); + connect(ui->pushButton5, SIGNAL(clicked()), this, SLOT(OnAnsyProgram5())); + connect(ui->pushButton6, SIGNAL(clicked()), this, SLOT(OnAnsyProgram6())); + connect(ui->pushButton7, SIGNAL(clicked()), this, SLOT(OnAnsyProgram7())); + connect(ui->pushButton8, SIGNAL(clicked()), this, SLOT(OnAnsyProgram8())); + connect(ui->pushButton9, SIGNAL(clicked()), this, SLOT(OnAnsyProgram9())); + connect(ui->pushButton10, SIGNAL(clicked()), this, SLOT(OnAnsyProgram10())); + connect(ui->pushButton11, SIGNAL(clicked()), this, SLOT(OnAnsyProgram11())); + connect(ui->pushButton12, SIGNAL(clicked()), this, SLOT(OnAnsyProgram12())); + connect(ui->pushButton13, SIGNAL(clicked()), this, SLOT(OnAnsyProgram13())); + connect(ui->pushButton14, SIGNAL(clicked()), this, SLOT(OnAnsyProgram14())); + connect(ui->pushButton15, SIGNAL(clicked()), this, SLOT(OnAnsyProgram15())); + connect(ui->pushButton16, SIGNAL(clicked()), this, SLOT(OnAnsyProgram16())); + connect(ui->pushButton17, SIGNAL(clicked()), this, SLOT(OnAnsyProgram17())); + connect(ui->pushButton18, SIGNAL(clicked()), this, SLOT(OnAnsyProgram18())); + connect(ui->pushButton19, SIGNAL(clicked()), this, SLOT(OnAnsyProgram19())); + connect(ui->pushButton20, SIGNAL(clicked()), this, SLOT(OnAnsyProgram20())); + connect(ui->pushButtonClearLog, SIGNAL(clicked()), this, SLOT(OnClearLog())); + connect(ui->pushButtonSend, SIGNAL(clicked()), this, SLOT(OnAnsyProgramCustom())); + connect(ui->pushButtonNext, SIGNAL(clicked()), this, SLOT(OnAnsyProgramNext())); + connect(ui->pushButtonPrevious, SIGNAL(clicked()), this, SLOT(OnAnsyProgramPrevious())); + connect(ui->pushButtonLoop, SIGNAL(clicked()), this, SLOT(OnAnsyProgramLoop())); + connect(ui->pushButtonBrightnessSet, SIGNAL(clicked()), this, SLOT(OnBrightnessSet())); + connect(ui->pushButtonScreenOn, SIGNAL(clicked()), this, SLOT(OnScreenOn())); + connect(ui->pushButtonScreenOff, SIGNAL(clicked()), this, SLOT(OnScreenOff())); + connect(ui->spinBox_ProgramIndex, SIGNAL(valueChanged(int)), this, SLOT(OnAnsyProgramCustomByChanged(int))); + connect(ui->spinBox_BrightnessValue, SIGNAL(valueChanged(int)), this, SLOT(OnBrightnessSetByChanged(int))); + connect(ui->pushButtonRefresh, SIGNAL(clicked()), this, SLOT(OnRefresh())); +} + +mGuangYingPinWidget::~mGuangYingPinWidget(){ + delete ui; +} + +void mGuangYingPinWidget::changeEvent(QEvent *event) { + QWidget::changeEvent(event); + if(event->type() == QEvent::LanguageChange) transUi(); +} +void mGuangYingPinWidget::transUi() { + ui->pushButtonSend->setText(tr("Send")); + ui->pushButtonMainOpen->setText(tr("Open")); + ui->pushButtonAuxOpen->setText(tr("Open")); + ui->pushButtonBrightnessSet->setText(tr("Set")); + ui->pushButtonScreenOn->setText(tr("Screen On")); + ui->pushButtonScreenOff->setText(tr("Screen Off")); + ui->pushButtonRefresh->setText(tr("Refresh")); + ui->groupBoxMain->setTitle(tr("Main")); + ui->groupBoxAux->setTitle(tr("Auxiliary")); + ui->groupBoxParam->setTitle(tr("Param configuration")); + ui->label_PortName->setText(tr("PortName")); + ui->label_BaudRate->setText(tr("BaudRate")); + ui->label_DataBit->setText(tr("DataBit")); + ui->label_OEBit->setText(tr("OEBit")); + ui->label_StopBit->setText(tr("StopBit")); + ui->label_PortNameAux->setText(tr("PortName")); + ui->label_BaudRateAux->setText(tr("BaudRate")); + ui->label_DataBitAux->setText(tr("DataBit")); + ui->label_OEBitAux->setText(tr("OEBit")); + ui->label_StopBitAux->setText(tr("StopBit")); + + ui->label_ResendTimes->setText(tr("Resend times")); + ui->label_DelayMill->setText(tr("Delay millsecond")); + ui->label_ProgramNum->setText(tr("Program number")); + ui->label_BrightNess->setText(tr("Brightness")); + ui->label_ComStatus->setText(tr("State:Off")); + ui->label_ComStatusAux->setText(tr("State:Off")); + ui->pushButtonClearLog->setText(tr("Clear")); + ui->checkBoxDebug->setText(tr("Debug")); + ui->groupBox_Network->setTitle(tr("Network")); + ui->groupBox_com->setTitle(tr("Com")); +} + +void mGuangYingPinWidget::OnAnsyProgram1(void) +{ + MACRO_ANSY_PROGRAM(1) +} +void mGuangYingPinWidget::OnAnsyProgram2(void) +{ + MACRO_ANSY_PROGRAM(2) + +}void mGuangYingPinWidget::OnAnsyProgram3(void) +{ + MACRO_ANSY_PROGRAM(3) +}void mGuangYingPinWidget::OnAnsyProgram4(void) +{ + MACRO_ANSY_PROGRAM(4) +}void mGuangYingPinWidget::OnAnsyProgram5(void) +{ + MACRO_ANSY_PROGRAM(5) +}void mGuangYingPinWidget::OnAnsyProgram6(void) +{ + MACRO_ANSY_PROGRAM(6) +}void mGuangYingPinWidget::OnAnsyProgram7(void) +{ + MACRO_ANSY_PROGRAM(7) +}void mGuangYingPinWidget::OnAnsyProgram8(void) +{ + MACRO_ANSY_PROGRAM(8) +}void mGuangYingPinWidget::OnAnsyProgram9(void) +{ + MACRO_ANSY_PROGRAM(9) +}void mGuangYingPinWidget::OnAnsyProgram10(void) +{ + MACRO_ANSY_PROGRAM(10) +}void mGuangYingPinWidget::OnAnsyProgram11(void) +{ + MACRO_ANSY_PROGRAM(11) +}void mGuangYingPinWidget::OnAnsyProgram12(void) +{ + MACRO_ANSY_PROGRAM(12) +}void mGuangYingPinWidget::OnAnsyProgram13(void) +{ + MACRO_ANSY_PROGRAM(13) +}void mGuangYingPinWidget::OnAnsyProgram14(void) +{ + MACRO_ANSY_PROGRAM(14) +}void mGuangYingPinWidget::OnAnsyProgram15(void) +{ + MACRO_ANSY_PROGRAM(15) +}void mGuangYingPinWidget::OnAnsyProgram16(void) +{ + MACRO_ANSY_PROGRAM(16) +}void mGuangYingPinWidget::OnAnsyProgram17(void) +{ + MACRO_ANSY_PROGRAM(17) +}void mGuangYingPinWidget::OnAnsyProgram18(void) +{ + MACRO_ANSY_PROGRAM(18) +}void mGuangYingPinWidget::OnAnsyProgram19(void) +{ + MACRO_ANSY_PROGRAM(19) +} +void mGuangYingPinWidget::OnAnsyProgram20(void) +{ + MACRO_ANSY_PROGRAM(20) +} +void mGuangYingPinWidget::OnClearLog(void) +{ + ui->textEditReadBuf->clear(); +} +void mGuangYingPinWidget::OnAnsyProgramCustom(void) +{ + int itemp=ui->spinBox_ProgramIndex->value(); + MACRO_ANSY_PROGRAM(itemp) + + if(ui->checkBoxDebug->isChecked()) + { + ui->textEditReadBuf->append("OnAnsyProgramCustom"); + } +} +void mGuangYingPinWidget::OnAnsyProgramCustomByChanged(int icurIndex) +{ + MACRO_ANSY_PROGRAM(icurIndex) +} +void mGuangYingPinWidget::OnBrightnessSetByChanged(int icurValue) +{ + if(ui->pushButtonMainOpen->text()==tr("Close")) + Set_Brightness_buf_and_send(ui->comboBox_SPortName->currentIndex(),icurValue); + if(ui->pushButtonAuxOpen->text()==tr("Close")) + Set_Brightness_buf_and_send(ui->comboBox_SPortNameAux->currentIndex(),icurValue); + } + +void mGuangYingPinWidget::OnAnsyProgramNext(void) +{ + ui->spinBox_ProgramIndex->setValue(ui->spinBox_ProgramIndex->value()+1); + OnAnsyProgramCustom(); +// int itemp=ui->spinBox_ProgramIndex->value(); +// MACRO_ANSY_PROGRAM(itemp) +// if(ui->pushButtonMainOpen->text()==tr("Close")) +// NextProgram_buf_and_send(ui->comboBox_SPortName->currentIndex()); +// if(ui->pushButtonAuxOpen->text()==tr("Close")) +// NextProgram_buf_and_send(ui->comboBox_SPortNameAux->currentIndex()); + +} +void mGuangYingPinWidget::OnAnsyProgramPrevious(void) +{ + ui->spinBox_ProgramIndex->setValue(ui->spinBox_ProgramIndex->value()-1); + OnAnsyProgramCustom(); +// int itemp=ui->spinBox_ProgramIndex->value(); +// MACRO_ANSY_PROGRAM(itemp) +} +void mGuangYingPinWidget::OnAnsyProgramLoop(void) +{ + MACRO_ANSY_PROGRAM(0) +} +void mGuangYingPinWidget::OnBrightnessSet(void) +{ + if(ui->groupBox_com->isChecked()) + { + if(ui->pushButtonMainOpen->text()==tr("Close")) + Set_Brightness_buf_and_send(ui->comboBox_SPortName->currentIndex(),ui->spinBox_BrightnessValue->value()); + if(ui->pushButtonAuxOpen->text()==tr("Close")) + Set_Brightness_buf_and_send(ui->comboBox_SPortNameAux->currentIndex(),ui->spinBox_BrightnessValue->value()); + } + + if(ui->groupBox_Network->isChecked()) + { + Set_Brightness_buf_and_send_by_udp(ui->spinBox_BrightnessValue->value()); + } +} +void mGuangYingPinWidget::OnScreenOn(void) +{ + if(ui->groupBox_com->isChecked()) + { + if(ui->pushButtonMainOpen->text()==tr("Close")) + Screen_OnOff_buf_and_send(ui->comboBox_SPortName->currentIndex(),0x11); + if(ui->pushButtonAuxOpen->text()==tr("Close")) + Screen_OnOff_buf_and_send(ui->comboBox_SPortNameAux->currentIndex(),0x11); + } + if(ui->groupBox_Network->isChecked()) + { + Screen_OnOff_buf_and_send_by_udp(0x11); + } +} +void mGuangYingPinWidget::OnScreenOff(void) +{ + if(ui->groupBox_com->isChecked()) + { + if(ui->pushButtonMainOpen->text()==tr("Close")) + Screen_OnOff_buf_and_send(ui->comboBox_SPortName->currentIndex(),0x10); + if(ui->pushButtonAuxOpen->text()==tr("Close")) + Screen_OnOff_buf_and_send(ui->comboBox_SPortNameAux->currentIndex(),0x10); + } + if(ui->groupBox_Network->isChecked()) + { + Screen_OnOff_buf_and_send_by_udp(0x10); + + } +} +void mGuangYingPinWidget::OnRefresh() +{ + bool resetAllComboxFlag=true; + if(ui->comboBox_SPortName->count()>0) + resetAllComboxFlag=false; +// ui->comboBox_SPortName->clear(); +// ui->comboBox_SPortNameAux->clear(); + + sPortThread->SearchPort(); +// for (int m=0;mportCnt;m++) { + +// } + + + for(uint8_t i = 0;i < sPortThread->portCnt;i++) + { + bool iHaveFlag=false; + for(int j=0;jcomboBox_SPortName->count();j++) + { + if(ui->comboBox_SPortName->itemText(j)==sPortThread->m_arrSerial[i].portName()) + { + iHaveFlag=true; + break; + } + } + if(iHaveFlag==false) + { + ui->comboBox_SPortName->addItem(sPortThread->m_arrSerial[i].portName()); + } + bool iHaveAuxFlag=false; + for(int jj=0;jjcomboBox_SPortNameAux->count();jj++) + { + if(ui->comboBox_SPortNameAux->itemText(jj)==sPortThread->m_arrSerial[i].portName()) + { + iHaveAuxFlag=true; + break; + } + } + if(iHaveAuxFlag==false) + { + ui->comboBox_SPortNameAux->addItem(sPortThread->m_arrSerial[i].portName()); + if(ui->comboBox_SPortNameAux->count()>1&&ui->pushButtonAuxOpen->text()==tr("Open")) + { + ui->comboBox_SPortNameAux->setCurrentIndex(i); + } + + } +// ui->comboBox_SPortName->addItem(sPortThread->m_arrSerial[i].portName()); +// ui->comboBox_SPortNameAux->addItem(sPortThread->m_arrSerial[i].portName()); + } + + if(resetAllComboxFlag) + { + //0:1200 1:2400 2:4800 3:9600 4:19200 5:38400 6:57600 7:115200 + if(ui->comboBox_SPortName->count()>=1) + { + ui->comboBox_SPortBaud->setCurrentIndex(3); + //0:5 1:6 2:7 3:8 + ui->comboBox_SPortDataBit->setCurrentIndex(3); + //0:no p 2:e p 3:o p 4:s p 5:m p + ui->comboBox_SPortOEBit->setCurrentIndex(0); + //0:1 1:2 2:1.5 + ui->comboBox_SPortStopBit->setCurrentIndex(0); + + ui->graphicsView_ComStatus->setStyleSheet("background-color: rgb(255, 0, 0);"); + ui->label_ComStatus->setText(tr("State:Off")); + + ui->comboBox_SPortBaudAux->setCurrentIndex(3); + ui->comboBox_SPortDataBitAux->setCurrentIndex(3); + ui->comboBox_SPortOEBitAux->setCurrentIndex(0); + ui->comboBox_SPortStopBitAux->setCurrentIndex(0); + ui->graphicsView_ComStatusAux->setStyleSheet("background-color: rgb(255, 0, 0);"); + ui->label_ComStatusAux->setText(tr("State:Off")); + if(ui->comboBox_SPortName->count()>1) + { + ui->comboBox_SPortNameAux->setCurrentIndex(1); + } + } + + } + +} +void mGuangYingPinWidget::MWOnoffPort(void) +{ + uint8_t comIndex = ui->comboBox_SPortName->currentIndex(); + + if(ui->pushButtonMainOpen->text()==tr("Open")) + { + sPortThread->InitPortName(comIndex,ui->comboBox_SPortName->currentText()); + sPortThread->InitPortBaudRate(comIndex,ui->comboBox_SPortBaud->currentText().toInt()); + + //qDebug()<comboBox_SPortDataBit->currentIndex(); + switch(ui->comboBox_SPortDataBit->currentIndex()) + { + case 0: sPortThread->InitPortDataBits(comIndex,QSerialPort::Data5); break;//0:5 + case 1: sPortThread->InitPortDataBits(comIndex,QSerialPort::Data6); break;//1:6 + case 2: sPortThread->InitPortDataBits(comIndex,QSerialPort::Data7); break;//2:7 + case 3: sPortThread->InitPortDataBits(comIndex,QSerialPort::Data8); break;//3:8 + default: break; + } + + switch(ui->comboBox_SPortStopBit->currentIndex()) + { + case 0:sPortThread->InitPortStopBits(comIndex,QSerialPort::OneStop);break; + case 1:sPortThread->InitPortStopBits(comIndex,QSerialPort::TwoStop);break; + case 2:sPortThread->InitPortStopBits(comIndex,QSerialPort::OneAndHalfStop);break; + default: break; + } + + switch(ui->comboBox_SPortOEBit->currentIndex()) + { + case 0:sPortThread->InitPortParity(comIndex,QSerialPort::NoParity);break; + case 1:sPortThread->InitPortParity(comIndex,QSerialPort::EvenParity);break; + case 2:sPortThread->InitPortParity(comIndex,QSerialPort::OddParity);break; + case 3:sPortThread->InitPortParity(comIndex,QSerialPort::SpaceParity);break; + case 4:sPortThread->InitPortParity(comIndex,QSerialPort::MarkParity);break; + default: break; + } + if(sPortThread->OpenPort(comIndex)) + { + connect(&(sPortThread->m_arrSerial[comIndex]), SIGNAL(readyRead()), this, SLOT(MWReadData())); + + //参数设置禁止 + ui->comboBox_SPortName->setEnabled(false); + ui->comboBox_SPortBaud->setEnabled(false); + ui->comboBox_SPortDataBit->setEnabled(false); + ui->comboBox_SPortOEBit->setEnabled(false); + ui->comboBox_SPortStopBit->setEnabled(false); + ui->pushButtonMainOpen->setText(tr("Close")); + //发送设置使能 + ui->graphicsView_ComStatus->setStyleSheet("background-color: rgb(0, 255, 0);"); + ui->label_ComStatus->setText(tr("State:On")); + } + else { + X_UIMsgBoxOk *pDlg=new X_UIMsgBoxOk(tr("Tip"),tr("OpenPort COM failed"),this,1); + pDlg->exec(); + } + + + } + else + { + sPortThread->ClosePort(comIndex); + //参数设置使能 + ui->comboBox_SPortName->setEnabled(true); + ui->comboBox_SPortBaud->setEnabled(true); + ui->comboBox_SPortDataBit->setEnabled(true); + ui->comboBox_SPortOEBit->setEnabled(true); + ui->comboBox_SPortStopBit->setEnabled(true); + ui->pushButtonMainOpen->setText(tr("Open")); + //发送设置禁止 + ui->graphicsView_ComStatus->setStyleSheet("background-color: rgb(255, 0, 0);"); + ui->label_ComStatus->setText(tr("State:Off")); + } +} +void mGuangYingPinWidget::MWOnoffPortAux(void) +{ + uint8_t comIndex = ui->comboBox_SPortNameAux->currentIndex(); + + if(ui->pushButtonAuxOpen->text()==tr("Open")) + { + sPortThread->InitPortName(comIndex,ui->comboBox_SPortNameAux->currentText()); + sPortThread->InitPortBaudRate(comIndex,ui->comboBox_SPortBaudAux->currentText().toInt()); + + //qDebug()<comboBox_SPortDataBit->currentIndex(); + switch(ui->comboBox_SPortDataBitAux->currentIndex()) + { + case 0: sPortThread->InitPortDataBits(comIndex,QSerialPort::Data5); break;//0:5 + case 1: sPortThread->InitPortDataBits(comIndex,QSerialPort::Data6); break;//1:6 + case 2: sPortThread->InitPortDataBits(comIndex,QSerialPort::Data7); break;//2:7 + case 3: sPortThread->InitPortDataBits(comIndex,QSerialPort::Data8); break;//3:8 + default: break; + } + + switch(ui->comboBox_SPortStopBitAux->currentIndex()) + { + case 0:sPortThread->InitPortStopBits(comIndex,QSerialPort::OneStop);break; + case 1:sPortThread->InitPortStopBits(comIndex,QSerialPort::TwoStop);break; + case 2:sPortThread->InitPortStopBits(comIndex,QSerialPort::OneAndHalfStop);break; + default: break; + } + + switch(ui->comboBox_SPortOEBitAux->currentIndex()) + { + case 0:sPortThread->InitPortParity(comIndex,QSerialPort::NoParity);break; + case 1:sPortThread->InitPortParity(comIndex,QSerialPort::EvenParity);break; + case 2:sPortThread->InitPortParity(comIndex,QSerialPort::OddParity);break; + case 3:sPortThread->InitPortParity(comIndex,QSerialPort::SpaceParity);break; + case 4:sPortThread->InitPortParity(comIndex,QSerialPort::MarkParity);break; + default: break; + } + if(sPortThread->OpenPort(comIndex)) + { + connect(&(sPortThread->m_arrSerial[comIndex]), SIGNAL(readyRead()), this, SLOT(MWReadDataAux())); + + //参数设置禁止 + ui->comboBox_SPortNameAux->setEnabled(false); + ui->comboBox_SPortBaudAux->setEnabled(false); + ui->comboBox_SPortDataBitAux->setEnabled(false); + ui->comboBox_SPortOEBitAux->setEnabled(false); + ui->comboBox_SPortStopBitAux->setEnabled(false); + ui->pushButtonAuxOpen->setText(tr("Close")); + //发送设置使能 + ui->graphicsView_ComStatusAux->setStyleSheet("background-color: rgb(0, 255, 0);"); + ui->label_ComStatusAux->setText(tr("State:On")); + + } + else { + X_UIMsgBoxOk *pDlg=new X_UIMsgBoxOk(tr("Tip"),tr("OpenPort COM failed"),this,1); + pDlg->exec(); + + } + + } + else + { + sPortThread->ClosePort(comIndex); + //参数设置使能 + ui->comboBox_SPortNameAux->setEnabled(true); + ui->comboBox_SPortBaudAux->setEnabled(true); + ui->comboBox_SPortDataBitAux->setEnabled(true); + ui->comboBox_SPortOEBitAux->setEnabled(true); + ui->comboBox_SPortStopBitAux->setEnabled(true); + ui->pushButtonAuxOpen->setText(tr("Open")); + //发送设置禁止 + ui->graphicsView_ComStatusAux->setStyleSheet("background-color: rgb(255, 0, 0);"); + ui->label_ComStatusAux->setText(tr("State:Off")); + } +} +void mGuangYingPinWidget::Set_program_buf_and_send(int iComIndex,int iProgramIndex) +{ + unsigned char uctemp[3]={0}; + uctemp[0]=0x30+iProgramIndex; + int m_uiResendTimes=ui->lineEdit_ResendTimes->text().toInt(); + int m_uimillisecond=ui->lineEdit_DelayMill->text().toInt(); + unsigned short iDelayTimes=m_uiResendTimes*m_uimillisecond; + qint64 dwStart; + qint64 dwStop; + dwStart = QDateTime::currentMSecsSinceEpoch(); + dwStop=dwStart; + for(int i=0;i<(int)m_uiResendTimes;i++) + { + int itiaozheng=dwStop-dwStart-m_uimillisecond;//时间发送间隔和参数发送间隔的差异 + if(itiaozheng<0) + itiaozheng=0; + unsigned short itemp=(iDelayTimes-i*m_uimillisecond)-itiaozheng;//补充差异,比如实际用了110毫秒,参数100毫秒,则发送过去的协议数据应该是让控制卡减少延时,所以在延时值上再减去补差 + if(itemp<0) + itemp=0; + dwStart=dwStop; + memcpy(&uctemp[1],(unsigned char *)&itemp,2*sizeof(unsigned char)); + MWSendCmd(iComIndex,0x42,uctemp,3,g_iCountCmd); + + + int itempDelay=0; + if(itiaozheng>0) + itempDelay=m_uimillisecond-itiaozheng; + else + itempDelay=m_uimillisecond; + mymidelay(itempDelay); + dwStop = QDateTime::currentMSecsSinceEpoch(); + if(ui->checkBoxDebug->isChecked()) + { + ui->textEditReadBuf->append("dwStart="+QString::number(dwStart)+",dwStop="+QString::number(dwStop)+",dwStop-dwStart="+QString::number(dwStop-dwStart)+",Delay="+QString::number(itempDelay)+",buf delay value="+QString::number(itemp)+"\r\n"); + } + } + g_iCountCmd++; + +} +void mGuangYingPinWidget::Set_program_buf_and_send_by_udp(int iProgramIndex) +{ + unsigned char uctemp[3]={0}; + uctemp[0]=0x30+iProgramIndex; + int m_uiResendTimes=ui->lineEdit_ResendTimes->text().toInt(); + int m_uimillisecond=ui->lineEdit_DelayMill->text().toInt(); + unsigned short iDelayTimes=m_uiResendTimes*m_uimillisecond; + qint64 dwStart; + qint64 dwStop; + dwStart = QDateTime::currentMSecsSinceEpoch(); + dwStop=dwStart; + for(int i=0;i<(int)m_uiResendTimes;i++) + { + int itiaozheng=dwStop-dwStart-m_uimillisecond;//时间发送间隔和参数发送间隔的差异 + if(itiaozheng<0) + itiaozheng=0; + unsigned short itemp=(iDelayTimes-i*m_uimillisecond)-itiaozheng;//补充差异,比如实际用了110毫秒,参数100毫秒,则发送过去的协议数据应该是让控制卡减少延时,所以在延时值上再减去补差 + if(itemp<0) + itemp=0; + dwStart=dwStop; + memcpy(&uctemp[1],(unsigned char *)&itemp,2*sizeof(unsigned char)); + MWSendCmdByUdp(0x42,uctemp,3,g_iCountCmd); + + + int itempDelay=0; + if(itiaozheng>0) + itempDelay=m_uimillisecond-itiaozheng; + else + itempDelay=m_uimillisecond; + mymidelay(itempDelay); + dwStop = QDateTime::currentMSecsSinceEpoch(); + if(ui->checkBoxDebug->isChecked()) + { + ui->textEditReadBuf->append("dwStart="+QString::number(dwStart)+",dwStop="+QString::number(dwStop)+",dwStop-dwStart="+QString::number(dwStop-dwStart)+",Delay="+QString::number(itempDelay)+",buf delay value="+QString::number(itemp)+"\r\n"); + } + } + g_iCountCmd++; + +} +void mGuangYingPinWidget::Set_Brightness_buf_and_send(int iComIndex,int iBrightnessValue) +{ + unsigned char uctemp[2]={0}; + uctemp[0]=0xF1; + uctemp[1]=iBrightnessValue; + int m_uiResendTimes=ui->lineEdit_ResendTimes->text().toInt(); + int m_uimillisecond=ui->lineEdit_DelayMill->text().toInt(); + for(int i=0;i<(int)m_uiResendTimes;i++) + { + MWSendCmd(iComIndex,0x42,uctemp,2,g_iCountCmd); + if(ui->checkBoxDebug->isChecked()) + { + ui->textEditReadBuf->append("SetBrightNess="+QString::number(iBrightnessValue)); + } + mymidelay(m_uimillisecond); + } +} +void mGuangYingPinWidget::Set_Brightness_buf_and_send_by_udp(int iBrightnessValue) +{ + unsigned char uctemp[2]={0}; + uctemp[0]=0xF1; + uctemp[1]=iBrightnessValue; + int m_uiResendTimes=ui->lineEdit_ResendTimes->text().toInt(); + int m_uimillisecond=ui->lineEdit_DelayMill->text().toInt(); + for(int i=0;i<(int)m_uiResendTimes;i++) + { + MWSendCmdByUdp(0x42,uctemp,2,g_iCountCmd); + if(ui->checkBoxDebug->isChecked()) + { + ui->textEditReadBuf->append("SetBrightNess="+QString::number(iBrightnessValue)); + } + mymidelay(m_uimillisecond); + } +} +void mGuangYingPinWidget::Screen_OnOff_buf_and_send(int iComIndex,int iScreenOnOff) +{ + unsigned char uctemp[3]={0}; + uctemp[0]=iScreenOnOff; + uctemp[1]=0; + uctemp[2]=0; + int m_uiResendTimes=ui->lineEdit_ResendTimes->text().toInt(); + int m_uimillisecond=ui->lineEdit_DelayMill->text().toInt(); + for(int i=0;i<(int)m_uiResendTimes;i++) + { + MWSendCmd(iComIndex,0x42,uctemp,3,g_iCountCmd); + if(ui->checkBoxDebug->isChecked()) + { + if(iScreenOnOff==0x11) + ui->textEditReadBuf->append("Screen On"); + else + ui->textEditReadBuf->append("Screen Off"); + } + mymidelay(m_uimillisecond); + } +} +void mGuangYingPinWidget::Screen_OnOff_buf_and_send_by_udp(int iScreenOnOff) +{ + unsigned char uctemp[3]={0}; + uctemp[0]=iScreenOnOff; + uctemp[1]=0; + uctemp[2]=0; + int m_uiResendTimes=ui->lineEdit_ResendTimes->text().toInt(); + int m_uimillisecond=ui->lineEdit_DelayMill->text().toInt(); + for(int i=0;i<(int)m_uiResendTimes;i++) + { + MWSendCmdByUdp(0x42,uctemp,3,g_iCountCmd); + if(ui->checkBoxDebug->isChecked()) + { + if(iScreenOnOff==0x11) + ui->textEditReadBuf->append("Screen On"); + else + ui->textEditReadBuf->append("Screen Off"); + } + mymidelay(m_uimillisecond); + } +} +void mGuangYingPinWidget::NextProgram_buf_and_send(int iComIndex) +{ + unsigned char uctemp[1]={0}; + uctemp[0]=0xF3; + int m_uiResendTimes=ui->lineEdit_ResendTimes->text().toInt(); + int m_uimillisecond=ui->lineEdit_DelayMill->text().toInt(); + for(int i=0;i<(int)m_uiResendTimes;i++) + { + MWSendCmd(iComIndex,0x42,uctemp,1,g_iCountCmd); + if(ui->checkBoxDebug->isChecked()) + { + ui->textEditReadBuf->append("Next Program"); + } + mymidelay(m_uimillisecond); + } +} +void mGuangYingPinWidget::NextProgram_buf_and_send_by_udp() +{ + unsigned char uctemp[1]={0}; + uctemp[0]=0xF3; + int m_uiResendTimes=ui->lineEdit_ResendTimes->text().toInt(); + int m_uimillisecond=ui->lineEdit_DelayMill->text().toInt(); + for(int i=0;i<(int)m_uiResendTimes;i++) + { + MWSendCmdByUdp(0x42,uctemp,1,g_iCountCmd); + if(ui->checkBoxDebug->isChecked()) + { + ui->textEditReadBuf->append("Next Program"); + } + mymidelay(m_uimillisecond); + } +} +void mGuangYingPinWidget::mymidelay(int imlsec) +{ + qint64 dwStart, dwStop; + dwStart = QDateTime::currentMSecsSinceEpoch(); + do{ + dwStop = QDateTime::currentMSecsSinceEpoch(); + } while(dwStop-imlsec(&tempStreadPakcet), iLenPacket); + //sPortThread->SendDataBuf(iComIndex,databuf); + + + QList networkinterfaces = QNetworkInterface::allInterfaces(); + foreach (QNetworkInterface interfaces, networkinterfaces) //networkinterfaces负责提供主机的IP地址和网络接口的列表 + { + foreach (QNetworkAddressEntry entry, interfaces.addressEntries())//QNetworkAddressEntry存储了一个IP地址,子网掩码和广播地址 + { + QHostAddress broadcastAddress("255.255.255.255"); + entry.setBroadcast(QHostAddress::Broadcast); + QUdpSocket *tempUdpSocket= new QUdpSocket(this); + if(!tempUdpSocket->bind(entry.ip())) + break; + int iSendLength=tempUdpSocket->writeDatagram((char *)&tempStreadPakcet,iLenPacket,broadcastAddress,31296); + if(iSendLength != iLenPacket) { + char *aa=reinterpret_cast(&tempStreadPakcet); + tempUdpSocket->writeDatagram(&aa[iSendLength],iLenPacket-iSendLength,broadcastAddress,31296); + } + delete tempUdpSocket; + } + } + if(ui->checkBoxDebug->isChecked()) { + ui->textEditReadBuf->append("udp:"+tr(databuf.toHex())); + } +} +void mGuangYingPinWidget::MWSendCmd(uint8_t iComIndex,unsigned char cmd,unsigned char *pUcValue,unsigned int iLength,int iCountCmd) +{ + ST_ANSY_PROGRAM_PACKET tempStreadPakcet; + tempStreadPakcet.SyncHead[0]=0x7e; + tempStreadPakcet.SyncHead[1]=0x7e; + tempStreadPakcet.SyncHead[2]=0x55; + tempStreadPakcet.ucCommType=cmd; + tempStreadPakcet.iBaoLiu=iCountCmd; + tempStreadPakcet.iLength=iLength; + memcpy(tempStreadPakcet.pDataBuffer,pUcValue,iLength); + tempStreadPakcet.pDataBuffer[tempStreadPakcet.iLength]=GetCheckCodeIn8(&tempStreadPakcet.ucCommType,tempStreadPakcet.iLength+sizeof(tempStreadPakcet.iBaoLiu)+sizeof(tempStreadPakcet.ucCommType)+sizeof(tempStreadPakcet.iLength)); + int iLenPacket=3*sizeof(unsigned char)+sizeof(char)+sizeof(int)+sizeof(int)+tempStreadPakcet.iLength+sizeof(char);/////除正文外的协议结构大小; + QByteArray databuf = QByteArray(reinterpret_cast(&tempStreadPakcet), iLenPacket); + sPortThread->SendDataBuf(iComIndex,databuf); + if(ui->checkBoxDebug->isChecked()) + { + ui->textEditReadBuf->append("com:"+tr(databuf.toHex())); + } +//sPortThread->SendDataBuf(ui->comboBox_SPortName->currentIndex(),ui->textEdit->toPlainText().toLatin1()); +// m_sendNum += (ui->textEdit->toPlainText().toLatin1()).length(); +// MWRSNumDisplay(); +} + +void mGuangYingPinWidget::MWReadData(void) +{ + QByteArray buf; + buf = sPortThread->GetDataBuf(ui->comboBox_SPortName->currentIndex()); + if(!buf.isEmpty()) + { + QString str = tr(buf.toHex()); + if(ui->checkBoxDebug->isChecked()) + { + ui->textEditReadBuf->moveCursor(QTextCursor::End); + ui->textEditReadBuf->insertPlainText(str); + } + MWRSNumDisplay(); + } + buf.clear(); +} +void mGuangYingPinWidget::MWReadDataAux(void) +{ + QByteArray buf; + buf = sPortThread->GetDataBuf(ui->comboBox_SPortNameAux->currentIndex()); + if(!buf.isEmpty()) + { + QString str = tr(buf.toHex()); + if(ui->checkBoxDebug->isChecked()) + { + ui->textEditReadBuf->moveCursor(QTextCursor::End); + ui->textEditReadBuf->insertPlainText(str); + } + MWRSNumDisplay(); + } + buf.clear(); +} +QString mGuangYingPinWidget::ByteArrayToHexString(QByteArray &ba) +{ + QDataStream out(&ba,QIODevice::ReadWrite); //将str的数据 读到out里面去 + QString buf; + while(!out.atEnd()) + { + qint8 outChar = 0; + out >> outChar; //每次一个字节的填充到 outchar + QString str = QString("%1").arg(outChar&0xFF,2,16,QLatin1Char('0')).toUpper() + QString(" "); //2 字符宽度 + buf += str; + } + return buf; +} +void mGuangYingPinWidget::MWClearRecv(void) +{ +// ui->textBrowser->clear(); +// m_recvNum = 0; +// m_sendNum = 0; +// MWRSNumDisplay(); +} + +void mGuangYingPinWidget::MWRSNumDisplay(void) +{ +// ui->label_RecvNum->setText(tr("已接收:") + QString::number(m_recvNum,10)); +// ui->label_SendNum->setText(tr("已发送:") + QString::number(m_sendNum,10)); +} diff --git a/LedOK/mguangyingpinwidget.h b/LedOK/mguangyingpinwidget.h index 0963ca5..acdcebb 100644 --- a/LedOK/mguangyingpinwidget.h +++ b/LedOK/mguangyingpinwidget.h @@ -1,95 +1,95 @@ -#ifndef MGUANGYINGPINWIDGET_H -#define MGUANGYINGPINWIDGET_H - -#include -#include "communication/taserialthread.h" -#include -#include -namespace Ui { -class mGuangYingPinWidget; -} - -#define MACRO_ANSY_PROGRAM(PROGRAM_INDEX) \ - if(ui->groupBox_com->isChecked())\ - {\ - if(ui->pushButtonMainOpen->text()==tr("Close"))\ - Set_program_buf_and_send(ui->comboBox_SPortName->currentIndex(),PROGRAM_INDEX);\ - if(ui->pushButtonAuxOpen->text()==tr("Close"))\ - Set_program_buf_and_send(ui->comboBox_SPortNameAux->currentIndex(),PROGRAM_INDEX);\ - }\ - if(ui->groupBox_Network->isChecked())\ - {\ - Set_program_buf_and_send_by_udp(PROGRAM_INDEX);\ - } -class mGuangYingPinWidget : public QWidget { - Q_OBJECT -public: - explicit mGuangYingPinWidget(QWidget *parent = nullptr); - ~mGuangYingPinWidget(); -protected: - void changeEvent(QEvent *) override; - void transUi(); -public slots: - void MWOnoffPort(void); - void MWOnoffPortAux(void); - void MWSendCmd(uint8_t iComIndex,unsigned char cmd,unsigned char *pUcValue,unsigned int iLength,int iCountCmd); - void MWSendCmdByUdp(unsigned char cmd,unsigned char *pUcValue,unsigned int iLength,int iCountCmd); - - void MWReadData(void); - void MWReadDataAux(void); - void MWClearRecv(void); - void MWRSNumDisplay(void); - void OnAnsyProgram1(void); - void OnAnsyProgram2(void); - void OnAnsyProgram3(void); - void OnAnsyProgram4(void); - void OnAnsyProgram5(void); - void OnAnsyProgram6(void); - void OnAnsyProgram7(void); - void OnAnsyProgram8(void); - void OnAnsyProgram9(void); - void OnAnsyProgram10(void); - void OnAnsyProgram11(void); - void OnAnsyProgram12(void); - void OnAnsyProgram13(void); - void OnAnsyProgram14(void); - void OnAnsyProgram15(void); - void OnAnsyProgram16(void); - void OnAnsyProgram17(void); - void OnAnsyProgram18(void); - void OnAnsyProgram19(void); - void OnAnsyProgram20(void); - void OnClearLog(void); - void OnAnsyProgramCustom(void); - void OnAnsyProgramNext(void); - void OnAnsyProgramPrevious(void); - void OnAnsyProgramLoop(void); - void OnBrightnessSet(void); - void OnScreenOn(void); - void OnScreenOff(void); - void OnAnsyProgramCustomByChanged(int icurIndex); - void OnBrightnessSetByChanged(int icurValue); - void OnRefresh(void); -private: - Ui::mGuangYingPinWidget *ui; - TA_SerialThread *sPortThread; - volatile uint32_t m_recvNum; - volatile uint32_t m_sendNum; - int g_iCountCmd=0; - int m_port=31296; - void Set_program_buf_and_send(int iComIndex,int iProgramIndex); - void Set_program_buf_and_send_by_udp(int iProgramIndex); - void Set_Brightness_buf_and_send(int iComIndex,int iBrightnessValue); - void Set_Brightness_buf_and_send_by_udp(int iBrightnessValue); - void Screen_OnOff_buf_and_send(int iComIndex,int iScreenOnOff); - void Screen_OnOff_buf_and_send_by_udp(int iScreenOnOff); - void NextProgram_buf_and_send(int iComIndex); - void NextProgram_buf_and_send_by_udp(); - - - void mymidelay(int imlsec); - QString ByteArrayToHexString(QByteArray &ba); - -}; - -#endif // MGUANGYINGPINWIDGET_H +#ifndef MGUANGYINGPINWIDGET_H +#define MGUANGYINGPINWIDGET_H + +#include +#include "communication/taserialthread.h" +#include +#include +namespace Ui { +class mGuangYingPinWidget; +} + +#define MACRO_ANSY_PROGRAM(PROGRAM_INDEX) \ + if(ui->groupBox_com->isChecked())\ + {\ + if(ui->pushButtonMainOpen->text()==tr("Close"))\ + Set_program_buf_and_send(ui->comboBox_SPortName->currentIndex(),PROGRAM_INDEX);\ + if(ui->pushButtonAuxOpen->text()==tr("Close"))\ + Set_program_buf_and_send(ui->comboBox_SPortNameAux->currentIndex(),PROGRAM_INDEX);\ + }\ + if(ui->groupBox_Network->isChecked())\ + {\ + Set_program_buf_and_send_by_udp(PROGRAM_INDEX);\ + } +class mGuangYingPinWidget : public QWidget { + Q_OBJECT +public: + explicit mGuangYingPinWidget(QWidget *parent = nullptr); + ~mGuangYingPinWidget(); +protected: + void changeEvent(QEvent *) override; + void transUi(); +public slots: + void MWOnoffPort(void); + void MWOnoffPortAux(void); + void MWSendCmd(uint8_t iComIndex,unsigned char cmd,unsigned char *pUcValue,unsigned int iLength,int iCountCmd); + void MWSendCmdByUdp(unsigned char cmd,unsigned char *pUcValue,unsigned int iLength,int iCountCmd); + + void MWReadData(void); + void MWReadDataAux(void); + void MWClearRecv(void); + void MWRSNumDisplay(void); + void OnAnsyProgram1(void); + void OnAnsyProgram2(void); + void OnAnsyProgram3(void); + void OnAnsyProgram4(void); + void OnAnsyProgram5(void); + void OnAnsyProgram6(void); + void OnAnsyProgram7(void); + void OnAnsyProgram8(void); + void OnAnsyProgram9(void); + void OnAnsyProgram10(void); + void OnAnsyProgram11(void); + void OnAnsyProgram12(void); + void OnAnsyProgram13(void); + void OnAnsyProgram14(void); + void OnAnsyProgram15(void); + void OnAnsyProgram16(void); + void OnAnsyProgram17(void); + void OnAnsyProgram18(void); + void OnAnsyProgram19(void); + void OnAnsyProgram20(void); + void OnClearLog(void); + void OnAnsyProgramCustom(void); + void OnAnsyProgramNext(void); + void OnAnsyProgramPrevious(void); + void OnAnsyProgramLoop(void); + void OnBrightnessSet(void); + void OnScreenOn(void); + void OnScreenOff(void); + void OnAnsyProgramCustomByChanged(int icurIndex); + void OnBrightnessSetByChanged(int icurValue); + void OnRefresh(void); +private: + Ui::mGuangYingPinWidget *ui; + TA_SerialThread *sPortThread; + volatile uint32_t m_recvNum; + volatile uint32_t m_sendNum; + int g_iCountCmd=0; + int m_port=31296; + void Set_program_buf_and_send(int iComIndex,int iProgramIndex); + void Set_program_buf_and_send_by_udp(int iProgramIndex); + void Set_Brightness_buf_and_send(int iComIndex,int iBrightnessValue); + void Set_Brightness_buf_and_send_by_udp(int iBrightnessValue); + void Screen_OnOff_buf_and_send(int iComIndex,int iScreenOnOff); + void Screen_OnOff_buf_and_send_by_udp(int iScreenOnOff); + void NextProgram_buf_and_send(int iComIndex); + void NextProgram_buf_and_send_by_udp(); + + + void mymidelay(int imlsec); + QString ByteArrayToHexString(QByteArray &ba); + +}; + +#endif // MGUANGYINGPINWIDGET_H diff --git a/LedOK/mguangyingpinwidget.ui b/LedOK/mguangyingpinwidget.ui index b3049d5..9406f2e 100644 --- a/LedOK/mguangyingpinwidget.ui +++ b/LedOK/mguangyingpinwidget.ui @@ -1,1524 +1,1524 @@ - - - mGuangYingPinWidget - - - - 0 - 0 - 866 - 718 - - - - false - - - - - - - - - Qt::Horizontal - - - - - - - - - Qt::Vertical - - - - - - - Com - - - true - - - true - - - - - - 0 - - - - - - 200 - 16777215 - - - - - 12 - - - - Main - - - Qt::AlignCenter - - - true - - - - - - - - PortName - - - - - - - - 80 - 0 - - - - - - - - - - 0 - - - - - BaudRate - - - - - - - - 1200 - - - - - 2400 - - - - - 4800 - - - - - 9600 - - - - - 19200 - - - - - 38400 - - - - - 57600 - - - - - 115200 - - - - - - - - - - 0 - - - - - DataBit - - - - - - - - 5 - - - - - 6 - - - - - 7 - - - - - 8 - - - - - - - - - - 0 - - - - - OEBit - - - - - - - - No - - - - - Even - - - - - Odd - - - - - Space - - - - - Mark - - - - - - - - - - 0 - - - - - StopBit - - - - - - - - 1 - - - - - 2 - - - - - 1.5 - - - - - - - - - - 0 - - - - - State:Close - - - - - - - - 30 - 30 - - - - - - - - - - - - - 80 - 30 - - - - Open - - - - - - - - - - - - - - Qt::Vertical - - - - - - - 0 - - - - - - 200 - 16777215 - - - - - 12 - - - - Auxiliary - - - Qt::AlignCenter - - - true - - - false - - - - - - - - PortName - - - - - - - - 80 - 0 - - - - - - - - - - - - BaudRate - - - - - - - - 1200 - - - - - 2400 - - - - - 4800 - - - - - 9600 - - - - - 19200 - - - - - 38400 - - - - - 57600 - - - - - 115200 - - - - - - - - - - - - DataBit - - - - - - - - 5 - - - - - 6 - - - - - 7 - - - - - 8 - - - - - - - - - - - - OEBit - - - - - - - - No - - - - - Even - - - - - Odd - - - - - Space - - - - - Mark - - - - - - - - - - - - StopBit - - - - - - - - 1 - - - - - 2 - - - - - 1.5 - - - - - - - - - - - - State:Close - - - - - - - - 30 - 30 - - - - - - - - - - - - - 80 - 30 - - - - Open - - - - - - - - - - - - - - - 0 - 0 - - - - - 80 - 40 - - - - - 12 - - - - Refresh - - - - - - - - - - Network - - - true - - - true - - - false - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Vertical - - - - - - - Qt::Vertical - - - - - - - 0 - - - - - - 200 - 16777215 - - - - - 12 - - - - Param configuration - - - Qt::AlignCenter - - - true - - - - - - - - - 10 - - - - Resend times - - - - - - - - 80 - 16777215 - - - - 10 - - - - - - - - - - - - 10 - - - - Delay millsecond - - - - - - - - 80 - 16777215 - - - - 10 - - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Qt::Horizontal - - - - - - - - - 2 - - - - - 0 - - - - - 0 - - - - - - - - 40 - 40 - - - - - 40 - 40 - - - - 1 - - - - - - - - 40 - 40 - - - - - 40 - 40 - - - - 2 - - - - - - - - 40 - 40 - - - - - 40 - 40 - - - - 3 - - - - - - - - 40 - 40 - - - - - 40 - 40 - - - - 4 - - - - - - - - 40 - 40 - - - - - 40 - 40 - - - - 5 - - - - - - - - - - - - 40 - 40 - - - - - 40 - 40 - - - - 6 - - - - - - - - 40 - 40 - - - - - 40 - 40 - - - - 7 - - - - - - - - 40 - 40 - - - - - 40 - 40 - - - - 8 - - - - - - - - 40 - 40 - - - - - 40 - 40 - - - - 9 - - - - - - - - 40 - 40 - - - - - 40 - 40 - - - - 10 - - - - - - - - - - - - 40 - 40 - - - - - 40 - 40 - - - - 11 - - - - - - - - 40 - 40 - - - - - 40 - 40 - - - - 12 - - - - - - - - 40 - 40 - - - - - 40 - 40 - - - - 13 - - - - - - - - 40 - 40 - - - - - 40 - 40 - - - - 14 - - - - - - - - 40 - 40 - - - - - 40 - 40 - - - - 15 - - - - - - - - - - - - 40 - 40 - - - - - 40 - 40 - - - - 16 - - - - - - - - 40 - 40 - - - - - 40 - 40 - - - - 17 - - - - - - - - 40 - 40 - - - - - 40 - 40 - - - - 18 - - - - - - - - 40 - 40 - - - - - 40 - 40 - - - - 19 - - - - - - - - 40 - 40 - - - - - 40 - 40 - - - - 20 - - - - - - - - - - - - - Qt::Vertical - - - - - - - 0 - - - - - 0 - - - - - - 88 - 0 - - - - Program number - - - - - - - - 60 - 0 - - - - 999 - - - 21 - - - - - - - - 80 - 40 - - - - Send - - - - - - - Qt::Vertical - - - - - - - - 40 - 40 - - - - - - - - 32 - 32 - - - - true - - - - - - - - 40 - 40 - - - - - - - - 32 - 32 - - - - true - - - - - - - - 40 - 40 - - - - - - - - 32 - 32 - - - - true - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Qt::Horizontal - - - - - - - - - - 88 - 0 - - - - Brightness - - - - - - - - 60 - 0 - - - - 255 - - - 255 - - - - - - - - 80 - 40 - - - - Set - - - - - - - Qt::Vertical - - - - - - - - 80 - 40 - - - - Screen Off - - - - - - - - 80 - 40 - - - - Screen on - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - 20 - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Clear - - - - - - - Debug - - - false - - - - - - - - - - - - - - - Qt::Horizontal - - - - - - - - - - - QAbstractScrollArea::AdjustIgnored - - - false - - - true - - - - - - - - - - - - + + + mGuangYingPinWidget + + + + 0 + 0 + 866 + 718 + + + + false + + + + + + + + + Qt::Horizontal + + + + + + + + + Qt::Vertical + + + + + + + Com + + + true + + + true + + + + + + 0 + + + + + + 200 + 16777215 + + + + + 12 + + + + Main + + + Qt::AlignCenter + + + true + + + + + + + + PortName + + + + + + + + 80 + 0 + + + + + + + + + + 0 + + + + + BaudRate + + + + + + + + 1200 + + + + + 2400 + + + + + 4800 + + + + + 9600 + + + + + 19200 + + + + + 38400 + + + + + 57600 + + + + + 115200 + + + + + + + + + + 0 + + + + + DataBit + + + + + + + + 5 + + + + + 6 + + + + + 7 + + + + + 8 + + + + + + + + + + 0 + + + + + OEBit + + + + + + + + No + + + + + Even + + + + + Odd + + + + + Space + + + + + Mark + + + + + + + + + + 0 + + + + + StopBit + + + + + + + + 1 + + + + + 2 + + + + + 1.5 + + + + + + + + + + 0 + + + + + State:Close + + + + + + + + 30 + 30 + + + + + + + + + + + + + 80 + 30 + + + + Open + + + + + + + + + + + + + + Qt::Vertical + + + + + + + 0 + + + + + + 200 + 16777215 + + + + + 12 + + + + Auxiliary + + + Qt::AlignCenter + + + true + + + false + + + + + + + + PortName + + + + + + + + 80 + 0 + + + + + + + + + + + + BaudRate + + + + + + + + 1200 + + + + + 2400 + + + + + 4800 + + + + + 9600 + + + + + 19200 + + + + + 38400 + + + + + 57600 + + + + + 115200 + + + + + + + + + + + + DataBit + + + + + + + + 5 + + + + + 6 + + + + + 7 + + + + + 8 + + + + + + + + + + + + OEBit + + + + + + + + No + + + + + Even + + + + + Odd + + + + + Space + + + + + Mark + + + + + + + + + + + + StopBit + + + + + + + + 1 + + + + + 2 + + + + + 1.5 + + + + + + + + + + + + State:Close + + + + + + + + 30 + 30 + + + + + + + + + + + + + 80 + 30 + + + + Open + + + + + + + + + + + + + + + 0 + 0 + + + + + 80 + 40 + + + + + 12 + + + + Refresh + + + + + + + + + + Network + + + true + + + true + + + false + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Vertical + + + + + + + Qt::Vertical + + + + + + + 0 + + + + + + 200 + 16777215 + + + + + 12 + + + + Param configuration + + + Qt::AlignCenter + + + true + + + + + + + + + 10 + + + + Resend times + + + + + + + + 80 + 16777215 + + + + 10 + + + + + + + + + + + + 10 + + + + Delay millsecond + + + + + + + + 80 + 16777215 + + + + 10 + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Horizontal + + + + + + + + + 2 + + + + + 0 + + + + + 0 + + + + + + + + 40 + 40 + + + + + 40 + 40 + + + + 1 + + + + + + + + 40 + 40 + + + + + 40 + 40 + + + + 2 + + + + + + + + 40 + 40 + + + + + 40 + 40 + + + + 3 + + + + + + + + 40 + 40 + + + + + 40 + 40 + + + + 4 + + + + + + + + 40 + 40 + + + + + 40 + 40 + + + + 5 + + + + + + + + + + + + 40 + 40 + + + + + 40 + 40 + + + + 6 + + + + + + + + 40 + 40 + + + + + 40 + 40 + + + + 7 + + + + + + + + 40 + 40 + + + + + 40 + 40 + + + + 8 + + + + + + + + 40 + 40 + + + + + 40 + 40 + + + + 9 + + + + + + + + 40 + 40 + + + + + 40 + 40 + + + + 10 + + + + + + + + + + + + 40 + 40 + + + + + 40 + 40 + + + + 11 + + + + + + + + 40 + 40 + + + + + 40 + 40 + + + + 12 + + + + + + + + 40 + 40 + + + + + 40 + 40 + + + + 13 + + + + + + + + 40 + 40 + + + + + 40 + 40 + + + + 14 + + + + + + + + 40 + 40 + + + + + 40 + 40 + + + + 15 + + + + + + + + + + + + 40 + 40 + + + + + 40 + 40 + + + + 16 + + + + + + + + 40 + 40 + + + + + 40 + 40 + + + + 17 + + + + + + + + 40 + 40 + + + + + 40 + 40 + + + + 18 + + + + + + + + 40 + 40 + + + + + 40 + 40 + + + + 19 + + + + + + + + 40 + 40 + + + + + 40 + 40 + + + + 20 + + + + + + + + + + + + + Qt::Vertical + + + + + + + 0 + + + + + 0 + + + + + + 88 + 0 + + + + Program number + + + + + + + + 60 + 0 + + + + 999 + + + 21 + + + + + + + + 80 + 40 + + + + Send + + + + + + + Qt::Vertical + + + + + + + + 40 + 40 + + + + + + + + 32 + 32 + + + + true + + + + + + + + 40 + 40 + + + + + + + + 32 + 32 + + + + true + + + + + + + + 40 + 40 + + + + + + + + 32 + 32 + + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Horizontal + + + + + + + + + + 88 + 0 + + + + Brightness + + + + + + + + 60 + 0 + + + + 255 + + + 255 + + + + + + + + 80 + 40 + + + + Set + + + + + + + Qt::Vertical + + + + + + + + 80 + 40 + + + + Screen Off + + + + + + + + 80 + 40 + + + + Screen on + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + 20 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Clear + + + + + + + Debug + + + false + + + + + + + + + + + + + + + Qt::Horizontal + + + + + + + + + + + QAbstractScrollArea::AdjustIgnored + + + false + + + true + + + + + + + + + + + + diff --git a/LedOK/oescreenshot/oeamplifier.cpp b/LedOK/oescreenshot/oeamplifier.cpp index be42ae4..785823a 100644 --- a/LedOK/oescreenshot/oeamplifier.cpp +++ b/LedOK/oescreenshot/oeamplifier.cpp @@ -1,153 +1,153 @@ -/** - * @author : 陈鲁勇 - * @date : 2017年04月 - * @version: 1.0 - * @note : 根据 Apache 许可证 2.0 版(以下简称“许可证”)授权; - * 除非遵守本许可,否则您不能使用这个文件。 - * @remarks: 您可以获得该许可的副本: - * http://www.apache.org/licenses/LICENSE-2.0 - * 除非适用法律需要或者书面同意,按本许可分发的软件 - * 要按“原样”分发,没有任何形式的,明确或隐含的担保条款。 - * 参见按照本许可控制许可权限及限制的特定语言的许可证。 - * - * 你可以获得该代码的最新版本: - * - * https://git.oschina.net/Mr_ChenLuYong/screenshot - * - * 开源社区的所有人都期待与你的共同维护。 - * - * - * 如果你对这些代码还有不理解的地方可以通过最新的文章进行学习: - * - * 博客地址:http://blog.csdn.net/csnd_ayo - * - * 文章地址:http://blog.csdn.net/csnd_ayo/article/details/70197915 - * - * 期待你提交Bug,欢迎Issues。 - * -*/ - - - -#include "oeamplifier.h" - - -#include -#include - -#ifndef QT_NO_DEBUG -#include -#endif - - -#include "oecommonhelper.h" - -OEAmplifier::OEAmplifier(std::shared_ptr originPainting, QWidget *parent) : - QWidget(parent), originPainting_(originPainting) { - /// 设置成无边框对话框 - setWindowFlags(Qt::FramelessWindowHint|Qt::WindowSystemMenuHint); - /// 开启鼠标实时追踪 - setMouseTracking(true); - - /// 设置默认大小 - sideLength_ = 122 * OECommonHelper::getWindowHeightMultiplyingPower(); - imageHeight_ = 90 * OECommonHelper::getWindowHeightMultiplyingPower(); - setFixedSize(sideLength_,sideLength_); - - /// 默认隐藏 - hide(); -} - -void OEAmplifier::onSizeChange(int w, int h) { - screenSize_ = QSize(w, h); -} - -void OEAmplifier::onPostionChange(int x, int y) { - cursorPoint_ = QPoint(x, y); - raise(); - int dest_x = x + 4; - int dest_y = y + 26; - - /// 超出屏幕检测 - const QSize& parent_size = parentWidget()->size(); - if (dest_y + height() > parent_size.height()) { - dest_y = y - 26 - height(); - } - if (dest_x + width() > parent_size.width()) { - dest_x = x - 4 - width(); - } - - move(dest_x, dest_y); -} - - - -/// 绘制鼠标拖拽时选区矩形的右下顶点的放大图; -void OEAmplifier::paintEvent(QPaintEvent *) { - QPainter painter(this); - - /// 绘制背景 - painter.fillRect(rect(), QColor(0, 0, 0, 160)); - - QPixmap endPointImage; - /// 绘制放大图; - const QSize& parent_size = parentWidget()->size(); - /** - * @bug : 在屏幕边缘绘制放大图时会出现图片拉伸 - * 这里暂时做了边缘检测,若是屏幕边缘则不进行放大图的绘制,和QQ截图的采取方式是一致的。 - * - * @marker: 颜色还是照样识别,但是局部放大的效果暂时禁用 - * - * @note : 解决方法,可以发现边缘时,将不能放大的地方,不描绘,或填充黑色,以避免图片被非预期的拉伸问题。 - */ - if ((cursorPoint_.x() + 15 < parent_size.width() && cursorPoint_.x() - 15 > 0) - && (cursorPoint_.y() + 11 < parent_size.height() && cursorPoint_.y() - 11 > 0)) { - endPointImage = originPainting_-> - copy(QRect(cursorPoint_.x() - 15, - cursorPoint_.y() - 11, 30, 22)) - .scaled(sideLength_, imageHeight_); - painter.drawPixmap(0,0, endPointImage); - } - else { - endPointImage = originPainting_-> - copy(QRect(cursorPoint_.x() - 15, - cursorPoint_.y() - 11, 30, 22)); - } - - - /// 绘制十字 - painter.setPen(QPen(QColor(0, 180, 255 , 180), 4)); - // 竖线; - painter.drawLine(QPoint(sideLength_ >> 1, 0), - QPoint(sideLength_ >> 1, - imageHeight_ - 4)); - // 横线; - painter.drawLine(QPoint(0, imageHeight_ >> 1), - QPoint(sideLength_, - imageHeight_ >> 1)); - - /// 绘制大图内边框 - painter.setPen(QPen(Qt::white, 2)); - painter.drawRect(2,2,width()-4, imageHeight_-4); - - /// 绘制外边框 - painter.setPen(QPen(Qt::black, 1)); - painter.drawRect(0,0,width()-1,height()-1); - - /// 当前选中矩形的宽高信息; - QString select_screen_info = QString("%1×%2") - .arg(screenSize_.width()).arg(screenSize_.height()); - - /// 当前鼠标像素值的RGB信息 - QImage image = originPainting_->toImage(); - QColor cursor_pixel = image.pixel(cursorPoint_); - QString select_pt_rgb = QString("RGB:(%1,%2,%3)") - .arg(cursor_pixel.red()) - .arg(cursor_pixel.green()) - .arg(cursor_pixel.blue()); - - /// 绘制坐标轴相关数据 - painter.setPen(Qt::white); - painter.drawText(QPoint(6, imageHeight_+14),select_screen_info); - painter.drawText(QPoint(6, imageHeight_+27),select_pt_rgb); -} +/** + * @author : 陈鲁勇 + * @date : 2017年04月 + * @version: 1.0 + * @note : 根据 Apache 许可证 2.0 版(以下简称“许可证”)授权; + * 除非遵守本许可,否则您不能使用这个文件。 + * @remarks: 您可以获得该许可的副本: + * http://www.apache.org/licenses/LICENSE-2.0 + * 除非适用法律需要或者书面同意,按本许可分发的软件 + * 要按“原样”分发,没有任何形式的,明确或隐含的担保条款。 + * 参见按照本许可控制许可权限及限制的特定语言的许可证。 + * + * 你可以获得该代码的最新版本: + * + * https://git.oschina.net/Mr_ChenLuYong/screenshot + * + * 开源社区的所有人都期待与你的共同维护。 + * + * + * 如果你对这些代码还有不理解的地方可以通过最新的文章进行学习: + * + * 博客地址:http://blog.csdn.net/csnd_ayo + * + * 文章地址:http://blog.csdn.net/csnd_ayo/article/details/70197915 + * + * 期待你提交Bug,欢迎Issues。 + * +*/ + + + +#include "oeamplifier.h" + + +#include +#include + +#ifndef QT_NO_DEBUG +#include +#endif + + +#include "oecommonhelper.h" + +OEAmplifier::OEAmplifier(std::shared_ptr originPainting, QWidget *parent) : + QWidget(parent), originPainting_(originPainting) { + /// 设置成无边框对话框 + setWindowFlags(Qt::FramelessWindowHint|Qt::WindowSystemMenuHint); + /// 开启鼠标实时追踪 + setMouseTracking(true); + + /// 设置默认大小 + sideLength_ = 122 * OECommonHelper::getWindowHeightMultiplyingPower(); + imageHeight_ = 90 * OECommonHelper::getWindowHeightMultiplyingPower(); + setFixedSize(sideLength_,sideLength_); + + /// 默认隐藏 + hide(); +} + +void OEAmplifier::onSizeChange(int w, int h) { + screenSize_ = QSize(w, h); +} + +void OEAmplifier::onPostionChange(int x, int y) { + cursorPoint_ = QPoint(x, y); + raise(); + int dest_x = x + 4; + int dest_y = y + 26; + + /// 超出屏幕检测 + const QSize& parent_size = parentWidget()->size(); + if (dest_y + height() > parent_size.height()) { + dest_y = y - 26 - height(); + } + if (dest_x + width() > parent_size.width()) { + dest_x = x - 4 - width(); + } + + move(dest_x, dest_y); +} + + + +/// 绘制鼠标拖拽时选区矩形的右下顶点的放大图; +void OEAmplifier::paintEvent(QPaintEvent *) { + QPainter painter(this); + + /// 绘制背景 + painter.fillRect(rect(), QColor(0, 0, 0, 160)); + + QPixmap endPointImage; + /// 绘制放大图; + const QSize& parent_size = parentWidget()->size(); + /** + * @bug : 在屏幕边缘绘制放大图时会出现图片拉伸 + * 这里暂时做了边缘检测,若是屏幕边缘则不进行放大图的绘制,和QQ截图的采取方式是一致的。 + * + * @marker: 颜色还是照样识别,但是局部放大的效果暂时禁用 + * + * @note : 解决方法,可以发现边缘时,将不能放大的地方,不描绘,或填充黑色,以避免图片被非预期的拉伸问题。 + */ + if ((cursorPoint_.x() + 15 < parent_size.width() && cursorPoint_.x() - 15 > 0) + && (cursorPoint_.y() + 11 < parent_size.height() && cursorPoint_.y() - 11 > 0)) { + endPointImage = originPainting_-> + copy(QRect(cursorPoint_.x() - 15, + cursorPoint_.y() - 11, 30, 22)) + .scaled(sideLength_, imageHeight_); + painter.drawPixmap(0,0, endPointImage); + } + else { + endPointImage = originPainting_-> + copy(QRect(cursorPoint_.x() - 15, + cursorPoint_.y() - 11, 30, 22)); + } + + + /// 绘制十字 + painter.setPen(QPen(QColor(0, 180, 255 , 180), 4)); + // 竖线; + painter.drawLine(QPoint(sideLength_ >> 1, 0), + QPoint(sideLength_ >> 1, + imageHeight_ - 4)); + // 横线; + painter.drawLine(QPoint(0, imageHeight_ >> 1), + QPoint(sideLength_, + imageHeight_ >> 1)); + + /// 绘制大图内边框 + painter.setPen(QPen(Qt::white, 2)); + painter.drawRect(2,2,width()-4, imageHeight_-4); + + /// 绘制外边框 + painter.setPen(QPen(Qt::black, 1)); + painter.drawRect(0,0,width()-1,height()-1); + + /// 当前选中矩形的宽高信息; + QString select_screen_info = QString("%1×%2") + .arg(screenSize_.width()).arg(screenSize_.height()); + + /// 当前鼠标像素值的RGB信息 + QImage image = originPainting_->toImage(); + QColor cursor_pixel = image.pixel(cursorPoint_); + QString select_pt_rgb = QString("RGB:(%1,%2,%3)") + .arg(cursor_pixel.red()) + .arg(cursor_pixel.green()) + .arg(cursor_pixel.blue()); + + /// 绘制坐标轴相关数据 + painter.setPen(Qt::white); + painter.drawText(QPoint(6, imageHeight_+14),select_screen_info); + painter.drawText(QPoint(6, imageHeight_+27),select_pt_rgb); +} diff --git a/LedOK/oescreenshot/oeamplifier.h b/LedOK/oescreenshot/oeamplifier.h index d08b31c..3643152 100644 --- a/LedOK/oescreenshot/oeamplifier.h +++ b/LedOK/oescreenshot/oeamplifier.h @@ -1,93 +1,93 @@ -/** - * @author : 陈鲁勇 - * @date : 2017年04月 - * @version: 1.0 - * @note : 根据 Apache 许可证 2.0 版(以下简称“许可证”)授权; - * 除非遵守本许可,否则您不能使用这个文件。 - * @remarks: 您可以获得该许可的副本: - * http://www.apache.org/licenses/LICENSE-2.0 - * 除非适用法律需要或者书面同意,按本许可分发的软件 - * 要按“原样”分发,没有任何形式的,明确或隐含的担保条款。 - * 参见按照本许可控制许可权限及限制的特定语言的许可证。 - * - * 你可以获得该代码的最新版本: - * - * https://git.oschina.net/Mr_ChenLuYong/screenshot - * - * 开源社区的所有人都期待与你的共同维护。 - * - * - * 如果你对这些代码还有不理解的地方可以通过最新的文章进行学习: - * - * 博客地址:http://blog.csdn.net/csnd_ayo - * - * 文章地址:http://blog.csdn.net/csnd_ayo/article/details/70197915 - * - * 期待你提交Bug,欢迎Issues。 - * -*/ - - - -#ifndef OEAMPLIFIER_H -#define OEAMPLIFIER_H -#include -#include - - -/** - * @class : OEAmplifier - * @brief : 放大取色器 - * @note : 关于鼠标位置局部放大的操作以及色卡取值的操作 - */ -class OEAmplifier : public QWidget -{ - Q_OBJECT -public: - explicit OEAmplifier(std::shared_ptr originPainting, QWidget *parent = 0); - -signals: - -public slots: - - - /** - * @brief : 大小修改 - * @param : w 宽度 - * @param : h 高度 - * @date : 2017年4月29日 - */ - void onSizeChange(int w, int h); - - /** - * @brief : 大小修改 - * @param : w 宽度 - * @param : h 高度 - * @date : 2017年4月29日 - */ - void onPostionChange(int x, int y); - -protected: - - /** - * @brief : 窗口自绘事件 - * @date : 2017年4月29日 - */ - virtual void paintEvent(QPaintEvent *); - -private: - - /// 外部组件的大小信息 - QSize screenSize_; - /// 鼠标的位置 - QPoint cursorPoint_; - /// 取色放大器的边长 - int sideLength_; - /// 放大区的高度 - int imageHeight_; - /// 屏幕原画 - std::shared_ptr originPainting_; - -}; - -#endif /// OEAMPLIFIER_H +/** + * @author : 陈鲁勇 + * @date : 2017年04月 + * @version: 1.0 + * @note : 根据 Apache 许可证 2.0 版(以下简称“许可证”)授权; + * 除非遵守本许可,否则您不能使用这个文件。 + * @remarks: 您可以获得该许可的副本: + * http://www.apache.org/licenses/LICENSE-2.0 + * 除非适用法律需要或者书面同意,按本许可分发的软件 + * 要按“原样”分发,没有任何形式的,明确或隐含的担保条款。 + * 参见按照本许可控制许可权限及限制的特定语言的许可证。 + * + * 你可以获得该代码的最新版本: + * + * https://git.oschina.net/Mr_ChenLuYong/screenshot + * + * 开源社区的所有人都期待与你的共同维护。 + * + * + * 如果你对这些代码还有不理解的地方可以通过最新的文章进行学习: + * + * 博客地址:http://blog.csdn.net/csnd_ayo + * + * 文章地址:http://blog.csdn.net/csnd_ayo/article/details/70197915 + * + * 期待你提交Bug,欢迎Issues。 + * +*/ + + + +#ifndef OEAMPLIFIER_H +#define OEAMPLIFIER_H +#include +#include + + +/** + * @class : OEAmplifier + * @brief : 放大取色器 + * @note : 关于鼠标位置局部放大的操作以及色卡取值的操作 + */ +class OEAmplifier : public QWidget +{ + Q_OBJECT +public: + explicit OEAmplifier(std::shared_ptr originPainting, QWidget *parent = 0); + +signals: + +public slots: + + + /** + * @brief : 大小修改 + * @param : w 宽度 + * @param : h 高度 + * @date : 2017年4月29日 + */ + void onSizeChange(int w, int h); + + /** + * @brief : 大小修改 + * @param : w 宽度 + * @param : h 高度 + * @date : 2017年4月29日 + */ + void onPostionChange(int x, int y); + +protected: + + /** + * @brief : 窗口自绘事件 + * @date : 2017年4月29日 + */ + virtual void paintEvent(QPaintEvent *); + +private: + + /// 外部组件的大小信息 + QSize screenSize_; + /// 鼠标的位置 + QPoint cursorPoint_; + /// 取色放大器的边长 + int sideLength_; + /// 放大区的高度 + int imageHeight_; + /// 屏幕原画 + std::shared_ptr originPainting_; + +}; + +#endif /// OEAMPLIFIER_H diff --git a/LedOK/oescreenshot/oecommonhelper.cpp b/LedOK/oescreenshot/oecommonhelper.cpp index 6869685..d361f21 100644 --- a/LedOK/oescreenshot/oecommonhelper.cpp +++ b/LedOK/oescreenshot/oecommonhelper.cpp @@ -1,141 +1,141 @@ -/** - * @author : 陈鲁勇 - * @date : 2017年04月 - * @version: 1.0 - * @note : 根据 Apache 许可证 2.0 版(以下简称“许可证”)授权; - * 除非遵守本许可,否则您不能使用这个文件。 - * @remarks: 您可以获得该许可的副本: - * http://www.apache.org/licenses/LICENSE-2.0 - * 除非适用法律需要或者书面同意,按本许可分发的软件 - * 要按“原样”分发,没有任何形式的,明确或隐含的担保条款。 - * 参见按照本许可控制许可权限及限制的特定语言的许可证。 - * - * 你可以获得该代码的最新版本: - * - * https://git.oschina.net/Mr_ChenLuYong/screenshot - * - * 开源社区的所有人都期待与你的共同维护。 - * - * - * 如果你对这些代码还有不理解的地方可以通过最新的文章进行学习: - * - * 博客地址:http://blog.csdn.net/csnd_ayo - * - * 文章地址:http://blog.csdn.net/csnd_ayo/article/details/70197915 - * - * 期待你提交Bug,欢迎Issues。 - * -*/ - - -#include "oecommonhelper.h" - -#include -#include -#include -#include -#include - -#include - -#ifndef QT_NO_DEBUG -#include -#endif - - -#define WINDOW_BASESIZE_WIDTH (1920) -#define WINDOW_BASESIZE_HEIGHT (1080) - -float OECommonHelper::widthMultiplyingPower_ = 0; -float OECommonHelper::heightMultiplyingPower_ = 0; - -void OECommonHelper::setStyle(const QString &style) { - QFile qss(style); - qss.open(QFile::ReadOnly); - qApp->setStyleSheet(qss.readAll()); - qss.close(); -} - -void OECommonHelper::setLanguagePack(const QString &language) { - // 加载中文包 - QTranslator translator; - translator.load(language); - qApp->installTranslator(&translator); -} - -void OECommonHelper::moveCenter(QWidget *widget, QRect parentRect) { - if (parentRect.isEmpty()) { - parentRect = QApplication::desktop()->rect(); - } - widget->move (((parentRect.width() - widget->width()) >> 1), - ((parentRect.height() - widget->height()) >> 1)); -} - -const float &OECommonHelper::getWindowWidthMultiplyingPower() { - if (widthMultiplyingPower_ == 0) { - upWindowSizeMultiplyingPower(); - } - return widthMultiplyingPower_; -} - -const float & OECommonHelper::getWindowHeightMultiplyingPower() { - if (heightMultiplyingPower_ == 0) { - upWindowSizeMultiplyingPower(); - } - return heightMultiplyingPower_; -} - -void OECommonHelper::upWindowSizeMultiplyingPower() { - QSize temp_size = QApplication::desktop()->size(); - widthMultiplyingPower_ = (float)temp_size.width() - / (float)WINDOW_BASESIZE_WIDTH; - heightMultiplyingPower_ = (float)temp_size.height() - / (float)WINDOW_BASESIZE_HEIGHT; -} - -bool OECommonHelper::getSmallestWindowFromCursor(QRect& out_rect) { - HWND hwnd; - POINT pt; - // 获得当前鼠标位置 - ::GetCursorPos(&pt); - // 获得当前位置桌面上的子窗口 - hwnd = ::ChildWindowFromPointEx(::GetDesktopWindow(), pt, CWP_SKIPDISABLED | CWP_SKIPINVISIBLE); - if (hwnd != NULL) { - HWND temp_hwnd; - temp_hwnd = hwnd; - while (true) { - ::GetCursorPos(&pt); - ::ScreenToClient(temp_hwnd, &pt); - temp_hwnd = ::ChildWindowFromPointEx(temp_hwnd, pt, CWP_SKIPINVISIBLE); - if (temp_hwnd == NULL || temp_hwnd == hwnd) - break; - hwnd = temp_hwnd; - } - RECT temp_window; - ::GetWindowRect(hwnd, &temp_window); - out_rect.setRect(temp_window.left,temp_window.top, - temp_window.right - temp_window.left, - temp_window.bottom - temp_window.top); - return true; - } - return false; -} - -bool OECommonHelper::getCurrentWindowFromCursor(QRect &out_rect) -{ - HWND hwnd; - POINT pt; - // 获得当前鼠标位置 - ::GetCursorPos(&pt); - // 获得当前位置桌面上的子窗口 - hwnd = ::ChildWindowFromPointEx(::GetDesktopWindow(), pt, CWP_SKIPDISABLED | CWP_SKIPINVISIBLE); - if (hwnd != NULL) { - RECT temp_window; - ::GetWindowRect(hwnd, &temp_window); - out_rect.setRect(temp_window.left, temp_window.top, - temp_window.right - temp_window.left, - temp_window.bottom - temp_window.top); - return true; - } - return false; -} +/** + * @author : 陈鲁勇 + * @date : 2017年04月 + * @version: 1.0 + * @note : 根据 Apache 许可证 2.0 版(以下简称“许可证”)授权; + * 除非遵守本许可,否则您不能使用这个文件。 + * @remarks: 您可以获得该许可的副本: + * http://www.apache.org/licenses/LICENSE-2.0 + * 除非适用法律需要或者书面同意,按本许可分发的软件 + * 要按“原样”分发,没有任何形式的,明确或隐含的担保条款。 + * 参见按照本许可控制许可权限及限制的特定语言的许可证。 + * + * 你可以获得该代码的最新版本: + * + * https://git.oschina.net/Mr_ChenLuYong/screenshot + * + * 开源社区的所有人都期待与你的共同维护。 + * + * + * 如果你对这些代码还有不理解的地方可以通过最新的文章进行学习: + * + * 博客地址:http://blog.csdn.net/csnd_ayo + * + * 文章地址:http://blog.csdn.net/csnd_ayo/article/details/70197915 + * + * 期待你提交Bug,欢迎Issues。 + * +*/ + + +#include "oecommonhelper.h" + +#include +#include +#include +#include +#include + +#include + +#ifndef QT_NO_DEBUG +#include +#endif + + +#define WINDOW_BASESIZE_WIDTH (1920) +#define WINDOW_BASESIZE_HEIGHT (1080) + +float OECommonHelper::widthMultiplyingPower_ = 0; +float OECommonHelper::heightMultiplyingPower_ = 0; + +void OECommonHelper::setStyle(const QString &style) { + QFile qss(style); + qss.open(QFile::ReadOnly); + qApp->setStyleSheet(qss.readAll()); + qss.close(); +} + +void OECommonHelper::setLanguagePack(const QString &language) { + // 加载中文包 + QTranslator translator; + translator.load(language); + qApp->installTranslator(&translator); +} + +void OECommonHelper::moveCenter(QWidget *widget, QRect parentRect) { + if (parentRect.isEmpty()) { + parentRect = QApplication::desktop()->rect(); + } + widget->move (((parentRect.width() - widget->width()) >> 1), + ((parentRect.height() - widget->height()) >> 1)); +} + +const float &OECommonHelper::getWindowWidthMultiplyingPower() { + if (widthMultiplyingPower_ == 0) { + upWindowSizeMultiplyingPower(); + } + return widthMultiplyingPower_; +} + +const float & OECommonHelper::getWindowHeightMultiplyingPower() { + if (heightMultiplyingPower_ == 0) { + upWindowSizeMultiplyingPower(); + } + return heightMultiplyingPower_; +} + +void OECommonHelper::upWindowSizeMultiplyingPower() { + QSize temp_size = QApplication::desktop()->size(); + widthMultiplyingPower_ = (float)temp_size.width() + / (float)WINDOW_BASESIZE_WIDTH; + heightMultiplyingPower_ = (float)temp_size.height() + / (float)WINDOW_BASESIZE_HEIGHT; +} + +bool OECommonHelper::getSmallestWindowFromCursor(QRect& out_rect) { + HWND hwnd; + POINT pt; + // 获得当前鼠标位置 + ::GetCursorPos(&pt); + // 获得当前位置桌面上的子窗口 + hwnd = ::ChildWindowFromPointEx(::GetDesktopWindow(), pt, CWP_SKIPDISABLED | CWP_SKIPINVISIBLE); + if (hwnd != NULL) { + HWND temp_hwnd; + temp_hwnd = hwnd; + while (true) { + ::GetCursorPos(&pt); + ::ScreenToClient(temp_hwnd, &pt); + temp_hwnd = ::ChildWindowFromPointEx(temp_hwnd, pt, CWP_SKIPINVISIBLE); + if (temp_hwnd == NULL || temp_hwnd == hwnd) + break; + hwnd = temp_hwnd; + } + RECT temp_window; + ::GetWindowRect(hwnd, &temp_window); + out_rect.setRect(temp_window.left,temp_window.top, + temp_window.right - temp_window.left, + temp_window.bottom - temp_window.top); + return true; + } + return false; +} + +bool OECommonHelper::getCurrentWindowFromCursor(QRect &out_rect) +{ + HWND hwnd; + POINT pt; + // 获得当前鼠标位置 + ::GetCursorPos(&pt); + // 获得当前位置桌面上的子窗口 + hwnd = ::ChildWindowFromPointEx(::GetDesktopWindow(), pt, CWP_SKIPDISABLED | CWP_SKIPINVISIBLE); + if (hwnd != NULL) { + RECT temp_window; + ::GetWindowRect(hwnd, &temp_window); + out_rect.setRect(temp_window.left, temp_window.top, + temp_window.right - temp_window.left, + temp_window.bottom - temp_window.top); + return true; + } + return false; +} diff --git a/LedOK/oescreenshot/oecommonhelper.h b/LedOK/oescreenshot/oecommonhelper.h index e8c1e29..30d3c96 100644 --- a/LedOK/oescreenshot/oecommonhelper.h +++ b/LedOK/oescreenshot/oecommonhelper.h @@ -1,128 +1,128 @@ -/** - * @author : 陈鲁勇 - * @date : 2017年04月 - * @version: 1.0 - * @note : 根据 Apache 许可证 2.0 版(以下简称“许可证”)授权; - * 除非遵守本许可,否则您不能使用这个文件。 - * @remarks: 您可以获得该许可的副本: - * http://www.apache.org/licenses/LICENSE-2.0 - * 除非适用法律需要或者书面同意,按本许可分发的软件 - * 要按“原样”分发,没有任何形式的,明确或隐含的担保条款。 - * 参见按照本许可控制许可权限及限制的特定语言的许可证。 - * - * 你可以获得该代码的最新版本: - * - * https://git.oschina.net/Mr_ChenLuYong/screenshot - * - * 开源社区的所有人都期待与你的共同维护。 - * - * - * 如果你对这些代码还有不理解的地方可以通过最新的文章进行学习: - * - * 博客地址:http://blog.csdn.net/csnd_ayo - * - * 文章地址:http://blog.csdn.net/csnd_ayo/article/details/70197915 - * - * 期待你提交Bug,欢迎Issues。 - * -*/ - - - -#ifndef COMMONHELPER_H -#define COMMONHELPER_H -#include -#include - -class QWidget; - -/** - * @class : OECommonHelper - * @brief : 通用助手 - * @note : 完成一些比较常用又通用的功能 - */ -class OECommonHelper -{ -public: - - /** - * @brief : 设置QSS文件 - * @param : style 文件名 - * @author: 陈鲁勇 - * @date : 2017年04月10日 - * @remark: 如果是qrc路径,请带上 qrc:/ - **/ - static void setStyle(const QString &style); - - /** - * @brief : 设置语言包 - * @param : language 语言包的文件名 - * @author: 陈鲁勇 - * @date : 2017年04月10日 - **/ - static void setLanguagePack(const QString& language); - - /** - * @brief : 将窗口移动到中心 - * @param : widget 要移动的窗口 - * @param : parentRect 矩形几何数据 - * @author: 陈鲁勇 - * @date : 2017年04月10日 - **/ - static void moveCenter(QWidget* widget, QRect parentRect = {}); - - - /** - * @brief : 获得当前界面与开发时的界面之间的横向倍率 - * @return: float 倍率 - * @author: 陈鲁勇 - * @date : 2017年04月10日 - **/ - static const float& getWindowWidthMultiplyingPower(void); - - - /** - * @brief : 获得当前界面与开发时的界面之间的纵向倍率 - * @return: float 倍率 - * @author: 陈鲁勇 - * @date : 2017年04月10日 - **/ - static const float& getWindowHeightMultiplyingPower(void); - - - /** - * @brief : 获得当前鼠标位置最小的子窗口 - * @param : out_rect 矩形 (返回) - * @return: 成功:true - * @author: 陈鲁勇 - * @date : 2017年04月10日 - **/ - static bool getSmallestWindowFromCursor(QRect &out_rect); - - /** - * @brief : 获得当前鼠标位置的窗口 - * @param : out_rect 矩形 (返回) - * @return: 成功:true - * @author: 陈鲁勇 - * @date : 2017年04月10日 - **/ - static bool getCurrentWindowFromCursor(QRect &out_rect); - -protected: - - /** - * @brief : 更新窗口倍率 - * @author: 陈鲁勇 - * @date : 2017年04月10日 - **/ - static void upWindowSizeMultiplyingPower(void); - - -private: - /// 窗口横向倍率 - static float widthMultiplyingPower_; - /// 窗口纵向倍率 - static float heightMultiplyingPower_; -}; - -#endif /// COMMONHELPER_H +/** + * @author : 陈鲁勇 + * @date : 2017年04月 + * @version: 1.0 + * @note : 根据 Apache 许可证 2.0 版(以下简称“许可证”)授权; + * 除非遵守本许可,否则您不能使用这个文件。 + * @remarks: 您可以获得该许可的副本: + * http://www.apache.org/licenses/LICENSE-2.0 + * 除非适用法律需要或者书面同意,按本许可分发的软件 + * 要按“原样”分发,没有任何形式的,明确或隐含的担保条款。 + * 参见按照本许可控制许可权限及限制的特定语言的许可证。 + * + * 你可以获得该代码的最新版本: + * + * https://git.oschina.net/Mr_ChenLuYong/screenshot + * + * 开源社区的所有人都期待与你的共同维护。 + * + * + * 如果你对这些代码还有不理解的地方可以通过最新的文章进行学习: + * + * 博客地址:http://blog.csdn.net/csnd_ayo + * + * 文章地址:http://blog.csdn.net/csnd_ayo/article/details/70197915 + * + * 期待你提交Bug,欢迎Issues。 + * +*/ + + + +#ifndef COMMONHELPER_H +#define COMMONHELPER_H +#include +#include + +class QWidget; + +/** + * @class : OECommonHelper + * @brief : 通用助手 + * @note : 完成一些比较常用又通用的功能 + */ +class OECommonHelper +{ +public: + + /** + * @brief : 设置QSS文件 + * @param : style 文件名 + * @author: 陈鲁勇 + * @date : 2017年04月10日 + * @remark: 如果是qrc路径,请带上 qrc:/ + **/ + static void setStyle(const QString &style); + + /** + * @brief : 设置语言包 + * @param : language 语言包的文件名 + * @author: 陈鲁勇 + * @date : 2017年04月10日 + **/ + static void setLanguagePack(const QString& language); + + /** + * @brief : 将窗口移动到中心 + * @param : widget 要移动的窗口 + * @param : parentRect 矩形几何数据 + * @author: 陈鲁勇 + * @date : 2017年04月10日 + **/ + static void moveCenter(QWidget* widget, QRect parentRect = {}); + + + /** + * @brief : 获得当前界面与开发时的界面之间的横向倍率 + * @return: float 倍率 + * @author: 陈鲁勇 + * @date : 2017年04月10日 + **/ + static const float& getWindowWidthMultiplyingPower(void); + + + /** + * @brief : 获得当前界面与开发时的界面之间的纵向倍率 + * @return: float 倍率 + * @author: 陈鲁勇 + * @date : 2017年04月10日 + **/ + static const float& getWindowHeightMultiplyingPower(void); + + + /** + * @brief : 获得当前鼠标位置最小的子窗口 + * @param : out_rect 矩形 (返回) + * @return: 成功:true + * @author: 陈鲁勇 + * @date : 2017年04月10日 + **/ + static bool getSmallestWindowFromCursor(QRect &out_rect); + + /** + * @brief : 获得当前鼠标位置的窗口 + * @param : out_rect 矩形 (返回) + * @return: 成功:true + * @author: 陈鲁勇 + * @date : 2017年04月10日 + **/ + static bool getCurrentWindowFromCursor(QRect &out_rect); + +protected: + + /** + * @brief : 更新窗口倍率 + * @author: 陈鲁勇 + * @date : 2017年04月10日 + **/ + static void upWindowSizeMultiplyingPower(void); + + +private: + /// 窗口横向倍率 + static float widthMultiplyingPower_; + /// 窗口纵向倍率 + static float heightMultiplyingPower_; +}; + +#endif /// COMMONHELPER_H diff --git a/LedOK/oescreenshot/oemodelview.cpp b/LedOK/oescreenshot/oemodelview.cpp index 0accfc1..3f9f81c 100644 --- a/LedOK/oescreenshot/oemodelview.cpp +++ b/LedOK/oescreenshot/oemodelview.cpp @@ -1,86 +1,86 @@ -#include "oemodelview.h" - -#include -#include -#include -#include -#include -/// @test : 测试变量 -QPoint startPoint_; -QPoint endPoint_; - - -OEModelView::OEModelView(MODEL model, - QWidget *parent) : QWidget(parent), - color_(Qt::red) { - /// 确定画图样式 - switch (model) { - case MODEL::Arrows: - { - drawFunc_ = &OEModelView::drawArrows; - break; - } - default: - { - drawFunc_ = &OEModelView::drawArrows; - } - } -} - - -void OEModelView::paintEvent(QPaintEvent *) { - QPainter paiter(this); - - /// @test : 测试变量 - startPoint_ = QPoint(width(),height()); - endPoint_ = {}; - - /// 绘制图形 - (this->*drawFunc_)(startPoint_, endPoint_, paiter); -} - - -void OEModelView::drawArrows(const QPoint& startPoint, - const QPoint& endPoint, - QPainter &paiter) { - /// 消锯齿 - paiter.setRenderHint(QPainter::Antialiasing, true); - /// 创建画笔,设置画刷 - QPen pen; - pen.setColor(color_); - pen.setWidth(1); - paiter.setPen(pen); - paiter.setBrush(color_); - - - /// 箭头部分三角形的腰长 - double par = 15.0; - double slopy = atan2((endPoint.y() - startPoint.y()), - (endPoint.x() - startPoint.x())); - double cos_y = cos(slopy); - double sin_y = sin(slopy); - QPoint head_point1 = QPoint(endPoint.x() + int(-par*cos_y - (par / 2.0 * sin_y)), - endPoint.y() + int(-par*sin_y + (par / 2.0 * cos_y))); - QPoint head_point2 = QPoint(endPoint.x() + int(-par*cos_y + (par / 2.0 * sin_y)), - endPoint.y() - int(par / 2.0*cos_y + par * sin_y)); - QPoint head_points[3] = { endPoint, head_point1, head_point2 }; - /// 绘制箭头部分 - paiter.drawPolygon(head_points, 3); - - - /// 计算箭身部分 - int offset_x = int(par*sin_y / 3); - int offset_y = int(par*cos_y / 3); - QPoint body_point1, body_point2; - body_point1 = QPoint(endPoint.x() + int(-par*cos_y - (par / 2.0*sin_y)) + - offset_x, endPoint.y() + int(-par*sin_y + (par / 2.0*cos_y)) - offset_y); - body_point2 = QPoint(endPoint.x() + int(-par*cos_y + (par / 2.0*sin_y) - offset_x), - endPoint.y() - int(par / 2.0*cos_y + par*sin_y) + offset_y); - QPoint body_points[3] = { startPoint, body_point1, body_point2 }; - /// 绘制箭身部分 - paiter.drawPolygon(body_points, 3); - -} -void OEModelView::onColor(const QColor &color) { - color_ = color; -} +#include "oemodelview.h" + +#include +#include +#include +#include +#include +/// @test : 测试变量 +QPoint startPoint_; +QPoint endPoint_; + + +OEModelView::OEModelView(MODEL model, + QWidget *parent) : QWidget(parent), + color_(Qt::red) { + /// 确定画图样式 + switch (model) { + case MODEL::Arrows: + { + drawFunc_ = &OEModelView::drawArrows; + break; + } + default: + { + drawFunc_ = &OEModelView::drawArrows; + } + } +} + + +void OEModelView::paintEvent(QPaintEvent *) { + QPainter paiter(this); + + /// @test : 测试变量 + startPoint_ = QPoint(width(),height()); + endPoint_ = {}; + + /// 绘制图形 + (this->*drawFunc_)(startPoint_, endPoint_, paiter); +} + + +void OEModelView::drawArrows(const QPoint& startPoint, + const QPoint& endPoint, + QPainter &paiter) { + /// 消锯齿 + paiter.setRenderHint(QPainter::Antialiasing, true); + /// 创建画笔,设置画刷 + QPen pen; + pen.setColor(color_); + pen.setWidth(1); + paiter.setPen(pen); + paiter.setBrush(color_); + + + /// 箭头部分三角形的腰长 + double par = 15.0; + double slopy = atan2((endPoint.y() - startPoint.y()), + (endPoint.x() - startPoint.x())); + double cos_y = cos(slopy); + double sin_y = sin(slopy); + QPoint head_point1 = QPoint(endPoint.x() + int(-par*cos_y - (par / 2.0 * sin_y)), + endPoint.y() + int(-par*sin_y + (par / 2.0 * cos_y))); + QPoint head_point2 = QPoint(endPoint.x() + int(-par*cos_y + (par / 2.0 * sin_y)), + endPoint.y() - int(par / 2.0*cos_y + par * sin_y)); + QPoint head_points[3] = { endPoint, head_point1, head_point2 }; + /// 绘制箭头部分 + paiter.drawPolygon(head_points, 3); + + + /// 计算箭身部分 + int offset_x = int(par*sin_y / 3); + int offset_y = int(par*cos_y / 3); + QPoint body_point1, body_point2; + body_point1 = QPoint(endPoint.x() + int(-par*cos_y - (par / 2.0*sin_y)) + + offset_x, endPoint.y() + int(-par*sin_y + (par / 2.0*cos_y)) - offset_y); + body_point2 = QPoint(endPoint.x() + int(-par*cos_y + (par / 2.0*sin_y) - offset_x), + endPoint.y() - int(par / 2.0*cos_y + par*sin_y) + offset_y); + QPoint body_points[3] = { startPoint, body_point1, body_point2 }; + /// 绘制箭身部分 + paiter.drawPolygon(body_points, 3); + +} +void OEModelView::onColor(const QColor &color) { + color_ = color; +} diff --git a/LedOK/oescreenshot/oemodelview.h b/LedOK/oescreenshot/oemodelview.h index 6dbbd6a..56eeff9 100644 --- a/LedOK/oescreenshot/oemodelview.h +++ b/LedOK/oescreenshot/oemodelview.h @@ -1,61 +1,61 @@ -#ifndef OEMODELVIEW_H -#define OEMODELVIEW_H - -#include -#include -#include -#include - -class OEModelView : public QWidget -{ - Q_OBJECT - -public: - - /** - * @brief : 模型种类 - */ - enum MODEL{ - Arrows = 0, /// 箭头 - Rectangle = 1, /// 矩形 - Roundness /// 圆形 - }; - -private: - typedef void (OEModelView::*PDRAWFUNC) - (const QPoint &,const QPoint &, QPainter&); - - -signals: - -public: - explicit OEModelView(MODEL model = MODEL::Arrows, - QWidget *parent = 0); - -protected: - - /** - * @brief : 自绘事件 - */ - virtual void paintEvent(QPaintEvent *); - -private: - - void drawArrows(const QPoint &startPoint, - const QPoint &endPoint, - QPainter& paiter); - -public slots: - - void onColor(const QColor &color); - -private: - QColor color_; - PDRAWFUNC drawFunc_; - /// @bug : 莫名,开启此处变量的声明,程序就会崩溃。 -// QPoint ssPoint331_; -// QPoint esoint233_; -}; - - -#endif // OEMODELVIEW_H +#ifndef OEMODELVIEW_H +#define OEMODELVIEW_H + +#include +#include +#include +#include + +class OEModelView : public QWidget +{ + Q_OBJECT + +public: + + /** + * @brief : 模型种类 + */ + enum MODEL{ + Arrows = 0, /// 箭头 + Rectangle = 1, /// 矩形 + Roundness /// 圆形 + }; + +private: + typedef void (OEModelView::*PDRAWFUNC) + (const QPoint &,const QPoint &, QPainter&); + + +signals: + +public: + explicit OEModelView(MODEL model = MODEL::Arrows, + QWidget *parent = 0); + +protected: + + /** + * @brief : 自绘事件 + */ + virtual void paintEvent(QPaintEvent *); + +private: + + void drawArrows(const QPoint &startPoint, + const QPoint &endPoint, + QPainter& paiter); + +public slots: + + void onColor(const QColor &color); + +private: + QColor color_; + PDRAWFUNC drawFunc_; + /// @bug : 莫名,开启此处变量的声明,程序就会崩溃。 +// QPoint ssPoint331_; +// QPoint esoint233_; +}; + + +#endif // OEMODELVIEW_H diff --git a/LedOK/oescreenshot/oescreenshot.cpp b/LedOK/oescreenshot/oescreenshot.cpp index 9b846a5..fdece1e 100644 --- a/LedOK/oescreenshot/oescreenshot.cpp +++ b/LedOK/oescreenshot/oescreenshot.cpp @@ -1,768 +1,768 @@ -/** - * @author : 陈鲁勇 - * @date : 2017年04月 - * @version: 1.0 - * @note : 根据 Apache 许可证 2.0 版(以下简称“许可证”)授权; - * 除非遵守本许可,否则您不能使用这个文件。 - * @remarks: 您可以获得该许可的副本: - * http://www.apache.org/licenses/LICENSE-2.0 - * 除非适用法律需要或者书面同意,按本许可分发的软件 - * 要按“原样”分发,没有任何形式的,明确或隐含的担保条款。 - * 参见按照本许可控制许可权限及限制的特定语言的许可证。 - * - * 你可以获得该代码的最新版本: - * - * https://git.oschina.net/Mr_ChenLuYong/screenshot - * - * 开源社区的所有人都期待与你的共同维护。 - * - * - * 如果你对这些代码还有不理解的地方可以通过最新的文章进行学习: - * - * 博客地址:http://blog.csdn.net/csnd_ayo - * - * 文章地址:http://blog.csdn.net/csnd_ayo/article/details/70197915 - * - * 期待你提交Bug,欢迎Issues。 - * -*/ - -#include "oescreenshot.h" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifndef QT_NO_DEBUG -#include -#endif - -#include - -#include "oeamplifier.h" -#include "oecommonhelper.h" - - -/// 鼠标按钮图片的十六进制数据 -static const unsigned char uc_mouse_image[] = { - 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52 - ,0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x2D, 0x08, 0x06, 0x00, 0x00, 0x00, 0x52, 0xE9, 0x60 - ,0xA2, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0B, 0x13, 0x00, 0x00, 0x0B - ,0x13, 0x01, 0x00, 0x9A, 0x9C, 0x18, 0x00, 0x00, 0x01, 0x40, 0x49, 0x44, 0x41, 0x54, 0x58, 0x85 - ,0xED, 0xD5, 0x21, 0x6E, 0xC3, 0x30, 0x14, 0xC6, 0xF1, 0xFF, 0x9B, 0xC6, 0x36, 0x30, 0x38, 0xA9 - ,0x05, 0x01, 0x05, 0x81, 0x05, 0x03, 0x39, 0xCA, 0x60, 0x8F, 0xD2, 0x03, 0xEC, 0x10, 0x3B, 0x46 - ,0xC1, 0xC0, 0xC6, 0x0A, 0x3B, 0x96, 0xB1, 0x80, 0x82, 0xC1, 0x56, 0x2A, 0xFF, 0x06, 0xE2, 0x36 - ,0x75, 0x9A, 0xB4, 0xCA, 0xEC, 0x4E, 0x9A, 0xE4, 0x2F, 0xB2, 0x42, 0x22, 0xFF, 0xF2, 0xFC, 0x9C - ,0x18, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0xFE, 0x55, 0xE4, 0xC6, 0xA0 - ,0xDC, 0xC4, 0x71, 0x87, 0xC1, 0xC1, 0x68, 0x01, 0xCC, 0x06, 0xC2, 0x51, 0xD0, 0x29, 0xB0, 0x18 - ,0x00, 0xDF, 0xC6, 0x40, 0x33, 0x37, 0x84, 0x30, 0x4C, 0x80, 0x85, 0xCE, 0x7B, 0x2E, 0x2A, 0x91 - ,0x84, 0x24, 0xBE, 0x25, 0xDE, 0x25, 0x5E, 0x2F, 0x6E, 0xAE, 0xD0, 0x37, 0x92, 0x10, 0xF0, 0x09 - ,0x54, 0x40, 0xE9, 0xEE, 0x15, 0xC6, 0xA2, 0x77, 0xFE, 0xE0, 0xE5, 0x85, 0x8F, 0x16, 0x58, 0xDF - ,0x35, 0x06, 0x5B, 0xD3, 0xB9, 0xD4, 0x11, 0xD0, 0xA5, 0x8F, 0xDE, 0x57, 0x75, 0x83, 0x73, 0x50 - ,0x06, 0xF6, 0x72, 0x0A, 0x47, 0x40, 0x57, 0x0D, 0x38, 0xDE, 0xC0, 0x04, 0x6F, 0x68, 0x05, 0x36 - ,0xF5, 0xE1, 0x08, 0x3D, 0xCD, 0xEA, 0xEA, 0x5A, 0xD8, 0xBE, 0x5A, 0x46, 0xB0, 0x05, 0x1E, 0xAC - ,0xF1, 0xC2, 0xD1, 0xCC, 0x01, 0x6D, 0x74, 0x02, 0xDB, 0x3B, 0xBF, 0xD3, 0x73, 0x07, 0x87, 0x2F - ,0xEF, 0x53, 0x07, 0x38, 0x82, 0x2F, 0xF6, 0xFB, 0xB8, 0x81, 0x73, 0x41, 0x69, 0x28, 0x3A, 0x7A - ,0x5C, 0xDD, 0x73, 0xCF, 0x3A, 0x86, 0xA3, 0x05, 0x87, 0xEA, 0xCC, 0x60, 0xA1, 0x06, 0x75, 0x89 - ,0xFE, 0x77, 0x92, 0x76, 0x68, 0x23, 0xEF, 0x88, 0xD3, 0x4C, 0xA8, 0x10, 0x7A, 0xD4, 0xEF, 0x8E - ,0xBE, 0x8B, 0x68, 0x79, 0x3A, 0xB1, 0x72, 0xE1, 0xAE, 0xBC, 0x13, 0x0D, 0xDE, 0xBD, 0x3D, 0xF3 - ,0x08, 0x15, 0xD4, 0xDF, 0x4C, 0x06, 0x36, 0xF7, 0x9E, 0x09, 0xED, 0xE9, 0x99, 0x97, 0x3E, 0x42 - ,0xFF, 0x30, 0x42, 0x4B, 0xA1, 0x8D, 0xD8, 0xE9, 0x2A, 0xBD, 0xED, 0x41, 0x25, 0x2A, 0x89, 0x37 - ,0x1F, 0xBD, 0xEA, 0x61, 0x8B, 0x5F, 0xDD, 0xC1, 0xFA, 0x01, 0xD8, 0xA3, 0x8F, 0xFB, 0xCA, 0x70 - ,0x16, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82 -}; - - - -OEScreenshot * OEScreenshot::self_ = nullptr; -bool OEScreenshot::isActivity_ = false; -bool OEScreen::isInit_ = false; - -OEScreenshot::OEScreenshot(QWidget *parent) : QWidget(parent), - isLeftPressed_ (false), backgroundScreen_(nullptr), - originPainting_(nullptr), screenTool_(nullptr) { - /// 初始化鼠标 - initCursor(); - /// 截取屏幕信息 - initGlobalScreen(); - /// 初始化鼠标放大器 - initAmplifier(); - /// 初始化大小感知器 - initMeasureWidget(); - /// 全屏窗口 - showFullScreen(); - /// 窗口与显示屏对齐 - setGeometry(getScreenRect()); - /// 霸道置顶 - onEgoistic(); - /// 开启鼠标实时追踪 - setMouseTracking(true); - /// 更新鼠标的位置 - emit cursorPosChange(cursor().pos().x(), cursor().pos().y()); - /// 更新鼠标区域窗口 - updateMouse(); - /// 展示窗口 - show(); -} - -OEScreenshot::~OEScreenshot(void) { -} - -/** - * @brief:窗口实例 - * @return:OEScreenshot - */ -OEScreenshot *OEScreenshot::Instance(void) { - if (!isActivity_ && self_) { - destroy(); - } - static QMutex mutex; - if (!self_) { - QMutexLocker locker(&mutex); - if (!self_) { - isActivity_ = true; - self_ = new OEScreenshot; - } - } - return self_; -} - -void OEScreenshot::destroy(void) { - if (!isActivity_ && self_) { - delete self_; - self_ = nullptr; - } -} - -void OEScreenshot::hideEvent(QHideEvent *) { - isActivity_ = false; -} - - -void OEScreenshot::closeEvent(QCloseEvent *) { - isActivity_ = false; -} - -void OEScreenshot::mouseDoubleClickEvent(QMouseEvent *) { - emit doubleClick(); -} - - -/** - * 初始化放大镜 (色彩采集器) - */ -void OEScreenshot::initAmplifier(std::shared_ptr originPainting) { - std::shared_ptr temp_pm = originPainting; - if (temp_pm == nullptr) { - temp_pm = originPainting_; - } - amplifierTool_.reset(new OEAmplifier(temp_pm, this)); - connect(this,SIGNAL(cursorPosChange(int,int)), - amplifierTool_.get(), SLOT(onPostionChange(int,int))); - amplifierTool_->show(); - amplifierTool_->raise(); -} - -void OEScreenshot::initMeasureWidget(void) -{ - rectTool_.reset(new OERect(this)); - rectTool_->raise(); -} - -/** - * 功能:获得当前屏幕的大小 - */ -const QRect &OEScreenshot::getScreenRect(void) { - if (!desktopRect_.isEmpty()) { - return desktopRect_; - } - /// 获得屏幕个数 - int temp_screen_num = QApplication::screens().size(); - /// 获得屏幕大小 - desktopRect_ = QApplication::desktop()->rect(); - if (temp_screen_num != 1) { - /// 多屏幕策略 - const int& temp = desktopRect_.width() - - (desktopRect_.width() / temp_screen_num); - /// 重新设置矩形 - desktopRect_ = QRect(-temp, 0, - desktopRect_.width(), desktopRect_.height()); - } - return desktopRect_; -} - -std::shared_ptr OEScreenshot::initGlobalScreen(void) { - if (backgroundScreen_.get() != nullptr) { - return backgroundScreen_; - } - /// 获得屏幕原画 - std::shared_ptr temp_screen = getGlobalScreen(); - - /// 制作暗色屏幕背景 - QPixmap temp_dim_pix(temp_screen->width(), temp_screen->height()); - temp_dim_pix.fill((QColor(0, 0, 0, 160))); - backgroundScreen_.reset(new QPixmap(*temp_screen)); - QPainter p(backgroundScreen_.get()); - p.drawPixmap(0, 0, temp_dim_pix); - - return backgroundScreen_; -} - -/* - * 获得屏幕的原画 - * 返回:QPixmap* 指针 - */ -std::shared_ptr OEScreenshot::getGlobalScreen(void) { - if (originPainting_.get() == nullptr) { - /// 截取当前桌面,作为截屏的背景图 - QScreen *screen = QGuiApplication::primaryScreen(); - const QRect& temp_rect = getScreenRect(); - originPainting_.reset(new QPixmap(screen->grabWindow(0, temp_rect.x(), - temp_rect.y(), temp_rect.width(), - temp_rect.height()))); - } - return originPainting_; -} -void OEScreenshot::onEgoistic(void) -{ - /// 窗口置顶 -#ifdef Q_OS_WIN32 - // SetWindowPos(HWND)this->winId(),HWND_TOPMOST,this->pos().x(),this->pos().y(),this->width(),this->height(),SWP_SHOWWINDOW); -#else - Qt::WindowFlags flags = windowFlags(); - flags |= Qt::WindowStaysOnTopHint; - setWindowFlags(flags); -#endif -} - -/* - * 初始化鼠标 - * 参数:_ico 鼠标图片的资源文件 - */ -void OEScreenshot::initCursor(const QString& ico) { - QPixmap pixmap; - if (ico.isEmpty()) { - pixmap.loadFromData(uc_mouse_image, sizeof(uc_mouse_image)); - } - else { - pixmap.load(ico); - } - QCursor cursor; - cursor = QCursor(pixmap, 15, 23); - setCursor(cursor); -} - -std::shared_ptr OEScreenshot::createScreen(const QPoint &pos) { - if (screenTool_.get() == nullptr) { - /// 创建截图器 - screenTool_.reset(new OEScreen(originPainting_, pos, this)); - /// 建立信号连接 - connect (this, SIGNAL(cursorPosChange(int,int)), - screenTool_.get(),SLOT(onMouseChange(int,int))); - /// 建立主界面双击保存信号关联 - connect (this, SIGNAL(doubleClick()), - screenTool_.get(),SLOT(onSaveScreen())); - /// 建立截图器大小关联 - connect(screenTool_.get(), SIGNAL(sizeChange(int,int)), - rectTool_.get(), SLOT(onSizeChange(int,int))); - connect(screenTool_.get(), SIGNAL(sizeChange(int,int)), - amplifierTool_.get(), SLOT(onSizeChange(int,int))); - /// 建立截图器与感知器的位置关联 - connect(screenTool_.get(), SIGNAL(postionChange(int,int)), - rectTool_.get(), SLOT(onPostionChange(int,int))); - - /// 获得截图器当前起始位置 - startPoint_ = pos; - isLeftPressed_ = true; - } - return screenTool_; -} - -void OEScreenshot::destroyScreen() { - if (screenTool_.get() != nullptr) { - /// 断开信号资源 - disconnect (this, SIGNAL(doubleClick()), - screenTool_.get(),SLOT(onSaveScreen())); - disconnect(screenTool_.get(), SIGNAL(sizeChange(int,int)), - rectTool_.get(), SLOT(onSizeChange(int,int))); - disconnect(screenTool_.get(), SIGNAL(postionChange(int,int)), - rectTool_.get(), SLOT(onPostionChange(int,int))); - /// 清理工具 - screenTool_.reset(); - screenTool_ = nullptr; - isLeftPressed_ = false; - update(); - return; - } -} - -void OEScreenshot::mousePressEvent(QMouseEvent *e) { - if (e->button() == Qt::LeftButton) { - createScreen(e->pos()); - return ; - } -} - -void OEScreenshot::mouseReleaseEvent(QMouseEvent *e) { - if (e->button() == Qt::RightButton) { - if (screenTool_.get() != nullptr) { - rectTool_->hide(); - amplifierTool_->onPostionChange(e->x(), e->y()); - amplifierTool_->show(); - return destroyScreen(); - } - close(); - return ; - } - else if (isLeftPressed_ == true - && e->button() == Qt::LeftButton) { - /// 选择窗口选区 - if (startPoint_ == e->pos() - && !windowRect_.isEmpty()) { - screenTool_->setGeometry(windowRect_); - screenTool_->show(); - windowRect_ = {}; - } - /// 断开鼠标移动的信号 - disconnect (this, SIGNAL(cursorPosChange(int,int)), - screenTool_.get(),SLOT(onMouseChange(int,int))); - /// 隐藏放大器 - amplifierTool_->hide(); - /// 断开截图器的大小修改信号 - disconnect (screenTool_.get(), SIGNAL(sizeChange(int,int)), - amplifierTool_.get(),SLOT(onSizeChange(int,int))); - isLeftPressed_ = false; - } - QWidget::mouseReleaseEvent(e); -} - -void OEScreenshot::mouseMoveEvent(QMouseEvent *e) { - emit cursorPosChange(e->x(), e->y()); - if (isLeftPressed_) { - amplifierTool_->raise(); - windowRect_ = {}; - update(); - } - else if (isLeftPressed_ == false - && false == OEScreen::state()){ - /// 霸道置顶 - onEgoistic(); - - /// 更新当前鼠标选中的窗口 - updateMouse(); - } - QWidget::mouseMoveEvent(e); -} - -void OEScreenshot::paintEvent(QPaintEvent *) { - QPainter painter(this); - /// 画全屏图 - painter.drawPixmap(0,0,desktopRect_.width(), - desktopRect_.height(), *backgroundScreen_); - - if (!windowRect_.isEmpty()) { - /// 绘制选区 - QPen pen = painter.pen(); - pen.setColor(QColor(0,175,255)); - pen.setWidth(2); - painter.setPen(pen); - painter.drawRect(windowRect_.x(),windowRect_.y(), - windowRect_.width(),windowRect_.height()); - painter.drawPixmap(QPoint(windowRect_.x(),windowRect_.y()), - *originPainting_, windowRect_); - } -} - -void OEScreenshot::updateMouse(void) { - /// 获取当前鼠标选中的窗口 - ::EnableWindow((HWND)winId(), FALSE); - OECommonHelper::getSmallestWindowFromCursor(windowRect_); - QPoint temp_pt = mapFromGlobal(QPoint(windowRect_.x(), windowRect_.y())); - windowRect_ = QRect(temp_pt.x(), temp_pt.y(), - windowRect_.width(), windowRect_.height()); - ::EnableWindow((HWND)winId(), TRUE); - amplifierTool_->onSizeChange(windowRect_.width(),windowRect_.height()); - emit findChildWind(windowRect_); - update(); -} - -void OEScreenshot::keyPressEvent(QKeyEvent *e) { - /// Esc 键退出截图; - if (e->key() == Qt::Key_Escape) { - close(); - } - else { - e->ignore(); - } - -} - - - -/////////////////////////////////////////////////////////// - - - - -OERect::OERect(QWidget *parent) : QWidget(parent) { - - /// 设置感知器默认大小 - setFixedSize(95 * OECommonHelper::getWindowHeightMultiplyingPower(), - 20 * OECommonHelper::getWindowHeightMultiplyingPower()); - - /// 填充默认背景 - backgroundPixmap_.reset(new QPixmap(width(),height())); - backgroundPixmap_->fill((QColor(8, 8, 8, 160))); - - /// 默认隐藏 - hide(); -} - - -void OERect::paintEvent(QPaintEvent *) { - QPainter painter(this); - painter.drawPixmap(rect(),*backgroundPixmap_); - painter.setPen(QPen(QColor(Qt::white))); - painter.drawText(rect(), Qt::AlignCenter, info_); -} - -void OERect::onPostionChange(int x, int y) { - if (x < 0) x = 0; - if (y < 0) y = 0; - const int& ry = y - height() - 1; - if (ry < 0) { - this->raise(); - } - move(x, ((ry < 0) ? y : ry)); - show(); -} - -void OERect::onSizeChange(int w, int h) { - info_ = QString("%1 × %2").arg(w).arg(h); -} - - - - -/////////////////////////////////////////////////////////// - - - - - -OEScreen::OEScreen(std::shared_ptr originPainting, QPoint pos, QWidget *parent) - : QWidget(parent), direction_(NONE), originPoint_(pos), - isPressed_(false), originPainting_(originPainting) { - menu_ = new QMenu(this); - menu_->addAction("完成截图", this, SLOT(onSaveScreen())); - menu_->addAction("保存", this, SLOT(onSaveScreenOther())); - menu_->addSeparator(); - menu_->addAction("退出截图", this, SLOT(quitScreenshot())); - - /// 双击即完成 - connect(this, SIGNAL(doubleClick()), - this, SLOT(onSaveScreen())); - - /// 开启鼠标实时追踪 - setMouseTracking(true); - /// 默认隐藏 - hide(); -} - -OEScreen::DIRECTION OEScreen::getRegion(const QPoint &cursor) { - if (!isInit_) { - return NONE; - } - OEScreen::DIRECTION ret_dir = NONE; - // left upper - QPoint pt_lu = mapToParent(rect().topLeft()); - // right lower - QPoint pt_rl = mapToParent(rect().bottomRight()); - - int x = cursor.x(); - int y = cursor.y(); - - /// 获得鼠标当前所处窗口的边界方向 - if(pt_lu.x() + PADDING_ >= x - && pt_lu.x() <= x - && pt_lu.y() + PADDING_ >= y - && pt_lu.y() <= y) { - // 左上角 - ret_dir = LEFTUPPER; - this->setCursor(QCursor(Qt::SizeFDiagCursor)); - } else if(x >= pt_rl.x() - PADDING_ - && x <= pt_rl.x() - && y >= pt_rl.y() - PADDING_ - && y <= pt_rl.y()) { - // 右下角 - ret_dir = RIGHTLOWER; - this->setCursor(QCursor(Qt::SizeFDiagCursor)); - } else if(x <= pt_lu.x() + PADDING_ - && x >= pt_lu.x() - && y >= pt_rl.y() - PADDING_ - && y <= pt_rl.y()) { - // 左下角 - ret_dir = LEFTLOWER; - this->setCursor(QCursor(Qt::SizeBDiagCursor)); - } else if(x <= pt_rl.x() - && x >= pt_rl.x() - PADDING_ - && y >= pt_lu.y() - && y <= pt_lu.y() + PADDING_) { - // 右上角 - ret_dir = RIGHTUPPER; - this->setCursor(QCursor(Qt::SizeBDiagCursor)); - } else if(x <= pt_lu.x() + PADDING_ - && x >= pt_lu.x()) { - // 左边 - ret_dir = LEFT; - this->setCursor(QCursor(Qt::SizeHorCursor)); - } else if( x <= pt_rl.x() - && x >= pt_rl.x() - PADDING_) { - // 右边 - ret_dir = RIGHT; - this->setCursor(QCursor(Qt::SizeHorCursor)); - }else if(y >= pt_lu.y() - && y <= pt_lu.y() + PADDING_){ - // 上边 - ret_dir = UPPER; - this->setCursor(QCursor(Qt::SizeVerCursor)); - } else if(y <= pt_rl.y() - && y >= pt_rl.y() - PADDING_) { - // 下边 - ret_dir = LOWER; - this->setCursor(QCursor(Qt::SizeVerCursor)); - }else { - // 默认 - ret_dir = NONE; - this->setCursor(QCursor(Qt::SizeAllCursor)); - } - return ret_dir; -} - - -void OEScreen::contextMenuEvent(QContextMenuEvent *) { - /// 在鼠标位置弹射出菜单栏 - menu_->exec(cursor().pos()); -} - -void OEScreen::mouseDoubleClickEvent(QMouseEvent *e) { - if (e->button() == Qt::LeftButton) { - emit doubleClick(); - e->accept(); - } -} - -void OEScreen::mousePressEvent(QMouseEvent *e) { - if (e->button() == Qt::LeftButton) { - isPressed_ = true; - if(direction_ != NONE) { - this->mouseGrabber(); - } - /// @bug :这里可能存在问题, 不应当使用globalPos - movePos_ = e->globalPos() - pos(); - } -} - -void OEScreen::mouseReleaseEvent(QMouseEvent * e) { - if (e->button() == Qt::LeftButton) { - isPressed_ = false; - if(direction_ != NONE) { - setCursor(QCursor(Qt::SizeAllCursor)); - } - } -} - -void OEScreen::mouseMoveEvent(QMouseEvent * e) { - QPoint gloPoint = mapToParent(e->pos()); - // left upper - QPoint pt_lu = mapToParent(rect().topLeft()); - // left lower - QPoint pt_ll = mapToParent(rect().bottomLeft()); - // right lower - QPoint pt_rl = mapToParent(rect().bottomRight()); - // right upper - QPoint pt_ru = mapToParent(rect().topRight()); - if(!isPressed_) { - /// 检查鼠标鼠标方向 - direction_ = getRegion(gloPoint); - - /// 根据方位判断拖拉对应支点 - switch(direction_) { - case NONE: - case RIGHT: - case RIGHTLOWER: - originPoint_ = pt_lu; - break; - case RIGHTUPPER: - originPoint_ = pt_ll; - break; - case LEFT: - case LEFTLOWER: - originPoint_ = pt_ru; - break; - case LEFTUPPER: - case UPPER: - originPoint_ = pt_rl; - break; - case LOWER: - originPoint_ = pt_lu; - break; - } - } - else { - if(direction_ != NONE) { - const int& global_x = gloPoint.x(); - /// 鼠标进行拖拉拽 - switch(direction_) { - case LEFT: - return onMouseChange(global_x, pt_ll.y() + 1); - case RIGHT: - return onMouseChange(global_x, pt_rl.y() + 1); - case UPPER: - return onMouseChange(pt_lu.x(), gloPoint.y()); - case LOWER: - return onMouseChange(pt_rl.x() + 1, gloPoint.y()); - case LEFTUPPER: - case RIGHTUPPER: - case LEFTLOWER: - case RIGHTLOWER: - return onMouseChange(global_x, gloPoint.y()); - default: - break; - } - } - else { - /// 窗口的移动 - /// @bug :这里可能存在问题, 不应当使用globalPos - move(e->globalPos() - movePos_); - movePos_ = e->globalPos() - pos(); - e->accept(); - } - } - currentRect_ = geometry(); -} - -void OEScreen::moveEvent(QMoveEvent *) { - emit postionChange(x(), y()); -} - -void OEScreen::resizeEvent(QResizeEvent *) { - listMarker_.clear(); - - /// 重新计算八个锚点 - // 角点 - listMarker_.push_back(QPoint(0, 0)); - listMarker_.push_back(QPoint(width(), 0)); - listMarker_.push_back(QPoint(0, height())); - listMarker_.push_back(QPoint(width(), height())); - - // 中点 - listMarker_.push_back(QPoint((width() >> 1), 0)); - listMarker_.push_back(QPoint((width() >> 1), height())); - listMarker_.push_back(QPoint(0, (height() >> 1))); - listMarker_.push_back(QPoint(width(), (height() >> 1))); - - emit sizeChange(width(), height()); -} - -void OEScreen::showEvent(QShowEvent *) { - isInit_ = true; -} - -void OEScreen::hideEvent(QHideEvent *) { - currentRect_ = {}; - movePos_ = {}; - originPoint_ = {}; - isInit_ = false; -} - -void OEScreen::enterEvent(QEvent *e) { - setCursor(Qt::SizeAllCursor); - QWidget::enterEvent(e); -} - -void OEScreen::leaveEvent(QEvent *e) { - setCursor(Qt::ArrowCursor); - QWidget::leaveEvent(e); -} - -void OEScreen::closeEvent(QCloseEvent *) -{ - isInit_ = false; -} - -void OEScreen::paintEvent(QPaintEvent *) { - QPainter painter(this); - /// 绘制截屏编辑窗口 - painter.drawPixmap(QPoint(0,0), - *originPainting_, currentRect_); - - /// 绘制边框线 - QPen pen(QColor(0,174,255),2); - painter.setPen(pen); - painter.drawRect(rect()); - - /// 绘制八个点 - //改变点的宽度 - pen.setWidth(4); - pen.setColor(Qt::red); - painter.setPen(pen); - painter.drawPoints(listMarker_); -} - - -const QString OEScreen::getFileName(void) { - QString file_name = QDateTime::currentDateTime().toString("CSDN博客_瓯裔_yyyy-MM-dd-HH-mm-ss"); - return file_name; -} - - -void OEScreen::onSaveScreenOther(void) { - - QString fileName = QFileDialog::getSaveFileName(this, "保存图片", getFileName(), "JPEG Files (*.jpg)"); - if (fileName.length() > 0) { - originPainting_->copy(currentRect_).save(fileName, "jpg"); - quitScreenshot(); - } -} - -void OEScreen::onSaveScreen(void) { - /// 把图片放入剪切板 - QClipboard *board = QApplication::clipboard(); - board->setPixmap(originPainting_->copy(currentRect_)); - /// 退出当前截图工具 - quitScreenshot(); -} - - -void OEScreen::quitScreenshot(void) { - close(); - parentWidget()->close(); -} - -void OEScreen::onMouseChange(int x, int y) { - show(); - if (x < 0 || y < 0) { - return; - } - const int& rx = (x >= originPoint_.x()) ? originPoint_.x() : x; - const int& ry = (y >= originPoint_.y()) ? originPoint_.y() : y; - const int& rw = abs(x - originPoint_.x()); - const int& rh = abs(y - originPoint_.y()); - - /// 改变大小 - currentRect_ = QRect(rx, ry, rw, rh); - - this->setGeometry(currentRect_); - /// 改变大小后更新父窗口,防止父窗口未及时刷新而导致的问题 - parentWidget()->update(); -} +/** + * @author : 陈鲁勇 + * @date : 2017年04月 + * @version: 1.0 + * @note : 根据 Apache 许可证 2.0 版(以下简称“许可证”)授权; + * 除非遵守本许可,否则您不能使用这个文件。 + * @remarks: 您可以获得该许可的副本: + * http://www.apache.org/licenses/LICENSE-2.0 + * 除非适用法律需要或者书面同意,按本许可分发的软件 + * 要按“原样”分发,没有任何形式的,明确或隐含的担保条款。 + * 参见按照本许可控制许可权限及限制的特定语言的许可证。 + * + * 你可以获得该代码的最新版本: + * + * https://git.oschina.net/Mr_ChenLuYong/screenshot + * + * 开源社区的所有人都期待与你的共同维护。 + * + * + * 如果你对这些代码还有不理解的地方可以通过最新的文章进行学习: + * + * 博客地址:http://blog.csdn.net/csnd_ayo + * + * 文章地址:http://blog.csdn.net/csnd_ayo/article/details/70197915 + * + * 期待你提交Bug,欢迎Issues。 + * +*/ + +#include "oescreenshot.h" + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef QT_NO_DEBUG +#include +#endif + +#include + +#include "oeamplifier.h" +#include "oecommonhelper.h" + + +/// 鼠标按钮图片的十六进制数据 +static const unsigned char uc_mouse_image[] = { + 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52 + ,0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x2D, 0x08, 0x06, 0x00, 0x00, 0x00, 0x52, 0xE9, 0x60 + ,0xA2, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0B, 0x13, 0x00, 0x00, 0x0B + ,0x13, 0x01, 0x00, 0x9A, 0x9C, 0x18, 0x00, 0x00, 0x01, 0x40, 0x49, 0x44, 0x41, 0x54, 0x58, 0x85 + ,0xED, 0xD5, 0x21, 0x6E, 0xC3, 0x30, 0x14, 0xC6, 0xF1, 0xFF, 0x9B, 0xC6, 0x36, 0x30, 0x38, 0xA9 + ,0x05, 0x01, 0x05, 0x81, 0x05, 0x03, 0x39, 0xCA, 0x60, 0x8F, 0xD2, 0x03, 0xEC, 0x10, 0x3B, 0x46 + ,0xC1, 0xC0, 0xC6, 0x0A, 0x3B, 0x96, 0xB1, 0x80, 0x82, 0xC1, 0x56, 0x2A, 0xFF, 0x06, 0xE2, 0x36 + ,0x75, 0x9A, 0xB4, 0xCA, 0xEC, 0x4E, 0x9A, 0xE4, 0x2F, 0xB2, 0x42, 0x22, 0xFF, 0xF2, 0xFC, 0x9C + ,0x18, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0xFE, 0x55, 0xE4, 0xC6, 0xA0 + ,0xDC, 0xC4, 0x71, 0x87, 0xC1, 0xC1, 0x68, 0x01, 0xCC, 0x06, 0xC2, 0x51, 0xD0, 0x29, 0xB0, 0x18 + ,0x00, 0xDF, 0xC6, 0x40, 0x33, 0x37, 0x84, 0x30, 0x4C, 0x80, 0x85, 0xCE, 0x7B, 0x2E, 0x2A, 0x91 + ,0x84, 0x24, 0xBE, 0x25, 0xDE, 0x25, 0x5E, 0x2F, 0x6E, 0xAE, 0xD0, 0x37, 0x92, 0x10, 0xF0, 0x09 + ,0x54, 0x40, 0xE9, 0xEE, 0x15, 0xC6, 0xA2, 0x77, 0xFE, 0xE0, 0xE5, 0x85, 0x8F, 0x16, 0x58, 0xDF + ,0x35, 0x06, 0x5B, 0xD3, 0xB9, 0xD4, 0x11, 0xD0, 0xA5, 0x8F, 0xDE, 0x57, 0x75, 0x83, 0x73, 0x50 + ,0x06, 0xF6, 0x72, 0x0A, 0x47, 0x40, 0x57, 0x0D, 0x38, 0xDE, 0xC0, 0x04, 0x6F, 0x68, 0x05, 0x36 + ,0xF5, 0xE1, 0x08, 0x3D, 0xCD, 0xEA, 0xEA, 0x5A, 0xD8, 0xBE, 0x5A, 0x46, 0xB0, 0x05, 0x1E, 0xAC + ,0xF1, 0xC2, 0xD1, 0xCC, 0x01, 0x6D, 0x74, 0x02, 0xDB, 0x3B, 0xBF, 0xD3, 0x73, 0x07, 0x87, 0x2F + ,0xEF, 0x53, 0x07, 0x38, 0x82, 0x2F, 0xF6, 0xFB, 0xB8, 0x81, 0x73, 0x41, 0x69, 0x28, 0x3A, 0x7A + ,0x5C, 0xDD, 0x73, 0xCF, 0x3A, 0x86, 0xA3, 0x05, 0x87, 0xEA, 0xCC, 0x60, 0xA1, 0x06, 0x75, 0x89 + ,0xFE, 0x77, 0x92, 0x76, 0x68, 0x23, 0xEF, 0x88, 0xD3, 0x4C, 0xA8, 0x10, 0x7A, 0xD4, 0xEF, 0x8E + ,0xBE, 0x8B, 0x68, 0x79, 0x3A, 0xB1, 0x72, 0xE1, 0xAE, 0xBC, 0x13, 0x0D, 0xDE, 0xBD, 0x3D, 0xF3 + ,0x08, 0x15, 0xD4, 0xDF, 0x4C, 0x06, 0x36, 0xF7, 0x9E, 0x09, 0xED, 0xE9, 0x99, 0x97, 0x3E, 0x42 + ,0xFF, 0x30, 0x42, 0x4B, 0xA1, 0x8D, 0xD8, 0xE9, 0x2A, 0xBD, 0xED, 0x41, 0x25, 0x2A, 0x89, 0x37 + ,0x1F, 0xBD, 0xEA, 0x61, 0x8B, 0x5F, 0xDD, 0xC1, 0xFA, 0x01, 0xD8, 0xA3, 0x8F, 0xFB, 0xCA, 0x70 + ,0x16, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82 +}; + + + +OEScreenshot * OEScreenshot::self_ = nullptr; +bool OEScreenshot::isActivity_ = false; +bool OEScreen::isInit_ = false; + +OEScreenshot::OEScreenshot(QWidget *parent) : QWidget(parent), + isLeftPressed_ (false), backgroundScreen_(nullptr), + originPainting_(nullptr), screenTool_(nullptr) { + /// 初始化鼠标 + initCursor(); + /// 截取屏幕信息 + initGlobalScreen(); + /// 初始化鼠标放大器 + initAmplifier(); + /// 初始化大小感知器 + initMeasureWidget(); + /// 全屏窗口 + showFullScreen(); + /// 窗口与显示屏对齐 + setGeometry(getScreenRect()); + /// 霸道置顶 + onEgoistic(); + /// 开启鼠标实时追踪 + setMouseTracking(true); + /// 更新鼠标的位置 + emit cursorPosChange(cursor().pos().x(), cursor().pos().y()); + /// 更新鼠标区域窗口 + updateMouse(); + /// 展示窗口 + show(); +} + +OEScreenshot::~OEScreenshot(void) { +} + +/** + * @brief:窗口实例 + * @return:OEScreenshot + */ +OEScreenshot *OEScreenshot::Instance(void) { + if (!isActivity_ && self_) { + destroy(); + } + static QMutex mutex; + if (!self_) { + QMutexLocker locker(&mutex); + if (!self_) { + isActivity_ = true; + self_ = new OEScreenshot; + } + } + return self_; +} + +void OEScreenshot::destroy(void) { + if (!isActivity_ && self_) { + delete self_; + self_ = nullptr; + } +} + +void OEScreenshot::hideEvent(QHideEvent *) { + isActivity_ = false; +} + + +void OEScreenshot::closeEvent(QCloseEvent *) { + isActivity_ = false; +} + +void OEScreenshot::mouseDoubleClickEvent(QMouseEvent *) { + emit doubleClick(); +} + + +/** + * 初始化放大镜 (色彩采集器) + */ +void OEScreenshot::initAmplifier(std::shared_ptr originPainting) { + std::shared_ptr temp_pm = originPainting; + if (temp_pm == nullptr) { + temp_pm = originPainting_; + } + amplifierTool_.reset(new OEAmplifier(temp_pm, this)); + connect(this,SIGNAL(cursorPosChange(int,int)), + amplifierTool_.get(), SLOT(onPostionChange(int,int))); + amplifierTool_->show(); + amplifierTool_->raise(); +} + +void OEScreenshot::initMeasureWidget(void) +{ + rectTool_.reset(new OERect(this)); + rectTool_->raise(); +} + +/** + * 功能:获得当前屏幕的大小 + */ +const QRect &OEScreenshot::getScreenRect(void) { + if (!desktopRect_.isEmpty()) { + return desktopRect_; + } + /// 获得屏幕个数 + int temp_screen_num = QApplication::screens().size(); + /// 获得屏幕大小 + desktopRect_ = QApplication::desktop()->rect(); + if (temp_screen_num != 1) { + /// 多屏幕策略 + const int& temp = desktopRect_.width() - + (desktopRect_.width() / temp_screen_num); + /// 重新设置矩形 + desktopRect_ = QRect(-temp, 0, + desktopRect_.width(), desktopRect_.height()); + } + return desktopRect_; +} + +std::shared_ptr OEScreenshot::initGlobalScreen(void) { + if (backgroundScreen_.get() != nullptr) { + return backgroundScreen_; + } + /// 获得屏幕原画 + std::shared_ptr temp_screen = getGlobalScreen(); + + /// 制作暗色屏幕背景 + QPixmap temp_dim_pix(temp_screen->width(), temp_screen->height()); + temp_dim_pix.fill((QColor(0, 0, 0, 160))); + backgroundScreen_.reset(new QPixmap(*temp_screen)); + QPainter p(backgroundScreen_.get()); + p.drawPixmap(0, 0, temp_dim_pix); + + return backgroundScreen_; +} + +/* + * 获得屏幕的原画 + * 返回:QPixmap* 指针 + */ +std::shared_ptr OEScreenshot::getGlobalScreen(void) { + if (originPainting_.get() == nullptr) { + /// 截取当前桌面,作为截屏的背景图 + QScreen *screen = QGuiApplication::primaryScreen(); + const QRect& temp_rect = getScreenRect(); + originPainting_.reset(new QPixmap(screen->grabWindow(0, temp_rect.x(), + temp_rect.y(), temp_rect.width(), + temp_rect.height()))); + } + return originPainting_; +} +void OEScreenshot::onEgoistic(void) +{ + /// 窗口置顶 +#ifdef Q_OS_WIN32 + // SetWindowPos(HWND)this->winId(),HWND_TOPMOST,this->pos().x(),this->pos().y(),this->width(),this->height(),SWP_SHOWWINDOW); +#else + Qt::WindowFlags flags = windowFlags(); + flags |= Qt::WindowStaysOnTopHint; + setWindowFlags(flags); +#endif +} + +/* + * 初始化鼠标 + * 参数:_ico 鼠标图片的资源文件 + */ +void OEScreenshot::initCursor(const QString& ico) { + QPixmap pixmap; + if (ico.isEmpty()) { + pixmap.loadFromData(uc_mouse_image, sizeof(uc_mouse_image)); + } + else { + pixmap.load(ico); + } + QCursor cursor; + cursor = QCursor(pixmap, 15, 23); + setCursor(cursor); +} + +std::shared_ptr OEScreenshot::createScreen(const QPoint &pos) { + if (screenTool_.get() == nullptr) { + /// 创建截图器 + screenTool_.reset(new OEScreen(originPainting_, pos, this)); + /// 建立信号连接 + connect (this, SIGNAL(cursorPosChange(int,int)), + screenTool_.get(),SLOT(onMouseChange(int,int))); + /// 建立主界面双击保存信号关联 + connect (this, SIGNAL(doubleClick()), + screenTool_.get(),SLOT(onSaveScreen())); + /// 建立截图器大小关联 + connect(screenTool_.get(), SIGNAL(sizeChange(int,int)), + rectTool_.get(), SLOT(onSizeChange(int,int))); + connect(screenTool_.get(), SIGNAL(sizeChange(int,int)), + amplifierTool_.get(), SLOT(onSizeChange(int,int))); + /// 建立截图器与感知器的位置关联 + connect(screenTool_.get(), SIGNAL(postionChange(int,int)), + rectTool_.get(), SLOT(onPostionChange(int,int))); + + /// 获得截图器当前起始位置 + startPoint_ = pos; + isLeftPressed_ = true; + } + return screenTool_; +} + +void OEScreenshot::destroyScreen() { + if (screenTool_.get() != nullptr) { + /// 断开信号资源 + disconnect (this, SIGNAL(doubleClick()), + screenTool_.get(),SLOT(onSaveScreen())); + disconnect(screenTool_.get(), SIGNAL(sizeChange(int,int)), + rectTool_.get(), SLOT(onSizeChange(int,int))); + disconnect(screenTool_.get(), SIGNAL(postionChange(int,int)), + rectTool_.get(), SLOT(onPostionChange(int,int))); + /// 清理工具 + screenTool_.reset(); + screenTool_ = nullptr; + isLeftPressed_ = false; + update(); + return; + } +} + +void OEScreenshot::mousePressEvent(QMouseEvent *e) { + if (e->button() == Qt::LeftButton) { + createScreen(e->pos()); + return ; + } +} + +void OEScreenshot::mouseReleaseEvent(QMouseEvent *e) { + if (e->button() == Qt::RightButton) { + if (screenTool_.get() != nullptr) { + rectTool_->hide(); + amplifierTool_->onPostionChange(e->x(), e->y()); + amplifierTool_->show(); + return destroyScreen(); + } + close(); + return ; + } + else if (isLeftPressed_ == true + && e->button() == Qt::LeftButton) { + /// 选择窗口选区 + if (startPoint_ == e->pos() + && !windowRect_.isEmpty()) { + screenTool_->setGeometry(windowRect_); + screenTool_->show(); + windowRect_ = {}; + } + /// 断开鼠标移动的信号 + disconnect (this, SIGNAL(cursorPosChange(int,int)), + screenTool_.get(),SLOT(onMouseChange(int,int))); + /// 隐藏放大器 + amplifierTool_->hide(); + /// 断开截图器的大小修改信号 + disconnect (screenTool_.get(), SIGNAL(sizeChange(int,int)), + amplifierTool_.get(),SLOT(onSizeChange(int,int))); + isLeftPressed_ = false; + } + QWidget::mouseReleaseEvent(e); +} + +void OEScreenshot::mouseMoveEvent(QMouseEvent *e) { + emit cursorPosChange(e->x(), e->y()); + if (isLeftPressed_) { + amplifierTool_->raise(); + windowRect_ = {}; + update(); + } + else if (isLeftPressed_ == false + && false == OEScreen::state()){ + /// 霸道置顶 + onEgoistic(); + + /// 更新当前鼠标选中的窗口 + updateMouse(); + } + QWidget::mouseMoveEvent(e); +} + +void OEScreenshot::paintEvent(QPaintEvent *) { + QPainter painter(this); + /// 画全屏图 + painter.drawPixmap(0,0,desktopRect_.width(), + desktopRect_.height(), *backgroundScreen_); + + if (!windowRect_.isEmpty()) { + /// 绘制选区 + QPen pen = painter.pen(); + pen.setColor(QColor(0,175,255)); + pen.setWidth(2); + painter.setPen(pen); + painter.drawRect(windowRect_.x(),windowRect_.y(), + windowRect_.width(),windowRect_.height()); + painter.drawPixmap(QPoint(windowRect_.x(),windowRect_.y()), + *originPainting_, windowRect_); + } +} + +void OEScreenshot::updateMouse(void) { + /// 获取当前鼠标选中的窗口 + ::EnableWindow((HWND)winId(), FALSE); + OECommonHelper::getSmallestWindowFromCursor(windowRect_); + QPoint temp_pt = mapFromGlobal(QPoint(windowRect_.x(), windowRect_.y())); + windowRect_ = QRect(temp_pt.x(), temp_pt.y(), + windowRect_.width(), windowRect_.height()); + ::EnableWindow((HWND)winId(), TRUE); + amplifierTool_->onSizeChange(windowRect_.width(),windowRect_.height()); + emit findChildWind(windowRect_); + update(); +} + +void OEScreenshot::keyPressEvent(QKeyEvent *e) { + /// Esc 键退出截图; + if (e->key() == Qt::Key_Escape) { + close(); + } + else { + e->ignore(); + } + +} + + + +/////////////////////////////////////////////////////////// + + + + +OERect::OERect(QWidget *parent) : QWidget(parent) { + + /// 设置感知器默认大小 + setFixedSize(95 * OECommonHelper::getWindowHeightMultiplyingPower(), + 20 * OECommonHelper::getWindowHeightMultiplyingPower()); + + /// 填充默认背景 + backgroundPixmap_.reset(new QPixmap(width(),height())); + backgroundPixmap_->fill((QColor(8, 8, 8, 160))); + + /// 默认隐藏 + hide(); +} + + +void OERect::paintEvent(QPaintEvent *) { + QPainter painter(this); + painter.drawPixmap(rect(),*backgroundPixmap_); + painter.setPen(QPen(QColor(Qt::white))); + painter.drawText(rect(), Qt::AlignCenter, info_); +} + +void OERect::onPostionChange(int x, int y) { + if (x < 0) x = 0; + if (y < 0) y = 0; + const int& ry = y - height() - 1; + if (ry < 0) { + this->raise(); + } + move(x, ((ry < 0) ? y : ry)); + show(); +} + +void OERect::onSizeChange(int w, int h) { + info_ = QString("%1 × %2").arg(w).arg(h); +} + + + + +/////////////////////////////////////////////////////////// + + + + + +OEScreen::OEScreen(std::shared_ptr originPainting, QPoint pos, QWidget *parent) + : QWidget(parent), direction_(NONE), originPoint_(pos), + isPressed_(false), originPainting_(originPainting) { + menu_ = new QMenu(this); + menu_->addAction("完成截图", this, SLOT(onSaveScreen())); + menu_->addAction("保存", this, SLOT(onSaveScreenOther())); + menu_->addSeparator(); + menu_->addAction("退出截图", this, SLOT(quitScreenshot())); + + /// 双击即完成 + connect(this, SIGNAL(doubleClick()), + this, SLOT(onSaveScreen())); + + /// 开启鼠标实时追踪 + setMouseTracking(true); + /// 默认隐藏 + hide(); +} + +OEScreen::DIRECTION OEScreen::getRegion(const QPoint &cursor) { + if (!isInit_) { + return NONE; + } + OEScreen::DIRECTION ret_dir = NONE; + // left upper + QPoint pt_lu = mapToParent(rect().topLeft()); + // right lower + QPoint pt_rl = mapToParent(rect().bottomRight()); + + int x = cursor.x(); + int y = cursor.y(); + + /// 获得鼠标当前所处窗口的边界方向 + if(pt_lu.x() + PADDING_ >= x + && pt_lu.x() <= x + && pt_lu.y() + PADDING_ >= y + && pt_lu.y() <= y) { + // 左上角 + ret_dir = LEFTUPPER; + this->setCursor(QCursor(Qt::SizeFDiagCursor)); + } else if(x >= pt_rl.x() - PADDING_ + && x <= pt_rl.x() + && y >= pt_rl.y() - PADDING_ + && y <= pt_rl.y()) { + // 右下角 + ret_dir = RIGHTLOWER; + this->setCursor(QCursor(Qt::SizeFDiagCursor)); + } else if(x <= pt_lu.x() + PADDING_ + && x >= pt_lu.x() + && y >= pt_rl.y() - PADDING_ + && y <= pt_rl.y()) { + // 左下角 + ret_dir = LEFTLOWER; + this->setCursor(QCursor(Qt::SizeBDiagCursor)); + } else if(x <= pt_rl.x() + && x >= pt_rl.x() - PADDING_ + && y >= pt_lu.y() + && y <= pt_lu.y() + PADDING_) { + // 右上角 + ret_dir = RIGHTUPPER; + this->setCursor(QCursor(Qt::SizeBDiagCursor)); + } else if(x <= pt_lu.x() + PADDING_ + && x >= pt_lu.x()) { + // 左边 + ret_dir = LEFT; + this->setCursor(QCursor(Qt::SizeHorCursor)); + } else if( x <= pt_rl.x() + && x >= pt_rl.x() - PADDING_) { + // 右边 + ret_dir = RIGHT; + this->setCursor(QCursor(Qt::SizeHorCursor)); + }else if(y >= pt_lu.y() + && y <= pt_lu.y() + PADDING_){ + // 上边 + ret_dir = UPPER; + this->setCursor(QCursor(Qt::SizeVerCursor)); + } else if(y <= pt_rl.y() + && y >= pt_rl.y() - PADDING_) { + // 下边 + ret_dir = LOWER; + this->setCursor(QCursor(Qt::SizeVerCursor)); + }else { + // 默认 + ret_dir = NONE; + this->setCursor(QCursor(Qt::SizeAllCursor)); + } + return ret_dir; +} + + +void OEScreen::contextMenuEvent(QContextMenuEvent *) { + /// 在鼠标位置弹射出菜单栏 + menu_->exec(cursor().pos()); +} + +void OEScreen::mouseDoubleClickEvent(QMouseEvent *e) { + if (e->button() == Qt::LeftButton) { + emit doubleClick(); + e->accept(); + } +} + +void OEScreen::mousePressEvent(QMouseEvent *e) { + if (e->button() == Qt::LeftButton) { + isPressed_ = true; + if(direction_ != NONE) { + this->mouseGrabber(); + } + /// @bug :这里可能存在问题, 不应当使用globalPos + movePos_ = e->globalPos() - pos(); + } +} + +void OEScreen::mouseReleaseEvent(QMouseEvent * e) { + if (e->button() == Qt::LeftButton) { + isPressed_ = false; + if(direction_ != NONE) { + setCursor(QCursor(Qt::SizeAllCursor)); + } + } +} + +void OEScreen::mouseMoveEvent(QMouseEvent * e) { + QPoint gloPoint = mapToParent(e->pos()); + // left upper + QPoint pt_lu = mapToParent(rect().topLeft()); + // left lower + QPoint pt_ll = mapToParent(rect().bottomLeft()); + // right lower + QPoint pt_rl = mapToParent(rect().bottomRight()); + // right upper + QPoint pt_ru = mapToParent(rect().topRight()); + if(!isPressed_) { + /// 检查鼠标鼠标方向 + direction_ = getRegion(gloPoint); + + /// 根据方位判断拖拉对应支点 + switch(direction_) { + case NONE: + case RIGHT: + case RIGHTLOWER: + originPoint_ = pt_lu; + break; + case RIGHTUPPER: + originPoint_ = pt_ll; + break; + case LEFT: + case LEFTLOWER: + originPoint_ = pt_ru; + break; + case LEFTUPPER: + case UPPER: + originPoint_ = pt_rl; + break; + case LOWER: + originPoint_ = pt_lu; + break; + } + } + else { + if(direction_ != NONE) { + const int& global_x = gloPoint.x(); + /// 鼠标进行拖拉拽 + switch(direction_) { + case LEFT: + return onMouseChange(global_x, pt_ll.y() + 1); + case RIGHT: + return onMouseChange(global_x, pt_rl.y() + 1); + case UPPER: + return onMouseChange(pt_lu.x(), gloPoint.y()); + case LOWER: + return onMouseChange(pt_rl.x() + 1, gloPoint.y()); + case LEFTUPPER: + case RIGHTUPPER: + case LEFTLOWER: + case RIGHTLOWER: + return onMouseChange(global_x, gloPoint.y()); + default: + break; + } + } + else { + /// 窗口的移动 + /// @bug :这里可能存在问题, 不应当使用globalPos + move(e->globalPos() - movePos_); + movePos_ = e->globalPos() - pos(); + e->accept(); + } + } + currentRect_ = geometry(); +} + +void OEScreen::moveEvent(QMoveEvent *) { + emit postionChange(x(), y()); +} + +void OEScreen::resizeEvent(QResizeEvent *) { + listMarker_.clear(); + + /// 重新计算八个锚点 + // 角点 + listMarker_.push_back(QPoint(0, 0)); + listMarker_.push_back(QPoint(width(), 0)); + listMarker_.push_back(QPoint(0, height())); + listMarker_.push_back(QPoint(width(), height())); + + // 中点 + listMarker_.push_back(QPoint((width() >> 1), 0)); + listMarker_.push_back(QPoint((width() >> 1), height())); + listMarker_.push_back(QPoint(0, (height() >> 1))); + listMarker_.push_back(QPoint(width(), (height() >> 1))); + + emit sizeChange(width(), height()); +} + +void OEScreen::showEvent(QShowEvent *) { + isInit_ = true; +} + +void OEScreen::hideEvent(QHideEvent *) { + currentRect_ = {}; + movePos_ = {}; + originPoint_ = {}; + isInit_ = false; +} + +void OEScreen::enterEvent(QEvent *e) { + setCursor(Qt::SizeAllCursor); + QWidget::enterEvent(e); +} + +void OEScreen::leaveEvent(QEvent *e) { + setCursor(Qt::ArrowCursor); + QWidget::leaveEvent(e); +} + +void OEScreen::closeEvent(QCloseEvent *) +{ + isInit_ = false; +} + +void OEScreen::paintEvent(QPaintEvent *) { + QPainter painter(this); + /// 绘制截屏编辑窗口 + painter.drawPixmap(QPoint(0,0), + *originPainting_, currentRect_); + + /// 绘制边框线 + QPen pen(QColor(0,174,255),2); + painter.setPen(pen); + painter.drawRect(rect()); + + /// 绘制八个点 + //改变点的宽度 + pen.setWidth(4); + pen.setColor(Qt::red); + painter.setPen(pen); + painter.drawPoints(listMarker_); +} + + +const QString OEScreen::getFileName(void) { + QString file_name = QDateTime::currentDateTime().toString("CSDN博客_瓯裔_yyyy-MM-dd-HH-mm-ss"); + return file_name; +} + + +void OEScreen::onSaveScreenOther(void) { + + QString fileName = QFileDialog::getSaveFileName(this, "保存图片", getFileName(), "JPEG Files (*.jpg)"); + if (fileName.length() > 0) { + originPainting_->copy(currentRect_).save(fileName, "jpg"); + quitScreenshot(); + } +} + +void OEScreen::onSaveScreen(void) { + /// 把图片放入剪切板 + QClipboard *board = QApplication::clipboard(); + board->setPixmap(originPainting_->copy(currentRect_)); + /// 退出当前截图工具 + quitScreenshot(); +} + + +void OEScreen::quitScreenshot(void) { + close(); + parentWidget()->close(); +} + +void OEScreen::onMouseChange(int x, int y) { + show(); + if (x < 0 || y < 0) { + return; + } + const int& rx = (x >= originPoint_.x()) ? originPoint_.x() : x; + const int& ry = (y >= originPoint_.y()) ? originPoint_.y() : y; + const int& rw = abs(x - originPoint_.x()); + const int& rh = abs(y - originPoint_.y()); + + /// 改变大小 + currentRect_ = QRect(rx, ry, rw, rh); + + this->setGeometry(currentRect_); + /// 改变大小后更新父窗口,防止父窗口未及时刷新而导致的问题 + parentWidget()->update(); +} diff --git a/LedOK/oescreenshot/oescreenshot.h b/LedOK/oescreenshot/oescreenshot.h index d686608..0e85fd8 100644 --- a/LedOK/oescreenshot/oescreenshot.h +++ b/LedOK/oescreenshot/oescreenshot.h @@ -1,508 +1,508 @@ -/** - * @author : 陈鲁勇 - * @date : 2017年04月 - * @version: 1.0 - * @note : 根据 Apache 许可证 2.0 版(以下简称“许可证”)授权; - * 除非遵守本许可,否则您不能使用这个文件。 - * @remarks: 您可以获得该许可的副本: - * http://www.apache.org/licenses/LICENSE-2.0 - * 除非适用法律需要或者书面同意,按本许可分发的软件 - * 要按“原样”分发,没有任何形式的,明确或隐含的担保条款。 - * 参见按照本许可控制许可权限及限制的特定语言的许可证。 - * - * 你可以获得该代码的最新版本: - * - * https://git.oschina.net/Mr_ChenLuYong/screenshot - * - * 开源社区的所有人都期待与你的共同维护。 - * - * - * 如果你对这些代码还有不理解的地方可以通过最新的文章进行学习: - * - * 博客地址:http://blog.csdn.net/csnd_ayo - * - * 文章地址:http://blog.csdn.net/csnd_ayo/article/details/70197915 - * - * 期待你提交Bug,欢迎Issues。 - * -*/ - - -#ifndef OESCREENSHOT_H -#define OESCREENSHOT_H - -#include -#include -#include - -class OEScreen; -class OERect; -class OEAmplifier; -class QTimer; -class QMenu; - - -/** - * @class : OEScreenshot - * @brief : 截屏功能的主要入口, - * 管理全局热键,资源的回收与释放. - * @remark: 调用示例( OEScreenshot::Instance(); ) -*/ -class OEScreenshot : public QWidget { - Q_OBJECT - -signals: - - /** - * @brief : 鼠标移动(信号) - * @param : int x轴的坐标 - * @param : int y轴的坐标 - * @date : 2017年04月18日 - */ - void cursorPosChange(int, int); - - /** - * @brief : 双击(信号) - * @date : 2017年04月18日 - */ - void doubleClick(void); - - /** - * @brief : 鼠标当前位置最小的子窗口(信号) - * @param : QRect 当前窗口的矩形数据 - * @date : 2017年04月18日 - */ - void findChildWind(QRect); - -public: - /** - * @brief : 构造函数 - * @note : 当前依附的父窗口(一般不给父窗口) - * @date : 2017年04月16日 - */ - explicit OEScreenshot(QWidget *parent = 0); - ~OEScreenshot(void); - - /** - * @brief : 窗口实例 - * @note : 通过这个函数获得截图器的整个实例 - * @return: 返回 OEScreenshot 实例指针 - * @date : 2017年04月15日 - */ - static OEScreenshot *Instance(void); - - /** - * @brief : 摧毁截图窗口 - * @note : 通过这个函数可以摧毁整个截图窗口 - * @date : 2017年04月30日 - */ - static void destroy(void); - -protected: - - /** - * @brief : 隐藏窗口事件 - */ - virtual void hideEvent(QHideEvent *); - /** - * @brief : 关闭窗口事件 - */ - virtual void closeEvent(QCloseEvent *); - /** - * @brief : 双击事件 - */ - virtual void mouseDoubleClickEvent(QMouseEvent*); - /** - * @brief : 鼠标按下事件 - */ - virtual void mousePressEvent(QMouseEvent *); - /** - * @brief : 鼠标释放事件 - */ - virtual void mouseReleaseEvent(QMouseEvent *e); - /** - * @brief : 鼠标移动事件 - */ - virtual void mouseMoveEvent(QMouseEvent *e); - - /** - * @brief : 按键按下事件 - */ - virtual void keyPressEvent(QKeyEvent *e); - /** - * @brief : 自绘事件 - */ - virtual void paintEvent(QPaintEvent *); - - /** - * @brief : 更新当前鼠标选区的窗口 - */ - void updateMouse(void); - -private: - - - /** - * @brief : 初始化放大镜 (色彩采集器) - * @note : 他需要屏幕的原画作为放大器的放大元素 - * @param : originPainting 放大器必要的元素,若为空,则默认用originPainting_原画 - * @date : 2017年04月15日 - * @remark: 需先行调用getGlobalScreen。 - */ - void initAmplifier(std::shared_ptr originPainting = nullptr); - - /** - * @brief : 测量控件 (大小感知器) - * @date : 2017年04月27日 - */ - void initMeasureWidget(void); - - /** - * @brief : 初始化截屏背景 - * @return: QPixmap 经过暗色处理的屏幕图 - * @date : 2017年04月15日 - */ - std::shared_ptr initGlobalScreen(void); - - - /** - * @brief : 初始化鼠标 - * @note : 为鼠标设置默认状态下的图标样式 - * @param : ico 鼠标图片的资源文件路径 - * @date : 2017年04月15日 - * @remark: 若参数未填写,在使用本程序默认的鼠标Logo - */ - void initCursor(const QString& ico = ""); - - /** - * @brief : 创建截图器 - * @note : 若截图器已存在,则返回截图器示例,不会重复创建。 - * @param : pos 截图器的起始位置 (给当前鼠标位置即可) - * @date : 2017年04月16日 - * @remark: 创建截图器前,需要创建相关的组件,(例:大小感知器,放大取色器) - */ - std::shared_ptr createScreen(const QPoint &pos); - - /** - * @brief : 摧毁截图器 - * @note : 若截图器已存在,则摧毁示例,并清理示例创建的连带资源 - * @date : 2017年04月16日 - */ - void destroyScreen(void); - - - /** - * @brief : 获得当前屏幕的大小 - * @note : 这个函数是支持多屏幕的,示例:双屏幕 QRect(-1920, 0, 3840, 1080) - * @return: 返回 QRect 引用 - * @date : 2017年04月15日 - */ - const QRect& getScreenRect(void); - - /** - * @brief : 获得屏幕的原画 - * @note : 他不会重复获得屏幕原画,如果有,则返回原有的原画 - * @return: QPixmap* 指针 - * @date : 2017年04月15日 - * @remark: 若想重新获得屏幕原画,需要清理原有资源 - */ - std::shared_ptr getGlobalScreen(void); - - -private: - - /// 截屏窗口是否已经展示 - bool isLeftPressed_; - /// 用于检测误操作 - QPoint startPoint_; - /// 当前桌面屏幕的矩形数据 - QRect desktopRect_; - /// 屏幕暗色背景图 - std::shared_ptr backgroundScreen_; - /// 屏幕原画 - std::shared_ptr originPainting_; - /// 截图屏幕 - std::shared_ptr screenTool_; - /// 截图器大小感知器 - std::shared_ptr rectTool_; - /// 放大取色器 - std::shared_ptr amplifierTool_; - /// 当前鼠标选区最小的矩形窗口 - QRect windowRect_; - /// 截屏实例对象 - static OEScreenshot *self_; - /// 置顶定时器 - QTimer* egoisticTimer_; - /// 活动窗口 - static bool isActivity_; -private slots: - - /** - * @brief : Window下霸道置顶(唯我独尊) - * @date : 2017年04月28日 - * @remark: 使用该函数时,会终止右键菜单的行为,慎重使用,避免BUG - */ - void onEgoistic(void); -}; - - - - -/** - * @class : OERect - * @brief : 大小感知器 - * @note : 主要关乎截图器左上方的大小感知控件 -*/ -class OERect : public QWidget { - Q_OBJECT - -signals: - - -public: - - explicit OERect(QWidget *parent = 0); - -protected: - - /** - * @brief : 自绘函数 - */ - void paintEvent(QPaintEvent *); - -public slots: - - /** - * @brief : 外部组件位置修改(槽) - * @note : 感知器修改自身位置 - * @param : x 横向位置 - * @param : y 纵向位置 - * @date : 2017年04月15日 - */ - void onPostionChange(int x, int y); - - /** - * @brief : 外部组件大小修改 (槽) - * @note : 感知器修改显示的大小数据 - * @param : w 宽度 - * @param : h 高度 - * @date : 2017年04月15日 - */ - void onSizeChange(int w, int h); - -private: - /// 背景色 - std::shared_ptr backgroundPixmap_; - /// 显示的文字信息 - QString info_; -}; - - -/** - * @class : OEScreen - * @brief : 截图器 - * @note : 主要关乎图片的编辑与保存 -*/ -class OEScreen : public QWidget { - - Q_OBJECT - -signals: - - - /** - * @brief : 截图器大小修改(信号) - * @param : int 宽度 - * @param : int 高度 - * @date : 2017年04月17日 - */ - void sizeChange(int,int); - - /** - * @brief : 截图器窗口的位置(信号) - * @param : int 窗口的横向位置 - * @param : int 窗口的纵向位置 - * @date : 2017年04月17日 - */ - void postionChange(int,int); - - /** - * @brief : 双击 (信号) - * @date : 2017年04月17日 - */ - void doubleClick(void); - -protected: - - /// 内边距,决定拖拽的触发。 - const int PADDING_ = 6; - - /// 方位枚举 - enum DIRECTION { - UPPER=0, - LOWER=1, - LEFT, - RIGHT, - LEFTUPPER, - LEFTLOWER, - RIGHTLOWER, - RIGHTUPPER, - NONE - }; - -public: - - explicit OEScreen(std::shared_ptr originPainting, QPoint pos, QWidget *parent = 0); - - ~OEScreen() { isInit_ = false; } - - /** - * @brief : 获得当前截图器是否存在 - * @return: true : 存在 - * @date : 2017年04月17日 - */ - static bool state(void) { return isInit_; } - -protected: - - /** - * @brief : 获得当前坐标点的边界方位 - * @param : cursor 当前鼠标的位置 - * @return: DIRECTION 鼠标的方位枚举 - * @date : 2017年04月17日 - */ - DIRECTION getRegion(const QPoint &cursor); - - - /** - * @brief : 呼出菜单事件 - */ - virtual void contextMenuEvent(QContextMenuEvent *); - - /** - * @brief : 双击事件 - */ - virtual void mouseDoubleClickEvent(QMouseEvent *e); - - /** - * @brief : 鼠标按下事件 - */ - virtual void mousePressEvent(QMouseEvent *e); - - /** - * @brief : 鼠标释放事件 - */ - virtual void mouseReleaseEvent(QMouseEvent *e); - /** - * @brief : 鼠标移动事件 - */ - virtual void mouseMoveEvent(QMouseEvent *e); - - /** - * @brief : 窗口移动事件 - */ - virtual void moveEvent(QMoveEvent *); - - /** - * @brief : 窗口大小修改事件 - */ - virtual void resizeEvent(QResizeEvent *); - - - /** - * @brief : 窗口显示事件 - */ - virtual void showEvent(QShowEvent *); - - /** - * @brief : 窗口隐藏事件 - */ - virtual void hideEvent(QHideEvent *); - - /** - * @brief : 鼠标进入窗口事件 - */ - virtual void enterEvent(QEvent *e); - - /** - * @brief : 鼠标离开窗口事件 - */ - virtual void leaveEvent(QEvent *e); - - /** - * @brief : 窗口关闭事件 - */ - virtual void closeEvent(QCloseEvent *); - - /** - * @brief : 界面自绘事件 - */ - virtual void paintEvent(QPaintEvent *); - -private: - - /** - * @brief : 获得一个以时间格式命名的文件名 - * @return: QString 文件名 - * @date : 2017年04月16日 - */ - virtual const QString getFileName(void); - -public slots: - - - /** - * @brief : 根据鼠标位置修改窗口大小 - * @param : x 鼠标的横向位置 - * @param : y 鼠标的纵向位置 - * @date : 2017年04月16日 - */ - void onMouseChange(int x,int y); - - /** - * @brief : 保存屏幕到剪切板中 - * @date : 2017年04月16日 - */ - void onSaveScreen(void); - -protected slots: - - /** - * @brief : 保存编辑屏幕到其他路径下 - * @note : 会呼出路径选择的窗口 - * @date : 2017年04月16日 - */ - void onSaveScreenOther(void); - - /** - * @brief : 退出当前截图窗口 - * @date : 2017年04月16日 - */ - void quitScreenshot(void); - -private: - - /// 是否已经设置初始大小 - static bool isInit_; - /// 窗口大小改变时,记录改变方向 - DIRECTION direction_; - /// 起点 - QPoint originPoint_; - /// 鼠标是否按下 - bool isPressed_; - /// 拖动的距离 - QPoint movePos_; - /// 标记锚点 - QPolygon listMarker_; - /// 屏幕原画 - std::shared_ptr originPainting_; - /// 当前窗口几何数据 用于绘制截图区域 - QRect currentRect_; - /// 右键菜单对象 - QMenu *menu_; - -}; - - - -#endif /// OESCREENSHOT_H +/** + * @author : 陈鲁勇 + * @date : 2017年04月 + * @version: 1.0 + * @note : 根据 Apache 许可证 2.0 版(以下简称“许可证”)授权; + * 除非遵守本许可,否则您不能使用这个文件。 + * @remarks: 您可以获得该许可的副本: + * http://www.apache.org/licenses/LICENSE-2.0 + * 除非适用法律需要或者书面同意,按本许可分发的软件 + * 要按“原样”分发,没有任何形式的,明确或隐含的担保条款。 + * 参见按照本许可控制许可权限及限制的特定语言的许可证。 + * + * 你可以获得该代码的最新版本: + * + * https://git.oschina.net/Mr_ChenLuYong/screenshot + * + * 开源社区的所有人都期待与你的共同维护。 + * + * + * 如果你对这些代码还有不理解的地方可以通过最新的文章进行学习: + * + * 博客地址:http://blog.csdn.net/csnd_ayo + * + * 文章地址:http://blog.csdn.net/csnd_ayo/article/details/70197915 + * + * 期待你提交Bug,欢迎Issues。 + * +*/ + + +#ifndef OESCREENSHOT_H +#define OESCREENSHOT_H + +#include +#include +#include + +class OEScreen; +class OERect; +class OEAmplifier; +class QTimer; +class QMenu; + + +/** + * @class : OEScreenshot + * @brief : 截屏功能的主要入口, + * 管理全局热键,资源的回收与释放. + * @remark: 调用示例( OEScreenshot::Instance(); ) +*/ +class OEScreenshot : public QWidget { + Q_OBJECT + +signals: + + /** + * @brief : 鼠标移动(信号) + * @param : int x轴的坐标 + * @param : int y轴的坐标 + * @date : 2017年04月18日 + */ + void cursorPosChange(int, int); + + /** + * @brief : 双击(信号) + * @date : 2017年04月18日 + */ + void doubleClick(void); + + /** + * @brief : 鼠标当前位置最小的子窗口(信号) + * @param : QRect 当前窗口的矩形数据 + * @date : 2017年04月18日 + */ + void findChildWind(QRect); + +public: + /** + * @brief : 构造函数 + * @note : 当前依附的父窗口(一般不给父窗口) + * @date : 2017年04月16日 + */ + explicit OEScreenshot(QWidget *parent = 0); + ~OEScreenshot(void); + + /** + * @brief : 窗口实例 + * @note : 通过这个函数获得截图器的整个实例 + * @return: 返回 OEScreenshot 实例指针 + * @date : 2017年04月15日 + */ + static OEScreenshot *Instance(void); + + /** + * @brief : 摧毁截图窗口 + * @note : 通过这个函数可以摧毁整个截图窗口 + * @date : 2017年04月30日 + */ + static void destroy(void); + +protected: + + /** + * @brief : 隐藏窗口事件 + */ + virtual void hideEvent(QHideEvent *); + /** + * @brief : 关闭窗口事件 + */ + virtual void closeEvent(QCloseEvent *); + /** + * @brief : 双击事件 + */ + virtual void mouseDoubleClickEvent(QMouseEvent*); + /** + * @brief : 鼠标按下事件 + */ + virtual void mousePressEvent(QMouseEvent *); + /** + * @brief : 鼠标释放事件 + */ + virtual void mouseReleaseEvent(QMouseEvent *e); + /** + * @brief : 鼠标移动事件 + */ + virtual void mouseMoveEvent(QMouseEvent *e); + + /** + * @brief : 按键按下事件 + */ + virtual void keyPressEvent(QKeyEvent *e); + /** + * @brief : 自绘事件 + */ + virtual void paintEvent(QPaintEvent *); + + /** + * @brief : 更新当前鼠标选区的窗口 + */ + void updateMouse(void); + +private: + + + /** + * @brief : 初始化放大镜 (色彩采集器) + * @note : 他需要屏幕的原画作为放大器的放大元素 + * @param : originPainting 放大器必要的元素,若为空,则默认用originPainting_原画 + * @date : 2017年04月15日 + * @remark: 需先行调用getGlobalScreen。 + */ + void initAmplifier(std::shared_ptr originPainting = nullptr); + + /** + * @brief : 测量控件 (大小感知器) + * @date : 2017年04月27日 + */ + void initMeasureWidget(void); + + /** + * @brief : 初始化截屏背景 + * @return: QPixmap 经过暗色处理的屏幕图 + * @date : 2017年04月15日 + */ + std::shared_ptr initGlobalScreen(void); + + + /** + * @brief : 初始化鼠标 + * @note : 为鼠标设置默认状态下的图标样式 + * @param : ico 鼠标图片的资源文件路径 + * @date : 2017年04月15日 + * @remark: 若参数未填写,在使用本程序默认的鼠标Logo + */ + void initCursor(const QString& ico = ""); + + /** + * @brief : 创建截图器 + * @note : 若截图器已存在,则返回截图器示例,不会重复创建。 + * @param : pos 截图器的起始位置 (给当前鼠标位置即可) + * @date : 2017年04月16日 + * @remark: 创建截图器前,需要创建相关的组件,(例:大小感知器,放大取色器) + */ + std::shared_ptr createScreen(const QPoint &pos); + + /** + * @brief : 摧毁截图器 + * @note : 若截图器已存在,则摧毁示例,并清理示例创建的连带资源 + * @date : 2017年04月16日 + */ + void destroyScreen(void); + + + /** + * @brief : 获得当前屏幕的大小 + * @note : 这个函数是支持多屏幕的,示例:双屏幕 QRect(-1920, 0, 3840, 1080) + * @return: 返回 QRect 引用 + * @date : 2017年04月15日 + */ + const QRect& getScreenRect(void); + + /** + * @brief : 获得屏幕的原画 + * @note : 他不会重复获得屏幕原画,如果有,则返回原有的原画 + * @return: QPixmap* 指针 + * @date : 2017年04月15日 + * @remark: 若想重新获得屏幕原画,需要清理原有资源 + */ + std::shared_ptr getGlobalScreen(void); + + +private: + + /// 截屏窗口是否已经展示 + bool isLeftPressed_; + /// 用于检测误操作 + QPoint startPoint_; + /// 当前桌面屏幕的矩形数据 + QRect desktopRect_; + /// 屏幕暗色背景图 + std::shared_ptr backgroundScreen_; + /// 屏幕原画 + std::shared_ptr originPainting_; + /// 截图屏幕 + std::shared_ptr screenTool_; + /// 截图器大小感知器 + std::shared_ptr rectTool_; + /// 放大取色器 + std::shared_ptr amplifierTool_; + /// 当前鼠标选区最小的矩形窗口 + QRect windowRect_; + /// 截屏实例对象 + static OEScreenshot *self_; + /// 置顶定时器 + QTimer* egoisticTimer_; + /// 活动窗口 + static bool isActivity_; +private slots: + + /** + * @brief : Window下霸道置顶(唯我独尊) + * @date : 2017年04月28日 + * @remark: 使用该函数时,会终止右键菜单的行为,慎重使用,避免BUG + */ + void onEgoistic(void); +}; + + + + +/** + * @class : OERect + * @brief : 大小感知器 + * @note : 主要关乎截图器左上方的大小感知控件 +*/ +class OERect : public QWidget { + Q_OBJECT + +signals: + + +public: + + explicit OERect(QWidget *parent = 0); + +protected: + + /** + * @brief : 自绘函数 + */ + void paintEvent(QPaintEvent *); + +public slots: + + /** + * @brief : 外部组件位置修改(槽) + * @note : 感知器修改自身位置 + * @param : x 横向位置 + * @param : y 纵向位置 + * @date : 2017年04月15日 + */ + void onPostionChange(int x, int y); + + /** + * @brief : 外部组件大小修改 (槽) + * @note : 感知器修改显示的大小数据 + * @param : w 宽度 + * @param : h 高度 + * @date : 2017年04月15日 + */ + void onSizeChange(int w, int h); + +private: + /// 背景色 + std::shared_ptr backgroundPixmap_; + /// 显示的文字信息 + QString info_; +}; + + +/** + * @class : OEScreen + * @brief : 截图器 + * @note : 主要关乎图片的编辑与保存 +*/ +class OEScreen : public QWidget { + + Q_OBJECT + +signals: + + + /** + * @brief : 截图器大小修改(信号) + * @param : int 宽度 + * @param : int 高度 + * @date : 2017年04月17日 + */ + void sizeChange(int,int); + + /** + * @brief : 截图器窗口的位置(信号) + * @param : int 窗口的横向位置 + * @param : int 窗口的纵向位置 + * @date : 2017年04月17日 + */ + void postionChange(int,int); + + /** + * @brief : 双击 (信号) + * @date : 2017年04月17日 + */ + void doubleClick(void); + +protected: + + /// 内边距,决定拖拽的触发。 + const int PADDING_ = 6; + + /// 方位枚举 + enum DIRECTION { + UPPER=0, + LOWER=1, + LEFT, + RIGHT, + LEFTUPPER, + LEFTLOWER, + RIGHTLOWER, + RIGHTUPPER, + NONE + }; + +public: + + explicit OEScreen(std::shared_ptr originPainting, QPoint pos, QWidget *parent = 0); + + ~OEScreen() { isInit_ = false; } + + /** + * @brief : 获得当前截图器是否存在 + * @return: true : 存在 + * @date : 2017年04月17日 + */ + static bool state(void) { return isInit_; } + +protected: + + /** + * @brief : 获得当前坐标点的边界方位 + * @param : cursor 当前鼠标的位置 + * @return: DIRECTION 鼠标的方位枚举 + * @date : 2017年04月17日 + */ + DIRECTION getRegion(const QPoint &cursor); + + + /** + * @brief : 呼出菜单事件 + */ + virtual void contextMenuEvent(QContextMenuEvent *); + + /** + * @brief : 双击事件 + */ + virtual void mouseDoubleClickEvent(QMouseEvent *e); + + /** + * @brief : 鼠标按下事件 + */ + virtual void mousePressEvent(QMouseEvent *e); + + /** + * @brief : 鼠标释放事件 + */ + virtual void mouseReleaseEvent(QMouseEvent *e); + /** + * @brief : 鼠标移动事件 + */ + virtual void mouseMoveEvent(QMouseEvent *e); + + /** + * @brief : 窗口移动事件 + */ + virtual void moveEvent(QMoveEvent *); + + /** + * @brief : 窗口大小修改事件 + */ + virtual void resizeEvent(QResizeEvent *); + + + /** + * @brief : 窗口显示事件 + */ + virtual void showEvent(QShowEvent *); + + /** + * @brief : 窗口隐藏事件 + */ + virtual void hideEvent(QHideEvent *); + + /** + * @brief : 鼠标进入窗口事件 + */ + virtual void enterEvent(QEvent *e); + + /** + * @brief : 鼠标离开窗口事件 + */ + virtual void leaveEvent(QEvent *e); + + /** + * @brief : 窗口关闭事件 + */ + virtual void closeEvent(QCloseEvent *); + + /** + * @brief : 界面自绘事件 + */ + virtual void paintEvent(QPaintEvent *); + +private: + + /** + * @brief : 获得一个以时间格式命名的文件名 + * @return: QString 文件名 + * @date : 2017年04月16日 + */ + virtual const QString getFileName(void); + +public slots: + + + /** + * @brief : 根据鼠标位置修改窗口大小 + * @param : x 鼠标的横向位置 + * @param : y 鼠标的纵向位置 + * @date : 2017年04月16日 + */ + void onMouseChange(int x,int y); + + /** + * @brief : 保存屏幕到剪切板中 + * @date : 2017年04月16日 + */ + void onSaveScreen(void); + +protected slots: + + /** + * @brief : 保存编辑屏幕到其他路径下 + * @note : 会呼出路径选择的窗口 + * @date : 2017年04月16日 + */ + void onSaveScreenOther(void); + + /** + * @brief : 退出当前截图窗口 + * @date : 2017年04月16日 + */ + void quitScreenshot(void); + +private: + + /// 是否已经设置初始大小 + static bool isInit_; + /// 窗口大小改变时,记录改变方向 + DIRECTION direction_; + /// 起点 + QPoint originPoint_; + /// 鼠标是否按下 + bool isPressed_; + /// 拖动的距离 + QPoint movePos_; + /// 标记锚点 + QPolygon listMarker_; + /// 屏幕原画 + std::shared_ptr originPainting_; + /// 当前窗口几何数据 用于绘制截图区域 + QRect currentRect_; + /// 右键菜单对象 + QMenu *menu_; + +}; + + + +#endif /// OESCREENSHOT_H diff --git a/LedOK/passwordindlg.cpp b/LedOK/passwordindlg.cpp index 989fb37..1a46231 100644 --- a/LedOK/passwordindlg.cpp +++ b/LedOK/passwordindlg.cpp @@ -1,37 +1,37 @@ -#include "passwordindlg.h" -#include "base/changepasswordform.h" -#include -#include -#include - -PasswordInChDlg::PasswordInChDlg(QWidget *parent) : BaseDlg(parent) { - resize(213, 136); - setStyleSheet("QDialog{background-color: #eeeeee;} QLabel{background-color: transparent;}"); - auto vBox = new QVBoxLayout(this); - vBox->addStretch(); - - auto hBox = new QHBoxLayout(); - hBox->addWidget(new QLabel(tr("Input password"))); - - fdPassword = new QLineEdit(); - fdPassword->setEchoMode(QLineEdit::Password); - fdPassword->setFocus(); - hBox->addWidget(fdPassword); - vBox->addLayout(hBox); - - btnChangePassword = new QPushButton(tr("Change Password")); - btnChangePassword->setProperty("ssType", "progManageTool"); - vBox->addWidget(btnChangePassword, 0, Qt::AlignRight); - connect(btnChangePassword, &QPushButton::clicked, this, [this]() { - ChangePasswordForm dlg(this); - dlg.exec(); - }); - vBox->addStretch(); - - btnBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal); - btnBox->button(QDialogButtonBox::Ok)->setProperty("ssType", "progManageTool"); - btnBox->button(QDialogButtonBox::Cancel)->setProperty("ssType", "progManageTool"); - vBox->addWidget(btnBox, 0, Qt::AlignHCenter); - connect(btnBox, &QDialogButtonBox::rejected, this, &QDialog::reject); - vBox->addStretch(); -} +#include "passwordindlg.h" +#include "base/changepasswordform.h" +#include +#include +#include + +PasswordInChDlg::PasswordInChDlg(QWidget *parent) : BaseDlg(parent) { + resize(213, 136); + setStyleSheet("QDialog{background-color: #eeeeee;} QLabel{background-color: transparent;}"); + auto vBox = new QVBoxLayout(this); + vBox->addStretch(); + + auto hBox = new QHBoxLayout(); + hBox->addWidget(new QLabel(tr("Input password"))); + + fdPassword = new QLineEdit(); + fdPassword->setEchoMode(QLineEdit::Password); + fdPassword->setFocus(); + hBox->addWidget(fdPassword); + vBox->addLayout(hBox); + + btnChangePassword = new QPushButton(tr("Change Password")); + btnChangePassword->setProperty("ssType", "progManageTool"); + vBox->addWidget(btnChangePassword, 0, Qt::AlignRight); + connect(btnChangePassword, &QPushButton::clicked, this, [this]() { + ChangePasswordForm dlg(this); + dlg.exec(); + }); + vBox->addStretch(); + + btnBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal); + btnBox->button(QDialogButtonBox::Ok)->setProperty("ssType", "progManageTool"); + btnBox->button(QDialogButtonBox::Cancel)->setProperty("ssType", "progManageTool"); + vBox->addWidget(btnBox, 0, Qt::AlignHCenter); + connect(btnBox, &QDialogButtonBox::rejected, this, &QDialog::reject); + vBox->addStretch(); +} diff --git a/LedOK/passwordindlg.h b/LedOK/passwordindlg.h index 380753c..79ec393 100644 --- a/LedOK/passwordindlg.h +++ b/LedOK/passwordindlg.h @@ -1,18 +1,18 @@ -#ifndef PASSWORDINDLG_H -#define PASSWORDINDLG_H - -#include "basedlg.h" -#include -#include - -class PasswordInChDlg : public BaseDlg { - Q_OBJECT -public: - explicit PasswordInChDlg(QWidget *parent = nullptr); - - QLineEdit *fdPassword; - QPushButton *btnChangePassword; - QDialogButtonBox *btnBox; -}; - -#endif // PASSWORDINDLG_H +#ifndef PASSWORDINDLG_H +#define PASSWORDINDLG_H + +#include "basedlg.h" +#include +#include + +class PasswordInChDlg : public BaseDlg { + Q_OBJECT +public: + explicit PasswordInChDlg(QWidget *parent = nullptr); + + QLineEdit *fdPassword; + QPushButton *btnChangePassword; + QDialogButtonBox *btnBox; +}; + +#endif // PASSWORDINDLG_H diff --git a/LedOK/player/digiclock.cpp b/LedOK/player/digiclock.cpp index 40c321b..eb31a53 100644 --- a/LedOK/player/digiclock.cpp +++ b/LedOK/player/digiclock.cpp @@ -1,240 +1,240 @@ -#include "digiclock.h" -#include "gqt.h" -#include -#include -#include - -DigiClock::DigiClock(QString prefix, const QJsonObject &layer, QWidget *parent) : QWidget{parent} { - timeZone = QTimeZone(layer["timezone"].toString().toUtf8()); - auto spaceWidth = layer["spaceWidth"].toDouble(); - QJsonArray pics = layer["arrayPics"].toArray(); - foreach(auto pic, pics) imgs.insert(pic["name"].toString(), QPixmap(prefix+pic["id"].toString())); - int dateStyle = layer["dateStyle"].toInt(); - isSingleMonth = dateStyle==1||dateStyle==2||dateStyle==4||dateStyle==6||dateStyle==8||dateStyle==10||dateStyle==12; - QPixmap& timeSep = imgs["maohao"]; - weekly = layer["weekly"].toBool(); - bool hour12 = layer["hour12"].toBool(); - bool AmPm = hour12 ? layer["AmPm"].toBool() : false; - timeptn = hour12 ? "hhmmssa" : "HHmmss"; - bool hour = layer["hour"].toBool(); - bool min = layer["min"].toBool(); - bool sec = layer["sec"].toBool(); - multiline = layer["multiline"].toBool(); - if(multiline) { - QVBoxLayout *vBox = new QVBoxLayout(this); - vBox->setAlignment(Qt::AlignCenter); - vBox->setContentsMargins(0,0,0,0); - vBox->setSpacing(0); - vBox->addStretch(); - QHBoxLayout *hBox = new QHBoxLayout(); - vBox->addLayout(hBox); - hBox->addStretch(); - addDate(dateStyle, layer, hBox); - hBox->addStretch(); - if(weekly) { - hBox = new QHBoxLayout(); - vBox->addLayout(hBox); - hBox->addStretch(); - hBox->addWidget((QWidget*)weekComp); - hBox->addStretch(); - } - hBox = new QHBoxLayout(); - vBox->addLayout(hBox); - hBox->addStretch(); - if(AmPm) { - hBox->addWidget((QWidget*)ampmComp); - hBox->addSpacing(spaceWidth); - } - if(hour) { - hBox->addWidget((QWidget*)hourComps[0]); - hBox->addWidget((QWidget*)hourComps[1]); - } - if(hour&&min) hBox->addWidget((QWidget*)new ImgWgt(timeSep)); - if(min) { - hBox->addWidget((QWidget*)minComps[0]); - hBox->addWidget((QWidget*)minComps[1]); - } - if(min&&sec) hBox->addWidget((QWidget*)new ImgWgt(timeSep)); - if(sec) { - hBox->addWidget((QWidget*)secComps[0]); - hBox->addWidget((QWidget*)secComps[1]); - } - hBox->addStretch(); - vBox->addStretch(); - } else { - QHBoxLayout *hBox = new QHBoxLayout(this); - hBox->setContentsMargins(0,0,0,0); - hBox->setSpacing(0); - hBox->addStretch(); - addDate(dateStyle, layer, hBox); - if(hBox->count()>1) hBox->addSpacing(spaceWidth*2); - if(weekly) { - hBox->addWidget((QWidget*)weekComp); - hBox->addSpacing(spaceWidth*2); - } - if(AmPm) { - hBox->addWidget((QWidget*)ampmComp); - hBox->addSpacing(spaceWidth); - } - if(hour) { - hBox->addWidget((QWidget*)hourComps[0]); - hBox->addWidget((QWidget*)hourComps[1]); - } - if(hour&&min) hBox->addWidget((QWidget*)new ImgWgt(timeSep)); - if(min) { - hBox->addWidget((QWidget*)minComps[0]); - hBox->addWidget((QWidget*)minComps[1]); - } - if(min&&sec) hBox->addWidget((QWidget*)new ImgWgt(timeSep)); - if(sec) { - hBox->addWidget((QWidget*)secComps[0]); - hBox->addWidget((QWidget*)secComps[1]); - } - hBox->addStretch(); - } -} -void DigiClock::addDate(int dateStyle, QJsonObject layer, QHBoxLayout* tar) { - if(dateStyle==0 || dateStyle==1) { - addYear(layer, tar, imgs["YEAR"]); - if(layer["month"].toBool()) { - tar->addWidget((QWidget*)monthComps[0]); - tar->addWidget((QWidget*)monthComps[1]); - tar->addWidget((QWidget*)new ImgWgt(imgs["MONTH"])); - } - if(layer["day"].toBool()) { - tar->addWidget((QWidget*)dayComps[0]); - tar->addWidget((QWidget*)dayComps[1]); - tar->addWidget((QWidget*)new ImgWgt(imgs["DAY"])); - } - } else if(dateStyle==2 || dateStyle==3) { - QPixmap sep = imgs["xiegang"]; - if(layer["month"].toBool()) { - tar->addWidget((QWidget*)monthComps[0]); - tar->addWidget((QWidget*)monthComps[1]); - tar->addWidget((QWidget*)new ImgWgt(sep)); - } - if(layer["day"].toBool()) { - tar->addWidget((QWidget*)dayComps[0]); - tar->addWidget((QWidget*)dayComps[1]); - tar->addWidget((QWidget*)new ImgWgt(sep)); - } - addYear(layer, tar, QPixmap()); - } else if(dateStyle==4 || dateStyle==5) { - QPixmap sep = imgs["xiegang"]; - if(layer["day"].toBool()) { - tar->addWidget((QWidget*)dayComps[0]); - tar->addWidget((QWidget*)dayComps[1]); - tar->addWidget((QWidget*)new ImgWgt(sep)); - } - if(layer["month"].toBool()) { - tar->addWidget((QWidget*)monthComps[0]); - tar->addWidget((QWidget*)monthComps[1]); - tar->addWidget((QWidget*)new ImgWgt(sep)); - } - addYear(layer, tar, QPixmap()); - } else if(dateStyle==6 || dateStyle==7) { - QPixmap sep = imgs["xiegang"]; - addYear(layer, tar, sep); - if(layer["month"].toBool()) { - tar->addWidget((QWidget*)monthComps[0]); - tar->addWidget((QWidget*)monthComps[1]); - tar->addWidget((QWidget*)new ImgWgt(sep)); - } - if(layer["day"].toBool()) { - tar->addWidget((QWidget*)dayComps[0]); - tar->addWidget((QWidget*)dayComps[1]); - } - } else if(dateStyle==8 || dateStyle==9) { - QPixmap sep = imgs["hengxian"]; - if(layer["month"].toBool()) { - tar->addWidget((QWidget*)monthComps[0]); - tar->addWidget((QWidget*)monthComps[1]); - tar->addWidget((QWidget*)new ImgWgt(sep)); - } - if(layer["day"].toBool()) { - tar->addWidget((QWidget*)dayComps[0]); - tar->addWidget((QWidget*)dayComps[1]); - tar->addWidget((QWidget*)new ImgWgt(sep)); - } - addYear(layer, tar, QPixmap()); - } else if(dateStyle==10 || dateStyle==11) { - QPixmap sep = imgs["hengxian"]; - if(layer["day"].toBool()) { - tar->addWidget((QWidget*)dayComps[0]); - tar->addWidget((QWidget*)dayComps[1]); - tar->addWidget((QWidget*)new ImgWgt(sep)); - } - if(layer["month"].toBool()) { - tar->addWidget((QWidget*)monthComps[0]); - tar->addWidget((QWidget*)monthComps[1]); - tar->addWidget((QWidget*)new ImgWgt(sep)); - } - addYear(layer, tar, QPixmap()); - } else if(dateStyle==12 || dateStyle==13) { - QPixmap sep = imgs["hengxian"]; - addYear(layer, tar, sep); - if(layer["month"].toBool()) { - tar->addWidget((QWidget*)monthComps[0]); - tar->addWidget((QWidget*)monthComps[1]); - tar->addWidget((QWidget*)new ImgWgt(sep)); - } - if(layer["day"].toBool()) { - tar->addWidget((QWidget*)dayComps[0]); - tar->addWidget((QWidget*)dayComps[1]); - } - } -} -void DigiClock::addYear(QJsonObject layer, QHBoxLayout* tar, QPixmap sep) { - if(layer["year"].toBool()) { - if(layer["fullYear"].toBool()) { - tar->addWidget((QWidget*)yearComps[0]); - tar->addWidget((QWidget*)yearComps[1]); - } - tar->addWidget((QWidget*)yearComps[2]); - tar->addWidget((QWidget*)yearComps[3]); - if(!sep.isNull()) tar->addWidget((QWidget*)new ImgWgt(sep)); - } -} -void DigiClock::cal() { - QDateTime dt = QDateTime::currentDateTime().toTimeZone(timeZone); - QTime time = dt.time(); - QString hms = time.toString(timeptn); - *ampmComp = imgs[time.hour()<12?"AM":"PM"]; - *hourComps[0] = imgs[hms.mid(0,1)]; - *hourComps[1] = imgs[hms.mid(1,1)]; - *minComps[0] = imgs[hms.mid(2,1)]; - *minComps[1] = imgs[hms.mid(3,1)]; - *secComps[0] = imgs[hms.mid(4,1)]; - *secComps[1] = imgs[hms.mid(5,1)]; - if(yearComps[0]->img.isNull() || (time.hour()==0 && time.second()==0)) { - QDate date = dt.date(); - if(weekly) *weekComp = imgs[weeks[date.dayOfWeek()-1]]; - QString ymd = date.toString("yyyyMMdd"); - *yearComps[0] = imgs[ymd.mid(0,1)]; - *yearComps[1] = imgs[ymd.mid(1,1)]; - *yearComps[2] = imgs[ymd.mid(2,1)]; - *yearComps[3] = imgs[ymd.mid(3,1)]; - QChar ch = ymd.at(4); - if(isSingleMonth && ch=='0') *monthComps[0] = QPixmap(); - else *monthComps[0] = imgs[ymd.mid(4,1)]; - *monthComps[1] = imgs[ymd.mid(5,1)]; - *dayComps[0] = imgs[ymd.mid(6,1)]; - *dayComps[1] = imgs[ymd.mid(7,1)]; - } -} -void DigiClock::showEvent(QShowEvent *) { - if(timerId==0) { - timerId = startTimer(1000, Qt::PreciseTimer); - cal(); - } -} - -void DigiClock::timerEvent(QTimerEvent *) { - if(isVisible()) { - cal(); - update(); - } else if(timerId!=0) { - killTimer(timerId); - timerId = 0; - } -} +#include "digiclock.h" +#include "gutil/qgui.h" +#include +#include +#include + +DigiClock::DigiClock(QString prefix, const QJsonObject &layer, QWidget *parent) : QWidget{parent} { + timeZone = QTimeZone(layer["timezone"].toString().toUtf8()); + auto spaceWidth = layer["spaceWidth"].toDouble(); + QJsonArray pics = layer["arrayPics"].toArray(); + foreach(auto pic, pics) imgs.insert(pic["name"].toString(), QPixmap(prefix+pic["id"].toString())); + int dateStyle = layer["dateStyle"].toInt(); + isSingleMonth = dateStyle==1||dateStyle==2||dateStyle==4||dateStyle==6||dateStyle==8||dateStyle==10||dateStyle==12; + QPixmap& timeSep = imgs["maohao"]; + weekly = layer["weekly"].toBool(); + bool hour12 = layer["hour12"].toBool(); + bool AmPm = hour12 ? layer["AmPm"].toBool() : false; + timeptn = hour12 ? "hhmmssa" : "HHmmss"; + bool hour = layer["hour"].toBool(); + bool min = layer["min"].toBool(); + bool sec = layer["sec"].toBool(); + multiline = layer["multiline"].toBool(); + if(multiline) { + QVBoxLayout *vBox = new QVBoxLayout(this); + vBox->setAlignment(Qt::AlignCenter); + vBox->setContentsMargins(0,0,0,0); + vBox->setSpacing(0); + vBox->addStretch(); + QHBoxLayout *hBox = new QHBoxLayout(); + vBox->addLayout(hBox); + hBox->addStretch(); + addDate(dateStyle, layer, hBox); + hBox->addStretch(); + if(weekly) { + hBox = new QHBoxLayout(); + vBox->addLayout(hBox); + hBox->addStretch(); + hBox->addWidget((QWidget*)weekComp); + hBox->addStretch(); + } + hBox = new QHBoxLayout(); + vBox->addLayout(hBox); + hBox->addStretch(); + if(AmPm) { + hBox->addWidget((QWidget*)ampmComp); + hBox->addSpacing(spaceWidth); + } + if(hour) { + hBox->addWidget((QWidget*)hourComps[0]); + hBox->addWidget((QWidget*)hourComps[1]); + } + if(hour&&min) hBox->addWidget((QWidget*)new ImgWgt(timeSep)); + if(min) { + hBox->addWidget((QWidget*)minComps[0]); + hBox->addWidget((QWidget*)minComps[1]); + } + if(min&&sec) hBox->addWidget((QWidget*)new ImgWgt(timeSep)); + if(sec) { + hBox->addWidget((QWidget*)secComps[0]); + hBox->addWidget((QWidget*)secComps[1]); + } + hBox->addStretch(); + vBox->addStretch(); + } else { + QHBoxLayout *hBox = new QHBoxLayout(this); + hBox->setContentsMargins(0,0,0,0); + hBox->setSpacing(0); + hBox->addStretch(); + addDate(dateStyle, layer, hBox); + if(hBox->count()>1) hBox->addSpacing(spaceWidth*2); + if(weekly) { + hBox->addWidget((QWidget*)weekComp); + hBox->addSpacing(spaceWidth*2); + } + if(AmPm) { + hBox->addWidget((QWidget*)ampmComp); + hBox->addSpacing(spaceWidth); + } + if(hour) { + hBox->addWidget((QWidget*)hourComps[0]); + hBox->addWidget((QWidget*)hourComps[1]); + } + if(hour&&min) hBox->addWidget((QWidget*)new ImgWgt(timeSep)); + if(min) { + hBox->addWidget((QWidget*)minComps[0]); + hBox->addWidget((QWidget*)minComps[1]); + } + if(min&&sec) hBox->addWidget((QWidget*)new ImgWgt(timeSep)); + if(sec) { + hBox->addWidget((QWidget*)secComps[0]); + hBox->addWidget((QWidget*)secComps[1]); + } + hBox->addStretch(); + } +} +void DigiClock::addDate(int dateStyle, QJsonObject layer, QHBoxLayout* tar) { + if(dateStyle==0 || dateStyle==1) { + addYear(layer, tar, imgs["YEAR"]); + if(layer["month"].toBool()) { + tar->addWidget((QWidget*)monthComps[0]); + tar->addWidget((QWidget*)monthComps[1]); + tar->addWidget((QWidget*)new ImgWgt(imgs["MONTH"])); + } + if(layer["day"].toBool()) { + tar->addWidget((QWidget*)dayComps[0]); + tar->addWidget((QWidget*)dayComps[1]); + tar->addWidget((QWidget*)new ImgWgt(imgs["DAY"])); + } + } else if(dateStyle==2 || dateStyle==3) { + QPixmap sep = imgs["xiegang"]; + if(layer["month"].toBool()) { + tar->addWidget((QWidget*)monthComps[0]); + tar->addWidget((QWidget*)monthComps[1]); + tar->addWidget((QWidget*)new ImgWgt(sep)); + } + if(layer["day"].toBool()) { + tar->addWidget((QWidget*)dayComps[0]); + tar->addWidget((QWidget*)dayComps[1]); + tar->addWidget((QWidget*)new ImgWgt(sep)); + } + addYear(layer, tar, QPixmap()); + } else if(dateStyle==4 || dateStyle==5) { + QPixmap sep = imgs["xiegang"]; + if(layer["day"].toBool()) { + tar->addWidget((QWidget*)dayComps[0]); + tar->addWidget((QWidget*)dayComps[1]); + tar->addWidget((QWidget*)new ImgWgt(sep)); + } + if(layer["month"].toBool()) { + tar->addWidget((QWidget*)monthComps[0]); + tar->addWidget((QWidget*)monthComps[1]); + tar->addWidget((QWidget*)new ImgWgt(sep)); + } + addYear(layer, tar, QPixmap()); + } else if(dateStyle==6 || dateStyle==7) { + QPixmap sep = imgs["xiegang"]; + addYear(layer, tar, sep); + if(layer["month"].toBool()) { + tar->addWidget((QWidget*)monthComps[0]); + tar->addWidget((QWidget*)monthComps[1]); + tar->addWidget((QWidget*)new ImgWgt(sep)); + } + if(layer["day"].toBool()) { + tar->addWidget((QWidget*)dayComps[0]); + tar->addWidget((QWidget*)dayComps[1]); + } + } else if(dateStyle==8 || dateStyle==9) { + QPixmap sep = imgs["hengxian"]; + if(layer["month"].toBool()) { + tar->addWidget((QWidget*)monthComps[0]); + tar->addWidget((QWidget*)monthComps[1]); + tar->addWidget((QWidget*)new ImgWgt(sep)); + } + if(layer["day"].toBool()) { + tar->addWidget((QWidget*)dayComps[0]); + tar->addWidget((QWidget*)dayComps[1]); + tar->addWidget((QWidget*)new ImgWgt(sep)); + } + addYear(layer, tar, QPixmap()); + } else if(dateStyle==10 || dateStyle==11) { + QPixmap sep = imgs["hengxian"]; + if(layer["day"].toBool()) { + tar->addWidget((QWidget*)dayComps[0]); + tar->addWidget((QWidget*)dayComps[1]); + tar->addWidget((QWidget*)new ImgWgt(sep)); + } + if(layer["month"].toBool()) { + tar->addWidget((QWidget*)monthComps[0]); + tar->addWidget((QWidget*)monthComps[1]); + tar->addWidget((QWidget*)new ImgWgt(sep)); + } + addYear(layer, tar, QPixmap()); + } else if(dateStyle==12 || dateStyle==13) { + QPixmap sep = imgs["hengxian"]; + addYear(layer, tar, sep); + if(layer["month"].toBool()) { + tar->addWidget((QWidget*)monthComps[0]); + tar->addWidget((QWidget*)monthComps[1]); + tar->addWidget((QWidget*)new ImgWgt(sep)); + } + if(layer["day"].toBool()) { + tar->addWidget((QWidget*)dayComps[0]); + tar->addWidget((QWidget*)dayComps[1]); + } + } +} +void DigiClock::addYear(QJsonObject layer, QHBoxLayout* tar, QPixmap sep) { + if(layer["year"].toBool()) { + if(layer["fullYear"].toBool()) { + tar->addWidget((QWidget*)yearComps[0]); + tar->addWidget((QWidget*)yearComps[1]); + } + tar->addWidget((QWidget*)yearComps[2]); + tar->addWidget((QWidget*)yearComps[3]); + if(!sep.isNull()) tar->addWidget((QWidget*)new ImgWgt(sep)); + } +} +void DigiClock::cal() { + QDateTime dt = QDateTime::currentDateTime().toTimeZone(timeZone); + QTime time = dt.time(); + QString hms = time.toString(timeptn); + *ampmComp = imgs[time.hour()<12?"AM":"PM"]; + *hourComps[0] = imgs[hms.mid(0,1)]; + *hourComps[1] = imgs[hms.mid(1,1)]; + *minComps[0] = imgs[hms.mid(2,1)]; + *minComps[1] = imgs[hms.mid(3,1)]; + *secComps[0] = imgs[hms.mid(4,1)]; + *secComps[1] = imgs[hms.mid(5,1)]; + if(yearComps[0]->img.isNull() || (time.hour()==0 && time.second()==0)) { + QDate date = dt.date(); + if(weekly) *weekComp = imgs[weeks[date.dayOfWeek()-1]]; + QString ymd = date.toString("yyyyMMdd"); + *yearComps[0] = imgs[ymd.mid(0,1)]; + *yearComps[1] = imgs[ymd.mid(1,1)]; + *yearComps[2] = imgs[ymd.mid(2,1)]; + *yearComps[3] = imgs[ymd.mid(3,1)]; + QChar ch = ymd.at(4); + if(isSingleMonth && ch=='0') *monthComps[0] = QPixmap(); + else *monthComps[0] = imgs[ymd.mid(4,1)]; + *monthComps[1] = imgs[ymd.mid(5,1)]; + *dayComps[0] = imgs[ymd.mid(6,1)]; + *dayComps[1] = imgs[ymd.mid(7,1)]; + } +} +void DigiClock::showEvent(QShowEvent *) { + if(timerId==0) { + timerId = startTimer(1000, Qt::PreciseTimer); + cal(); + } +} + +void DigiClock::timerEvent(QTimerEvent *) { + if(isVisible()) { + cal(); + update(); + } else if(timerId!=0) { + killTimer(timerId); + timerId = 0; + } +} diff --git a/LedOK/player/digiclock.h b/LedOK/player/digiclock.h index 6d31453..7eebd42 100644 --- a/LedOK/player/digiclock.h +++ b/LedOK/player/digiclock.h @@ -1,67 +1,67 @@ -#ifndef DIGICLOCK_H -#define DIGICLOCK_H - -#include -#include -#include -#include - -class ImgWgt : public QWidget { -public: - ImgWgt(QWidget *parent = nullptr) : QWidget{parent} {} - ImgWgt(const QPixmap &img) :img(img){ - setFixedSize(this->img.size()); - } - ImgWgt(QPixmap &&img) { - this->img = std::move(img); - setFixedSize(this->img.size()); - } - ImgWgt &operator=(const QPixmap &img) { - this->img = img; - setFixedSize(this->img.size()); - return *this; - } - ImgWgt &operator=(QPixmap &&img) { - this->img = std::move(img); - setFixedSize(this->img.size()); - return *this; - } - QPixmap img; -protected: - virtual void paintEvent(QPaintEvent *) override { - if(img.isNull()) return; - QPainter painter(this); - painter.setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform); - painter.drawPixmap(0, 0, width(), height(), img); - } -}; - -const QString weeks[7]{"MON","TUE","WED","THU","FRI","SAT","SUN"}; - -class DigiClock : public QWidget { - Q_OBJECT -public: - DigiClock(QString path, const QJsonObject &layer, QWidget *parent = nullptr); - void cal(); - void addDate(int, QJsonObject, QHBoxLayout*); - void addYear(QJsonObject layer, QHBoxLayout* tar, QPixmap sep); - QTimeZone timeZone; - ImgWgt *yearComps[4] {new ImgWgt(), new ImgWgt(), new ImgWgt(), new ImgWgt()}; - ImgWgt *monthComps[2] {new ImgWgt(), new ImgWgt()}; - ImgWgt *dayComps[2] {new ImgWgt(), new ImgWgt()}; - ImgWgt *weekComp = new ImgWgt(), *ampmComp = new ImgWgt(); - ImgWgt *hourComps[2] {new ImgWgt(), new ImgWgt()}; - ImgWgt *minComps[2] {new ImgWgt(), new ImgWgt()}; - ImgWgt *secComps[2] {new ImgWgt(), new ImgWgt()}; - - QMap imgs; - QString timeptn; - bool multiline, weekly, isSingleMonth; - int timerId = 0; - -protected: - void timerEvent(QTimerEvent *) override; - void showEvent(QShowEvent *) override; -}; - -#endif // DIGICLOCK_H +#ifndef DIGICLOCK_H +#define DIGICLOCK_H + +#include +#include +#include +#include + +class ImgWgt : public QWidget { +public: + ImgWgt(QWidget *parent = nullptr) : QWidget{parent} {} + ImgWgt(const QPixmap &img) :img(img){ + setFixedSize(this->img.size()); + } + ImgWgt(QPixmap &&img) { + this->img = std::move(img); + setFixedSize(this->img.size()); + } + ImgWgt &operator=(const QPixmap &img) { + this->img = img; + setFixedSize(this->img.size()); + return *this; + } + ImgWgt &operator=(QPixmap &&img) { + this->img = std::move(img); + setFixedSize(this->img.size()); + return *this; + } + QPixmap img; +protected: + virtual void paintEvent(QPaintEvent *) override { + if(img.isNull()) return; + QPainter painter(this); + painter.setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform); + painter.drawPixmap(0, 0, width(), height(), img); + } +}; + +const QString weeks[7]{"MON","TUE","WED","THU","FRI","SAT","SUN"}; + +class DigiClock : public QWidget { + Q_OBJECT +public: + DigiClock(QString path, const QJsonObject &layer, QWidget *parent = nullptr); + void cal(); + void addDate(int, QJsonObject, QHBoxLayout*); + void addYear(QJsonObject layer, QHBoxLayout* tar, QPixmap sep); + QTimeZone timeZone; + ImgWgt *yearComps[4] {new ImgWgt(), new ImgWgt(), new ImgWgt(), new ImgWgt()}; + ImgWgt *monthComps[2] {new ImgWgt(), new ImgWgt()}; + ImgWgt *dayComps[2] {new ImgWgt(), new ImgWgt()}; + ImgWgt *weekComp = new ImgWgt(), *ampmComp = new ImgWgt(); + ImgWgt *hourComps[2] {new ImgWgt(), new ImgWgt()}; + ImgWgt *minComps[2] {new ImgWgt(), new ImgWgt()}; + ImgWgt *secComps[2] {new ImgWgt(), new ImgWgt()}; + + QMap imgs; + QString timeptn; + bool multiline, weekly, isSingleMonth; + int timerId = 0; + +protected: + void timerEvent(QTimerEvent *) override; + void showEvent(QShowEvent *) override; +}; + +#endif // DIGICLOCK_H diff --git a/LedOK/player/eleanaclock.cpp b/LedOK/player/eleanaclock.cpp index 4a5071a..a3d37cb 100644 --- a/LedOK/player/eleanaclock.cpp +++ b/LedOK/player/eleanaclock.cpp @@ -1,74 +1,82 @@ -#include "eleanaclock.h" -#include -#include -#include - -EleAnaClock::EleAnaClock(QString path, const QJsonObject &layer, QWidget *parent) : QWidget{parent} { - timeZone = QTimeZone(layer["timezone"].toString().toUtf8()); - img.load(path); - pinHourColor = layer["pinHourColor"].toString(); - pinMinColor = layer["pinMinColor"].toString(); - pinSecColor = layer["pinSecColor"].toString(); -} - -void EleAnaClock::cal() { - QTime time = QDateTime::currentDateTime().toTimeZone(timeZone).time(); - double rad = time.second()*M_PI/30; - double rsin = sin(rad); - double rcos = cos(rad); - double sideLen = width(); - if(height() < sideLen) sideLen = height(); - sPath = QPainterPath(QPointF(sideLen*0.55*rsin, sideLen*-0.55*rcos)); - double pinWidth = sideLen/36; - double sx = pinWidth*rcos; - double sy = pinWidth*rsin; - sPath.lineTo(sx, sy); - sPath.lineTo(-sx, -sy); - sPath.closeSubpath(); - - rad = time.minute()*M_PI/30 + rad/60; - rsin = sin(rad); - rcos = cos(rad); - mPath = QPainterPath(QPointF(sideLen*0.45*rsin, sideLen*-0.45*rcos)); - pinWidth = sideLen/30; - sx = pinWidth*rcos; - sy = pinWidth*rsin; - mPath.lineTo(sx, sy); - mPath.lineTo(-sx, -sy); - mPath.closeSubpath(); - - rad = time.hour()*M_PI/6 + rad/12; - rsin = sin(rad); - rcos = cos(rad); - hPath = QPainterPath(QPointF(sideLen*0.3*rsin, sideLen*-0.3*rcos)); - pinWidth = sideLen/18; - sx = pinWidth*rcos; - sy = pinWidth*rsin; - hPath.lineTo(sx, sy); - hPath.lineTo(-sx, -sy); - hPath.closeSubpath(); -} -void EleAnaClock::paintEvent(QPaintEvent *) { - if(timerId==0) { - timerId = startTimer(1000, Qt::PreciseTimer); - cal(); - } - QPainter painter(this); - painter.setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform); - if(! img.isNull()) painter.drawPixmap(0, 0, width(), height(), img); - painter.translate(width()/2, height()/2); - painter.fillPath(hPath, QBrush(pinHourColor)); - painter.fillPath(mPath, QBrush(pinMinColor)); - painter.fillPath(sPath, QBrush(pinSecColor)); - painter.translate(-width()/2, -height()/2); -} - -void EleAnaClock::timerEvent(QTimerEvent *) { - if(isVisible()) { - cal(); - repaint(); - } else if(timerId!=0) { - killTimer(timerId); - timerId = 0; - } -} +#include "eleanaclock.h" +#include +#include + +EleAnaClock::EleAnaClock(double w, double h, QString path, const QJsonObject &layer, QWidget *parent) : QWidget{parent} { + timeZone = QTimeZone(layer["timezone"].toString().toUtf8()); + img.load(path); + pinHourColor = layer["pinHourColor"].toString(); + pinMinColor = layer["pinMinColor"].toString(); + pinSecColor = layer["pinSecColor"].toString(); + auto hhLen = layer["pinHourLen"].toInt(); + auto mhLen = layer["pinMinLen"].toInt(); + auto shLen = layer["pinSecLen"].toInt(); + auto hhWidth = layer["pinHourWidth"].toInt(); + auto mhWidth = layer["pinMinWidth"].toInt(); + auto shWidth = layer["pinSecWidth"].toInt(); + showSecHand = layer["showSecond"].toBool(); + auto sideLen = w; + if(h < sideLen) sideLen = h; + auto lineWidth = sideLen/128; + if(lineWidth < 1) lineWidth = 1; + pen.setWidthF(lineWidth); + pen.setJoinStyle(Qt::RoundJoin); + + hPoses[0].rx() = hhWidth*sideLen/400; + hPoses[1].ry() = hhLen*sideLen/-200; + hPoses[2].rx() = -hPoses[0].rx(); + + mPoses[0].rx() = mhWidth*sideLen/400; + mPoses[1].ry() = mhLen*sideLen/-200; + mPoses[2].rx() = -mPoses[0].rx(); + + sPoses[0].rx() = shWidth*sideLen/400; + sPoses[1].ry() = shLen*sideLen/-200; + sPoses[2].rx() = -sPoses[0].rx(); +} + +void EleAnaClock::cal() { + auto time = QDateTime::currentDateTime().toTimeZone(timeZone).time(); + sAngle = time.second() * 6; + mAngle = time.minute() * 6 + sAngle/60; + hAngle = time.hour() * 30 + mAngle/12; +} +void EleAnaClock::paintEvent(QPaintEvent *) { + if(timerId==0) { + timerId = startTimer(500, Qt::PreciseTimer); + cal(); + } + QPainter painter(this); + painter.setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform); + if(! img.isNull()) painter.drawPixmap(0, 0, width(), height(), img); + painter.translate(width()/2, height()/2); + + pen.setColor(pinHourColor); + painter.setPen(pen); + painter.setBrush(pen.brush()); + painter.rotate(hAngle); + painter.drawPolygon(hPoses, 3); + + pen.setColor(pinMinColor); + painter.setPen(pen); + painter.setBrush(pen.brush()); + painter.rotate(mAngle-hAngle); + painter.drawPolygon(mPoses, 3); + if(showSecHand) { + pen.setColor(pinSecColor); + painter.setPen(pen); + painter.setBrush(pen.brush()); + painter.rotate(sAngle-mAngle); + painter.drawPolygon(sPoses, 3); + } +} + +void EleAnaClock::timerEvent(QTimerEvent *) { + if(isVisible()) { + cal(); + update(); + } else if(timerId!=0) { + killTimer(timerId); + timerId = 0; + } +} diff --git a/LedOK/player/eleanaclock.h b/LedOK/player/eleanaclock.h index b33cec6..71e94d2 100644 --- a/LedOK/player/eleanaclock.h +++ b/LedOK/player/eleanaclock.h @@ -1,24 +1,27 @@ -#ifndef ELEANACLOCK_H -#define ELEANACLOCK_H - -#include -#include -#include - -class EleAnaClock : public QWidget { - Q_OBJECT -public: - explicit EleAnaClock(QString path, const QJsonObject &layer, QWidget *parent = nullptr); - void cal(); - QTimeZone timeZone; - QPixmap img; - QColor pinHourColor, pinMinColor, pinSecColor; - QPainterPath sPath, mPath, hPath; - int timerId = 0; - -protected: - void paintEvent(QPaintEvent *) override; - void timerEvent(QTimerEvent *) override; -}; - -#endif // ELEANACLOCK_H +#ifndef ELEANACLOCK_H +#define ELEANACLOCK_H + +#include +#include +#include + +class EleAnaClock : public QWidget { + Q_OBJECT +public: + explicit EleAnaClock(double w, double h, QString path, const QJsonObject &layer, QWidget *parent = nullptr); + void cal(); + QTimeZone timeZone; + QPixmap img; + QColor pinHourColor, pinMinColor, pinSecColor; + QPointF hPoses[3]{}, mPoses[3]{}, sPoses[3]{}; + double hAngle, mAngle, sAngle; + QPen pen; + int timerId{0}; + bool showSecHand{true}; + +protected: + void paintEvent(QPaintEvent *) override; + void timerEvent(QTimerEvent *) override; +}; + +#endif // ELEANACLOCK_H diff --git a/LedOK/player/elebase.cpp b/LedOK/player/elebase.cpp index ca8907d..37cb708 100644 --- a/LedOK/player/elebase.cpp +++ b/LedOK/player/elebase.cpp @@ -1 +1 @@ -//#include "elebase.h" +//#include "elebase.h" diff --git a/LedOK/player/elebase.h b/LedOK/player/elebase.h index a92c4af..654992a 100644 --- a/LedOK/player/elebase.h +++ b/LedOK/player/elebase.h @@ -1,20 +1,20 @@ -#ifndef ELEBASE_H -#define ELEBASE_H -#include - -class EleBase { -public: - QString id; - QString type; - int x; - int y; - int w; - int h; - int startTime; - int timeSpan; - int endTime; - - QWidget* wgt = nullptr; -}; - -#endif // ELEBASE_H +#ifndef ELEBASE_H +#define ELEBASE_H +#include + +class EleBase { +public: + QString id; + QString type; + int x; + int y; + int w; + int h; + int startTime; + int endTime; + bool repeat; + + QWidget *wgt{0}; +}; + +#endif // ELEBASE_H diff --git a/LedOK/player/eleborder.cpp b/LedOK/player/eleborder.cpp index aaf9e35..01df0d3 100644 --- a/LedOK/player/eleborder.cpp +++ b/LedOK/player/eleborder.cpp @@ -1,76 +1,76 @@ -#include "eleborder.h" -#include -#include -#include -#include - -EleBorder::EleBorder(QString path, QString eff, int speed, QWidget *parent) : QWidget{parent}, speed(speed) { - img.load(path); - if(eff.startsWith("ro")) this->eff = 'r'; - else if(eff.startsWith("bl")) this->eff = 'b'; -} - -void EleBorder::paintEvent(QPaintEvent *) { - if(eff=='b' && off > 0) return; - if(timerId==0) { - if(eff=='r') timerId = startTimer(speed==1 ? 66 : (speed==2 ? 33 : 16), Qt::PreciseTimer); - else if(eff=='b') timerId = startTimer(speed==1 ? 500 : (speed==2 ? 250 : 66)); - } - int bdWidth = img.height(); - int halfBdWidth = (bdWidth+1)/2; - QBrush brush(img); - QTransform transTop = QTransform::fromTranslate(halfBdWidth+off, 0); - QTransform transRight = QTransform::fromTranslate(width() - bdWidth, halfBdWidth*3-width()+off); - transRight.rotate(90); - QTransform transBottom = QTransform::fromTranslate(halfBdWidth*3-height()-off, height() - bdWidth); - transBottom.rotate(180); - QTransform transLeft = QTransform::fromTranslate(0, halfBdWidth-off); - transLeft.rotate(270); - - QPainter painter(this); - brush.setTransform(transTop); - QPainterPath path(QPointF(0, 0)); - path.lineTo(width(), 0); - path.lineTo(width() - bdWidth, bdWidth); - path.lineTo(bdWidth, bdWidth); - path.closeSubpath(); - painter.fillPath(path, brush); - - brush.setTransform(transRight); - path = QPainterPath(QPointF(width(), 0)); - path.lineTo(width(), height()); - path.lineTo(width() - bdWidth, height() - bdWidth); - path.lineTo(width() - bdWidth, bdWidth); - path.closeSubpath(); - painter.fillPath(path, brush); - - brush.setTransform(transBottom); - path = QPainterPath(QPointF(width(), height())); - path.lineTo(0, height()); - path.lineTo(bdWidth, height() - bdWidth); - path.lineTo(width() - bdWidth, height() - bdWidth); - path.closeSubpath(); - painter.fillPath(path, brush); - - brush.setTransform(transLeft); - path = QPainterPath(QPointF(0, height())); - path.lineTo(0, 0); - path.lineTo(bdWidth, bdWidth); - path.lineTo(bdWidth, height() - bdWidth); - path.closeSubpath(); - painter.fillPath(path, brush); - -} - -void EleBorder::timerEvent(QTimerEvent *) { - if(isVisible()) { - if(eff=='r') { - if(off >= img.width() - 1) off = 0; - else off++; - } else off = off==0 ? 1 : 0; - update(); - } else if(timerId!=0) { - killTimer(timerId); - timerId = 0; - } -} +#include "eleborder.h" +#include +#include +#include +#include + +EleBorder::EleBorder(QString path, QString eff, int speed, QWidget *parent) : QWidget{parent}, speed(speed) { + img.load(path); + if(eff.startsWith("ro")) this->eff = 'r'; + else if(eff.startsWith("bl")) this->eff = 'b'; +} + +void EleBorder::paintEvent(QPaintEvent *) { + if(eff=='b' && off > 0) return; + if(timerId==0) { + if(eff=='r') timerId = startTimer(speed==1 ? 66 : (speed==2 ? 33 : 16), Qt::PreciseTimer); + else if(eff=='b') timerId = startTimer(speed==1 ? 500 : (speed==2 ? 250 : 66)); + } + int bdWidth = img.height(); + int halfBdWidth = (bdWidth+1)/2; + QBrush brush(img); + QTransform transTop = QTransform::fromTranslate(halfBdWidth+off, 0); + QTransform transRight = QTransform::fromTranslate(width() - bdWidth, halfBdWidth*3-width()+off); + transRight.rotate(90); + QTransform transBottom = QTransform::fromTranslate(halfBdWidth*3-height()-off, height() - bdWidth); + transBottom.rotate(180); + QTransform transLeft = QTransform::fromTranslate(0, halfBdWidth-off); + transLeft.rotate(270); + + QPainter painter(this); + brush.setTransform(transTop); + QPainterPath path(QPointF(0, 0)); + path.lineTo(width(), 0); + path.lineTo(width() - bdWidth, bdWidth); + path.lineTo(bdWidth, bdWidth); + path.closeSubpath(); + painter.fillPath(path, brush); + + brush.setTransform(transRight); + path = QPainterPath(QPointF(width(), 0)); + path.lineTo(width(), height()); + path.lineTo(width() - bdWidth, height() - bdWidth); + path.lineTo(width() - bdWidth, bdWidth); + path.closeSubpath(); + painter.fillPath(path, brush); + + brush.setTransform(transBottom); + path = QPainterPath(QPointF(width(), height())); + path.lineTo(0, height()); + path.lineTo(bdWidth, height() - bdWidth); + path.lineTo(width() - bdWidth, height() - bdWidth); + path.closeSubpath(); + painter.fillPath(path, brush); + + brush.setTransform(transLeft); + path = QPainterPath(QPointF(0, height())); + path.lineTo(0, 0); + path.lineTo(bdWidth, bdWidth); + path.lineTo(bdWidth, height() - bdWidth); + path.closeSubpath(); + painter.fillPath(path, brush); + +} + +void EleBorder::timerEvent(QTimerEvent *) { + if(isVisible()) { + if(eff=='r') { + if(off >= img.width() - 1) off = 0; + else off++; + } else off = off==0 ? 1 : 0; + update(); + } else if(timerId!=0) { + killTimer(timerId); + timerId = 0; + } +} diff --git a/LedOK/player/eleborder.h b/LedOK/player/eleborder.h index 1ff0730..aee62bc 100644 --- a/LedOK/player/eleborder.h +++ b/LedOK/player/eleborder.h @@ -1,19 +1,19 @@ -#ifndef ELEBORDER_H -#define ELEBORDER_H - -#include - -class EleBorder : public QWidget { - Q_OBJECT -public: - explicit EleBorder(QString, QString, int, QWidget *parent = nullptr); - QPixmap img; - char eff = 0; - int speed = 2, off = 0; - int timerId = 0; -protected: - void paintEvent(QPaintEvent *) override; - void timerEvent(QTimerEvent *) override; -}; - -#endif +#ifndef ELEBORDER_H +#define ELEBORDER_H + +#include + +class EleBorder : public QWidget { + Q_OBJECT +public: + explicit EleBorder(QString, QString, int, QWidget *parent = nullptr); + QPixmap img; + char eff = 0; + int speed = 2, off = 0; + int timerId = 0; +protected: + void paintEvent(QPaintEvent *) override; + void timerEvent(QTimerEvent *) override; +}; + +#endif diff --git a/LedOK/player/elegif.cpp b/LedOK/player/elegif.cpp index eb08c6c..0702d39 100644 --- a/LedOK/player/elegif.cpp +++ b/LedOK/player/elegif.cpp @@ -1,32 +1,32 @@ -#include "elegif.h" -#include -#include - -EleGif::EleGif(QString path, QWidget *parent) : QWidget{parent} { - movie = new QMovie(path, QByteArray(), this); - movie->setCacheMode(QMovie::CacheAll); - movie->jumpToFrame(0); -} - -void EleGif::paintEvent(QPaintEvent *){ - QPainter painter(this); - if(movie!=nullptr) { - painter.setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform); - painter.drawPixmap(0, 0, width(), height(), movie->currentPixmap()); - if(timer==nullptr) { - timer = new SyncTimer(movie->nextFrameDelay()); - connect(timer, &SyncTimer::timeout, this, &EleGif::sltNext, Qt::BlockingQueuedConnection); - timer->start(); - } - } -} -void EleGif::sltNext(){ - if(isVisible()) { - movie->jumpToNextFrame(); - timer->inter = movie->nextFrameDelay(); - repaint(); - } else if(timer!=nullptr) { - timer->stop(); - timer = nullptr; - } -} +#include "elegif.h" +#include +#include + +EleGif::EleGif(QString path, QWidget *parent) : QWidget{parent} { + movie = new QMovie(path, QByteArray(), this); + movie->setCacheMode(QMovie::CacheAll); + movie->jumpToFrame(0); +} + +void EleGif::paintEvent(QPaintEvent *){ + QPainter painter(this); + if(movie!=nullptr) { + painter.setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform); + painter.drawPixmap(0, 0, width(), height(), movie->currentPixmap()); + if(timer==nullptr) { + timer = new SyncTimer(movie->nextFrameDelay()); + connect(timer, &SyncTimer::timeout, this, &EleGif::sltNext, Qt::BlockingQueuedConnection); + timer->start(); + } + } +} +void EleGif::sltNext(){ + if(isVisible()) { + movie->jumpToNextFrame(); + timer->inter = movie->nextFrameDelay(); + update(); + } else if(timer!=nullptr) { + timer->stop(); + timer = nullptr; + } +} diff --git a/LedOK/player/elegif.h b/LedOK/player/elegif.h index 7d2771e..0a71ab0 100644 --- a/LedOK/player/elegif.h +++ b/LedOK/player/elegif.h @@ -1,21 +1,21 @@ -#ifndef ELEGIF_H -#define ELEGIF_H -#include "synctimer.h" -#include - -class EleGif : public QWidget { - Q_OBJECT -public: - explicit EleGif(QString path, QWidget *parent = nullptr); - - QMovie* movie = nullptr; - SyncTimer* timer = nullptr; - -public slots: - void sltNext(); - -protected: - void paintEvent(QPaintEvent *) override; -}; - -#endif // ELEGIF_H +#ifndef ELEGIF_H +#define ELEGIF_H +#include "synctimer.h" +#include + +class EleGif : public QWidget { + Q_OBJECT +public: + explicit EleGif(QString path, QWidget *parent = nullptr); + + QMovie* movie = nullptr; + SyncTimer* timer = nullptr; + +public slots: + void sltNext(); + +protected: + void paintEvent(QPaintEvent *) override; +}; + +#endif // ELEGIF_H diff --git a/LedOK/player/eleimg.cpp b/LedOK/player/eleimg.cpp index 4b250e7..dc91b4c 100644 --- a/LedOK/player/eleimg.cpp +++ b/LedOK/player/eleimg.cpp @@ -1,14 +1,14 @@ -#include "eleimg.h" -#include -#include - -EleImg::EleImg(QString path, QWidget *parent) : QWidget{parent} { - img.load(path); -} - -void EleImg::paintEvent(QPaintEvent *){ - QPainter painter(this); - painter.setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform); - if(! img.isNull()) painter.drawPixmap(0, 0, width(), height(), img); -} - +#include "eleimg.h" +#include +#include + +EleImg::EleImg(QString path, QWidget *parent) : QWidget{parent} { + img.load(path); +} + +void EleImg::paintEvent(QPaintEvent *){ + QPainter painter(this); + painter.setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform); + if(! img.isNull()) painter.drawPixmap(0, 0, width(), height(), img); +} + diff --git a/LedOK/player/eleimg.h b/LedOK/player/eleimg.h index b96d3cb..3f8e93e 100644 --- a/LedOK/player/eleimg.h +++ b/LedOK/player/eleimg.h @@ -1,15 +1,15 @@ -#ifndef ELEIMG_H -#define ELEIMG_H - -#include - -class EleImg : public QWidget { - Q_OBJECT -public: - explicit EleImg(QString, QWidget *parent = nullptr); - QPixmap img; -protected: - void paintEvent(QPaintEvent *) override; -}; - -#endif // ELEIMG_H +#ifndef ELEIMG_H +#define ELEIMG_H + +#include + +class EleImg : public QWidget { + Q_OBJECT +public: + explicit EleImg(QString, QWidget *parent = nullptr); + QPixmap img; +protected: + void paintEvent(QPaintEvent *) override; +}; + +#endif // ELEIMG_H diff --git a/LedOK/player/elemultipng.cpp b/LedOK/player/elemultipng.cpp index 3e6bd60..6ceb671 100644 --- a/LedOK/player/elemultipng.cpp +++ b/LedOK/player/elemultipng.cpp @@ -1,98 +1,104 @@ -#include "elemultipng.h" -#include -#include -#include -#include -const QChar effTypes[] = {'l', 't', 'r', 'b'}; - -EleMultiPng::EleMultiPng(QString dirPre, QJsonArray maps, QWidget *parent) : QWidget{parent} { - QJsonObject map = maps[0].toObject(); - EffDur = map["effectSpeed"].toInt()*1000; - if(EffDur==0) return; - picDur = map["picDuration"].toInt()*1000; - if(picDur==0) picDur = EffDur; - foreach(auto map, maps) imgs.append(QPixmap(dirPre+map["id"].toString())); - QString effStr = map["effect"].toString(); - if(effStr.isEmpty() || effStr=="no") EffDur = 0; - else if(effStr.endsWith("left")) effType = 'l'; - else if(effStr.endsWith("top")) effType = 't'; - else if(effStr.endsWith("right")) effType = 'r'; - else if(effStr.endsWith("bottom")) effType = 'b'; - else if(effStr == "random") needRand = true; - else EffDur = 0; -} - -void EleMultiPng::startMove() { - if(EffDur==0) return; - if(needRand) effType = effTypes[rand.generate() % 4]; - double effDurD = EffDur; - if(effType=='l') { - imgx = width(); - imgy = 0; - effDurD /= width(); - } else if(effType=='r') { - imgx = -width(); - imgy = 0; - effDurD /= width(); - } else if(effType=='t') { - imgx = 0; - imgy = height(); - effDurD /= height(); - } else if(effType=='b') { - imgx = 0; - imgy = -height(); - effDurD /= height(); - } else return; - movePx = ceil(17/effDurD); - moveInter = effDurD*movePx; - moveTimerId = startTimer(moveInter, Qt::PreciseTimer); -} - -void EleMultiPng::paintEvent(QPaintEvent *) { - if(timerId==0 && (EffDur!=0 || imgs.size()>1)) { - timerId = startTimer(picDur, Qt::PreciseTimer); - startMove(); - } - QPainter painter(this); - painter.setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform); - painter.drawPixmap(imgx, imgy, imgs[imgc]); -} - -void EleMultiPng::timerEvent(QTimerEvent *e) { - if(isVisible()) { - int id = e->timerId(); - if(id==timerId){ - if(imgc+2 > imgs.size()) imgc = 0; - else imgc++; - startMove(); - } else if(id==moveTimerId){ - if(effType=='l') { - imgx -= movePx; - if(imgx < 0) imgx = 0; - } else if(effType=='t') { - imgy -= movePx; - if(imgy < 0) imgy = 0; - } else if(effType=='r') { - imgx += movePx; - if(imgx > 0) imgx = 0; - } else if(effType=='b') { - imgy += movePx; - if(imgy > 0) imgy = 0; - } - if(imgx==0 && imgy==0) { - killTimer(moveTimerId); - moveTimerId = 0; - } - } - update(); - } else { - if(timerId!=0) { - killTimer(timerId); - timerId = 0; - } - if(moveTimerId!=0) { - killTimer(moveTimerId); - moveTimerId = 0; - } - } -} +#include "elemultipng.h" +#include +#include +#include +#include +const QChar effTypes[] = {'l', 't', 'r', 'b'}; + +EleMultiPng::EleMultiPng(QString dirPre, QJsonArray maps, QWidget *parent) : QWidget{parent} { + QJsonObject map = maps[0].toObject(); + picDur = map["picDuration"].toInt()*1000; + if(picDur==0) return; + EffDur = map["effectSpeed"].toInt()*1000; + foreach(auto map, maps) imgs.append(QPixmap(dirPre+map["id"].toString())); + QString effStr = map["effect"].toString(); + if(effStr.isEmpty() || effStr=="no") EffDur = 0; + else if(effStr.endsWith("left")) effType = 'l'; + else if(effStr.endsWith("top")) effType = 't'; + else if(effStr.endsWith("right")) effType = 'r'; + else if(effStr.endsWith("bottom")) effType = 'b'; + else if(effStr == "random") needRand = true; + else EffDur = 0; +} + +void EleMultiPng::startMove() { + if(EffDur==0) return; + if(needRand) effType = effTypes[rand.generate() % 4]; + double effDurD = EffDur; + if(effType=='l') { + imgx = width(); + imgy = 0; + effDurD /= width(); + } else if(effType=='r') { + imgx = -width(); + imgy = 0; + effDurD /= width(); + } else if(effType=='t') { + imgx = 0; + imgy = height(); + effDurD /= height(); + } else if(effType=='b') { + imgx = 0; + imgy = -height(); + effDurD /= height(); + } else return; + movePx = ceil(17/effDurD); + moveInter = effDurD*movePx; + moveTimerId = startTimer(moveInter, Qt::PreciseTimer); +} + +void EleMultiPng::paintEvent(QPaintEvent *) { + if(timerId==0 && (EffDur!=0 || imgs.size()>1)) { + timerId = startTimer(picDur, Qt::PreciseTimer); + startMove(); + } + QPainter painter(this); + painter.setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform); + painter.drawPixmap(imgx, imgy, imgs[imgc]); +} + +void EleMultiPng::timerEvent(QTimerEvent *e) { + if(isVisible()) { + int id = e->timerId(); + if(id==timerId){ + if(imgc+2 > imgs.size()) imgc = 0; + else imgc++; + startMove(); + } else if(id==moveTimerId){ + if(effType=='l') { + imgx -= movePx; + if(imgx < 0) imgx = 0; + } else if(effType=='t') { + imgy -= movePx; + if(imgy < 0) imgy = 0; + } else if(effType=='r') { + imgx += movePx; + if(imgx > 0) imgx = 0; + } else if(effType=='b') { + imgy += movePx; + if(imgy > 0) imgy = 0; + } + if(imgx==0 && imgy==0) { + killTimer(moveTimerId); + moveTimerId = 0; + } + } + update(); + foreach(auto split, splits) split->update(); + } else { + if(timerId!=0) { + killTimer(timerId); + timerId = 0; + } + if(moveTimerId!=0) { + killTimer(moveTimerId); + moveTimerId = 0; + } + } +} + +void EleSplitPng::paintEvent(QPaintEvent *) { + QPainter painter(this); + painter.setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform); + painter.drawPixmap(multiPng->imgx, multiPng->imgy, multiPng->imgs[multiPng->imgc]); +} diff --git a/LedOK/player/elemultipng.h b/LedOK/player/elemultipng.h index c658d71..2191b3e 100644 --- a/LedOK/player/elemultipng.h +++ b/LedOK/player/elemultipng.h @@ -1,24 +1,37 @@ -#ifndef ELEMULTIPNG_H -#define ELEMULTIPNG_H - -#include -#include - -class EleMultiPng : public QWidget { - Q_OBJECT -public: - explicit EleMultiPng(QString, QJsonArray, QWidget *parent = nullptr); - void startMove(); - - QVector imgs; - int timerId = 0, moveTimerId = 0; - int picDur = 0, EffDur = 0, moveInter = 0, movePx = 0, imgc = 0, imgx = 0, imgy = 0; - QChar effType = 0; - QRandomGenerator rand; - bool needRand = false; -protected: - void paintEvent(QPaintEvent *) override; - void timerEvent(QTimerEvent *) override; -}; - -#endif // ELEMULTIPNG_H +#ifndef ELEMULTIPNG_H +#define ELEMULTIPNG_H + +#include +#include +class EleSplitPng; +class EleMultiPng : public QWidget { + Q_OBJECT +public: + explicit EleMultiPng(QString, QJsonArray, QWidget *parent = nullptr); + void startMove(); + + QVector imgs; + int timerId = 0, moveTimerId = 0; + int picDur = 0, EffDur = 0, moveInter = 0, movePx = 0, imgc = 0, imgx = 0, imgy = 0; + QChar effType = 0; + QRandomGenerator rand; + bool needRand = false; + QList splits; + +protected: + void paintEvent(QPaintEvent *) override; + void timerEvent(QTimerEvent *) override; +}; + +class EleSplitPng : public QWidget { + Q_OBJECT +public: + explicit EleSplitPng(EleMultiPng *multiPng, QWidget *parent) : QWidget{parent}, multiPng(multiPng) {} + +protected: + void paintEvent(QPaintEvent *) override; + + EleMultiPng *multiPng; +}; + +#endif // ELEMULTIPNG_H diff --git a/LedOK/player/elescroll.cpp b/LedOK/player/elescroll.cpp index f29e3e4..b827bfb 100644 --- a/LedOK/player/elescroll.cpp +++ b/LedOK/player/elescroll.cpp @@ -1,72 +1,80 @@ -#include "elescroll.h" -#include -#include -#include - -EleScroll::EleScroll(QWidget *parent, QString dirPre, QJsonObject map) : QWidget{parent} { - img.load(dirPre + map["id"].toString()); - QString effStr = map["effect"].toString(); - if(effStr.isNull() || effStr=="no") return; - double effDurD = map["effectSpeed"].toInt()/2; - if(effDurD==0) return; - int idx = effStr.lastIndexOf(' '); - if(idx > -1) { - effect = effStr.at(idx+1).toLatin1(); - if(effect=='l') end = -(img.width()-1); - else if(effect=='r') end = img.width()-1; - else if(effect=='t') end = -(img.height()-1); - else if(effect=='b') end = img.height()-1; - } - interval = ceil(effDurD/16.666666)*16.666666; - curAdd = ceil(interval/effDurD); -} -EleScroll::EleScroll(QWidget *parent, QString imgPath, char effect, double effDur) : QWidget{parent}, effect(effect) { - img.load(imgPath); - if(effect==0) return; - if(effDur==0) return; - if(effect=='l') end = -(img.width()-1); - else if(effect=='r') end = img.width()-1; - else if(effect=='t') end = -(img.height()-1); - else if(effect=='b') end = img.height()-1; - interval = ceil(effDur/16.666666)*16.666666; - curAdd = ceil(interval/effDur); -} - -void EleScroll::paintEvent(QPaintEvent *) { - if(img.isNull()) return; - if(timerId==0 && effect!=0 && interval!=0) { - cur = 0; - timerId = startTimer(interval, Qt::PreciseTimer); - } - QPainter painter(this); - painter.setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform); - if(effect=='l') { - painter.drawPixmap(cur, 0, img); - painter.drawPixmap(cur+img.width(), 0, img); - } else if(effect=='r') { - painter.drawPixmap(cur, 0, img); - painter.drawPixmap(cur-img.width(), 0, img); - } else if(effect=='t') { - painter.drawPixmap(0, cur, img); - painter.drawPixmap(0, cur+img.height(), img); - } else if(effect=='b') { - painter.drawPixmap(0, cur, img); - painter.drawPixmap(0, cur-img.height(), img); - } else painter.drawPixmap(0, 0, img); -} - -void EleScroll::timerEvent(QTimerEvent *) { - if(isVisible()) { - if(effect=='t' || effect=='l') { - if(cur <= end) cur = 0; - else cur-=curAdd; - } else if(effect=='b' || effect=='r') { - if(cur >= end) cur = 0; - else cur+=curAdd; - } - update(); - } else if(timerId!=0) { - killTimer(timerId); - timerId = 0; - } -} +#include "elescroll.h" +#include +#include +#include + +EleScroll::EleScroll(QWidget *parent, QString dirPre, QJsonObject map) : QWidget{parent} { + img.load(dirPre + map["id"].toString()); + QString effStr = map["effect"].toString(); + if(effStr.isNull() || effStr=="no") return; + double effDurD = map["effectSpeed"].toInt()/2; + if(effDurD==0) return; + int idx = effStr.lastIndexOf(' '); + if(idx > -1) { + effect = effStr.at(idx+1).toLatin1(); + if(effect=='l') end = -(img.width()-1); + else if(effect=='r') end = img.width()-1; + else if(effect=='t') end = -(img.height()-1); + else if(effect=='b') end = img.height()-1; + } + interval = ceil(effDurD/16.666666)*16.666666; + curAdd = ceil(interval/effDurD); +} +EleScroll::EleScroll(QWidget *parent, QString imgPath, char effect, double effDur) : QWidget{parent}, effect(effect) { + img.load(imgPath); + if(effect==0) return; + if(effDur==0) return; + if(effect=='l') end = -(img.width()-1); + else if(effect=='r') end = img.width()-1; + else if(effect=='t') end = -(img.height()-1); + else if(effect=='b') end = img.height()-1; + interval = ceil(effDur/16.666666)*16.666666; + curAdd = ceil(interval/effDur); +} + +void EleScroll::paintEvent(QPaintEvent *) { + paint(this); +} +void EleScroll::paint(QPaintDevice *that) { + if(img.isNull()) return; + if(timerId==0 && effect!=0 && interval!=0) { + cur = 0; + timerId = startTimer(interval, Qt::PreciseTimer); + } + QPainter painter(that); + painter.setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform); + if(effect=='l') { + painter.drawPixmap(cur, 0, img); + painter.drawPixmap(cur+img.width(), 0, img); + } else if(effect=='r') { + painter.drawPixmap(cur, 0, img); + painter.drawPixmap(cur-img.width(), 0, img); + } else if(effect=='t') { + painter.drawPixmap(0, cur, img); + painter.drawPixmap(0, cur+img.height(), img); + } else if(effect=='b') { + painter.drawPixmap(0, cur, img); + painter.drawPixmap(0, cur-img.height(), img); + } else painter.drawPixmap(0, 0, img); +} + +void EleScroll::timerEvent(QTimerEvent *) { + if(isVisible()) { + if(effect=='t' || effect=='l') { + if(cur <= end) cur = 0; + else cur-=curAdd; + } else if(effect=='b' || effect=='r') { + if(cur >= end) cur = 0; + else cur+=curAdd; + } + update(); + foreach(auto split, splits) split->update(); + } else if(timerId!=0) { + killTimer(timerId); + timerId = 0; + } +} + +void EleSplitScroll::paintEvent(QPaintEvent *) { + scroll->paint(this); +} diff --git a/LedOK/player/elescroll.h b/LedOK/player/elescroll.h index 2941d32..b1be9bf 100644 --- a/LedOK/player/elescroll.h +++ b/LedOK/player/elescroll.h @@ -1,20 +1,31 @@ -#ifndef ELESCROLL_H -#define ELESCROLL_H - -#include - -class EleScroll : public QWidget { - Q_OBJECT -public: - explicit EleScroll(QWidget *, QString, QJsonObject); - explicit EleScroll(QWidget *, QString, char effect = 0, double effDur = 0.0); - QPixmap img; - char effect = 0; - int interval = 0, timerId = 0, cur = 0, end = 0, curAdd = 1; - -protected: - void paintEvent(QPaintEvent *) override; - void timerEvent(QTimerEvent *) override; -}; - -#endif // ELESCROLL_H +#ifndef ELESCROLL_H +#define ELESCROLL_H + +#include +class EleSplitScroll; +class EleScroll : public QWidget { + Q_OBJECT +public: + explicit EleScroll(QWidget *, QString, QJsonObject); + explicit EleScroll(QWidget *, QString, char effect = 0, double effDur = 0.0); + QPixmap img; + char effect = 0; + int interval = 0, timerId = 0, cur = 0, end = 0, curAdd = 1; + QList splits; + void paint(QPaintDevice *); +protected: + void paintEvent(QPaintEvent *) override; + void timerEvent(QTimerEvent *) override; +}; + +class EleSplitScroll : public QWidget { + Q_OBJECT +public: + explicit EleSplitScroll(QWidget *parent, EleScroll *scroll) : QWidget{parent}, scroll(scroll) {}; + +protected: + void paintEvent(QPaintEvent *) override; + + EleScroll *scroll; +}; +#endif // ELESCROLL_H diff --git a/LedOK/player/eletimer.cpp b/LedOK/player/eletimer.cpp index f878ee2..056e0f0 100644 --- a/LedOK/player/eletimer.cpp +++ b/LedOK/player/eletimer.cpp @@ -1,65 +1,65 @@ -#include "eletimer.h" -#include "tools.h" -#include "globaldefine.h" -#include -#include - -EleTimer::EleTimer(const QJsonObject &json, QWidget *parent) : QWidget{parent} { - isDown = json["isDown"].toBool(); - targetTime = QDateTime::fromString(json["targetTime"].toString(), "yyyy-MM-dd HH:mm:ss"); - hasDay = json["hasDay"].toBool(); - hasHour = json["hasHour"].toBool(); - hasMin = json["hasMin"].toBool(); - hasSec = json["hasSec"].toBool(); - text = json["text"].toString(); - isMultiline = json["isMultiline"].toBool(); - font = json["font"].toString(); - fontSize = json["fontSize"].toInt(); - fontBold = json["fontBold"].toBool(); - fontItalic = json["fontItalic"].toBool(); - fontUnderline = json["fontUnderline"].toBool(); - textColor = json["textColor"].toString(); - auto color = json["backColor"].toString(); - backColor = color.isEmpty() ? QColor(0,0,0,0) : color; - connect(Tools::getInstance(), &Tools::sTick, this, [this]() { - QDateTime cDateTime = QDateTime::currentDateTime(); - qint64 ofs = isDown ? cDateTime.secsTo(targetTime) : targetTime.secsTo(cDateTime); - if(ofs < 0) ofs = 0; - secs = ofs; - update(); - }); -} - -void EleTimer::paintEvent(QPaintEvent *){ - QString text; - if(! this->text.isEmpty()) { - text += this->text; - if(isMultiline) text += '\n'; - else text += " "; - } - int secs = this->secs; - if(hasDay) { - text.append(QString::number(secs/86400)).append(" ").append(tr("day")).append(" "); - secs %= 86400; - } - if(hasHour) { - text.append(QString::asprintf("%02d ", secs/3600)).append(tr("hour")).append(" "); - secs %= 3600; - } - if(hasMin) { - text.append(QString::asprintf("%02d ", secs/60)).append(tr("min")).append(" "); - secs %= 60; - } - if(hasSec) text.append(QString::asprintf("%02d ", secs)).append(tr("sec")).append(" "); - text = text.trimmed(); - QFont font(this->font, fontSize); - font.setBold(fontBold); - font.setItalic(fontItalic); - font.setUnderline(fontUnderline); - font.setStyleStrategy(gTextAntialiasing ? QFont::PreferAntialias : QFont::NoAntialias); - QPainter painter(this); - if(backColor.alpha() != 0) painter.fillRect(rect(), backColor); - painter.setFont(font); - painter.setPen(textColor); - painter.drawText(rect(), text, QTextOption(Qt::AlignCenter)); -} +#include "eletimer.h" +#include "tools.h" +#include "globaldefine.h" +#include +#include + +EleTimer::EleTimer(const QJsonObject &json, QWidget *parent) : QWidget{parent} { + isDown = json["isDown"].toBool(); + targetTime = QDateTime::fromString(json["targetTime"].toString(), "yyyy-MM-dd HH:mm:ss"); + hasDay = json["hasDay"].toBool(); + hasHour = json["hasHour"].toBool(); + hasMin = json["hasMin"].toBool(); + hasSec = json["hasSec"].toBool(); + text = json["text"].toString(); + isMultiline = json["isMultiline"].toBool(); + font = json["font"].toString(); + fontSize = json["fontSize"].toInt(); + fontBold = json["fontBold"].toBool(); + fontItalic = json["fontItalic"].toBool(); + fontUnderline = json["fontUnderline"].toBool(); + textColor = json["textColor"].toString(); + auto color = json["backColor"].toString(); + backColor = color.isEmpty() ? QColor(0,0,0,0) : color; + connect(Tools::getInstance(), &Tools::sTick, this, [this]() { + QDateTime cDateTime = QDateTime::currentDateTime(); + qint64 ofs = isDown ? cDateTime.secsTo(targetTime) : targetTime.secsTo(cDateTime); + if(ofs < 0) ofs = 0; + secs = ofs; + update(); + }); +} + +void EleTimer::paintEvent(QPaintEvent *){ + QString text; + if(! this->text.isEmpty()) { + text += this->text; + if(isMultiline) text += '\n'; + else text += " "; + } + int secs = this->secs; + if(hasDay) { + text.append(QString::number(secs/86400)).append(" ").append(tr("day")).append(" "); + secs %= 86400; + } + if(hasHour) { + text.append(QString::asprintf("%02d ", secs/3600)).append(tr("hour")).append(" "); + secs %= 3600; + } + if(hasMin) { + text.append(QString::asprintf("%02d ", secs/60)).append(tr("min")).append(" "); + secs %= 60; + } + if(hasSec) text.append(QString::asprintf("%02d ", secs)).append(tr("sec")).append(" "); + text = text.trimmed(); + QFont font(this->font, fontSize); + font.setBold(fontBold); + font.setItalic(fontItalic); + font.setUnderline(fontUnderline); + font.setStyleStrategy(gTextAntialiasing ? QFont::PreferAntialias : QFont::NoAntialias); + QPainter painter(this); + if(backColor.alpha() != 0) painter.fillRect(rect(), backColor); + painter.setFont(font); + painter.setPen(textColor); + painter.drawText(rect(), text, QTextOption(Qt::AlignCenter)); +} diff --git a/LedOK/player/eletimer.h b/LedOK/player/eletimer.h index 22ca696..ae9b3d1 100644 --- a/LedOK/player/eletimer.h +++ b/LedOK/player/eletimer.h @@ -1,31 +1,31 @@ -#ifndef ELETIMER_H -#define ELETIMER_H - -#include -#include - -class EleTimer : public QWidget { - Q_OBJECT -public: - explicit EleTimer(const QJsonObject&, QWidget *parent = nullptr); - QDateTime targetTime; - QString text; - QColor textColor; - QColor backColor; - QString font; - int fontSize; - bool fontBold; - bool fontItalic; - bool fontUnderline; - bool isDown; - bool isMultiline; - bool hasDay; - bool hasHour; - bool hasMin; - bool hasSec; - int secs = 0; -protected: - void paintEvent(QPaintEvent *) override; -}; - -#endif // ELETIMER_H +#ifndef ELETIMER_H +#define ELETIMER_H + +#include +#include + +class EleTimer : public QWidget { + Q_OBJECT +public: + explicit EleTimer(const QJsonObject&, QWidget *parent = nullptr); + QDateTime targetTime; + QString text; + QColor textColor; + QColor backColor; + QString font; + int fontSize; + bool fontBold; + bool fontItalic; + bool fontUnderline; + bool isDown; + bool isMultiline; + bool hasDay; + bool hasHour; + bool hasMin; + bool hasSec; + int secs = 0; +protected: + void paintEvent(QPaintEvent *) override; +}; + +#endif // ELETIMER_H diff --git a/LedOK/player/elevideo - qt.cpp b/LedOK/player/elevideo - qt.cpp index 4122b20..1aa05da 100644 --- a/LedOK/player/elevideo - qt.cpp +++ b/LedOK/player/elevideo - qt.cpp @@ -1,38 +1,38 @@ -#include "elevideo.h" -#include "tools.h" -#include -#include -#include -#include -#include -#include -#include - -EleVideo::EleVideo(QString path, int w, int h, QWidget *parent) : QGraphicsView{parent} { - setFrameStyle(QFrame::NoFrame); - setScene(new QGraphicsScene(this)); - setBackgroundBrush(QColor(0,0,0)); - auto videoItem = new QGraphicsVideoItem(); - videoItem->setSize(QSize(w,h)); - videoItem->setAspectRatioMode(Qt::IgnoreAspectRatio); - scene()->addItem(videoItem); - player = new QMediaPlayer(videoItem); - player->setVideoOutput(videoItem); - connect(player, &QMediaPlayer::mediaStatusChanged, this, [this](QMediaPlayer::MediaStatus status){ - if(status==QMediaPlayer::EndOfMedia) { - if(player->state() != QMediaPlayer::PlayingState && isVisible()) player->play(); - } - }); - void(QMediaPlayer::*player_error)(QMediaPlayer::Error) = &QMediaPlayer::error; - connect(player, player_error, this, [this](QMediaPlayer::Error error){ - QMessageBox::critical(this, "Video Error", Tools::playerErrStr(error)+": "+player->errorString()); - }); - player->setMedia(QUrl::fromLocalFile(path)); -} - -void EleVideo::showEvent(QShowEvent *) { - if(player!=nullptr && player->state() != QMediaPlayer::PlayingState) player->play(); -} -void EleVideo::hideEvent(QHideEvent *) { - if(player!=nullptr) player->stop(); -} +#include "elevideo.h" +#include "tools.h" +#include +#include +#include +#include +#include +#include +#include + +EleVideo::EleVideo(QString path, int w, int h, QWidget *parent) : QGraphicsView{parent} { + setFrameStyle(QFrame::NoFrame); + setScene(new QGraphicsScene(this)); + setBackgroundBrush(QColor(0,0,0)); + auto videoItem = new QGraphicsVideoItem(); + videoItem->setSize(QSize(w,h)); + videoItem->setAspectRatioMode(Qt::IgnoreAspectRatio); + scene()->addItem(videoItem); + player = new QMediaPlayer(videoItem); + player->setVideoOutput(videoItem); + connect(player, &QMediaPlayer::mediaStatusChanged, this, [this](QMediaPlayer::MediaStatus status){ + if(status==QMediaPlayer::EndOfMedia) { + if(player->state() != QMediaPlayer::PlayingState && isVisible()) player->play(); + } + }); + void(QMediaPlayer::*player_error)(QMediaPlayer::Error) = &QMediaPlayer::error; + connect(player, player_error, this, [this](QMediaPlayer::Error error){ + QMessageBox::critical(this, "Video Error", Tools::playerErrStr(error)+": "+player->errorString()); + }); + player->setMedia(QUrl::fromLocalFile(path)); +} + +void EleVideo::showEvent(QShowEvent *) { + if(player!=nullptr && player->state() != QMediaPlayer::PlayingState) player->play(); +} +void EleVideo::hideEvent(QHideEvent *) { + if(player!=nullptr) player->stop(); +} diff --git a/LedOK/player/elevideo - qt.h b/LedOK/player/elevideo - qt.h index 3eff40a..af73591 100644 --- a/LedOK/player/elevideo - qt.h +++ b/LedOK/player/elevideo - qt.h @@ -1,16 +1,16 @@ -#ifndef ELEVIDEO_H -#define ELEVIDEO_H -#include -#include - -class EleVideo : public QGraphicsView { - Q_OBJECT -public: - explicit EleVideo(QString path, int, int, QWidget *parent = nullptr); - QMediaPlayer *player = nullptr; -protected: - void showEvent(QShowEvent *event) override; - void hideEvent(QHideEvent *event) override; -}; - -#endif // ELEVIDEO_H +#ifndef ELEVIDEO_H +#define ELEVIDEO_H +#include +#include + +class EleVideo : public QGraphicsView { + Q_OBJECT +public: + explicit EleVideo(QString path, int, int, QWidget *parent = nullptr); + QMediaPlayer *player = nullptr; +protected: + void showEvent(QShowEvent *event) override; + void hideEvent(QHideEvent *event) override; +}; + +#endif // ELEVIDEO_H diff --git a/LedOK/player/elevideo - vlc.cpp b/LedOK/player/elevideo - vlc.cpp index f7d7462..c5aa60a 100644 --- a/LedOK/player/elevideo - vlc.cpp +++ b/LedOK/player/elevideo - vlc.cpp @@ -1,61 +1,61 @@ -#include "elevideo.h" -#include "tools.h" -#include -#include -#include - -static void *lock(void *opaque, void **planes) { - auto that = (EleVideo *) opaque; - that->imgRaw = QImage(that->mWidth, that->mHeight, QImage::Format_RGB32); - *planes = that->imgRaw.bits(); /*tell VLC to put decoded data to this buffer*/ - return 0; /* picture identifier, not needed here */ -} -static void unlock(void *opaque, void *picture, void *const *planes) { -} - -static void display(void *opaque, void *picture) { - auto that = (EleVideo *) opaque; - that->emDisplay(that->imgRaw); -} - -EleVideo::EleVideo(QString path, QWidget *parent) : QWidget{parent} { - vlc = libvlc_new(0, NULL); - auto pathChars = path.replace("/","\\").toUtf8(); - auto media = libvlc_media_new_path(vlc, pathChars.data()); - qDebug()<<"media"<img; -// qDebug()<<"viCurTime"<viCurTime; -// qDebug()<<"viSize"<viSize; -//} -void EleVideo::showEvent(QShowEvent *) { - if(player!=nullptr) libvlc_media_player_play(player); -} -void EleVideo::hideEvent(QHideEvent *) { - if(player!=nullptr) libvlc_media_player_stop(player); -} - -void EleVideo::paintEvent(QPaintEvent *e) { - QWidget::paintEvent(e); - QPainter painter(this); - painter.drawImage(QRectF(0, 0, width(), height()), img); -} +#include "elevideo.h" +#include "tools.h" +#include +#include +#include + +static void *lock(void *opaque, void **planes) { + auto that = (EleVideo *) opaque; + that->imgRaw = QImage(that->mWidth, that->mHeight, QImage::Format_RGB32); + *planes = that->imgRaw.bits(); /*tell VLC to put decoded data to this buffer*/ + return 0; /* picture identifier, not needed here */ +} +static void unlock(void *opaque, void *picture, void *const *planes) { +} + +static void display(void *opaque, void *picture) { + auto that = (EleVideo *) opaque; + that->emDisplay(that->imgRaw); +} + +EleVideo::EleVideo(QString path, QWidget *parent) : QWidget{parent} { + vlc = libvlc_new(0, NULL); + auto pathChars = path.replace("/","\\").toUtf8(); + auto media = libvlc_media_new_path(vlc, pathChars.data()); + qDebug()<<"media"<img; +// qDebug()<<"viCurTime"<viCurTime; +// qDebug()<<"viSize"<viSize; +//} +void EleVideo::showEvent(QShowEvent *) { + if(player!=nullptr) libvlc_media_player_play(player); +} +void EleVideo::hideEvent(QHideEvent *) { + if(player!=nullptr) libvlc_media_player_stop(player); +} + +void EleVideo::paintEvent(QPaintEvent *e) { + QWidget::paintEvent(e); + QPainter painter(this); + painter.drawImage(QRectF(0, 0, width(), height()), img); +} diff --git a/LedOK/player/elevideo - vlc.h b/LedOK/player/elevideo - vlc.h index d40ab40..5447e0b 100644 --- a/LedOK/player/elevideo - vlc.h +++ b/LedOK/player/elevideo - vlc.h @@ -1,29 +1,29 @@ -#ifndef ELEVIDEO_H -#define ELEVIDEO_H - -#include -#include - -class EleVideo : public QWidget { - Q_OBJECT -public: - explicit EleVideo(QString path, QWidget *parent = nullptr); - ~EleVideo() { - if(vlc) libvlc_release(vlc); - if(player) libvlc_media_player_release(player); - } - - unsigned mWidth{0}, mHeight{0}; - QImage imgRaw; - QImage img; - libvlc_instance_t *vlc{0}; - libvlc_media_player_t *player{0}; -protected: - void paintEvent(QPaintEvent *) override; - void showEvent(QShowEvent *) override; - void hideEvent(QHideEvent *) override; -signals: - void emDisplay(QImage img); -}; - -#endif // ELEVIDEO_H +#ifndef ELEVIDEO_H +#define ELEVIDEO_H + +#include +#include + +class EleVideo : public QWidget { + Q_OBJECT +public: + explicit EleVideo(QString path, QWidget *parent = nullptr); + ~EleVideo() { + if(vlc) libvlc_release(vlc); + if(player) libvlc_media_player_release(player); + } + + unsigned mWidth{0}, mHeight{0}; + QImage imgRaw; + QImage img; + libvlc_instance_t *vlc{0}; + libvlc_media_player_t *player{0}; +protected: + void paintEvent(QPaintEvent *) override; + void showEvent(QShowEvent *) override; + void hideEvent(QHideEvent *) override; +signals: + void emDisplay(QImage img); +}; + +#endif // ELEVIDEO_H diff --git a/LedOK/player/elevideo.cpp b/LedOK/player/elevideo.cpp index 9a072a8..b77272c 100644 --- a/LedOK/player/elevideo.cpp +++ b/LedOK/player/elevideo.cpp @@ -1,45 +1,45 @@ -#include "elevideo.h" -#include "tools.h" -#include -#include -#include - -class GL : public QOpenGLWidget { -public: - explicit GL(QWidget *parent) : QOpenGLWidget{parent} { - setGeometry(-1,-1,1,1); - connect(this, &QOpenGLWidget::frameSwapped, this, (void(QOpenGLWidget::*)())&QOpenGLWidget::update, Qt::QueuedConnection); - } -}; - -EleVideo::EleVideo(QString path, QWidget *parent) : QWidget{parent} { - player = new FFPlayer(); - connect(new GL(this), &QOpenGLWidget::frameSwapped, player, &FFPlayer::updFrame, Qt::QueuedConnection); - connect(player, &FFPlayer::emUpd, this, [this](QImage img) { - this->img = img; - update(); - }); - connect(player, &FFPlayer::emError, this, [this](QString err) { - QMessageBox::critical(this, "Video Error", err); - }); - player->open(path.toUtf8()); -} - -//void EleVideo::mouseDoubleClickEvent(QMouseEvent *) { -// qDebug()<<"img"<img; -// qDebug()<<"viCurTime"<viCurTime; -// qDebug()<<"viSize"<viSize; -//} -void EleVideo::showEvent(QShowEvent *) { - if(player!=nullptr) player->play(); -} -void EleVideo::hideEvent(QHideEvent *) { - if(player!=nullptr) player->stop(); -} - -void EleVideo::paintEvent(QPaintEvent *e) { - QWidget::paintEvent(e); - QPainter painter(this); - painter.drawImage(QRectF(0, 0, width(), height()), img); -} +#include "elevideo.h" +#include "tools.h" +#include +#include +#include + +class GL : public QOpenGLWidget { +public: + explicit GL(QWidget *parent) : QOpenGLWidget{parent} { + setGeometry(-1,-1,1,1); + connect(this, &QOpenGLWidget::frameSwapped, this, (void(QOpenGLWidget::*)())&QOpenGLWidget::update, Qt::QueuedConnection); + } +}; + +EleVideo::EleVideo(QString path, QWidget *parent) : QWidget{parent} { + player = new FFPlayer(); + connect(new GL(this), &QOpenGLWidget::frameSwapped, player, &FFPlayer::updFrame, Qt::QueuedConnection); + connect(player, &FFPlayer::emUpd, this, [this](QImage img) { + this->img = img; + update(); + }); + connect(player, &FFPlayer::emError, this, [this](QString err) { + QMessageBox::critical(this, "Video Error", err); + }); + player->open(path.toUtf8()); +} + +//void EleVideo::mouseDoubleClickEvent(QMouseEvent *) { +// qDebug()<<"img"<img; +// qDebug()<<"viCurTime"<viCurTime; +// qDebug()<<"viSize"<viSize; +//} +void EleVideo::showEvent(QShowEvent *) { + if(player) player->play(); +} +void EleVideo::hideEvent(QHideEvent *) { + if(player) player->stop(); +} + +void EleVideo::paintEvent(QPaintEvent *e) { + QWidget::paintEvent(e); + QPainter painter(this); + painter.drawImage(QRectF(0, 0, width(), height()), img); +} diff --git a/LedOK/player/elevideo.h b/LedOK/player/elevideo.h index 23fad59..638033d 100644 --- a/LedOK/player/elevideo.h +++ b/LedOK/player/elevideo.h @@ -1,20 +1,20 @@ -#ifndef ELEVIDEO_H -#define ELEVIDEO_H - -#include "ffplayer.h" -#include - -class EleVideo : public QWidget { - Q_OBJECT -public: - explicit EleVideo(QString path, QWidget *parent = nullptr); - ~EleVideo() {if(player!=0) player->quit(); } - FFPlayer *player = nullptr; - QImage img; -protected: - void paintEvent(QPaintEvent *) override; - void showEvent(QShowEvent *) override; - void hideEvent(QHideEvent *) override; -}; - -#endif // ELEVIDEO_H +#ifndef ELEVIDEO_H +#define ELEVIDEO_H + +#include "ffplayer.h" +#include + +class EleVideo : public QWidget { + Q_OBJECT +public: + explicit EleVideo(QString path, QWidget *parent = nullptr); + ~EleVideo() {if(player!=0) player->quit(); } + FFPlayer *player = nullptr; + QImage img; +protected: + void paintEvent(QPaintEvent *) override; + void showEvent(QShowEvent *) override; + void hideEvent(QHideEvent *) override; +}; + +#endif // ELEVIDEO_H diff --git a/LedOK/player/playwin.cpp b/LedOK/player/playwin.cpp index 4d6f77a..dfea6eb 100644 --- a/LedOK/player/playwin.cpp +++ b/LedOK/player/playwin.cpp @@ -1,228 +1,259 @@ -#include "playwin.h" -#include "digiclock.h" -#include "eleanaclock.h" -#include "eleborder.h" -#include "elegif.h" -#include "eleimg.h" -#include "elemultipng.h" -#include "elescroll.h" -#include "eletimer.h" -#include "elevideo.h" -#include "gqt.h" -#include "posdlg.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -PlayWin* PlayWin::self = nullptr; -QPoint gPlayPos{0, 0}; - -Page::Page(QWidget *parent) : QWidget{parent} { - -} - -PlayWin *PlayWin::newIns(int width, int height, QString dir, const QJsonObject &aprog, QWidget *parent) { - if(! gPlayPos.isNull() && QGuiApplication::screenAt(QPoint(gPlayPos.x()+width/2, gPlayPos.y()+height/2))==0) gPlayPos = QPoint(); - return new PlayWin(gPlayPos.x(), gPlayPos.y(), width, height, dir, aprog, parent); -} - -PlayWin::PlayWin(int x, int y, int width, int height, QString dir, const QJsonObject &aprog, QWidget *parent) : QWidget(parent) { - setAttribute(Qt::WA_DeleteOnClose); - setAttribute(Qt::WA_QuitOnClose, false); - setWindowFlag(Qt::FramelessWindowHint); - setWindowFlag(Qt::WindowStaysOnTopHint); - setGeometry(x, y, width, height); - QPalette plt = palette(); - plt.setColor(QPalette::Window, QColor(0,0,0)); - setPalette(plt); - connect(this, &PlayWin::sigSetVisible, this, &PlayWin::sltSetVisible); - - QJsonObject prog = aprog["task"].toObject(); - QJsonArray pageMaps = prog["items"].toArray(); - int pageCnt = pageMaps.size(); - EleBase ele; Page *page; - for(int p=0; psetGeometry(0, 0, width, height); - page->setVisible(false); - for(int ll=layers.size()-1; ll>=0; ll--) { - QJsonObject layer = layers[ll].toObject(); - QJsonArray srcMaps = layer["sources"].toArray(); - QJsonValue border = layer["border"]; - EleBorder *bdEle = nullptr; - int bdWidth = 0, startTime = 0xffff, endTime = 0; - if(! border.isNull()) { - bdEle = new EleBorder(dir+"/"+border["img"].toString(), border["eff"].toString(), border["speed"].toInt(), page); - bdWidth = bdEle->img.height(); - } - foreach(auto srcMap, srcMaps) { - ele.type = srcMap["_type"].toString(); - if(ele.type.isEmpty()) continue; - ele.timeSpan = srcMap["timeSpan"].toInt()*1000; - if(ele.timeSpan==0) continue; - ele.x = srcMap["left"].toInt()+bdWidth; - ele.y = srcMap["top"].toInt()+bdWidth; - ele.w = srcMap["width"].toInt()-bdWidth-bdWidth; - ele.h = srcMap["height"].toInt()-bdWidth-bdWidth; - bool notAudio = ele.type!="Audio"; - if((ele.w<=0 || ele.h<=0) && notAudio) continue; - ele.startTime = srcMap["playTime"].toInt()*1000; - if(startTime > ele.startTime) startTime = ele.startTime; - ele.endTime = ele.startTime + ele.timeSpan; - if(endTime < ele.endTime) endTime = ele.endTime; - if(ele.endTime > page->timeSpan && notAudio) page->timeSpan = ele.endTime; - ele.id = srcMap["id"].toString(); - ele.wgt = nullptr; - if(ele.type=="Image") { - if(srcMap["mime"].toString().endsWith("gif")) ele.wgt = new EleGif(dir+"/"+ele.id, page); - else ele.wgt = new EleImg(dir+"/"+ele.id, page); - } else if(ele.type.startsWith("Environ")) { - QJsonValue arrayPics = srcMap["arrayPics"]; - for(int i=arrayPics.toArray().size()-1; i>=0; i--) if(arrayPics[i]["name"].toString() == "previewTmp") { - if(srcMap["bSingleScroll"].toBool()) ele.wgt = new EleScroll(page, dir+"/" + arrayPics[i]["id"].toString(), 'l', srcMap["iScrollSpeed"].toDouble()); - else ele.wgt = new EleScroll(page, dir+"/"+arrayPics[i]["id"].toString()); - break; - } - } else if(ele.type=="MultiPng") { - QJsonArray imgs = srcMap["arrayPics"].toArray(); - if(imgs.isEmpty()) continue; - if(imgs.size()==1 && imgs.at(0)["picDuration"].toInt()==0) ele.wgt = new EleScroll(page, dir+"/", imgs[0].toObject()); - else ele.wgt = new EleMultiPng(dir+"/", imgs, page); - } else if(ele.type=="DigitalClockNew") ele.wgt = new DigiClock(dir+"/", srcMap.toObject(), page); - else if(ele.type=="AnalogClock") ele.wgt = new EleAnaClock(dir+"/"+ele.id, srcMap.toObject(), page); - else if(ele.type=="Video" || ele.type=="Audio") { - auto video = new EleVideo(dir+"/"+ele.id, page); - auto vol = srcMap["vol"].toInt(100); - if(vol<100) video->player->setVol(vol/100.0); - ele.wgt = video; - } else if(ele.type=="WebURL") { - auto web = new QWebEngineView(page); - web->load(QUrl(srcMap["url"].toString())); - ele.wgt = web; - } - else if(ele.type=="Timer") ele.wgt = new EleTimer(srcMap.toObject(), page); - else continue; - if(ele.wgt==nullptr) continue; - if(ele.startTime>0) ele.wgt->setVisible(false); - ele.wgt->setGeometry(ele.x, ele.y, ele.w, ele.h); - page->eles.append(ele); - } - if(bdEle!=nullptr && srcMaps.size()>0) { - QJsonArray geometry = border["geometry"].toArray(); - ele.x = geometry[0].toInt(); - ele.y = geometry[1].toInt(); - ele.w = geometry[2].toInt(); - ele.h = geometry[3].toInt(); - ele.startTime = startTime; - ele.endTime = endTime; - ele.timeSpan = endTime - startTime; - ele.wgt = bdEle; - if(ele.startTime>0) ele.wgt->setVisible(false); - ele.wgt->setGeometry(ele.x, ele.y, ele.w, ele.h); - page->eles.append(ele); - } - } - if(page->timeSpan>0) pages.append(page); - } - setVisible(true); - if(! pages.isEmpty()) { - Page* page0 = pages[0]; - EleBase* eleptr; - for(int ee=0; eeeles.size(); ee++) if((eleptr = &page0->eles[ee])->startTime > 0 || eleptr->endTime < page0->timeSpan) { - if(eleptr->startTime > 0) timerMap.insert(startTimer(eleptr->startTime), TimerValue(eleptr->wgt, true)); - timerMap.insert(startTimer(eleptr->endTime), TimerValue(eleptr->wgt, false)); - } - } - - menu = new QMenu(this); - auto act = menu->addAction(tr("Move to Top Left")); - connect(act, &QAction::triggered, this, [this] { - move(0,0); - }); - act = menu->addAction(tr("Set Position")); - connect(act, &QAction::triggered, this, [this] { - PosDlg dlg(this); - dlg.exec(); - }); - act = menu->addAction(tr("Close")); - connect(act, &QAction::triggered, this, [this] { - if(self==this) self = nullptr; - close(); - }); -} -void PlayWin::sltNext() { - if(isVisible()) { - pages[cur]->setVisible(false); - if(cur+2 > pages.size()) cur = 0; - else cur++; - Page* page = pages[cur]; - if(timer!=nullptr) timer->inter = page->timeSpan; - EleBase* ele; - for(int ee=0; eeeles.size(); ee++) if((ele = &page->eles[ee])->startTime > 0 || ele->endTime < page->timeSpan) { - if(ele->startTime > 0) timerMap.insert(startTimer(ele->startTime), TimerValue(ele->wgt, true)); - else ele->wgt->setVisible(true); - timerMap.insert(startTimer(ele->endTime), TimerValue(ele->wgt, false)); - } - page->setVisible(true); - } else if(timer!=nullptr) { - timer->stop(); - timer = nullptr; - } -} -void PlayWin::timerEvent(QTimerEvent *e){ - int id = e->timerId(); - killTimer(id); - TimerValue value = timerMap[id]; - if(value.ele!=nullptr){ - timerMap.remove(id); - value.ele->setVisible(value.visible); - } -} -void PlayWin::paintEvent(QPaintEvent *e){ - if(timer==nullptr && isVisible() && ! pages.isEmpty()) { - if(cur!=0) { - pages[cur]->setVisible(false); - cur = 0; - } - pages[cur]->setVisible(true); - timer = new SyncTimer(pages[cur]->timeSpan); - connect(timer, &SyncTimer::timeout, this, &PlayWin::sltNext, Qt::BlockingQueuedConnection); - timer->start(); - } - QWidget::paintEvent(e); -} - -void PlayWin::mousePressEvent(QMouseEvent *e) { - if(e->button() == Qt::LeftButton) { - mPressRel = pos() - e->globalPos(); - } -} -void PlayWin::mouseReleaseEvent(QMouseEvent *e) { - if(e->button() == Qt::LeftButton) mPressRel.setX(INT_MAX); -} -void PlayWin::mouseMoveEvent(QMouseEvent *e) { - if(e->buttons() & Qt::LeftButton) { - if(mPressRel.x()==INT_MAX) return; - move(mPressRel + e->globalPos()); - } -} -void PlayWin::leaveEvent(QEvent *) { - mPressRel.setX(INT_MAX); -} - -void PlayWin::contextMenuEvent(QContextMenuEvent *event){ - menu->exec(event->globalPos()); -} -void PlayWin::closeEvent(QCloseEvent *) { - if(self==this) self = nullptr; - gPlayPos = pos(); -} +#include "playwin.h" +#include "digiclock.h" +#include "eleanaclock.h" +#include "eleborder.h" +#include "elegif.h" +#include "eleimg.h" +#include "elemultipng.h" +#include "elescroll.h" +#include "eletimer.h" +#include "elevideo.h" +#include "gutil/qgui.h" +#include "posdlg.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +PlayWin* PlayWin::self = nullptr; +QPoint gPlayPos{0, 0}; + +Page::Page(QWidget *parent) : QWidget{parent} { + +} + +PlayWin *PlayWin::newIns(int width, int height, QString dir, const QJsonObject &aprog, QWidget *parent) { + if(! gPlayPos.isNull() && QGuiApplication::screenAt(QPoint(gPlayPos.x()+width/2, gPlayPos.y()+height/2))==0) gPlayPos = QPoint(); + return new PlayWin(gPlayPos.x(), gPlayPos.y(), width, height, dir, aprog, parent); +} + +PlayWin::PlayWin(int x, int y, int width, int height, QString dir, const QJsonObject &aprog, QWidget *parent) : QWidget(parent) { + setAttribute(Qt::WA_DeleteOnClose); + setAttribute(Qt::WA_QuitOnClose, false); + setWindowFlag(Qt::FramelessWindowHint); + setWindowFlag(Qt::WindowStaysOnTopHint); + setGeometry(x, y, width, height); + QPalette plt = palette(); + plt.setColor(QPalette::Window, QColor(0,0,0)); + setPalette(plt); + connect(this, &PlayWin::sigSetVisible, this, &PlayWin::sltSetVisible); + + const auto pageMaps = aprog["task"]["items"].toArray(); + int pageCnt = pageMaps.size(); + EleBase ele; Page *page; + for(int p=0; psetGeometry(0, 0, width, height); + page->setVisible(false); + for(int ll=layers.size()-1; ll>=0; ll--) { + QJsonObject layer = layers[ll].toObject(); + auto repeat = layer["repeat"].toBool(); + QJsonArray srcMaps = layer["sources"].toArray(); + QJsonValue border = layer["border"]; + EleBorder *bdEle = nullptr; + int bdWidth = 0, bdStart = 0xffff, bdEnd = 0; + if(! border.isNull()) { + bdEle = new EleBorder(dir+"/"+border["img"].toString(), border["eff"].toString(), border["speed"].toInt(), page); + bdWidth = bdEle->img.height(); + } + foreach(auto srcMap, srcMaps) { + ele.type = srcMap["_type"].toString(); + if(ele.type.isEmpty()) continue; + auto timeSpan = srcMap["timeSpan"].toInt()*1000; + if(timeSpan==0) continue; + ele.x = srcMap["left"].toInt()+bdWidth; + ele.y = srcMap["top"].toInt()+bdWidth; + ele.w = srcMap["width"].toInt()-bdWidth-bdWidth; + ele.h = srcMap["height"].toInt()-bdWidth-bdWidth; + bool notAudio = ele.type!="Audio"; + if((ele.w<=0 || ele.h<=0) && notAudio) continue; + ele.repeat = repeat; + ele.startTime = srcMap["playTime"].toInt()*1000; + if(bdStart > ele.startTime) bdStart = ele.startTime; + ele.endTime = ele.startTime + timeSpan; + if(bdEnd < ele.endTime) bdEnd = ele.endTime; + if(page->timeSpan < ele.endTime && notAudio) page->timeSpan = ele.endTime; + ele.id = srcMap["id"].toString(); + ele.wgt = 0; + if(ele.type=="Image") { + if(srcMap["mime"].toString().endsWith("gif")) ele.wgt = new EleGif(dir+"/"+ele.id, page); + else ele.wgt = new EleImg(dir+"/"+ele.id, page); + } else if(ele.type.startsWith("Environ")) { + QJsonValue arrayPics = srcMap["arrayPics"]; + for(int i=arrayPics.toArray().size()-1; i>=0; i--) if(arrayPics[i]["name"].toString() == "previewTmp") { + if(srcMap["bSingleScroll"].toBool()) ele.wgt = new EleScroll(page, dir+"/" + arrayPics[i]["id"].toString(), 'l', srcMap["iScrollSpeed"].toDouble()); + else ele.wgt = new EleScroll(page, dir+"/"+arrayPics[i]["id"].toString()); + break; + } + } else if(ele.type=="MultiPng") { + QJsonArray imgs = srcMap["arrayPics"].toArray(); + if(imgs.isEmpty()) continue; + if(imgs.size()==1 && imgs.at(0)["picDuration"].toInt()==0) ele.wgt = new EleScroll(page, dir+"/", imgs[0].toObject()); + else ele.wgt = new EleMultiPng(dir+"/", imgs, page); + } else if(ele.type=="SplitText") { + QJsonArray imgs = srcMap["arrayPics"].toArray(); + if(imgs.isEmpty()) continue; + ele.wgt = new QWidget(page); + ele.wgt->setGeometry(0, 0, width, height); + auto height = _program["height"].toInt(); + if(imgs.size()==1 && imgs.at(0)["picDuration"].toInt()==0) { + auto wgt = new EleScroll(ele.wgt, dir+"/", imgs[0].toObject()); + wgt->setGeometry(ele.x, ele.y, ele.w, ele.h); + for(int i=1; isetGeometry(ele.x, ele.y, splitWidths[i].toInt()-ele.x, ele.h); + wgt->splits.append(split); + } + } else { + auto wgt = new EleMultiPng(dir+"/", imgs, ele.wgt); + wgt->setGeometry(ele.x, ele.y, ele.w, ele.h); + for(int i=1; isetGeometry(ele.x, ele.y, splitWidths[i].toInt()-ele.x, ele.h); + wgt->splits.append(split); + } + } + ele.w = 0; + } else if(ele.type=="DigitalClockNew") ele.wgt = new DigiClock(dir+"/", srcMap.toObject(), page); + else if(ele.type=="AnalogClock") ele.wgt = new EleAnaClock(ele.w, ele.h, dir+"/"+ele.id, srcMap.toObject(), page); + else if(ele.type=="Video" || ele.type=="Audio") { + auto video = new EleVideo(dir+"/"+ele.id, page); + auto vol = srcMap["vol"].toInt(100); + if(vol<100) video->player->setVol(vol/100.0); + ele.wgt = video; + } else if(ele.type=="WebURL") { + auto web = new QWebEngineView(page); + web->load(QUrl(srcMap["url"].toString())); + ele.wgt = web; + } + else if(ele.type=="Timer") ele.wgt = new EleTimer(srcMap.toObject(), page); + else continue; + if(ele.wgt==0) continue; + if(ele.startTime>0) ele.wgt->setVisible(false); + if(ele.w) ele.wgt->setGeometry(ele.x, ele.y, ele.w, ele.h); + page->eles.append(ele); + } + if(bdEle && ! srcMaps.isEmpty()) { + QJsonArray geometry = border["geometry"].toArray(); + ele.x = geometry[0].toInt(); + ele.y = geometry[1].toInt(); + ele.w = geometry[2].toInt(); + ele.h = geometry[3].toInt(); + ele.startTime = bdStart; + ele.endTime = bdEnd; + ele.wgt = bdEle; + if(ele.startTime>0) ele.wgt->setVisible(false); + ele.wgt->setGeometry(ele.x, ele.y, ele.w, ele.h); + page->eles.append(ele); + } + } + if(page->timeSpan==0) continue; + for(int i=0; ieles.size(); i++) if(page->eles[i].repeat) page->eles[i].endTime = page->timeSpan; + pages.append(page); + } + setVisible(true); + if(! pages.isEmpty()) { + Page* page0 = pages[0]; + EleBase* eleptr; + for(int ee=0; eeeles.size(); ee++) if((eleptr = &page0->eles[ee])->startTime > 0 || eleptr->endTime < page0->timeSpan) { + if(eleptr->startTime > 0) timerMap.insert(startTimer(eleptr->startTime), TimerValue(eleptr->wgt, true)); + timerMap.insert(startTimer(eleptr->endTime), TimerValue(eleptr->wgt, false)); + } + } + + menu = new QMenu(this); + auto act = menu->addAction(tr("Move to Top Left")); + connect(act, &QAction::triggered, this, [this] { + move(0,0); + }); + act = menu->addAction(tr("Set Position")); + connect(act, &QAction::triggered, this, [this] { + PosDlg dlg(this); + dlg.exec(); + }); + act = menu->addAction(tr("Close")); + connect(act, &QAction::triggered, this, [this] { + if(self==this) self = nullptr; + close(); + }); +} +void PlayWin::sltNext() { + if(isVisible()) { + pages[cur]->setVisible(false); + if(cur+2 > pages.size()) cur = 0; + else cur++; + Page* page = pages[cur]; + if(timer) timer->inter = page->timeSpan; + EleBase* ele; + for(int ee=0; eeeles.size(); ee++) if((ele = &page->eles[ee])->startTime > 0 || ele->endTime < page->timeSpan) { + if(ele->startTime > 0) timerMap.insert(startTimer(ele->startTime), TimerValue(ele->wgt, true)); + else ele->wgt->setVisible(true); + timerMap.insert(startTimer(ele->endTime), TimerValue(ele->wgt, false)); + } + page->setVisible(true); + } else if(timer) { + timer->stop(); + timer = 0; + } +} +void PlayWin::timerEvent(QTimerEvent *e){ + int id = e->timerId(); + killTimer(id); + TimerValue value = timerMap[id]; + if(value.ele) { + timerMap.remove(id); + value.ele->setVisible(value.visible); + } +} +void PlayWin::paintEvent(QPaintEvent *e){ + if(timer==0 && isVisible() && ! pages.isEmpty()) { + if(cur!=0) { + pages[cur]->setVisible(false); + cur = 0; + } + pages[cur]->setVisible(true); + timer = new SyncTimer(pages[cur]->timeSpan); + connect(timer, &SyncTimer::timeout, this, &PlayWin::sltNext, Qt::BlockingQueuedConnection); + timer->start(); + } + QWidget::paintEvent(e); +} + +void PlayWin::mousePressEvent(QMouseEvent *e) { + if(e->button() == Qt::LeftButton) { + mPressRel = pos() - e->globalPos(); + } +} +void PlayWin::mouseReleaseEvent(QMouseEvent *e) { + if(e->button() == Qt::LeftButton) mPressRel.setX(INT_MAX); +} +void PlayWin::mouseMoveEvent(QMouseEvent *e) { + if(e->buttons() & Qt::LeftButton) { + if(mPressRel.x()==INT_MAX) return; + move(mPressRel + e->globalPos()); + } +} +void PlayWin::leaveEvent(QEvent *) { + mPressRel.setX(INT_MAX); +} + +void PlayWin::contextMenuEvent(QContextMenuEvent *event){ + menu->exec(event->globalPos()); +} +void PlayWin::closeEvent(QCloseEvent *) { + if(self==this) self = nullptr; + gPlayPos = pos(); +} diff --git a/LedOK/player/playwin.h b/LedOK/player/playwin.h index 9caa8f1..01296bf 100644 --- a/LedOK/player/playwin.h +++ b/LedOK/player/playwin.h @@ -1,56 +1,56 @@ -#ifndef PLAYWIN_H -#define PLAYWIN_H -#include "elebase.h" -#include "synctimer.h" -#include -#include -#include -#include - -class Page : public QWidget { -public: - explicit Page(QWidget *parent = nullptr); - int timeSpan = 0; - QVector eles; -}; - -class TimerValue{ -public: - TimerValue(QWidget *ele = nullptr, bool visible = false): ele(ele), visible(visible){} - QWidget* ele; - bool visible; -}; - -class PlayWin : public QWidget { - Q_OBJECT -public: - static PlayWin *self; - static PlayWin *newIns(int width, int height, QString dir, const QJsonObject &prog, QWidget *parent = nullptr); - PlayWin(int x, int y, int width, int height, QString dir, const QJsonObject &prog, QWidget *parent = nullptr); - - SyncTimer* timer = nullptr; - int cur = 0; - QVector pages; - QMap timerMap; - QPoint mPressRel; - QMenu *menu; - -public slots: - void sltNext(); - void sltSetVisible(QWidget *wgt, bool visible){ - wgt->setVisible(visible); - } -signals: - void sigSetVisible(QWidget *, bool); -protected: - void paintEvent(QPaintEvent *) override; - void timerEvent(QTimerEvent *) override; - void mousePressEvent(QMouseEvent *) override; - void mouseReleaseEvent(QMouseEvent *) override; - void mouseMoveEvent(QMouseEvent *) override; - void leaveEvent(QEvent *) override; - void contextMenuEvent(QContextMenuEvent *) override; - void closeEvent(QCloseEvent *) override; -}; - -#endif // PLAYWIN_H +#ifndef PLAYWIN_H +#define PLAYWIN_H +#include "elebase.h" +#include "synctimer.h" +#include +#include +#include +#include + +class Page : public QWidget { +public: + explicit Page(QWidget *parent = nullptr); + int timeSpan{0}; + QVector eles; +}; + +class TimerValue{ +public: + TimerValue(QWidget *ele = nullptr, bool visible = false): ele(ele), visible(visible){} + QWidget* ele; + bool visible; +}; + +class PlayWin : public QWidget { + Q_OBJECT +public: + static PlayWin *self; + static PlayWin *newIns(int width, int height, QString dir, const QJsonObject &prog, QWidget *parent = nullptr); + PlayWin(int x, int y, int width, int height, QString dir, const QJsonObject &prog, QWidget *parent = nullptr); + + SyncTimer* timer = 0; + int cur = 0; + QVector pages; + QMap timerMap; + QPoint mPressRel; + QMenu *menu; + +public slots: + void sltNext(); + void sltSetVisible(QWidget *wgt, bool visible){ + wgt->setVisible(visible); + } +signals: + void sigSetVisible(QWidget *, bool); +protected: + void paintEvent(QPaintEvent *) override; + void timerEvent(QTimerEvent *) override; + void mousePressEvent(QMouseEvent *) override; + void mouseReleaseEvent(QMouseEvent *) override; + void mouseMoveEvent(QMouseEvent *) override; + void leaveEvent(QEvent *) override; + void contextMenuEvent(QContextMenuEvent *) override; + void closeEvent(QCloseEvent *) override; +}; + +#endif // PLAYWIN_H diff --git a/LedOK/player/posdlg.cpp b/LedOK/player/posdlg.cpp index 38f3e1b..c083ee0 100644 --- a/LedOK/player/posdlg.cpp +++ b/LedOK/player/posdlg.cpp @@ -1,43 +1,43 @@ -#include "posdlg.h" -#include -#include -#include -#include - -PosDlg::PosDlg(QWidget *parent) : QDialog{parent} { - setWindowTitle(tr("Set Position")); - setWindowFlag(Qt::WindowContextHelpButtonHint, false); - - auto vBox = new QVBoxLayout(this); - auto hBox = new QHBoxLayout(); - hBox->addStretch(); - hBox->addWidget(new QLabel("X")); - auto fdX = new QLineEdit(QString::number(parent->x())); - fdX->setMaximumWidth(80); - hBox->addWidget(fdX); - hBox->addStretch(); - - vBox->addLayout(hBox); - - hBox = new QHBoxLayout(); - hBox->addStretch(); - hBox->addWidget(new QLabel("Y")); - auto fdY = new QLineEdit(QString::number(parent->y())); - fdY->setMaximumWidth(80); - hBox->addWidget(fdY); - hBox->addStretch(); - - vBox->addLayout(hBox); - - hBox = new QHBoxLayout(); - hBox->addStretch(); - - auto btnOk = new QPushButton(tr("OK")); - connect(btnOk, &QPushButton::clicked, this, [parent, fdX, fdY] { - parent->move(fdX->text().toInt(), fdY->text().toInt()); - }); - hBox->addWidget(btnOk); - hBox->addStretch(); - - vBox->addLayout(hBox); -} +#include "posdlg.h" +#include +#include +#include +#include + +PosDlg::PosDlg(QWidget *parent) : QDialog{parent} { + setWindowTitle(tr("Set Position")); + setWindowFlag(Qt::WindowContextHelpButtonHint, false); + + auto vBox = new QVBoxLayout(this); + auto hBox = new QHBoxLayout(); + hBox->addStretch(); + hBox->addWidget(new QLabel("X")); + auto fdX = new QLineEdit(QString::number(parent->x())); + fdX->setMaximumWidth(80); + hBox->addWidget(fdX); + hBox->addStretch(); + + vBox->addLayout(hBox); + + hBox = new QHBoxLayout(); + hBox->addStretch(); + hBox->addWidget(new QLabel("Y")); + auto fdY = new QLineEdit(QString::number(parent->y())); + fdY->setMaximumWidth(80); + hBox->addWidget(fdY); + hBox->addStretch(); + + vBox->addLayout(hBox); + + hBox = new QHBoxLayout(); + hBox->addStretch(); + + auto btnOk = new QPushButton(tr("OK")); + connect(btnOk, &QPushButton::clicked, this, [parent, fdX, fdY] { + parent->move(fdX->text().toInt(), fdY->text().toInt()); + }); + hBox->addWidget(btnOk); + hBox->addStretch(); + + vBox->addLayout(hBox); +} diff --git a/LedOK/player/posdlg.h b/LedOK/player/posdlg.h index 2940168..f7bc7a5 100644 --- a/LedOK/player/posdlg.h +++ b/LedOK/player/posdlg.h @@ -1,13 +1,13 @@ -#ifndef POSDLG_H -#define POSDLG_H - -#include - -class PosDlg : public QDialog { - Q_OBJECT -public: - explicit PosDlg(QWidget *parent = nullptr); - -}; - -#endif // POSDLG_H +#ifndef POSDLG_H +#define POSDLG_H + +#include + +class PosDlg : public QDialog { + Q_OBJECT +public: + explicit PosDlg(QWidget *parent = nullptr); + +}; + +#endif // POSDLG_H diff --git a/LedOK/progpanel.cpp b/LedOK/progpanel.cpp index 0025b93..541fd9a 100644 --- a/LedOK/progpanel.cpp +++ b/LedOK/progpanel.cpp @@ -1,12 +1,17 @@ #include "progpanel.h" #include "globaldefine.h" #include "tools.h" +#include "gutil/qgui.h" +#include "cfg.h" #include "player/playwin.h" -#include "tipdialog.h" +#include "program/progcreatedlg.h" +#include "program/progeditorwin.h" +#include "program/copydirthread.h" #include #include #include -#include +#include +#include ProgPanel::ProgPanel(QSettings &settings, QWidget *parent) : QWidget(parent) { setAttribute(Qt::WA_DeleteOnClose); @@ -28,10 +33,27 @@ ProgPanel::ProgPanel(QSettings &settings, QWidget *parent) : QWidget(parent) { bnNew->setProperty("ssType", "progManageTool"); hBox->addWidget(bnNew); connect(bnNew, &QPushButton::clicked, this, [this] { - ProgCreateDlg dlg(QDateTime::currentDateTime().toString("yyyyMMddhhmmsszzz"), 512, 512, "", this); + ProgCreateDlg dlg("", 512, 256, "", "", this); if(dlg.exec() != QDialog::Accepted) return; if(checkIfNameRepeated(dlg.fdName->text())) return; - auto item = new ProgItem(mProgsDir, dlg.fdName->text(), dlg.fdWidth->value(), dlg.fdHeight->value(), dlg.fdRemark->toPlainText(), dlg.fdSplitWidth->value(), mProgTree, this); + auto splitWidths = dlg.fdSplitWidths->text().split(" ", Qt::SkipEmptyParts); + QList widths; int max = 0, ttl = 0; + foreach(auto splitWidth, splitWidths) { + int val = splitWidth.toInt(); + if(val==0) continue; + if(max < val) max = val; + ttl += val; + widths.append(val); + } + auto width = dlg.fdWidth->value(); + if(max) { + while(ttl < width) { + widths.append(max); + ttl += max; + } + if(ttl > width) widths.last() -= ttl - width; + } + auto item = new ProgItem(mProgsDir, dlg.fdName->text(), width, dlg.fdHeight->value(), dlg.fdRemark->toPlainText(), widths, max, mProgTree, this); item->save();//保存pro.json mProgTree->adjustCheckState(); auto editor = new ProgEditorWin(item, gMainWin); @@ -53,13 +75,60 @@ ProgPanel::ProgPanel(QSettings &settings, QWidget *parent) : QWidget(parent) { connect(bnDelete, SIGNAL(clicked(bool)), this, SLOT(onDeleteClicked(bool))); bnImport = new QPushButton(tr("Import")); - bnImport->setFixedSize(QSize(88, 38)); + bnImport->setFixedSize(88, 38); bnImport->setProperty("ssType", "progManageTool"); hBox->addWidget(bnImport); connect(bnImport, &QPushButton::clicked, this, [this] { - auto dlg = new TipDialog(this, ENUM_IMPORT_DLG); - connect(dlg, SIGNAL(sigAcceptData(QString,QString)), this, SLOT(onImportProgram(QString,QString))); - dlg->exec(); + QString dir = QFileDialog::getExistingDirectory(this, tr("Choose Directory"), "/home", QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); + if(dir.isEmpty()) return; + QString progsDir = programsDir(); + if(dir.contains(progsDir, Qt::CaseInsensitive)) { + QMessageBox::warning(this, tr("Tip"), tr("The imported directory is already in the working directory, so there is no need to import it again!")); + return; + } + QStringList progDirs; + if(QFileInfo::exists(dir + "/pro.json")) progDirs.append(dir); + else { + QStringList subdirNames = QDir(dir).entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks); + foreach(QString subdirName, subdirNames) { + auto subdir = dir + "/" + subdirName; + if(! QFileInfo::exists(subdir + "/pro.json")) continue; + if(QFileInfo::exists(progsDir + "/" + subdirName)) { + auto res = QMessageBox::information(gMainWin, tr("Tip Info"), subdirName + tr(":solution(s) already exist.are you sure you want to overwrite the existing solution(s)?"), QMessageBox::Yes, QMessageBox::No); + if(res == QMessageBox::No) continue; + } + progDirs.append(subdir); + } + if(progDirs.isEmpty()) return; + } + ProgPortDlg dlg(this, tr("Import")); + dlg.table->setRowCount(progDirs.count()); + for(int i=0; isetItem(i, 0, new QTableWidgetItem(QFileInfo(progDirs[i]).fileName())); + dlg.table->setCellWidget(i, 1, new QProgressBar); + } + connect(dlg.bnOK, &QPushButton::clicked, this, [=, &dlg] { + for(int i=0; icellWidget(i, 1))->setMaximum(dirFileSize(progDirs[i])); + auto thread = new CopyDirThread(); + thread->dirSrcs = progDirs; + thread->dirDst = progsDir; + connect(thread, &CopyDirThread::sigProgress, &dlg, [&dlg](int i, int value) { + ((QProgressBar*)dlg.table->cellWidget(i, 1))->setValue(value); + }); + thread->start(); + }); + dlg.exec(); + + mProgTree->clear(); + QStringList progNames = QDir(mProgsDir).entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks); + foreach(QString pro_name, progNames) { + QFile jFile(mProgsDir + "/" + pro_name + "/pro.json"); + if(! jFile.exists()) continue; + if(! jFile.open(QIODevice::ReadOnly)) continue; + auto data = jFile.readAll(); + jFile.close(); + m_pwPorgramItemList.append(new ProgItem(mProgsDir, QJsonDocument::fromJson(data).object(), mProgTree,this)); + } }); bnExport = new QPushButton(tr("Export")); @@ -67,7 +136,36 @@ ProgPanel::ProgPanel(QSettings &settings, QWidget *parent) : QWidget(parent) { bnExport->setEnabled(false); bnExport->setProperty("ssType", "progManageTool"); hBox->addWidget(bnExport); - connect(bnExport, SIGNAL(clicked(bool)), this, SLOT(onExportClicked(bool))); + connect(bnExport, &QPushButton::clicked, this, [=] { + int cnt = mProgTree->topLevelItemCount(); + QStringList progNames; + for(int i=0; itopLevelItem(i)->checkState(0) == Qt::Checked) progNames.append(static_cast(mProgTree->topLevelItem(i))->mName); + if(progNames.isEmpty()) return; + + ProgPortDlg dlg(this, tr("Export")); + dlg.table->setRowCount(progNames.count()); + for(int i=0; isetItem(i, 0, new QTableWidgetItem(progNames[i])); + dlg.table->setCellWidget(i, 1, new QProgressBar); + } + connect(dlg.bnOK, &QPushButton::clicked, this, [=, &dlg] { + QString dirDst = QFileDialog::getExistingDirectory(this, tr("Choose Directory"), "/home", QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); + if(dirDst.isEmpty()) return; + auto progsDir = programsDir(); + auto thread = new CopyDirThread(); + for(int i=0; icellWidget(i, 1))->setMaximum(dirFileSize(dir)); + thread->dirSrcs.append(dir); + } + thread->dirDst = dirDst; + connect(thread, &CopyDirThread::sigProgress, &dlg, [&dlg](int i, int value) { + ((QProgressBar*)dlg.table->cellWidget(i, 1))->setValue(value); + }); + thread->start(); + }); + dlg.exec(); + }); bnSend = new QPushButton(tr("Send")); bnSend->setFixedSize(QSize(88, 38)); @@ -95,11 +193,8 @@ ProgPanel::ProgPanel(QSettings &settings, QWidget *parent) : QWidget(parent) { QJsonObject prog = QJsonDocument::fromJson(value.toUtf8(), &jsErr).object(); if(jsErr.error) return; if(PlayWin::self!=nullptr) PlayWin::self->close(); - if(item->mSplitWidth==0) PlayWin::self = PlayWin::newIns(item->mWidth, item->mHeight, dir, prog); - else { - int cnt = (item->mWidth+item->mSplitWidth-1) / item->mSplitWidth; - PlayWin::self = PlayWin::newIns(item->mSplitWidth, item->mHeight*cnt, dir, prog); - } + if(item->mSplitWidths.isEmpty()) PlayWin::self = PlayWin::newIns(item->mWidth, item->mHeight, dir, prog); + else PlayWin::self = PlayWin::newIns(item->mMaxWidth, item->mHeight * item->mSplitWidths.size(), dir, prog); break; } } @@ -111,7 +206,7 @@ ProgPanel::ProgPanel(QSettings &settings, QWidget *parent) : QWidget(parent) { auto txtSearch = new QLineEdit(this); txtSearch->setFixedSize(QSize(240, 36)); QAction *search = new QAction(txtSearch); - search->setIcon(QIcon(":/res/ProgramManager/bnSearch.png")); + search->setIcon(QIcon(":/res/program/bnSearch.png")); txtSearch->addAction(search, QLineEdit::LeadingPosition); txtSearch->setClearButtonEnabled(true); txtSearch->setStyleSheet("border: 2px solid #aaaaaa;"); @@ -252,10 +347,10 @@ bool ProgPanel::checkIfNameRepeated(const QString &name, QTreeWidgetItem *skip){ } return false; } -void ProgPanel::onCreateNewProgramOnOpenEditProgramWidget(QString name, QSize res, QString remarks, int sp) +void ProgPanel::onCreateNewProgramOnOpenEditProgramWidget(QString name, QSize res, QString remarks, QList &splitWidths, int max) { if(checkIfNameRepeated(name)) return; - auto item = new ProgItem(mProgsDir, name, res.width(), res.height(), remarks, sp, mProgTree, this); + auto item = new ProgItem(mProgsDir, name, res.width(), res.height(), remarks, splitWidths, max, mProgTree, this); item->save();//保存pro.json mProgTree->adjustCheckState(); auto editor = new ProgEditorWin(item, gMainWin); @@ -281,40 +376,6 @@ void ProgPanel::onDeleteClicked(bool){ } } -void ProgPanel::onImportProgram(QString strImportDir, QString){ - if(!strImportDir.isEmpty()){ - mProgTree->clear(); - //查找根路径下的项目文件夹,查找文件夹下的节目pro.json信息,包括节目名称,大小,像素,备注等信息 - if(!mProgsDir.isEmpty()) { - QDir root_dir(mProgsDir); - QStringList pro_list = root_dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks); - foreach(QString pro_name, pro_list) { - QDir pro_dir(mProgsDir + MACRO_FENGEFU + pro_name); - if(pro_dir.exists("pro.json")) { - QFile fPro(pro_dir.path() + MACRO_FENGEFU+"pro.json"); - fPro.open(QIODevice::ReadOnly); - QJsonDocument pro = QJsonDocument::fromJson(fPro.readAll()); - fPro.close(); - m_pwPorgramItemList.append(new ProgItem(mProgsDir, pro.object(), mProgTree,this)); - } - } - } - } -} - -void ProgPanel::onExportClicked(bool){ - int cnt = mProgTree->topLevelItemCount(); - QStringList selectProgramlist; - for(int i=0; itopLevelItem(i)->checkState(0) == Qt::Checked) { - QString string =static_cast(mProgTree->topLevelItem(i))->m_bnName->text(); - selectProgramlist.append(string); - } - } - TipDialog *dlg = new TipDialog(this,ENUM_EXPORT_DLG,&selectProgramlist,0); - dlg->exec(); -} - void ProgPanel::FilterProgram(const QString &strtemp){ if (strtemp.isEmpty()) //显示全部 { @@ -358,3 +419,47 @@ void ProgPanel::FilterProgram(const QString &strtemp){ } +ProgPortDlg::ProgPortDlg(QWidget *parent, QString title) : BaseDlg(parent) { + resize(600, 400); + + auto vBox = new VBox(this); + auto hBox = new HBox(vBox); + hBox->setContentsMargins(0, 0, 0, 0); + hBox->addStretch(); + + auto fdTitle = new QLabel(title); + fdTitle->setStyleSheet("QLabel{font-size:16px;}"); + hBox->addWidget(fdTitle); + hBox->addStretch(); + + bnClose = new QPushButton("X"); + bnClose->setFixedSize(30, 24); + connect(bnClose, &QPushButton::clicked, this, &BaseDlg::close); + hBox->addWidget(bnClose); + + auto line = new QFrame; + line->setFrameShape(QFrame::HLine); + line->setFrameShadow(QFrame::Sunken); + vBox->addWidget(line); + + + table = new QTableWidget(0, 2); + table->setSelectionMode(QTableWidget::NoSelection); + table->setEditTriggers(QAbstractItemView::NoEditTriggers); + table->setAlternatingRowColors(true); + table->horizontalHeader()->setBackgroundRole(QPalette::Window); + table->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); + table->horizontalHeader()->resizeSection(1, 200); + table->setHorizontalHeaderLabels({tr("Solution Name"), tr("Progress")}); + vBox->addWidget(table); + + hBox = new HBox(vBox); + hBox->addStretch(); + + bnOK = new QPushButton(title); + hBox->addWidget(bnOK); + + auto bnDone = new QPushButton(tr("Done")); + connect(bnDone, &QPushButton::clicked, this, &BaseDlg::accept); + hBox->addWidget(bnDone); +} diff --git a/LedOK/progpanel.h b/LedOK/progpanel.h index 3ba4116..52d1b24 100644 --- a/LedOK/progpanel.h +++ b/LedOK/progpanel.h @@ -1,31 +1,12 @@ #ifndef PROGPANEL_H #define PROGPANEL_H -#include -#include -#include -#include -#include -#include -#include +#include "base/loqtreewidget.h" +#include "program/progitem.h" +#include "basedlg.h" #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include - -#include "cfg.h" -#include -#include -#include -#include "wProgramManager/progitem.h" +#include class ProgPanel : public QWidget { Q_OBJECT @@ -42,9 +23,7 @@ protected: public slots: void onEditClicked(bool f); void onDeleteClicked(bool f); - void onExportClicked(bool f); - void onCreateNewProgramOnOpenEditProgramWidget(QString name, QSize res, QString remarks, int); - void onImportProgram(QString strImportDir,QString strTip1); + void onCreateNewProgramOnOpenEditProgramWidget(QString name, QSize res, QString remarks, QList &, int); void FilterProgram(const QString &strtemp); private slots: @@ -60,4 +39,13 @@ private: QPushButton *bnSend, *btnPlay; }; +class ProgPortDlg : public BaseDlg { + Q_OBJECT +public: + ProgPortDlg(QWidget *parent, QString title); + + QTableWidget *table{0}; + QPushButton *bnOK, *bnClose; +}; + #endif // PROGPANEL_H diff --git a/LedOK/program/copydirthread.cpp b/LedOK/program/copydirthread.cpp new file mode 100644 index 0000000..ad308a0 --- /dev/null +++ b/LedOK/program/copydirthread.cpp @@ -0,0 +1,32 @@ +#include "copydirthread.h" +#include + +CopyDirThread::CopyDirThread() { + connect(this, &CopyDirThread::finished, this, &CopyDirThread::deleteLater); +} + +void CopyDirThread::run() { + for(; i + +class CopyDirThread : public QThread { + Q_OBJECT +public: + CopyDirThread(); + QStringList dirSrcs; + QString dirDst; +protected: + void run(); + bool copyDir(const QString &fromDir, const QString &toDir, bool coverFileIfExist); + + int i{0}; + int copiedSize = 0; +signals: + void sigProgress(int, int); +}; +#endif // COPYDIRTHREAD_H diff --git a/LedOK/wProgramManager/eaclock.cpp b/LedOK/program/eaclock.cpp similarity index 63% rename from LedOK/wProgramManager/eaclock.cpp rename to LedOK/program/eaclock.cpp index 14718cc..413e2e2 100644 --- a/LedOK/wProgramManager/eaclock.cpp +++ b/LedOK/program/eaclock.cpp @@ -1,39 +1,34 @@ #include "eaclock.h" #include "cfg.h" #include "globaldefine.h" +#include "gutil/qgui.h" #include "tools.h" +#include "base/locolorselector.h" +#include #include #include #include #include -#include +#include +#include +#include -eAClock::eAClock(EBase *multiWin) : EBase(multiWin) { +EAClock::EAClock(EBase *multiWin) : EBase(multiWin) { mType = EBase::AClock; - m_attr.timeZoneId = QTimeZone::systemTimeZoneId(); - m_attr.hourMark = 0; - m_attr.hourMarkSize = 5; - m_attr.hourMarkColor = Qt::green; - m_attr.minMark = 1; - m_attr.minMarkSize = 2; - m_attr.minMarkColor = Qt::yellow; - m_attr.hourHandColor = Qt::yellow; - m_attr.minHandColor = Qt::green; - m_attr.secHandColor = Qt::red; - m_attr.textFont = QFont("Arial", 9); - m_attr.textColor = Qt::red; - m_attr.playDuration = 10; - m_attr.hasDialImg = false; - init(); + m_attr.timeZone = QTimeZone::systemTimeZone(); + m_attr.hourHandColor = Qt::yellow; + m_attr.minHandColor = Qt::green; + m_attr.secHandColor = Qt::red; + m_attr.textColor = Qt::red; } -eAClock::eAClock(const QJsonObject &json, EBase *multiWin) : EBase(multiWin) { +EAClock::EAClock(const QJsonObject &json, EBase *multiWin) : EBase(multiWin) { mType = EBase::AClock; setBaseAttr(json); auto widget = json["widget"]; - m_attr.timeZoneId = QByteArray().append(widget["timeZone"].toString().toUtf8()); - m_attr.hourMark = widget["hourMark"].toInt(); - m_attr.hourMarkSize = widget["hourMarkSize"].toInt(); + m_attr.timeZone = QTimeZone(widget["timeZone"].toString().toUtf8()); + m_attr.hourMark = widget["hourMark"].toInt(); + m_attr.hourMarkSize = widget["hourMarkSize"].toInt(); auto color = widget["hourMarkColor"]; m_attr.hourMarkColor = color.isString() ? QColor(color.toString()) : Tools::int2Color(color.toInt()); m_attr.minMark = widget["minMark"].toInt(); @@ -53,6 +48,13 @@ eAClock::eAClock(const QJsonObject &json, EBase *multiWin) : EBase(multiWin) { m_attr.textFont.setBold(widget["textFontBold"].toBool()); m_attr.textFont.setItalic(widget["textFontItalics"].toBool()); m_attr.textFont.setUnderline(widget["textFontUnderline"].toBool()); + m_attr.hhLen = widget["hhLen"].toInt(m_attr.hhLen); + m_attr.mhLen = widget["mhLen"].toInt(m_attr.mhLen); + m_attr.shLen = widget["shLen"].toInt(m_attr.shLen); + m_attr.hhWidth = widget["hhWidth"].toInt(m_attr.hhWidth); + m_attr.mhWidth = widget["mhWidth"].toInt(m_attr.mhWidth); + m_attr.shWidth = widget["shWidth"].toInt(m_attr.shWidth); + m_attr.showSecHand = widget["showSecHand"].toBool(true); m_attr.playDuration = json["play"]["duration"].toInt(); m_attr.path = widget["path"].toString(); m_attr.name = widget["name"].toString(); @@ -61,27 +63,24 @@ eAClock::eAClock(const QJsonObject &json, EBase *multiWin) : EBase(multiWin) { if(! m_attr.hasDialImg) m_attr.selfCreateDialName = QString("%1%2%3%4%5.png").arg((int)zValue()).arg((int)x()).arg((int)y()).arg((int)mWidth).arg((int)mHeight); else dial_img.load(m_attr.path+"/"+m_attr.name); - init(); } -void eAClock::init() { - connect(Tools::getInstance(), &Tools::sTick, this, [this]() { - time = QDateTime::currentDateTime().toTimeZone(QTimeZone(m_attr.timeZoneId)).time(); +void EAClock::timerEvent(QTimerEvent *) { + if(isVisible()) { + cal(); update(); - }); + } else if(timerId) { + killTimer(timerId); + timerId = 0; + } } - -qreal eAClock::radiusHour() const { - qreal r = (rect().width() < rect().height() ? rect().width() : rect().height()) / 2; - return r - m_attr.hourMarkSize / 2; +void EAClock::cal() { + auto time = QDateTime::currentDateTime().toTimeZone(m_attr.timeZone).time(); + sAngle = time.second() * 6; + mAngle = time.minute() * 6 + sAngle/60; + hAngle = time.hour() * 30 + mAngle/12; } - -qreal eAClock::radiusMin() const { - qreal r = (rect().width() < rect().height() ? rect().width() : rect().height()) / 2; - return r - m_attr.minMarkSize / 2; -} - -void eAClock::paintDial(QPainter *painter) { +void EAClock::paintDial(QPainter *painter) { if(! m_attr.hasDialImg || dial_img.isNull()) { auto inner = innerRect(); qreal r = radius(); @@ -150,7 +149,7 @@ void eAClock::paintDial(QPainter *painter) { } } -void eAClock::drawMarkCircular(QPainter *painter, const QPointF &pos, const QColor &color, qreal diameter) { +void EAClock::drawMarkCircular(QPainter *painter, const QPointF &pos, const QColor &color, qreal diameter) { QPointF cp(pos.x(), pos.y()); qreal r = diameter / 2; painter->save(); @@ -161,7 +160,7 @@ void eAClock::drawMarkCircular(QPainter *painter, const QPointF &pos, const QCol painter->restore(); } -void eAClock::drawMarkRectangle(QPainter *painter, const QPointF &pos, const QColor &color, qreal len, qreal angle) +void EAClock::drawMarkRectangle(QPainter *painter, const QPointF &pos, const QColor &color, qreal len, qreal angle) { QPointF cp(pos.x(), pos.y()); QRectF rect(-len/2, -len/2, len, len); @@ -175,7 +174,7 @@ void eAClock::drawMarkRectangle(QPainter *painter, const QPointF &pos, const QCo painter->restore(); } -void eAClock::drawMarkNumber(QPainter *painter, const QPointF &pos, const QColor &color, qreal len, int num) +void EAClock::drawMarkNumber(QPainter *painter, const QPointF &pos, const QColor &color, qreal len, int num) { QRectF rect(pos.x()-len/2, pos.y()-len/2, len, len); QFont font("Arial"); @@ -192,61 +191,72 @@ void eAClock::drawMarkNumber(QPainter *painter, const QPointF &pos, const QColor painter->restore(); } -void eAClock::drawHand(QPainter *painter, qreal angle, const QColor &color, qreal len, qreal base) { - auto inner = innerRect(); - qreal cx = inner.width() / 2; - qreal cy = inner.height() / 2; - QPointF points[3] = { - QPointF(-base, 0), - QPointF( base, 0), - QPointF( 0, -len), - }; - painter->save(); - painter->setBrush(color); - painter->setPen(color); - painter->translate(cx, cy); - painter->rotate(angle); - painter->setRenderHint(QPainter::Antialiasing); - painter->drawPolygon(points, 3); - painter->restore(); -} - -void eAClock::paintText(QPainter *painter){ +void EAClock::paintText(QPainter *painter){ if(m_attr.text.isNull() || m_attr.text.isEmpty()) return; - QRectF r(0, rect().height()/6, rect().width(), rect().height()/4); - QTextOption opt; - opt.setAlignment(Qt::AlignCenter); - painter->save(); + auto inner = innerRect(); painter->setPen(m_attr.textColor); m_attr.textFont.setStyleStrategy(gTextAntialiasing ? QFont::PreferAntialias : QFont::NoAntialias); painter->setFont(m_attr.textFont); - painter->drawText(r, m_attr.text, opt); - painter->restore(); + painter->drawText(QRectF(0, inner.height()/6, inner.width(), inner.height()/4), m_attr.text, QTextOption(Qt::AlignCenter)); } -void eAClock::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { +void EAClock::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { + if(timerId==0) { + timerId = startTimer(500, Qt::PreciseTimer); + cal(); + } painter->save(); + painter->setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform); auto inner = innerRect(); + auto sideLen = qMin(inner.width(), inner.height()); + auto lineWidth = sideLen/128; + if(lineWidth < 1) lineWidth = 1; painter->translate(inner.x(), inner.y()); paintDial(painter); paintText(painter); - drawHand(painter, time.hour() * 30.0, m_attr.hourHandColor, radius()/2, radius() / 20); - drawHand(painter, time.minute() * 6.0, m_attr.minHandColor, radius()*3/4, radius() / 30); - drawHand(painter, time.second() * 6.0, m_attr.secHandColor, radius(), radius() / 40); + painter->translate(inner.width() / 2, inner.height() / 2); + + QPen pen(m_attr.hourHandColor, lineWidth); + pen.setJoinStyle(Qt::RoundJoin); + painter->setPen(pen); + painter->setBrush(pen.brush()); + painter->rotate(hAngle); + QPointF poses[3]{{m_attr.hhWidth*sideLen/400, 0}, {0, m_attr.hhLen*sideLen/-200}}; + poses[2].rx() = -poses[0].rx(); + painter->drawPolygon(poses, 3); + + pen.setColor(m_attr.minHandColor); + painter->setPen(pen); + painter->setBrush(pen.brush()); + painter->rotate(mAngle-hAngle); + poses[0].rx() = m_attr.mhWidth*sideLen/400; + poses[1].ry() = m_attr.mhLen*sideLen/-200; + poses[2].rx() = -poses[0].rx(); + painter->drawPolygon(poses, 3); + if(m_attr.showSecHand) { + pen.setColor(m_attr.secHandColor); + painter->setPen(pen); + painter->setBrush(pen.brush()); + painter->rotate(sAngle-mAngle); + poses[0].rx() = m_attr.shWidth*sideLen/400; + poses[1].ry() = m_attr.shLen*sideLen/-200; + poses[2].rx() = -poses[0].rx(); + painter->drawPolygon(poses, 3); + } painter->restore(); EBase::paint(painter, option, widget); } -QWidget* eAClock::attrWgt() { +QWidget* EAClock::attrWgt() { auto wgtAttr = new QWidget(); - auto vBox = new QVBoxLayout(wgtAttr); + auto vBox = new VBox(wgtAttr); vBox->setContentsMargins(6, 0, 6, 0); - if(mMultiWin!=nullptr) vBox->setSpacing(3); + if(mMultiWin) vBox->setSpacing(3); addBaseAttrWgt(vBox); - auto hBox = new QHBoxLayout(); + auto hBox = new HBox(vBox); hBox->addWidget(new QLabel(tr("Basic Properties"))); auto line = new QFrame(); @@ -254,26 +264,24 @@ QWidget* eAClock::attrWgt() { line->setFrameShadow(QFrame::Sunken); hBox->addWidget(line, 1); - vBox->addLayout(hBox); - hBox = new QHBoxLayout(); + hBox = new HBox(vBox); hBox->addSpacing(6); hBox->addWidget(new QLabel(tr("Time Zone"))); auto wTimeZone = new QComboBox(); QList ids = QTimeZone::availableTimeZoneIds(); foreach(QByteArray id, ids) wTimeZone->addItem(QString::fromUtf8(id)); - wTimeZone->setCurrentText(m_attr.timeZoneId); + wTimeZone->setCurrentText(m_attr.timeZone.id()); connect(wTimeZone, &QComboBox::currentTextChanged, this, [this](const QString &text) { - m_attr.timeZoneId = text.toUtf8(); + m_attr.timeZone = QTimeZone(text.toUtf8()); update(); }); hBox->addWidget(wTimeZone); hBox->addStretch(); - vBox->addLayout(hBox); - hBox = new QHBoxLayout(); + hBox = new HBox(vBox); auto fdHasDialImg = new QCheckBox(tr("Custom Dial")); fdHasDialImg->setChecked(m_attr.hasDialImg); hBox->addWidget(fdHasDialImg); @@ -283,11 +291,10 @@ QWidget* eAClock::attrWgt() { line->setFrameShadow(QFrame::Sunken); hBox->addWidget(line, 1); - vBox->addLayout(hBox); auto wgtDial = new QWidget(); if(! m_attr.hasDialImg) wgtDial->setVisible(false); - hBox = new QHBoxLayout(wgtDial); + hBox = new HBox(wgtDial); hBox->setContentsMargins(0, 0, 0, 0); hBox->addSpacing(6); auto fdDialImg = new QLineEdit(); @@ -334,10 +341,10 @@ QWidget* eAClock::attrWgt() { update(); }); - auto vbMarks = new QVBoxLayout(wgtMarks); + auto vbMarks = new VBox(wgtMarks); vbMarks->setContentsMargins(0, 0, 0, 0); - hBox = new QHBoxLayout(); + hBox = new HBox(vbMarks); hBox->addSpacing(6); hBox->addWidget(new QLabel(tr("Hour Mark"))); @@ -370,9 +377,8 @@ QWidget* eAClock::attrWgt() { hBox->addWidget(fdHourMarkColor); hBox->addStretch(); - vbMarks->addLayout(hBox); - hBox = new QHBoxLayout(); + hBox = new HBox(vbMarks); hBox->addSpacing(6); hBox->addWidget(new QLabel(tr("Min Mark"))); @@ -404,40 +410,108 @@ QWidget* eAClock::attrWgt() { hBox->addWidget(fdMinMarkColor); hBox->addStretch(); - vbMarks->addLayout(hBox); - vBox->addWidget(wgtMarks); - hBox = new QHBoxLayout(); - hBox->addSpacing(6); - hBox->addWidget(new QLabel(tr("Hand Color"))); + auto grid = new QGridLayout; + grid->setColumnStretch(4, 1); + vBox->addLayout(grid); - auto fdHourHandColor = new LoColorSelector(tr("H"), m_attr.hourHandColor); + grid->addWidget(new QLabel(tr("Color")), 0, 1); + grid->addWidget(new QLabel(tr("Length")+" (%)"), 0, 2); + grid->addWidget(new QLabel(tr("Width")+" (%)"), 0, 3); + + grid->addWidget(new QLabel(tr("Hour Hand")), 1, 0, Qt::AlignRight); + + auto fdHourHandColor = new LoColorSelector("", m_attr.hourHandColor); fdHourHandColor->setFixedWidth(30); connect(fdHourHandColor, &LoColorSelector::sColorChanged, this, [this](const QColor &color) { m_attr.hourHandColor = color; update(); }); - hBox->addWidget(fdHourHandColor); + grid->addWidget(fdHourHandColor, 1, 1); - auto fdMinHandColor = new LoColorSelector(tr("M"), m_attr.minHandColor); + auto hhLen = new QSpinBox; + hhLen->setRange(0, 999); + hhLen->setValue(m_attr.hhLen); + connect(hhLen, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this](int value) { + m_attr.hhLen = value; + update(); + }); + grid->addWidget(hhLen, 1, 2); + + auto hhWidth = new QSpinBox; + hhWidth->setRange(0, 999); + hhWidth->setValue(m_attr.hhWidth); + connect(hhWidth, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this](int value) { + m_attr.hhWidth = value; + update(); + }); + grid->addWidget(hhWidth, 1, 3); + + grid->addWidget(new QLabel(tr("Min Hand")), 2, 0, Qt::AlignRight); + + auto fdMinHandColor = new LoColorSelector("", m_attr.minHandColor); fdMinHandColor->setFixedWidth(30); connect(fdMinHandColor, &LoColorSelector::sColorChanged, this, [this](const QColor &color) { m_attr.minHandColor = color; update(); }); - hBox->addWidget(fdMinHandColor); + grid->addWidget(fdMinHandColor, 2, 1); - auto fdSecHandColor = new LoColorSelector(tr("S"), m_attr.secHandColor); + auto mhLen = new QSpinBox; + mhLen->setRange(0, 999); + mhLen->setValue(m_attr.mhLen); + connect(mhLen, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this](int value) { + m_attr.mhLen = value; + update(); + }); + grid->addWidget(mhLen, 2, 2); + + auto mhWidth = new QSpinBox; + mhWidth->setRange(0, 999); + mhWidth->setValue(m_attr.mhWidth); + connect(mhWidth, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this](int value) { + m_attr.mhWidth = value; + update(); + }); + grid->addWidget(mhWidth, 2, 3); + + grid->addWidget(new QLabel(tr("Sec Hand")), 3, 0, Qt::AlignRight); + + auto fdSecHandColor = new LoColorSelector("", m_attr.secHandColor); fdSecHandColor->setFixedWidth(30); connect(fdSecHandColor, &LoColorSelector::sColorChanged, this, [this](const QColor &color) { m_attr.secHandColor = color; update(); }); - hBox->addWidget(fdSecHandColor); - hBox->addStretch(); + grid->addWidget(fdSecHandColor, 3, 1); + + auto shLen = new QSpinBox; + shLen->setRange(0, 999); + shLen->setValue(m_attr.shLen); + connect(shLen, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this](int value) { + m_attr.shLen = value; + update(); + }); + grid->addWidget(shLen, 3, 2); + + auto shWidth = new QSpinBox; + shWidth->setRange(0, 999); + shWidth->setValue(m_attr.shWidth); + connect(shWidth, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this](int value) { + m_attr.shWidth = value; + update(); + }); + grid->addWidget(shWidth, 3, 3); + + auto fdShowSecHand = new QCheckBox(tr("Show")); + fdShowSecHand->setChecked(m_attr.showSecHand); + connect(fdShowSecHand, &QCheckBox::toggled, this, [this](bool checked) { + m_attr.showSecHand = checked; + update(); + }); + grid->addWidget(fdShowSecHand, 3, 4); - vBox->addLayout(hBox); line = new QFrame(); line->setFrameShape(QFrame::HLine); @@ -452,7 +526,7 @@ QWidget* eAClock::attrWgt() { }); vBox->addWidget(fdText); - hBox = new QHBoxLayout(); + hBox = new HBox(vBox); hBox->addSpacing(6); auto fdFontFamily = new QFontComboBox(); @@ -478,20 +552,14 @@ QWidget* eAClock::attrWgt() { hBox->addWidget(fdFontSize); hBox->addStretch(); - vBox->addLayout(hBox); - hBox = new QHBoxLayout(); + hBox = new HBox(vBox); hBox->addSpacing(6); - auto fdBold = new QPushButton(); + auto fdBold = new QPushButton("B"); + fdBold->setStyleSheet("QPushButton{background: #bbb; color: #888; font-size: 20px; font-weight: bold;} QPushButton:checked{background: #29c; color: #fff;}"); fdBold->setFixedSize(30, 30); - QIcon icon; - icon.addFile(":/res/ProgramManager/EditProgram/FontBold_u.png", QSize(), QIcon::Normal, QIcon::Off); - icon.addFile(":/res/ProgramManager/EditProgram/FontBold_s.png", QSize(), QIcon::Normal, QIcon::On); - fdBold->setIcon(icon); - fdBold->setIconSize(QSize(30, 30)); fdBold->setCheckable(true); - fdBold->setFlat(true); fdBold->setChecked(m_attr.textFont.bold()); connect(fdBold, &QPushButton::toggled, this, [this](bool checked) { m_attr.textFont.setBold(checked); @@ -499,15 +567,10 @@ QWidget* eAClock::attrWgt() { }); hBox->addWidget(fdBold); - auto fdItalic = new QPushButton(); + auto fdItalic = new QPushButton("I"); + fdItalic->setStyleSheet("QPushButton{background: #bbb; color: #888; font-size: 20px; font-style: italic;} QPushButton:checked{background: #29c; color: #fff;}"); fdItalic->setFixedSize(30, 30); - QIcon icon1; - icon1.addFile(":/res/ProgramManager/EditProgram/FontItalics_u.png", QSize(), QIcon::Normal, QIcon::Off); - icon1.addFile(":/res/ProgramManager/EditProgram/FontItalics_s.png", QSize(), QIcon::Normal, QIcon::On); - fdItalic->setIcon(icon1); - fdItalic->setIconSize(QSize(30, 30)); fdItalic->setCheckable(true); - fdItalic->setFlat(true); fdItalic->setChecked(m_attr.textFont.italic()); connect(fdItalic, &QPushButton::toggled, this, [this](bool checked) { m_attr.textFont.setItalic(checked); @@ -515,15 +578,10 @@ QWidget* eAClock::attrWgt() { }); hBox->addWidget(fdItalic); - auto fdUnderline = new QPushButton(); + auto fdUnderline = new QPushButton("U"); + fdUnderline->setStyleSheet("QPushButton{background: #bbb; color: #888; font-size: 20px; text-decoration: underline;} QPushButton:checked{background: #29c; color: #fff;}"); fdUnderline->setFixedSize(30, 30); - QIcon icon2; - icon2.addFile(":/res/ProgramManager/EditProgram/FontUnderline_u.png", QSize(), QIcon::Normal, QIcon::Off); - icon2.addFile(":/res/ProgramManager/EditProgram/FontUnderline_s.png", QSize(), QIcon::Normal, QIcon::On); - fdUnderline->setIcon(icon2); - fdUnderline->setIconSize(QSize(30, 30)); fdUnderline->setCheckable(true); - fdUnderline->setFlat(true); fdUnderline->setChecked(m_attr.textFont.underline()); connect(fdUnderline, &QPushButton::toggled, this, [this](bool checked) { m_attr.textFont.setUnderline(checked); @@ -541,9 +599,8 @@ QWidget* eAClock::attrWgt() { hBox->addStretch(); - vBox->addLayout(hBox); - hBox = new QHBoxLayout(); + hBox = new HBox(vBox); hBox->addWidget(new QLabel(tr("Play Properties"))); line = new QFrame(); @@ -551,9 +608,8 @@ QWidget* eAClock::attrWgt() { line->setFrameShadow(QFrame::Sunken); hBox->addWidget(line, 1); - vBox->addLayout(hBox); - hBox = new QHBoxLayout(); + hBox = new HBox(vBox); hBox->addSpacing(6); hBox->addWidget(new QLabel(tr("Play Duration"))); @@ -568,12 +624,11 @@ QWidget* eAClock::attrWgt() { hBox->addWidget(new QLabel(tr("s"))); hBox->addStretch(); - vBox->addLayout(hBox); vBox->addStretch(); return wgtAttr; } -bool eAClock::save(const QString &pRoot){ +bool EAClock::save(const QString &pRoot){ if(m_attr.hasDialImg) { QString file0 = m_attr.path + PAGEDEL_SUFFIX + "/" + m_attr.name; QString file1 = m_attr.path + "/" + m_attr.name; @@ -595,45 +650,50 @@ bool eAClock::save(const QString &pRoot){ m_attr.selfCreateDialName = QString("%1%2%3%4%5.png").arg((int)zValue()).arg((int)x()).arg((int)y()).arg((int)mWidth).arg((int)mHeight); m_attr.path = pRoot; QRectF inner = innerRect(); - QPixmap *tempPixamp = new QPixmap(inner.width(), inner.height()); - tempPixamp->fill(Qt::transparent); - QPainter painter; - painter.begin(tempPixamp); - this->paintDial(&painter); - this->paintText(&painter); - painter.end(); - tempPixamp->save(pRoot+"/"+m_attr.selfCreateDialName, "PNG"); - delete tempPixamp; - //生成表盘背景图 + QImage img(inner.width(), inner.height(), QImage::Format_ARGB32); + img.fill(Qt::transparent); + { + QPainter painter(&img); + paintDial(&painter); + paintText(&painter); + } + img.save(pRoot+"/"+m_attr.selfCreateDialName, "PNG"); return true; } -QJsonObject eAClock::attrJson() const { - QJsonObject oRoot; - addBaseAttr(oRoot); - oRoot["elementType"] = "AClock"; - QJsonObject oWidget; - oWidget["timeZone"] = QString::fromUtf8(m_attr.timeZoneId); - oWidget["hourMark"] = m_attr.hourMark; - oWidget["hourMarkSize"] = m_attr.hourMarkSize; - oWidget["hourMarkColor"] = m_attr.hourMarkColor.name(); - oWidget["minMark"] = m_attr.minMark; - oWidget["minMarkSize"] = m_attr.minMarkSize; - oWidget["minMarkColor"] = m_attr.minMarkColor.name(); - oWidget["hourHandColor"] = m_attr.hourHandColor.name(); - oWidget["minHandColor"] = m_attr.minHandColor.name(); - oWidget["secHandColor"] = m_attr.secHandColor.name(); - oWidget["text"] = m_attr.text; - oWidget["textFontFamily"] = m_attr.textFont.family(); - oWidget["textFontSize"] = m_attr.textFont.pointSize(); - oWidget["textFontBold"] = m_attr.textFont.bold(); - oWidget["textFontItalics"] = m_attr.textFont.italic(); - oWidget["textFontUnderline"] = m_attr.textFont.underline(); - oWidget["textColor"] = m_attr.textColor.name(); - oWidget["path"] = m_attr.path; - oWidget["name"] = m_attr.name; - oWidget["selfCreateDialName"] = m_attr.selfCreateDialName; - oWidget["bCustomDial"] = m_attr.hasDialImg; - oRoot["widget"] = oWidget; - oRoot["play"] = QJsonObject{{"duration", m_attr.playDuration}}; - return oRoot; +QJsonObject EAClock::attrJson() const { + QJsonObject json; + addBaseAttr(json); + json["elementType"] = "AClock"; + QJsonObject widget; + widget["timeZone"] = QString::fromUtf8(m_attr.timeZone.id()); + widget["hourMark"] = m_attr.hourMark; + widget["hourMarkSize"] = m_attr.hourMarkSize; + widget["hourMarkColor"] = m_attr.hourMarkColor.name(); + widget["minMark"] = m_attr.minMark; + widget["minMarkSize"] = m_attr.minMarkSize; + widget["minMarkColor"] = m_attr.minMarkColor.name(); + widget["hourHandColor"] = m_attr.hourHandColor.name(); + widget["minHandColor"] = m_attr.minHandColor.name(); + widget["secHandColor"] = m_attr.secHandColor.name(); + widget["text"] = m_attr.text; + widget["textFontFamily"] = m_attr.textFont.family(); + widget["textFontSize"] = m_attr.textFont.pointSize(); + widget["textFontBold"] = m_attr.textFont.bold(); + widget["textFontItalics"] = m_attr.textFont.italic(); + widget["textFontUnderline"] = m_attr.textFont.underline(); + widget["textColor"] = m_attr.textColor.name(); + widget["hhLen"] = m_attr.hhLen; + widget["mhLen"] = m_attr.mhLen; + widget["shLen"] = m_attr.shLen; + widget["hhWidth"] = m_attr.hhWidth; + widget["mhWidth"] = m_attr.mhWidth; + widget["shWidth"] = m_attr.shWidth; + widget["showSecHand"] = m_attr.showSecHand; + widget["path"] = m_attr.path; + widget["name"] = m_attr.name; + widget["selfCreateDialName"] = m_attr.selfCreateDialName; + widget["bCustomDial"] = m_attr.hasDialImg; + json["widget"] = widget; + json["play"] = QJsonObject{{"duration", m_attr.playDuration}}; + return json; } diff --git a/LedOK/program/eaclock.h b/LedOK/program/eaclock.h new file mode 100644 index 0000000..785ce4c --- /dev/null +++ b/LedOK/program/eaclock.h @@ -0,0 +1,67 @@ +#ifndef EACLOCK_H +#define EACLOCK_H + +#include "ebase.h" +#include +#include + +class EAClock : public EBase { + Q_OBJECT +public: + struct Data { + QTimeZone timeZone; + int hourMark{0};//时针 + int hourMarkSize{5};//时针大小 + QColor hourMarkColor{Qt::green};//时针颜色 + int minMark{1};//分针 + int minMarkSize{2};//分针大小 + QColor minMarkColor{Qt::yellow};//分针颜色 + QColor hourHandColor;//秒针 + QColor minHandColor;//秒针大小 + QColor secHandColor;//秒针颜色 + int hhLen{50}, mhLen{75}, shLen{100}; + int hhWidth{15}, mhWidth{10}, shWidth{5}; + // r/2, r / 20 + // r*3/4, r / 30 + // r, r / 40 + QString text;//标题 + QFont textFont{"Arial", 9};//标题字体 + QColor textColor;//标题字体颜色 + int playDuration{10};// + QString path; + QString name; + QString selfCreateDialName; + bool hasDialImg{false}; + bool showSecHand{true}; + }; + + explicit EAClock(EBase *multiWin = nullptr); + explicit EAClock(const QJsonObject &json, EBase *multiWin = nullptr); + + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; + int type() const override { return EBase::AClock; } + QWidget* attrWgt() override; + bool save(const QString &pRoot) override; + QJsonObject attrJson() const override; + +protected: + void timerEvent(QTimerEvent *) override; + void drawMarkCircular (QPainter *painter, const QPointF &pos, const QColor &color, qreal diameter); + void drawMarkRectangle(QPainter *painter, const QPointF &pos, const QColor &color, qreal len, qreal rotate); + void drawMarkNumber (QPainter *painter, const QPointF &pos, const QColor &color, qreal len, int num); + void paintDial(QPainter *painter); + void paintText(QPainter *painter); + + qreal radius() const { + return (qMin(rect().width(), rect().height()) - qMax(m_attr.minMarkSize, m_attr.hourMarkSize)) / 2; + } + + void cal(); + + Data m_attr; + QImage dial_img; + double hAngle, mAngle, sAngle; + int timerId{0}; +}; + +#endif // EACLOCK_H diff --git a/LedOK/wProgramManager/eaudio.cpp b/LedOK/program/eaudio.cpp similarity index 96% rename from LedOK/wProgramManager/eaudio.cpp rename to LedOK/program/eaudio.cpp index 48e05a3..599c72d 100644 --- a/LedOK/wProgramManager/eaudio.cpp +++ b/LedOK/program/eaudio.cpp @@ -1,6 +1,7 @@ #include "eaudio.h" #include "cfg.h" #include "tools.h" +#include "base/ffutil.h" #include #include #include @@ -13,7 +14,7 @@ EAudio *EAudio::create(const QString &file, PageListItem *pageItem, EBase *multiWin) { int64_t dur; - QString err = Tools::audioInfo(file.toUtf8(), &dur); + QString err = audioInfo(file.toUtf8(), &dur); if(! err.isEmpty()) { QMessageBox::critical(gMainWin, "Audio Error", err+"\n"+file); return nullptr; @@ -79,7 +80,7 @@ bool EAudio::save(const QString &pageDir) { void EAudio::paint(QPainter *painter, const QStyleOptionGraphicsItem *a, QWidget *b) { painter->setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform); - static auto img = QPixmap(":/res/ProgramManager/EditProgram/Audio.png"); + static auto img = QPixmap(":/res/program/Audio.png"); auto inner = innerRect(); if(inner.width() > inner.height()) inner.setWidth(inner.height()); else if(inner.height() > inner.width()) inner.setHeight(inner.width()); @@ -144,7 +145,7 @@ QWidget* EAudio::attrWgt() { auto file = QFileDialog::getOpenFileName(gMainWin, tr("Select File"), gFileHome, EAudio::filters()); if(file.isEmpty()) return; int64_t dur; - QString err = Tools::audioInfo(file.toUtf8(), &dur); + QString err = audioInfo(file.toUtf8(), &dur); if(! err.isEmpty()) { QMessageBox::critical(gMainWin, "Audio Error", err+"\n"+file); return; diff --git a/LedOK/wProgramManager/eaudio.h b/LedOK/program/eaudio.h similarity index 100% rename from LedOK/wProgramManager/eaudio.h rename to LedOK/program/eaudio.h diff --git a/LedOK/wProgramManager/ebase.cpp b/LedOK/program/ebase.cpp similarity index 98% rename from LedOK/wProgramManager/ebase.cpp rename to LedOK/program/ebase.cpp index 50bc2e6..2e32c7b 100644 --- a/LedOK/wProgramManager/ebase.cpp +++ b/LedOK/program/ebase.cpp @@ -1,5 +1,5 @@ #include "ebase.h" -#include "gqt.h" +#include "gutil/qgui.h" #include "tools.h" #include #include @@ -90,7 +90,7 @@ void EBase::addBaseAttr(QJsonObject &obj) const { } QRectF EBase::innerRect() const { - auto ele = mMultiWin!=nullptr ? mMultiWin : this; + auto ele = mMultiWin ? mMultiWin : this; int bdWidth = ele->bdImgIdx > -1 ? borderImgs[ele->bdImgIdx].img.height() : 0; return QRectF(bdWidth, bdWidth, ele->mWidth-bdWidth-bdWidth, ele->mHeight-bdWidth-bdWidth); } @@ -520,7 +520,7 @@ void EBase::clearSnap() { update(); } -void EBase::addBaseAttrWgt(QVBoxLayout *vBox) { +void EBase::addBaseAttrWgt(QBoxLayout *vBox) { if(mMultiWin!=nullptr) return; auto hBox = new QHBoxLayout(); hBox->addWidget(new QLabel(tr("Area"))); @@ -648,10 +648,11 @@ void EBase::addBaseAttrWgt(QVBoxLayout *vBox) { hBox->setSpacing(0); hBox->addStretch(); - auto borderFd = new QComboBox(); + auto borderFd = new QComboBox; borderFd->addItem(tr("None")); for(int i=0; iaddItem(QIcon(borderImgs[i].img), QString::number(borderImgs[i].img.height()), borderImgs[i].name); borderFd->setIconSize(QSize(borderImgMaxWidth, borderImgMaxHeight)); + if(bdImgIdx>-1) borderFd->setCurrentIndex(bdImgIdx+1); connect(borderFd, (void(QComboBox::*)(int))&QComboBox::currentIndexChanged, this, [this](int idx){ bdImgIdx = idx-1; if(bdImgIdx==-1 && bdTimerId>0) { @@ -670,6 +671,7 @@ void EBase::addBaseAttrWgt(QVBoxLayout *vBox) { borderEffFd->addItem(tr("Rotate"), "rotate"); borderEffFd->addItem(tr("Blink"), "blink"); borderEffFd->addItem(tr("None"), ""); + if(bdImgIdx>-1) setCurrentData(borderEffFd, bdEff); connect(borderEffFd, (void(QComboBox::*)(int))&QComboBox::currentIndexChanged, this, [this, borderEffFd] { bdEff = borderEffFd->currentData().toString(); if(bdTimerId>0) { @@ -687,7 +689,7 @@ void EBase::addBaseAttrWgt(QVBoxLayout *vBox) { borderSpeedFd->addItem(tr("Slow"), 1); borderSpeedFd->addItem(tr("Moderate"), 2); borderSpeedFd->addItem(tr("Fast"), 3); - borderSpeedFd->setCurrentIndex(1); + if(bdImgIdx>-1) setCurrentData(borderSpeedFd, bdSpeed); connect(borderSpeedFd, (void(QComboBox::*)(int))&QComboBox::currentIndexChanged, this, [this, borderSpeedFd] { bdSpeed = borderSpeedFd->currentData().toInt(); if(bdTimerId>0) { @@ -700,10 +702,4 @@ void EBase::addBaseAttrWgt(QVBoxLayout *vBox) { hBox->addStretch(); vBox->addLayout(hBox); - - if(bdImgIdx>-1) { - borderFd->setCurrentIndex(bdImgIdx+1); - select(borderEffFd, bdEff); - select(borderSpeedFd, bdSpeed); - } } diff --git a/LedOK/wProgramManager/ebase.h b/LedOK/program/ebase.h similarity index 98% rename from LedOK/wProgramManager/ebase.h rename to LedOK/program/ebase.h index 578b52b..7a88e12 100644 --- a/LedOK/wProgramManager/ebase.h +++ b/LedOK/program/ebase.h @@ -31,7 +31,7 @@ public: virtual bool save(const QString &) {return true;} virtual QWidget* attrWgt() = 0; - void addBaseAttrWgt(QVBoxLayout *vBox); + void addBaseAttrWgt(QBoxLayout *vBox); inline void setSize(qreal width, qreal height) { prepareGeometryChange(); mWidth = width; diff --git a/LedOK/wProgramManager/edclock.cpp b/LedOK/program/edclock.cpp similarity index 89% rename from LedOK/wProgramManager/edclock.cpp rename to LedOK/program/edclock.cpp index b5ece55..a63fb8d 100644 --- a/LedOK/wProgramManager/edclock.cpp +++ b/LedOK/program/edclock.cpp @@ -7,8 +7,9 @@ #include #include #include +#include -eDClock::eDClock(EBase *multiWin) : EBase(multiWin) { +EDClock::EDClock(EBase *multiWin) : EBase(multiWin) { mType = EBase::DClock; m_attr.timeZoneId = QTimeZone::systemTimeZoneId(); m_attr.font = QFont("Arial", 9); @@ -29,7 +30,7 @@ eDClock::eDClock(EBase *multiWin) : EBase(multiWin) { init(); } -eDClock::eDClock(const QJsonObject &json, EBase *multiWin) : EBase(multiWin) { +EDClock::EDClock(const QJsonObject &json, EBase *multiWin) : EBase(multiWin) { mType = EBase::DClock; setBaseAttr(json); auto widget = json["widget"]; @@ -58,14 +59,14 @@ eDClock::eDClock(const QJsonObject &json, EBase *multiWin) : EBase(multiWin) { init(); } -void eDClock::init() { +void EDClock::init() { connect(Tools::getInstance(), &Tools::sTick, this, [this]() { datetime = QDateTime::currentDateTime().toTimeZone(QTimeZone(m_attr.timeZoneId)); update(); }); } -void eDClock::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { +void EDClock::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { QString text; QDate date = datetime.date(); QTime time = datetime.time(); @@ -133,7 +134,7 @@ void eDClock::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, Q EBase::paint(painter, option, widget); } -QWidget* eDClock::attrWgt() { +QWidget* EDClock::attrWgt() { auto wgtAttr = new QWidget(); auto vBox = new QVBoxLayout(wgtAttr); vBox->setContentsMargins(6, 0, 6, 0); @@ -378,15 +379,10 @@ QWidget* eDClock::attrWgt() { hBox = new QHBoxLayout(); hBox->addSpacing(6); - auto fdBold = new QPushButton(); + auto fdBold = new QPushButton("B"); + fdBold->setStyleSheet("QPushButton{background: #bbb; color: #888; font-size: 20px; font-weight: bold;} QPushButton:checked{background: #29c; color: #fff;}"); fdBold->setFixedSize(30, 30); - QIcon icon; - icon.addFile(QString::fromUtf8(":/res/ProgramManager/EditProgram/FontBold_u.png"), QSize(), QIcon::Normal, QIcon::Off); - icon.addFile(QString::fromUtf8(":/res/ProgramManager/EditProgram/FontBold_s.png"), QSize(), QIcon::Normal, QIcon::On); - fdBold->setIcon(icon); - fdBold->setIconSize(QSize(30, 30)); fdBold->setCheckable(true); - fdBold->setFlat(true); fdBold->setChecked(m_attr.font.bold()); connect(fdBold, &QCheckBox::toggled, this, [this](bool checked) { m_attr.font.setBold(checked); @@ -394,15 +390,10 @@ QWidget* eDClock::attrWgt() { }); hBox->addWidget(fdBold); - auto fdItalic = new QPushButton(); + auto fdItalic = new QPushButton("I"); + fdItalic->setStyleSheet("QPushButton{background: #bbb; color: #888; font-size: 20px; font-style: italic;} QPushButton:checked{background: #29c; color: #fff;}"); fdItalic->setFixedSize(30, 30); - QIcon icon1; - icon1.addFile(QString::fromUtf8(":/res/ProgramManager/EditProgram/FontItalics_u.png"), QSize(), QIcon::Normal, QIcon::Off); - icon1.addFile(QString::fromUtf8(":/res/ProgramManager/EditProgram/FontItalics_s.png"), QSize(), QIcon::Normal, QIcon::On); - fdItalic->setIcon(icon1); - fdItalic->setIconSize(QSize(30, 30)); fdItalic->setCheckable(true); - fdItalic->setFlat(true); fdItalic->setChecked(m_attr.font.italic()); connect(fdItalic, &QCheckBox::toggled, this, [this](bool checked) { m_attr.font.setItalic(checked); @@ -410,21 +401,16 @@ QWidget* eDClock::attrWgt() { }); hBox->addWidget(fdItalic); - auto fdUnderline = new QPushButton(); - fdUnderline->setFixedSize(30, 30); - QIcon icon2; - icon2.addFile(QString::fromUtf8(":/res/ProgramManager/EditProgram/FontUnderline_u.png"), QSize(), QIcon::Normal, QIcon::Off); - icon2.addFile(QString::fromUtf8(":/res/ProgramManager/EditProgram/FontUnderline_s.png"), QSize(), QIcon::Normal, QIcon::On); - fdUnderline->setIcon(icon2); - fdUnderline->setIconSize(QSize(30, 30)); - fdUnderline->setCheckable(true); - fdUnderline->setFlat(true); - fdUnderline->setChecked(m_attr.font.underline()); - connect(fdUnderline, &QCheckBox::toggled, this, [this](bool checked) { + auto fdFontUnderline = new QPushButton("U"); + fdFontUnderline->setStyleSheet("QPushButton{background: #bbb; color: #888; font-size: 20px; text-decoration: underline;} QPushButton:checked{background: #29c; color: #fff;}"); + fdFontUnderline->setFixedSize(30, 30); + fdFontUnderline->setCheckable(true); + fdFontUnderline->setChecked(m_attr.font.underline()); + connect(fdFontUnderline, &QCheckBox::toggled, this, [this](bool checked) { m_attr.font.setUnderline(checked); update(); }); - hBox->addWidget(fdUnderline); + hBox->addWidget(fdFontUnderline); auto fdColor = new LoColorSelector("T", m_attr.textColor); fdColor->setFixedWidth(30); @@ -467,7 +453,7 @@ QWidget* eDClock::attrWgt() { return wgtAttr; } -QJsonObject eDClock::attrJson() const{ +QJsonObject EDClock::attrJson() const{ QJsonObject oWidget; oWidget["timeZone"] = QString::fromUtf8(m_attr.timeZoneId); oWidget["year"] = m_attr.year; diff --git a/LedOK/wProgramManager/edclock.h b/LedOK/program/edclock.h similarity index 88% rename from LedOK/wProgramManager/edclock.h rename to LedOK/program/edclock.h index 23cbba9..fbce201 100644 --- a/LedOK/wProgramManager/edclock.h +++ b/LedOK/program/edclock.h @@ -9,7 +9,7 @@ #include #include "ebase.h" -class eDClock : public EBase { +class EDClock : public EBase { Q_OBJECT public: struct Data { @@ -32,8 +32,8 @@ public: int playDuration = 10; }; - explicit eDClock(EBase *multiWin = nullptr); - explicit eDClock(const QJsonObject &json, EBase *multiWin = nullptr); + explicit EDClock(EBase *multiWin = nullptr); + explicit EDClock(const QJsonObject &json, EBase *multiWin = nullptr); void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; int type() const override { return EBase::DClock; } diff --git a/LedOK/wProgramManager/eenviron.cpp b/LedOK/program/eenviron.cpp similarity index 94% rename from LedOK/wProgramManager/eenviron.cpp rename to LedOK/program/eenviron.cpp index e5a2d20..4a92384 100644 --- a/LedOK/wProgramManager/eenviron.cpp +++ b/LedOK/program/eenviron.cpp @@ -13,6 +13,7 @@ #include #include #include +#include QJsonObject EEnviron::genProg(const QJsonObject &json, const QString &dstDir, const QString &srcPageDir) { auto widget = json["widget"]; @@ -602,54 +603,41 @@ QWidget* EEnviron::attrWgt() { hBox = new QHBoxLayout(); hBox->addSpacing(6); - auto fdBold = new QPushButton(); - fdBold->setFixedSize(QSize(30, 30)); - fdBold->setIconSize(QSize(30, 30)); - QIcon icon(":/res/ProgramManager/EditProgram/FontBold_u.png"); - icon.addFile(":/res/ProgramManager/EditProgram/FontBold_s.png", QSize(), QIcon::Normal, QIcon::On); - fdBold->setIcon(icon); - fdBold->setCheckable(true); - fdBold->setFlat(true); - fdBold->setChecked(m_attr.font.bold()); - connect(fdBold, &QPushButton::toggled, this, [this](bool checked) { + auto fdFontBold = new QPushButton("B"); + fdFontBold->setStyleSheet("QPushButton{background: #bbb; color: #888; font-size: 20px; font-weight: bold;} QPushButton:checked{background: #29c; color: #fff;}"); + fdFontBold->setFixedSize(30, 30); + fdFontBold->setCheckable(true); + fdFontBold->setChecked(m_attr.font.bold()); + connect(fdFontBold, &QPushButton::toggled, this, [this](bool checked) { m_attr.font.setBold(checked); calAttr(); update(); }); - hBox->addWidget(fdBold); + hBox->addWidget(fdFontBold); - auto fdItalic = new QPushButton(); - fdItalic->setFixedSize(QSize(30, 30)); - fdItalic->setIconSize(QSize(30, 30)); - QIcon icon1(":/res/ProgramManager/EditProgram/FontItalics_u.png"); - icon1.addFile(":/res/ProgramManager/EditProgram/FontItalics_s.png", QSize(), QIcon::Normal, QIcon::On); - fdItalic->setIcon(icon1); - fdItalic->setCheckable(true); - fdItalic->setFlat(true); - fdItalic->setChecked(m_attr.font.italic()); - connect(fdItalic, &QPushButton::toggled, this, [this](bool checked) { + auto fdFontItalic = new QPushButton("I"); + fdFontItalic->setStyleSheet("QPushButton{background: #bbb; color: #888; font-size: 20px; font-style: italic;} QPushButton:checked{background: #29c; color: #fff;}"); + fdFontItalic->setFixedSize(30, 30); + fdFontItalic->setCheckable(true); + fdFontItalic->setChecked(m_attr.font.italic()); + connect(fdFontItalic, &QPushButton::toggled, this, [this](bool checked) { m_attr.font.setItalic(checked); calAttr(); update(); }); - hBox->addWidget(fdItalic); + hBox->addWidget(fdFontItalic); - auto fdUnderline = new QPushButton(); - fdUnderline->setFixedSize(QSize(30, 30)); - fdUnderline->setIconSize(QSize(30, 30)); - QIcon icon2(":/res/ProgramManager/EditProgram/FontUnderline_u.png"); - icon2.addFile(":/res/ProgramManager/EditProgram/FontUnderline_s.png", QSize(), QIcon::Normal, QIcon::On); - fdUnderline->setIcon(icon2); - fdUnderline->setCheckable(true); - fdUnderline->setFlat(true); - fdUnderline->setChecked(m_attr.font.underline()); - connect(fdUnderline, &QPushButton::toggled, this, [this](bool checked) { + auto fdFontUnderline = new QPushButton("U"); + fdFontUnderline->setStyleSheet("QPushButton{background: #bbb; color: #888; font-size: 20px; text-decoration: underline;} QPushButton:checked{background: #29c; color: #fff;}"); + fdFontUnderline->setFixedSize(30, 30); + fdFontUnderline->setCheckable(true); + fdFontUnderline->setChecked(m_attr.font.underline()); + connect(fdFontUnderline, &QPushButton::toggled, this, [this](bool checked) { m_attr.font.setUnderline(checked); calAttr(); update(); }); - hBox->addWidget(fdUnderline); - + hBox->addWidget(fdFontUnderline); auto fdColor = new LoColorSelector("T", m_attr.textColor); fdColor->setFixedWidth(30); diff --git a/LedOK/wProgramManager/eenviron.h b/LedOK/program/eenviron.h similarity index 100% rename from LedOK/wProgramManager/eenviron.h rename to LedOK/program/eenviron.h diff --git a/LedOK/wProgramManager/egif.cpp b/LedOK/program/egif.cpp similarity index 100% rename from LedOK/wProgramManager/egif.cpp rename to LedOK/program/egif.cpp diff --git a/LedOK/wProgramManager/egif.h b/LedOK/program/egif.h similarity index 100% rename from LedOK/wProgramManager/egif.h rename to LedOK/program/egif.h diff --git a/LedOK/wProgramManager/emultiwin.cpp b/LedOK/program/emultiwin.cpp similarity index 80% rename from LedOK/wProgramManager/emultiwin.cpp rename to LedOK/program/emultiwin.cpp index 581d074..64a6f08 100644 --- a/LedOK/wProgramManager/emultiwin.cpp +++ b/LedOK/program/emultiwin.cpp @@ -34,8 +34,8 @@ EMultiWin::EMultiWin(const QJsonObject &json, PageListItem *pageItem) : mPageIte else if(type=="Photo") inner = EPhoto::create(element.toObject(), pageItem, this); else if(type=="Gif") inner = EGif::create(element.toObject(), pageItem, this); else if(type=="Movie") inner = EVideo::create(element.toObject(), pageItem, this); - else if(type=="DClock") inner = new eDClock(element.toObject(), this); - else if(type=="AClock") inner = new eAClock(element.toObject(), this); + else if(type=="DClock") inner = new EDClock(element.toObject(), this); + else if(type=="AClock") inner = new EAClock(element.toObject(), this); else if(type=="Temp") inner = new EEnviron(element.toObject(), this); else if(type=="Web") inner = new EWeb(element.toObject(), this); else if(type=="Timer") inner = new ETimer(element.toObject(), this); @@ -123,16 +123,16 @@ QWidget* EMultiWin::attrWgt() { auto hBox = new QHBoxLayout(); auto btnAdd = new QPushButton(); - btnAdd->setIcon(QIcon(":/res/ProgramManager/EditProgram/Add.png")); + btnAdd->setIcon(QIcon(":/res/program/Add.png")); btnAdd->setProperty("style","multiTool"); auto menu = new QMenu(); - menu->addAction(QIcon(":/res/ProgramManager/EditProgram/Text.png"), tr("Text"))->setData(EBase::Text); - menu->addAction(QIcon(":/res/ProgramManager/EditProgram/Photo.png"), tr("Photo"))->setData(EBase::Photo); - menu->addAction(QIcon(":/res/ProgramManager/EditProgram/Movie.png"), tr("Video"))->setData(EBase::Video); - menu->addAction(QIcon(":/res/ProgramManager/EditProgram/Gif.png"), tr("Gif"))->setData(EBase::Gif); - menu->addAction(QIcon(":/res/ProgramManager/EditProgram/DClock.png"), tr("DClock"))->setData(EBase::DClock); - menu->addAction(QIcon(":/res/ProgramManager/EditProgram/AClock.png"), tr("AClock"))->setData(EBase::AClock); + menu->addAction(QIcon(":/res/program/Text.png"), tr("Text"))->setData(EBase::Text); + menu->addAction(QIcon(":/res/program/Photo.png"), tr("Photo"))->setData(EBase::Photo); + menu->addAction(QIcon(":/res/program/Movie.png"), tr("Video"))->setData(EBase::Video); + menu->addAction(QIcon(":/res/program/Gif.png"), tr("Gif"))->setData(EBase::Gif); + menu->addAction(QIcon(":/res/program/DClock.png"), tr("DClock"))->setData(EBase::DClock); + menu->addAction(QIcon(":/res/program/AClock.png"), tr("AClock"))->setData(EBase::AClock); auto listWgt = new MListWidget(); connect(menu, &QMenu::triggered, this, [this, listWgt](QAction *act) { int type = act->data().toInt(); @@ -148,7 +148,7 @@ QWidget* EMultiWin::attrWgt() { ePhoto->setZValue(order++); ePhoto->setFlag(QGraphicsItem::ItemStacksBehindParent); inners.append(ePhoto); - auto item = new QListWidgetItem(QIcon(":/res/ProgramManager/EditProgram/Photo.png"), tr("Photo")+" "+ePhoto->mName); + auto item = new QListWidgetItem(QIcon(":/res/program/Photo.png"), tr("Photo")+" "+ePhoto->mName); item->setData(Qt::UserRole, QVariant::fromValue(static_cast(ePhoto))); listWgt->addItem(item); if(i==files.count()-1) { @@ -165,7 +165,7 @@ QWidget* EMultiWin::attrWgt() { eGif->setZValue(order++); eGif->setFlag(QGraphicsItem::ItemStacksBehindParent); inners.append(eGif); - auto item = new QListWidgetItem(QIcon(":/res/ProgramManager/EditProgram/Gif.png"), tr("Gif")+" "+eGif->mName); + auto item = new QListWidgetItem(QIcon(":/res/program/Gif.png"), tr("Gif")+" "+eGif->mName); item->setData(Qt::UserRole, QVariant::fromValue(static_cast(eGif))); listWgt->addItem(item); if(i == files.count()-1) { @@ -178,25 +178,25 @@ QWidget* EMultiWin::attrWgt() { if(! file.isEmpty()) { auto eVideo = EVideo::create(file, mPageItem, this); if(eVideo==nullptr) return; - item = new QListWidgetItem(QIcon(":/res/ProgramManager/EditProgram/Movie.png"), tr("Video")+" "+eVideo->mRawName); + item = new QListWidgetItem(QIcon(":/res/program/Movie.png"), tr("Video")+" "+eVideo->mRawName); gFileHome = eVideo->mRawDir; ele = eVideo; } } else if(type==EBase::Text) { ele = new EText(this); - item = new QListWidgetItem(QIcon(":/res/ProgramManager/EditProgram/Text.png"), tr("Text")); + item = new QListWidgetItem(QIcon(":/res/program/Text.png"), tr("Text")); } else if(type==EBase::DClock) { - ele = new eDClock(this); - item = new QListWidgetItem(QIcon(":/res/ProgramManager/EditProgram/DClock.png"), tr("DClock")); + ele = new EDClock(this); + item = new QListWidgetItem(QIcon(":/res/program/DClock.png"), tr("DClock")); } else if(type==EBase::AClock) { - ele = new eAClock(this); - item = new QListWidgetItem(QIcon(":/res/ProgramManager/EditProgram/AClock.png"), tr("AClock")); + ele = new EAClock(this); + item = new QListWidgetItem(QIcon(":/res/program/AClock.png"), tr("AClock")); } else if(type==EBase::Environ) { ele = new EEnviron(this); - item = new QListWidgetItem(QIcon(":/res/ProgramManager/EditProgram/Temp.png"), tr("Environment")); + item = new QListWidgetItem(QIcon(":/res/program/Temp.png"), tr("Environment")); } else if(type==EBase::Timer) { ele = new ETimer(this); - item = new QListWidgetItem(QIcon(":/res/ProgramManager/EditProgram/Timer.png"), tr("Timer")); + item = new QListWidgetItem(QIcon(":/res/program/Timer.png"), tr("Timer")); } if(ele != nullptr) { ele->setSize(mWidth, mHeight); @@ -212,7 +212,7 @@ QWidget* EMultiWin::attrWgt() { hBox->addWidget(btnAdd); auto btnDel = new QPushButton(); - btnDel->setIcon(QIcon(":/res/ProgramManager/EditProgram/Delete.png")); + btnDel->setIcon(QIcon(":/res/program/Delete.png")); btnDel->setProperty("style","multiTool"); connect(btnDel, &QPushButton::clicked, this, [this, listWgt] { auto row = listWgt->currentRow(); @@ -229,7 +229,7 @@ QWidget* EMultiWin::attrWgt() { hBox->addWidget(btnDel); auto btnClean = new QPushButton(); - btnClean->setIcon(QIcon(":/res/ProgramManager/EditProgram/Clean.png")); + btnClean->setIcon(QIcon(":/res/program/Clean.png")); btnClean->setProperty("style","multiTool"); connect(btnClean, &QPushButton::clicked, this, [this, listWgt] { listWgt->clear(); @@ -239,7 +239,7 @@ QWidget* EMultiWin::attrWgt() { hBox->addWidget(btnClean); auto btnGoUp = new QPushButton(); - btnGoUp->setIcon(QIcon(":/res/ProgramManager/EditProgram/GoUp.png")); + btnGoUp->setIcon(QIcon(":/res/program/GoUp.png")); btnGoUp->setProperty("style","multiTool"); connect(btnGoUp, &QPushButton::clicked, this, [this, listWgt] { int row = listWgt->currentRow(); @@ -253,7 +253,7 @@ QWidget* EMultiWin::attrWgt() { hBox->addWidget(btnGoUp); auto btnGoDown = new QPushButton(); - btnGoDown->setIcon(QIcon(":/res/ProgramManager/EditProgram/GoDown.png")); + btnGoDown->setIcon(QIcon(":/res/program/GoDown.png")); btnGoDown->setProperty("style","multiTool"); connect(btnGoDown, &QPushButton::clicked, this, [this, listWgt] { int row = listWgt->currentRow(); @@ -273,14 +273,14 @@ QWidget* EMultiWin::attrWgt() { foreach(auto inner, inners) { QListWidgetItem *item = nullptr; int type = inner->type(); - if(type==EBase::Text) item = new QListWidgetItem(QIcon(":/res/ProgramManager/EditProgram/Text.png"), tr("Text")); - else if(type==EBase::Photo) item = new QListWidgetItem(QIcon(":/res/ProgramManager/EditProgram/Photo.png"), tr("Photo")+" "+static_cast(inner)->mName); - else if(type==EBase::Video) item = new QListWidgetItem(QIcon(":/res/ProgramManager/EditProgram/Movie.png"), tr("Video")+" "+static_cast(inner)->mRawName); - else if(type==EBase::Gif) item = new QListWidgetItem(QIcon(":/res/ProgramManager/EditProgram/Gif.png"), tr("Gif")+" "+static_cast(inner)->mName); - else if(type==EBase::DClock) item = new QListWidgetItem(QIcon(":/res/ProgramManager/EditProgram/DClock.png"), tr("DClock")); - else if(type==EBase::AClock) item = new QListWidgetItem(QIcon(":/res/ProgramManager/EditProgram/AClock.png"), tr("AClock")); - else if(type==EBase::Environ) item = new QListWidgetItem(QIcon(":/res/ProgramManager/EditProgram/Temp.png"), tr("Environment")); - else if(type==EBase::Timer) item = new QListWidgetItem(QIcon(":/res/ProgramManager/EditProgram/Timer.png"), tr("Timer")); + if(type==EBase::Text) item = new QListWidgetItem(QIcon(":/res/program/Text.png"), tr("Text")); + else if(type==EBase::Photo) item = new QListWidgetItem(QIcon(":/res/program/Photo.png"), tr("Photo")+" "+static_cast(inner)->mName); + else if(type==EBase::Video) item = new QListWidgetItem(QIcon(":/res/program/Movie.png"), tr("Video")+" "+static_cast(inner)->mRawName); + else if(type==EBase::Gif) item = new QListWidgetItem(QIcon(":/res/program/Gif.png"), tr("Gif")+" "+static_cast(inner)->mName); + else if(type==EBase::DClock) item = new QListWidgetItem(QIcon(":/res/program/DClock.png"), tr("DClock")); + else if(type==EBase::AClock) item = new QListWidgetItem(QIcon(":/res/program/AClock.png"), tr("AClock")); + else if(type==EBase::Environ) item = new QListWidgetItem(QIcon(":/res/program/Temp.png"), tr("Environment")); + else if(type==EBase::Timer) item = new QListWidgetItem(QIcon(":/res/program/Timer.png"), tr("Timer")); if(item != nullptr) { item->setData(Qt::UserRole, QVariant::fromValue(static_cast(inner))); listWgt->addItem(item); diff --git a/LedOK/wProgramManager/emultiwin.h b/LedOK/program/emultiwin.h similarity index 100% rename from LedOK/wProgramManager/emultiwin.h rename to LedOK/program/emultiwin.h diff --git a/LedOK/wProgramManager/ephoto.cpp b/LedOK/program/ephoto.cpp similarity index 95% rename from LedOK/wProgramManager/ephoto.cpp rename to LedOK/program/ephoto.cpp index 531b807..b2451a9 100644 --- a/LedOK/wProgramManager/ephoto.cpp +++ b/LedOK/program/ephoto.cpp @@ -76,14 +76,14 @@ void EPhoto::loadFiles() { if(! img.isNull()) return; if(! QFileInfo::exists(mDir + "/" + mName)) return; img = QImage(mDir + "/" + mName); - if(gProgItem->mSplitWidth) { - int cnt = (gProgItem->mWidth+gProgItem->mSplitWidth-1) / gProgItem->mSplitWidth; - QImage square(gProgItem->mSplitWidth, gProgItem->mHeight*cnt, QImage::Format_ARGB32); + if(gProgItem->mMaxWidth) { + QImage square(gProgItem->mMaxWidth, gProgItem->mHeight*gProgItem->mSplitWidths.size(), QImage::Format_ARGB32); QPainter painter(&square); - auto rect = innerRect(); + QRectF rect(x(), y(), mWidth, mHeight); painter.drawImage(rect, img); - for(int i=1; imSplitWidth, rect.y() + gProgItem->mHeight); + auto end = gProgItem->mSplitWidths.size() - 1; + for(int i=0; imSplitWidths[i], rect.y() + gProgItem->mHeight); painter.drawImage(rect, img); } square.save(mDir + "/" + mName+"-square.png", "PNG"); diff --git a/LedOK/wProgramManager/ephoto.h b/LedOK/program/ephoto.h similarity index 100% rename from LedOK/wProgramManager/ephoto.h rename to LedOK/program/ephoto.h diff --git a/LedOK/program/etext.cpp b/LedOK/program/etext.cpp new file mode 100644 index 0000000..421f667 --- /dev/null +++ b/LedOK/program/etext.cpp @@ -0,0 +1,819 @@ +#include "base/locolorselector.h" +#include "cfg.h" +#include "etext.h" +#include "globaldefine.h" +#include "tools.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static QColor charColors[]{"#fff","#f00","#f00","#f0f","#c0c","#ff0","#f80","#0f0","#0f0","#0a0","#0a0","#7b0","#00f","#00f","#0af","#0ef"}; + +EText::EText(EBase *multiWin) : EBase(multiWin) { + mType = EBase::Text; + m_attr.text = ""+tr("Enter your text")+""; + connect(this, &EText::sizeChanged, this, &EText::updImg); + updImg(); +} +EText::EText(const QJsonObject &json, EBase *multiWin) : EBase(multiWin) { + mType = EBase::Text; + setBaseAttr(json); + setElement(json, m_attr); + connect(this, &EText::sizeChanged, this, &EText::updImg); + updImg(); +} + +void EText::setElement(const QJsonObject &json, Data &attr) { + auto widget = json["widget"]; + attr.text = widget["text"].toString(); + attr.align = static_cast(widget["align"].toInt()); + auto backColor = widget["backColor"].toString(); + attr.backColor = backColor.isEmpty() ? QColor(0,0,0,0) : QColor(backColor); + auto play = json["play"]; + attr.playMode = play["style"].toInt(); + auto turning = play["turning"]; + attr.flip.effect = turning["strEffect"].toString(); + attr.flip.pageDuration = turning["iEffectTime"].toInt(); + attr.flip.effectDuration = turning["iEffectSpeed"].toInt(); + auto rolling = play["rolling"]; + attr.scroll.effect = rolling["rollingStyle"].toInt(); + attr.scroll.effectSpeed = rolling["rollingSpeed"].toInt(); + attr.scroll.headTailSpacing = rolling["headTailSpacing"].toInt(); + attr.scroll.duration = rolling["playDuration"].toInt(); + attr.duration = play["static"]["playDuration"].toInt(); +} + +class TTextEdit : public QTextEdit { +public: + TTextEdit() {} + explicit TTextEdit(const QString &text) : QTextEdit(text){} + QSize minimumSizeHint() const override { + return sizeHint(); + }; + QSize sizeHint() const override { + auto size = QTextEdit::sizeHint(); + auto minH = minimumHeight(); + if(minH > 0) size.setHeight(minH+0xfff); + return size; + }; +}; +QWidget* EText::attrWgt() { + auto wgtAttr = new QWidget; + auto vBox = new QVBoxLayout(wgtAttr); + vBox->setContentsMargins(4, 0, 4, 0); + vBox->setSpacing(3); + + addBaseAttrWgt(vBox); + + auto hBox = new QHBoxLayout; + hBox->addWidget(new QLabel(tr("Basic Properties"))); + + auto line = new QFrame; + line->setFrameShape(QFrame::HLine); + line->setFrameShadow(QFrame::Sunken); + hBox->addWidget(line, 1); + + vBox->addLayout(hBox); + + hBox = new QHBoxLayout; + + auto fdText = new TTextEdit(""); + + auto fdFontFamily = new QFontComboBox; + fdFontFamily->setEditable(false); + fdFontFamily->setCurrentFont(QFont("黑体")); + connect(fdFontFamily, &QFontComboBox::currentFontChanged, fdText, [fdText](const QFont &f) { + QTextCharFormat fmt; + fmt.setFontFamilies({f.family()}); + QTextCursor cursor = fdText->textCursor(); + if(! cursor.hasSelection()) cursor.select(QTextCursor::WordUnderCursor); + cursor.mergeCharFormat(fmt); + }); + hBox->addWidget(fdFontFamily); + + hBox->addStretch(); + + auto fdFontSize = new QSpinBox; + fdFontSize->setRange(4, 9999); + fdFontSize->setValue(16); + connect(fdFontSize, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, fdText, [fdText](int value) { + if(value <= 0) return; + QTextCharFormat fmt; + fmt.setProperty(QTextFormat::FontPixelSize, value); + QTextCursor cursor = fdText->textCursor(); + if(! cursor.hasSelection()) cursor.select(QTextCursor::WordUnderCursor); + cursor.mergeCharFormat(fmt); + }); + hBox->addWidget(fdFontSize); + + vBox->addLayout(hBox); + + hBox = new QHBoxLayout; + hBox->setSpacing(3); + + auto wTextAlignHL = new QPushButton(QIcon(":/res/program/TextAlignHL.png"), ""); + wTextAlignHL->setStyleSheet("QPushButton{border: none; background: #bbb;} QPushButton:checked{background: #29c;}"); + wTextAlignHL->setFixedSize(30, 30); + wTextAlignHL->setIconSize(QSize(30, 30)); + wTextAlignHL->setCheckable(true); + wTextAlignHL->setChecked(true); + hBox->addWidget(wTextAlignHL); + + auto wTextAlignHC = new QPushButton(QIcon(":/res/program/TextAlignHC.png"), ""); + wTextAlignHC->setStyleSheet("QPushButton{border: none; background: #bbb;} QPushButton:checked{background: #29c;}"); + wTextAlignHC->setFixedSize(30, 30); + wTextAlignHC->setIconSize(QSize(30, 30)); + wTextAlignHC->setCheckable(true); + hBox->addWidget(wTextAlignHC); + + auto wTextAlignHR = new QPushButton(QIcon(":/res/program/TextAlignHR.png"), ""); + wTextAlignHR->setStyleSheet("QPushButton{border: none; background: #bbb;} QPushButton:checked{background: #29c;}"); + wTextAlignHR->setFixedSize(30, 30); + wTextAlignHR->setIconSize(QSize(30, 30)); + wTextAlignHR->setCheckable(true); + hBox->addWidget(wTextAlignHR); + + hBox->addStretch(); + + auto fdFontBold = new QPushButton("B"); + fdFontBold->setStyleSheet("QPushButton{background: #bbb; color: #888; font-size: 20px; font-weight: bold;} QPushButton:checked{background: #29c; color: #fff;}"); + fdFontBold->setFixedSize(30, 30); + fdFontBold->setCheckable(true); + connect(fdFontBold, &QToolButton::toggled, fdText, [fdText](bool checked) { + QTextCharFormat fmt; + fmt.setFontWeight(checked ? QFont::Bold : QFont::Normal); + Tools::mergeFormat(fdText, fmt); + }); + hBox->addWidget(fdFontBold); + + auto fdFontItalic = new QPushButton("I"); + fdFontItalic->setStyleSheet("QPushButton{background: #bbb; color: #888; font-size: 20px; font-style: italic;} QPushButton:checked{background: #29c; color: #fff;}"); + fdFontItalic->setFixedSize(30, 30); + fdFontItalic->setCheckable(true); + connect(fdFontItalic, &QToolButton::toggled, fdText, [fdText](bool checked) { + QTextCharFormat fmt; + fmt.setFontItalic(checked); + Tools::mergeFormat(fdText, fmt); + }); + hBox->addWidget(fdFontItalic); + + auto fdFontUnderline = new QPushButton("U"); + fdFontUnderline->setStyleSheet("QPushButton{background: #bbb; color: #888; font-size: 20px; text-decoration: underline;} QPushButton:checked{background: #29c; color: #fff;}"); + fdFontUnderline->setFixedSize(30, 30); + fdFontUnderline->setCheckable(true); + connect(fdFontUnderline, &QToolButton::toggled, fdText, [fdText](bool checked) { + QTextCharFormat fmt; + fmt.setFontUnderline(checked); + Tools::mergeFormat(fdText, fmt); + }); + hBox->addWidget(fdFontUnderline); + + hBox->addStretch(); + + auto fdTextColor = new LoColorSelector("T", Qt::white); + fdTextColor->setToolTip(tr("Text Color")); + fdTextColor->setFixedSize(30, 30); + connect(fdTextColor, &LoColorSelector::sColorChanged, fdText, [fdText](const QColor &color) { + if(! color.isValid()) return; + QTextCharFormat fmt; + fmt.setForeground(color); + Tools::mergeFormat(fdText, fmt); + }); + hBox->addWidget(fdTextColor); + + auto fdBackColor = new LoColorSelector("B", m_attr.backColor); + fdBackColor->setToolTip(tr("Back Color")); + fdBackColor->setFixedSize(30, 30); + connect(fdBackColor, &LoColorSelector::sColorChanged, this, [this](const QColor &color) { + if(! color.isValid()) return; + m_attr.backColor = color; + updImg(); + }); + hBox->addWidget(fdBackColor); + + auto fdRandomColor = new QPushButton(QIcon(":/res/random.png"), ""); + fdRandomColor->setToolTip(tr("Colorful Text")); + fdRandomColor->setFixedSize(30, 30); + fdRandomColor->setIconSize(QSize(30, 30)); + connect(fdRandomColor, &QPushButton::clicked, fdText, [fdText] { + auto cursor = fdText->textCursor(); + auto len = fdText->document()->characterCount(); + QTextCharFormat fmt; + int last = -1, idx; + for(int i=0; iaddWidget(fdRandomColor); + + vBox->addLayout(hBox); + + hBox = new QHBoxLayout; + hBox->setSpacing(3); + + auto wTextAlignVT = new QPushButton(QIcon(":/res/program/TextAlignVT.png"), ""); + wTextAlignVT->setStyleSheet("QPushButton{border: none; background: #bbb;} QPushButton:checked{background: #29c;}"); + wTextAlignVT->setFixedSize(30, 30); + wTextAlignVT->setIconSize(QSize(30, 30)); + wTextAlignVT->setCheckable(true); + hBox->addWidget(wTextAlignVT); + + auto wTextAlignVC = new QPushButton(QIcon(":/res/program/TextAlignVC.png"), ""); + wTextAlignVC->setStyleSheet("QPushButton{border: none; background: #bbb;} QPushButton:checked{background: #29c;}"); + wTextAlignVC->setFixedSize(30, 30); + wTextAlignVC->setIconSize(QSize(30, 30)); + wTextAlignVC->setCheckable(true); + hBox->addWidget(wTextAlignVC); + + auto wTextAlignVB = new QPushButton(QIcon(":/res/program/TextAlignVB.png"), ""); + wTextAlignVB->setStyleSheet("QPushButton{border: none; background: #bbb;} QPushButton:checked{background: #29c;}"); + wTextAlignVB->setFixedSize(30, 30); + wTextAlignVB->setIconSize(QSize(30, 30)); + wTextAlignVB->setCheckable(true); + hBox->addWidget(wTextAlignVB); + + hBox->addStretch(); + + auto lb = new QLabel(tr("Kerning")); + lb->setToolTip(lb->text()); + hBox->addWidget(lb); + + auto fdLetterSpacing = new QSpinBox(); + fdLetterSpacing->setMaximum(999); + connect(fdLetterSpacing, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this, fdText](int value) { + QTextCharFormat fmt; + fmt.setFontLetterSpacing(value); + QTextCursor cursor = fdText->textCursor(); + if(! cursor.hasSelection()) cursor.select(QTextCursor::WordUnderCursor); + cursor.mergeCharFormat(fmt); + updImg(); + }); + hBox->addWidget(fdLetterSpacing); + + lb = new QLabel(tr("Line Spacing")); + lb->setToolTip(lb->text()); + hBox->addWidget(lb); + + auto fdLineSpacing = new QSpinBox(); + fdLineSpacing->setRange(-99, 999); + connect(fdLineSpacing, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this, fdText](int value) { + QTextBlockFormat fmt; + fmt.setLineHeight(value, QTextBlockFormat::LineDistanceHeight); + QTextCursor cursor = fdText->textCursor(); + if(! cursor.hasSelection()) cursor.select(QTextCursor::WordUnderCursor); + cursor.mergeBlockFormat(fmt); + updImg(); + }); + hBox->addWidget(fdLineSpacing); + + vBox->addLayout(hBox); + + auto wTextAlignH = new QButtonGroup(wgtAttr); + wTextAlignH->addButton(wTextAlignHL, Qt::AlignLeft); + wTextAlignH->addButton(wTextAlignHC, Qt::AlignHCenter); + wTextAlignH->addButton(wTextAlignHR, Qt::AlignRight); + connect(wTextAlignH, &QButtonGroup::idClicked, this, [this, fdText](int value) { + QTextBlockFormat fmt; + fmt.setAlignment((Qt::Alignment) value); + QTextCursor cursor = fdText->textCursor(); + cursor.mergeBlockFormat(fmt); + updImg(); + }); + + auto wTextAlignV = new QButtonGroup(wgtAttr); + wTextAlignV->addButton(wTextAlignVT, Qt::AlignTop); + wTextAlignV->addButton(wTextAlignVC, Qt::AlignVCenter); + wTextAlignV->addButton(wTextAlignVB, Qt::AlignBottom); + connect(wTextAlignV, &QButtonGroup::idClicked, this, [this](int value) { + m_attr.align = (Qt::Alignment) value; + updImg(); + }); + + auto v_align = m_attr.align & Qt::AlignVertical_Mask; + if(v_align==Qt::AlignTop) wTextAlignVT->setChecked(true); + if(v_align==Qt::AlignVCenter) wTextAlignVC->setChecked(true); + if(v_align==Qt::AlignBottom) wTextAlignVB->setChecked(true); + + fdText->setMinimumHeight(160); + auto doc = fdText->document(); + if(doc) doc->setDocumentMargin(2); + auto font = fdText->font(); + font.setFamilies({"Arial","黑体"}); + font.setPixelSize(16); + if(! gTextAntialiasing) font.setStyleStrategy(QFont::NoAntialias); + fdText->setFont(font); + auto pal = fdText->palette(); + pal.setColor(QPalette::Base, Qt::black); + pal.setColor(QPalette::Text, Qt::white); + fdText->setPalette(pal); + fdText->setFrameShape(QFrame::NoFrame); + fdText->setAcceptRichText(false); + fdText->setHtml(m_attr.text); + connect(fdText, &QTextEdit::textChanged, this, [this, fdText] { + m_attr.text = fdText->toHtml(); + updImg(); + }); + vBox->addWidget(fdText); + + hBox = new QHBoxLayout; + hBox->addStretch(); + + auto pageInfoWgt = new QWidget; + auto hhh = new QHBoxLayout(pageInfoWgt); + hhh->setContentsMargins(0,0,0,0); + + hhh->addWidget(new QLabel(tr("PageCount:"))); + + auto fdPageCnt = new QLabel(QString::number(mImgs.size())); + hhh->addWidget(fdPageCnt); + + hhh->addSpacing(20); + hhh->addWidget(new QLabel(tr("page"))); + + auto fdPageIdx = new QSpinBox(); + fdPageIdx->setRange(1, mImgs.size()); + connect(fdPageIdx, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this](int idx) { + curIdx = idx - 1; + update(); + }); + hhh->addWidget(fdPageIdx); + hBox->addWidget(pageInfoWgt); + + hBox->addStretch(); + + auto btnImport = new QPushButton(tr("Import txt File")); + btnImport->setProperty("ssType", "progManageTool"); + connect(btnImport, &QPushButton::clicked, fdText, [fdText] { + auto filePath = QFileDialog::getOpenFileName(gMainWin, tr("Select File"), gFileHome, "Txt(*.txt)"); + if(filePath.isEmpty()) return; + QFile file(filePath); + if(! file.open(QFile::ReadOnly)) { + QMessageBox::critical(gMainWin, tr("Fail"), tr("File Open Fail")); + return; + } + auto data = file.readAll(); + file.close(); + QTextCodec::ConverterState state; + QString text = QTextCodec::codecForName("UTF-8")->toUnicode(data.constData(), data.size(), &state); + if(state.invalidChars > 0) text = QString::fromLocal8Bit(data); + fdText->setText(text); + }); + hBox->addWidget(btnImport); + + vBox->addLayout(hBox); + + hBox = new QHBoxLayout; + hBox->addWidget(new QLabel(tr("Play Properties"))); + + line = new QFrame(); + line->setFrameShape(QFrame::HLine); + line->setFrameShadow(QFrame::Sunken); + hBox->addWidget(line, 1); + + vBox->addLayout(hBox); + + hBox = new QHBoxLayout; + hBox->addStretch(); + + auto fdFlip = new QRadioButton(tr("Flip")); + hBox->addWidget(fdFlip); + hBox->addStretch(); + + auto fdScroll = new QRadioButton(tr("Scroll")); + hBox->addWidget(fdScroll); + hBox->addStretch(); + + auto fdStatic = new QRadioButton(tr("Static")); + hBox->addWidget(fdStatic); + hBox->addStretch(); + + vBox->addLayout(hBox); + + auto fdPlayStyle = new QButtonGroup(wgtAttr); + fdPlayStyle->addButton(fdFlip, EText::Flip); + fdPlayStyle->addButton(fdScroll, EText::Scroll); + fdPlayStyle->addButton(fdStatic, EText::Static); + if(m_attr.playMode==EText::Flip) fdFlip->setChecked(true); + else if(m_attr.playMode==EText::Scroll) fdScroll->setChecked(true); + else if(m_attr.playMode==EText::Static) fdStatic->setChecked(true); + + auto wgtAttrFlip = new QWidget(); + auto fdDur = new QTimeEdit(QTime::fromMSecsSinceStartOfDay(m_attr.flip.pageDuration * mImgs.size() * 1000)); + auto fdPageDur = new QTimeEdit(QTime::fromMSecsSinceStartOfDay(m_attr.flip.pageDuration * 1000)); + { + auto vBox = new QVBoxLayout(wgtAttrFlip); + vBox->setContentsMargins(2, 0, 2, 0); + vBox->setSpacing(3); + + hBox = new QHBoxLayout; + + auto label = new QLabel(tr("Play Duration")); + label->setMinimumWidth(100); + hBox->addWidget(label); + + fdDur->setReadOnly(true); + fdDur->setButtonSymbols(QAbstractSpinBox::NoButtons); + fdDur->setDisplayFormat("H:mm:ss"); + fdDur->setStyleSheet("QTimeEdit{background-color:#ddd;}"); + hBox->addWidget(fdDur); + hBox->addStretch(); + + vBox->addLayout(hBox); + + hBox = new QHBoxLayout(); + + label = new QLabel(tr("Duration/Page")); + label->setMinimumWidth(100); + hBox->addWidget(label); + + fdPageDur->setDisplayFormat("H:mm:ss"); + fdPageDur->setCurrentSection(QTimeEdit::SecondSection); + hBox->addWidget(fdPageDur); + hBox->addStretch(); + + vBox->addLayout(hBox); + + hBox = new QHBoxLayout(); + + label = new QLabel(tr("Entrance Effect")); + label->setMinimumWidth(100); + hBox->addWidget(label); + + auto fdEff = new QComboBox(); + fdEff->addItem(tr("no"), "no"); + fdEff->addItem(tr("random"), "random"); + fdEff->addItem(tr("right to left"), "right to left"); + fdEff->addItem(tr("bottom to top"), "bottom to top"); + fdEff->addItem(tr("left to right"), "left to right"); + fdEff->addItem(tr("top to bottom"), "top to bottom"); + int idx = fdEff->findData(m_attr.flip.effect); + if(idx!=-1) fdEff->setCurrentIndex(idx); + connect(fdEff, (void(QComboBox::*)(int))&QComboBox::currentIndexChanged, this, [this, fdEff] { + m_attr.flip.effect = fdEff->currentData().toString(); + update(); + }); + hBox->addWidget(fdEff); + hBox->addStretch(); + + vBox->addLayout(hBox); + + hBox = new QHBoxLayout(); + + label = new QLabel(tr("Effect time")); + label->setMinimumWidth(100); + hBox->addWidget(label); + + auto wEffectSpeed = new QSpinBox(); + wEffectSpeed->setValue(m_attr.flip.effectDuration); + hBox->addWidget(wEffectSpeed); + hBox->addWidget(new QLabel(tr("s"))); + hBox->addStretch(); + + vBox->addLayout(hBox); + vBox->addStretch(); + + connect(fdPageDur, &QTimeEdit::timeChanged, this, [this, wEffectSpeed, fdPageDur, fdDur](const QTime &time) { + int effDur = wEffectSpeed->value(); + int pageDur = time.msecsSinceStartOfDay()/1000; + if(pageDur < effDur) { + QMessageBox::warning(gMainWin, tr("Tip Info"), tr("Effect time cannot be longer than duration time")); + pageDur = effDur; + fdPageDur->setTime(QTime::fromMSecsSinceStartOfDay(pageDur*1000)); + fdPageDur->setFocus(); + } + m_attr.flip.pageDuration = pageDur; + fdDur->setTime(QTime::fromMSecsSinceStartOfDay(pageDur * mImgs.size() * 1000)); + }); + connect(wEffectSpeed, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this, wEffectSpeed, fdPageDur](int value) { + int pageDur = fdPageDur->time().msecsSinceStartOfDay()/1000; + if(value > pageDur) { + QMessageBox::warning(gMainWin, tr("Tip Info"), tr("Effect time cannot be longer than duration time")); + if(pageDur>1) value = pageDur-1; + else value = 0; + wEffectSpeed->setValue(value); + wEffectSpeed->setFocus(); + } + m_attr.flip.effectDuration = value; + }); + } + auto wgtAttrScroll = new QWidget(); + { + auto vBox = new QVBoxLayout(wgtAttrScroll); + vBox->setContentsMargins(2, 0, 2, 0); + vBox->setSpacing(3); + + auto hBox = new QHBoxLayout(); + + auto label = new QLabel(tr("Play Duration")); + label->setMinimumWidth(100); + hBox->addWidget(label); + + auto timeEdit = new QTimeEdit(QTime::fromMSecsSinceStartOfDay(m_attr.scroll.duration*1000)); + timeEdit->setDisplayFormat("H:mm:ss"); + timeEdit->setCurrentSectionIndex(2); + connect(timeEdit, &QTimeEdit::timeChanged, this, [this](const QTime &time) { + m_attr.scroll.duration = time.msecsSinceStartOfDay()/1000; + }); + hBox->addWidget(timeEdit); + hBox->addStretch(); + + vBox->addLayout(hBox); + + hBox = new QHBoxLayout(); + + label = new QLabel(tr("Head-Tail Spacing")); + label->setMinimumWidth(100); + hBox->addWidget(label); + + auto wHeadTailSpacing = new QSpinBox; + wHeadTailSpacing->setRange(0, 9999); + wHeadTailSpacing->setValue(m_attr.scroll.headTailSpacing); + connect(wHeadTailSpacing, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this](int value) { + m_attr.scroll.headTailSpacing = value; + }); + hBox->addWidget(wHeadTailSpacing); + hBox->addStretch(); + + vBox->addLayout(hBox); + + hBox = new QHBoxLayout(); + + label = new QLabel(tr("Scroll Style")); + label->setMinimumWidth(100); + hBox->addWidget(label); + + auto wRollingStyle = new QComboBox; + wRollingStyle->addItem(tr("Right -> Left")); + wRollingStyle->addItem(tr("Bottom -> Top")); + wRollingStyle->addItem(tr("Left -> Right")); + wRollingStyle->addItem(tr("Top -> Bottom")); + wRollingStyle->setCurrentIndex(m_attr.scroll.effect); + connect(wRollingStyle, (void(QComboBox::*)(int))&QComboBox::currentIndexChanged, this, [this](int index) { + m_attr.scroll.effect = index; + updImg(); + }); + hBox->addWidget(wRollingStyle); + hBox->addStretch(); + + vBox->addLayout(hBox); + + hBox = new QHBoxLayout(); + + label = new QLabel(tr("Scroll Speed")); + label->setMinimumWidth(100); + hBox->addWidget(label); + + auto wRollingSpeed = new QSpinBox(); + wRollingSpeed->setMaximum(9999); + wRollingSpeed->setValue(m_attr.scroll.effectSpeed); + connect(wRollingSpeed, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this](int value) { + m_attr.scroll.effectSpeed = value; + }); + hBox->addWidget(wRollingSpeed); + hBox->addStretch(); + + vBox->addLayout(hBox); + vBox->addStretch(); + } + auto wgtAttrStatic = new QWidget(); + { + auto vBox = new QVBoxLayout(wgtAttrStatic); + vBox->setContentsMargins(2, 0, 2, 0); + vBox->setSpacing(3); + + hBox = new QHBoxLayout(); + auto label = new QLabel(tr("Play Duration")); + label->setMinimumWidth(100); + hBox->addWidget(label); + + auto timeEdit = new QTimeEdit(QTime::fromMSecsSinceStartOfDay(m_attr.duration*1000)); + timeEdit->setDisplayFormat("H:mm:ss"); + timeEdit->setCurrentSectionIndex(2); + connect(timeEdit, &QTimeEdit::timeChanged, this, [this](const QTime &time) { + m_attr.duration = time.msecsSinceStartOfDay() / 1000; + }); + hBox->addWidget(timeEdit); + hBox->addStretch(); + + vBox->addLayout(hBox); + vBox->addStretch(); + } + auto stackBox = new QStackedLayout; + vBox->addLayout(stackBox); + stackBox->addWidget(wgtAttrFlip); + stackBox->addWidget(wgtAttrScroll); + stackBox->addWidget(wgtAttrStatic); + stackBox->setCurrentIndex(m_attr.playMode); + connect(fdPlayStyle, &QButtonGroup::idToggled, this, [this, stackBox, pageInfoWgt](int value, bool checked) { + if(! checked) return; + m_attr.playMode = value; + updImg(); + stackBox->setCurrentIndex(value); + pageInfoWgt->setVisible(value==Flip); + }); + connect(this, &EText::updPageCnt, wgtAttr, [this, fdPageCnt, fdPageIdx, fdPageDur, fdDur] { + fdPageCnt->setText(QString::number(mImgs.size())); + fdPageIdx->setRange(1, mImgs.size()); + fdPageIdx->setValue(1); + fdDur->setTime(QTime::fromMSecsSinceStartOfDay(fdPageDur->time().msecsSinceStartOfDay() * mImgs.size())); + }); + return wgtAttr; +} + +bool EText::save(const QString &pageDir) { + QString idDir = pageDir + QString("/%1-%2-%3-%4-%5").arg(zValue()).arg((int)x()).arg((int)y()).arg((int)mWidth).arg((int)mHeight); + QDir(idDir).mkdir("."); + for(int i=0; isave(); + auto rect = innerRect(); + if(m_attr.playMode!=EText::Flip) curIdx = 0; + else if(curIdx>=mImgs.size()) curIdx = mImgs.size() - 1; + else if(curIdx < 0) curIdx = 0; + if(m_attr.playMode==EText::Scroll) painter->drawImage(rect.x(), rect.y(), mImgs[0], 0, 0, rect.width(), rect.height()); + else painter->drawImage(rect.x(), rect.y(), mImgs[curIdx]); + painter->restore(); + EBase::paint(painter, option, widget); +} + +void EText::updImg() { + auto innerRect = this->innerRect(); + int width = innerRect.width(); + int height = innerRect.height(); + if(width<1 || height<1) return; + QTextDocument doc; + doc.setDocumentMargin(0); + QFont font; + font.setFamilies({"Arial","黑体"}); + font.setPixelSize(16); + if(! gTextAntialiasing) font.setStyleStrategy(QFont::NoAntialias); + doc.setDefaultFont(font); + doc.setDefaultStyleSheet("body {color: #fff;}"); + doc.setHtml(m_attr.text); + if(m_attr.playMode==EText::Flip) { + doc.setPageSize(innerRect.size()); + auto pageHeight = height; + auto pageCnt = doc.pageCount(); + QImage img(width, pageHeight*pageCnt, QImage::Format_ARGB32); + img.fill(m_attr.backColor); + { + QPainter painter(&img); + doc.drawContents(&painter); + } + if(pageCnt > 1) { + check: + for(int y=pageHeight-1; y 1) { + for(int y=img.height()-pageHeight; yss; ee--) for(int i=0; i=0; ee--) for(int i=0; i mImgs; + int curIdx{0}; +}; + +#endif // ETEXT_H diff --git a/LedOK/wProgramManager/etimer.cpp b/LedOK/program/etimer.cpp similarity index 89% rename from LedOK/wProgramManager/etimer.cpp rename to LedOK/program/etimer.cpp index 7cce05c..3163e32 100644 --- a/LedOK/wProgramManager/etimer.cpp +++ b/LedOK/program/etimer.cpp @@ -15,7 +15,7 @@ #include #include #include - +#include ETimer::ETimer(EBase *multiWin) : EBase(multiWin) { mType = EBase::Timer; @@ -243,48 +243,33 @@ QWidget* ETimer::attrWgt() { hBox = new QHBoxLayout(); hBox->addSpacing(6); - auto fdFontBold = new QPushButton(); - fdFontBold->setChecked(attr.font.bold()); + auto fdFontBold = new QPushButton("B"); + fdFontBold->setStyleSheet("QPushButton{background: #bbb; color: #888; font-size: 20px; font-weight: bold;} QPushButton:checked{background: #29c; color: #fff;}"); fdFontBold->setFixedSize(30, 30); - QIcon icon; - icon.addFile(QString::fromUtf8(":/res/ProgramManager/EditProgram/FontBold_u.png"), QSize(), QIcon::Normal, QIcon::Off); - icon.addFile(QString::fromUtf8(":/res/ProgramManager/EditProgram/FontBold_s.png"), QSize(), QIcon::Normal, QIcon::On); - fdFontBold->setIcon(icon); - fdFontBold->setIconSize(QSize(30, 30)); fdFontBold->setCheckable(true); - fdFontBold->setFlat(true); + fdFontBold->setChecked(attr.font.bold()); connect(fdFontBold, &QCheckBox::toggled, this, [this](bool checked) { attr.font.setBold(checked); update(); }); hBox->addWidget(fdFontBold); - auto fdFontItalic = new QPushButton(); - fdFontItalic->setChecked(attr.font.italic()); + auto fdFontItalic = new QPushButton("I"); + fdFontItalic->setStyleSheet("QPushButton{background: #bbb; color: #888; font-size: 20px; font-style: italic;} QPushButton:checked{background: #29c; color: #fff;}"); fdFontItalic->setFixedSize(30, 30); - icon = QIcon(); - icon.addFile(QString::fromUtf8(":/res/ProgramManager/EditProgram/FontItalics_u.png"), QSize(), QIcon::Normal, QIcon::Off); - icon.addFile(QString::fromUtf8(":/res/ProgramManager/EditProgram/FontItalics_s.png"), QSize(), QIcon::Normal, QIcon::On); - fdFontItalic->setIcon(icon); - fdFontItalic->setIconSize(QSize(30, 30)); fdFontItalic->setCheckable(true); - fdFontItalic->setFlat(true); + fdFontItalic->setChecked(attr.font.italic()); connect(fdFontItalic, &QCheckBox::toggled, this, [this](bool checked) { attr.font.setItalic(checked); update(); }); hBox->addWidget(fdFontItalic); - auto fdFontUnderline = new QPushButton(); - fdFontUnderline->setChecked(attr.font.underline()); + auto fdFontUnderline = new QPushButton("U"); + fdFontUnderline->setStyleSheet("QPushButton{background: #bbb; color: #888; font-size: 20px; text-decoration: underline;} QPushButton:checked{background: #29c; color: #fff;}"); fdFontUnderline->setFixedSize(30, 30); - icon = QIcon(); - icon.addFile(QString::fromUtf8(":/res/ProgramManager/EditProgram/FontUnderline_u.png"), QSize(), QIcon::Normal, QIcon::Off); - icon.addFile(QString::fromUtf8(":/res/ProgramManager/EditProgram/FontUnderline_s.png"), QSize(), QIcon::Normal, QIcon::On); - fdFontUnderline->setIcon(icon); - fdFontUnderline->setIconSize(QSize(30, 30)); fdFontUnderline->setCheckable(true); - fdFontUnderline->setFlat(true); + fdFontUnderline->setChecked(attr.font.underline()); connect(fdFontUnderline, &QCheckBox::toggled, this, [this](bool checked) { attr.font.setUnderline(checked); update(); diff --git a/LedOK/wProgramManager/etimer.h b/LedOK/program/etimer.h similarity index 100% rename from LedOK/wProgramManager/etimer.h rename to LedOK/program/etimer.h diff --git a/LedOK/wProgramManager/evideo.cpp b/LedOK/program/evideo.cpp similarity index 94% rename from LedOK/wProgramManager/evideo.cpp rename to LedOK/program/evideo.cpp index abd6e27..916b5f3 100644 --- a/LedOK/wProgramManager/evideo.cpp +++ b/LedOK/program/evideo.cpp @@ -2,6 +2,7 @@ #include "cfg.h" #include "tools.h" #include "base/waitingdlg.h" +#include "base/ffutil.h" #include "videosplitthread.h" #include #include @@ -14,7 +15,7 @@ EVideo *EVideo::create(const QString &file, PageListItem *pageItem, EBase *multi int64_t dur; AVCodecID codecId; QImage img; - QString err = Tools::videoInfo(file.toUtf8(), img, &dur, &codecId); + QString err = videoInfo(file.toUtf8(), img, &dur, &codecId); if(! err.isEmpty()) { QMessageBox::critical(gMainWin, "Video Error", err+"\n"+file); return 0; @@ -38,7 +39,7 @@ EVideo *EVideo::create(const QJsonObject &json, PageListItem *pageItem, EBase *m else return nullptr; int64_t dur; QImage img; - QString err = Tools::videoInfo(file.toUtf8(), img, &dur, 0); + QString err = videoInfo(file.toUtf8(), img, &dur, 0); if(! err.isEmpty()) return nullptr; auto ins = new EVideo(dir, name, widget["pathRaw"].toString(), widget["fileRaw"].toString(), img, dur/1000000, pageItem, multiWin); ins->setBaseAttr(json); @@ -52,7 +53,7 @@ QJsonObject EVideo::genProg(const QJsonObject &ele, const QString &dstDir, ProgI auto widget = ele["widget"]; auto path = widget["path"].toString(); auto name = widget["file"].toString(); - if(progItem->mSplitWidth) name += "-square.mp4"; + if(progItem->mMaxWidth) name += "-square.mp4"; QString srcFile = path + "/" + name; QFileInfo srcInfo(srcFile); if(! srcInfo.isFile()) return QJsonObject(); @@ -175,7 +176,7 @@ QWidget* EVideo::attrWgt() { QFileInfo rawInfo(rawFile); int64_t dur; AVCodecID codecId; - QString err = Tools::videoInfo(rawFile.toUtf8(), mCoverImg, &dur, &codecId); + QString err = videoInfo(rawFile.toUtf8(), mCoverImg, &dur, &codecId); if(! err.isEmpty()) { QMessageBox::critical(gMainWin, "Video Error", err+"\n"+rawFile); return; @@ -228,10 +229,9 @@ bool EVideo::save(const QString &pageDir) { else return false; QFile(oldFile).copy(saveFile); mDir = pageDir; - if(gProgItem->mSplitWidth) { - int cnt = (gProgItem->mWidth+gProgItem->mSplitWidth-1) / gProgItem->mSplitWidth; + if(gProgItem->mMaxWidth) { auto waitingDlg = new WaitingDlg(gProgEditorWin, "正在转码视频 ..."); - auto thread = new VideoSplitThread(mWidth, mHeight, gProgItem->mSplitWidth, gProgItem->mHeight*cnt, cnt, pos(), saveFile.toUtf8()); + auto thread = new VideoSplitThread(mWidth, mHeight, gProgItem->mMaxWidth, gProgItem->mHeight, gProgItem->mSplitWidths, pos(), saveFile.toUtf8()); connect(thread, &VideoSplitThread::emErr, this, [saveFile, waitingDlg](QString err) { waitingDlg->close(); if(! err.isEmpty()) QMessageBox::critical(gProgEditorWin, "Video trans error", err+"\n"+saveFile); @@ -264,9 +264,9 @@ QJsonObject EVideo::attrJson() const { QString EVideo::transcoding(QString rawFile, QString rawName, QString dir, int w, int h, AVCodecID codec_id) { QSettings settings; - int rawMin = qMin(w, h); - if(settings.value("VideoCompress", true).toBool() && rawMin > 768 && w > gProgItem->mWidth && h > gProgItem->mHeight) { - double rate = 720.0 / rawMin; + int rawMax = qMax(w, h); + if(settings.value("VideoCompress", true).toBool() && rawMax > 1360 && (w > gProgItem->mWidth || h > gProgItem->mHeight)) { + double rate = 1280.0 / rawMax; w *= rate; h *= rate; } else if(! settings.value("VideoTranscoding", true).toBool() || codec_id == AV_CODEC_ID_H264) { diff --git a/LedOK/wProgramManager/evideo.h b/LedOK/program/evideo.h similarity index 100% rename from LedOK/wProgramManager/evideo.h rename to LedOK/program/evideo.h diff --git a/LedOK/wProgramManager/eweb.cpp b/LedOK/program/eweb.cpp similarity index 98% rename from LedOK/wProgramManager/eweb.cpp rename to LedOK/program/eweb.cpp index a61cb5a..1a4b6de 100644 --- a/LedOK/wProgramManager/eweb.cpp +++ b/LedOK/program/eweb.cpp @@ -1,5 +1,5 @@ #include "eweb.h" -#include "wProgramManager/progeditorwin.h" +#include "program/progeditorwin.h" #include #include #include diff --git a/LedOK/wProgramManager/eweb.h b/LedOK/program/eweb.h similarity index 87% rename from LedOK/wProgramManager/eweb.h rename to LedOK/program/eweb.h index 2316a17..7b08a96 100644 --- a/LedOK/wProgramManager/eweb.h +++ b/LedOK/program/eweb.h @@ -8,7 +8,7 @@ class EWeb : public EBase { Q_OBJECT public: static const QImage &holder() { - static const QImage holder = QImage(":/res/ProgramManager/EditProgram/Web.png"); + static const QImage holder = QImage(":/res/program/Web.png"); return holder; } diff --git a/LedOK/wProgramManager/gentmpthread.cpp b/LedOK/program/gentmpthread.cpp similarity index 78% rename from LedOK/wProgramManager/gentmpthread.cpp rename to LedOK/program/gentmpthread.cpp index 2893530..b6835db 100644 --- a/LedOK/wProgramManager/gentmpthread.cpp +++ b/LedOK/program/gentmpthread.cpp @@ -2,19 +2,24 @@ #include "cfg.h" #include "globaldefine.h" #include "tools.h" -#include "wProgramManager/eaclock.h" -#include "wProgramManager/eaudio.h" -#include "wProgramManager/edclock.h" -#include "wProgramManager/eenviron.h" -#include "wProgramManager/egif.h" -#include "wProgramManager/etext.h" -#include "wProgramManager/etimer.h" -#include "wProgramManager/evideo.h" +#include "program/eaclock.h" +#include "program/eaudio.h" +#include "program/edclock.h" +#include "program/eenviron.h" +#include "program/egif.h" +#include "program/etext.h" +#include "program/etimer.h" +#include "program/evideo.h" #include #include #include +#include GenTmpThread::GenTmpThread(ProgItem *progItem, const QString &prog_name, const QString &zip_file, const QString &password, QObject *parent) : QThread(parent), mProgItem(progItem), prog_name(prog_name), zip_file(zip_file), password(password) { + connect(this, &QThread::finished, this, &QThread::deleteLater); + connect(this, &GenTmpThread::onErr, this, [](QString err) { + QMessageBox::warning(gMainWin, "GenTmpThread Error", err); + }); } void GenTmpThread::run() { @@ -22,18 +27,32 @@ void GenTmpThread::run() { dstDir = srcDir + "_tmp"; //清空目录 emit sProgress(tr("Preparing ..."), 0); - QDir rootDir(programsDir()); - rootDir.remove(prog_name + "_tmp.zip"); + QDir progsDir(programsDir()); + progsDir.remove(prog_name + "_tmp.zip"); QDir dstQDir(dstDir); if(! dstQDir.exists() || dstQDir.removeRecursively()) { int iReTryCount = 0; - while(!rootDir.mkdir(prog_name + "_tmp")) { + while(!progsDir.mkdir(prog_name + "_tmp")) { QThread::msleep(250); iReTryCount++; if(iReTryCount > 4) break; } } + QFile jsonFile(srcDir+"/pro.json"); + if(! jsonFile.open(QIODevice::ReadOnly)) { + onErr("Can't open "+srcDir+"/pro.json"); + return; + } + auto data = jsonFile.readAll(); + jsonFile.close(); + QJsonParseError error; + auto proJson = QJsonDocument::fromJson(data, &error); + if(error.error != QJsonParseError::NoError) { + onErr("Parse "+srcDir+"/pro.json Error: "+error.errorString()); + return; + } + //扫描节目, 返回多个节目数组 emit sProgress(tr("Scan program ..."), 30); QStringList pageNames = QDir(srcDir).entryList(QDir::Dirs | QDir::NoDotAndDotDot); @@ -42,20 +61,21 @@ void GenTmpThread::run() { QList pageJsons; foreach(QString pageName, pageNames) { QFile jsonFile(srcDir+"/"+pageName+"/page.json"); - if(jsonFile.open(QIODevice::ReadOnly)){ - QJsonDocument pageJson = QJsonDocument::fromJson(jsonFile.readAll()); + if(jsonFile.open(QIODevice::ReadOnly)) { + auto data = jsonFile.readAll(); jsonFile.close(); - pageJsons.append(pageJson); + auto pageJson = QJsonDocument::fromJson(data, &error); + if(error.error == QJsonParseError::NoError) pageJsons.append(pageJson); } } - //根据order排序 std::sort(pageJsons.begin(), pageJsons.end(), [](const QJsonDocument &a, const QJsonDocument &b) { return a["order"].toInt() < b["order"].toInt(); }); + QJsonArray items; foreach(QJsonDocument pageJson, pageJsons) { srcPageDir = srcDir + "/" + pageJson["name"].toString(); - items.append(cvtPage(pageJson)); + items.append(cvtPage(pageJson, proJson)); } emit sProgress(tr("Create json ..."), 60); @@ -85,8 +105,9 @@ void GenTmpThread::run() { } //此处需要把幻灯片中的元素按层顺序排序,再放入layers中,每个元素对一个layer。ewindow中的多个顺序元素为一个层上的时间轴上的素材 -QJsonObject GenTmpThread::cvtPage(const QJsonDocument &pageJson) { +QJsonObject GenTmpThread::cvtPage(const QJsonDocument &pageJson, const QJsonDocument &proJson) { auto audios = pageJson["audios"].toArray(); + auto sourceRepeat = pageJson["loop"].toBool(); QJsonArray sources; int start = 0; foreach(auto audio, audios) { @@ -119,7 +140,7 @@ QJsonObject GenTmpThread::cvtPage(const QJsonDocument &pageJson) { start += dur; } QJsonArray layers; - if(! sources.isEmpty()) layers.append(QJsonObject{{"repeat", true}, {"sources", sources}}); + if(! sources.isEmpty()) layers.append(QJsonObject{{"repeat", sourceRepeat}, {"sources", sources}}); auto elements = pageJson["elements"].toArray(); foreach(auto ele, elements) { @@ -152,24 +173,23 @@ QJsonObject GenTmpThread::cvtPage(const QJsonDocument &pageJson) { } else { QJsonObject source = cvtEle(type, ele.toObject()); if(! source.isEmpty()) { - if(mProgItem->mSplitWidth==0) { + if(mProgItem->mMaxWidth && (type=="Photo" || type=="Movie")) { + source["left"] = 0; + source["top"] = 0; + source["width"] = mProgItem->mMaxWidth; + source["height"] = mProgItem->mHeight * mProgItem->mSplitWidths.size(); + } else { source["left"] = geometry["x"]; source["top"] = geometry["y"]; source["width"] = geometry["w"]; source["height"] = geometry["h"]; - } else { - source["left"] = 0; - source["top"] = 0; - source["width"] = mProgItem->mSplitWidth; - int cnt = (gProgItem->mWidth+gProgItem->mSplitWidth-1) / gProgItem->mSplitWidth; - source["height"] = mProgItem->mHeight*cnt; } source["playTime"] = 0; sources.append(source); } } if(! sources.isEmpty()) { - QJsonObject layer{{"repeat", false}, {"sources", sources}}; + QJsonObject layer{{"repeat", sourceRepeat}, {"sources", sources}}; auto border = ele["border"].toString(); if(! border.isEmpty()) { QString bdSrc = ":res/borders/"+border; @@ -225,7 +245,6 @@ QJsonObject GenTmpThread::cvtPage(const QJsonDocument &pageJson) { schedules.append(schedule); } } - return QJsonObject{ {"_id", QUuid::createUuid().toString(QUuid::WithoutBraces)}, {"priority", 0}, @@ -235,8 +254,9 @@ QJsonObject GenTmpThread::cvtPage(const QJsonDocument &pageJson) { {"_id", QUuid::createUuid().toString(QUuid::WithoutBraces)}, {"totalSize", 0}, {"name", pageJson["name"].toString()}, - {"width", pageJson["resolution"]["w"]}, - {"height", pageJson["resolution"]["h"]}, + {"width", proJson["resolution"]["w"]}, + {"height", proJson["resolution"]["h"]}, + {"splitWidths", proJson["splitWidths"]}, {"_company", "alahover"}, {"_department", "alahover"}, {"_role", "alahover"}, @@ -266,17 +286,28 @@ QJsonObject GenTmpThread::cvtEle(const QString &type, const QJsonObject &ele) { QJsonObject GenTmpThread::convertText(const QJsonObject &json) { EText::Data attr; EText::setElement(json, attr); - QJsonObject oRes; - oRes["_type"] = "MultiPng"; - oRes["name"] = "MultiPng"; - oRes["id"] = res_id++; - //把["widget"]["files"]字段的数组转成[{"text0.png","move up"}] + QJsonObject source; + auto type = mProgItem->mMaxWidth ? "SplitText" : "MultiPng"; + source["_type"] = type; + source["name"] = type; + source["id"] = res_id++; auto widget = json["widget"]; QJsonArray srcFiles = widget["files"].toArray(); - oRes["iPicCount"] = srcFiles.count(); + source["iPicCount"] = srcFiles.size(); + if(attr.playMode==EText::Flip) { + source["playMode"] = "Flip"; + source["timeSpan"] = attr.flip.pageDuration * srcFiles.size(); + if(attr.flip.effectDuration >= attr.flip.pageDuration) attr.flip.effectDuration = attr.flip.pageDuration / 2; + } else if(attr.playMode==EText::Scroll) { + source["playMode"] = "Scroll"; + source["timeSpan"] = attr.scroll.duration; + } else if(attr.playMode==EText::Static) { + source["playMode"] = "Static"; + source["timeSpan"] = attr.duration; + } QJsonArray arrayPics; QString filePrefix = srcPageDir+"/"+widget["idDir"].toString()+"/"; - for(int i=0; i=attr.turning.pageDuration) attr.turning.effectDuration=attr.turning.pageDuration/2; - arrayPic["effectSpeed"]=attr.turning.effectDuration; - arrayPic["picDuration"]=attr.turning.pageDuration; - break; - case EText::Scroll: - if(attr.rolling.rollingStyle==0) arrayPic["effect"] = "right to left"; - else if(attr.rolling.rollingStyle==1) arrayPic["effect"] = "bottom to top"; - else if(attr.rolling.rollingStyle==2) arrayPic["effect"] = "left to right"; - else if(attr.rolling.rollingStyle==3) arrayPic["effect"] = "top to bottom"; - oRes["timeSpan"] = attr.rolling.playDuration; - arrayPic["effectSpeed"] = attr.rolling.rollingSpeed; + if(attr.playMode==EText::Flip) { + arrayPic["effect"] = attr.flip.effect; + arrayPic["effectSpeed"] = attr.flip.effectDuration; + arrayPic["picDuration"] = attr.flip.pageDuration; + } else if(attr.playMode==EText::Scroll) { + if(attr.scroll.effect==0) arrayPic["effect"] = "right to left"; + else if(attr.scroll.effect==1) arrayPic["effect"] = "bottom to top"; + else if(attr.scroll.effect==2) arrayPic["effect"] = "left to right"; + else if(attr.scroll.effect==3) arrayPic["effect"] = "top to bottom"; + arrayPic["effectSpeed"] = attr.scroll.effectSpeed; arrayPic["picDuration"] = 0; - break; - case EText::Static: - arrayPic["effect"]="no"; - oRes["timeSpan"] = attr.playDuration; - arrayPic["effectSpeed"]=0; - arrayPic["picDuration"]=attr.playDuration; - break; - //转换成plainText - default: break; + } else if(attr.playMode==EText::Static) { + arrayPic["effect"] = "no"; + arrayPic["effectSpeed"] = 0; + arrayPic["picDuration"] = attr.duration; } arrayPics.append(arrayPic); } - oRes["arrayPics"] = arrayPics; - return oRes; + source["arrayPics"] = arrayPics; + return source; } //转换图片 QJsonObject GenTmpThread::convertPhoto(const QJsonObject &ele){ @@ -325,7 +345,7 @@ QJsonObject GenTmpThread::convertPhoto(const QJsonObject &ele){ QFileInfo srcInfo(srcFile); QJsonObject source; if(! srcInfo.isFile()) return source; - if(mProgItem->mSplitWidth) { + if(mProgItem->mMaxWidth) { srcFile += "-square.png"; auto md5 = Tools::fileMd5(srcFile); if(md5.isEmpty()) return source; @@ -488,11 +508,11 @@ QJsonObject GenTmpThread::convertAClock(const QJsonObject &json) { oRes["mime"] = "image/png"; oRes["name"] = "001"; oRes["timeSpan"] = json["play"]["duration"]; - oRes["shade"] = 0;//表盘形状 - oRes["opacity"] = 1;//透明度 - oRes["showBg"] = false;//是否显示背景色 - oRes["bgColor"] = 0; - oRes["showHourScale"] = false;//是否显示时针 + oRes["shade"] = 0;//表盘形状 + oRes["opacity"] = 1;//透明度 + oRes["showBg"] = false;//是否显示背景色 + oRes["bgColor"] = 0; + oRes["showHourScale"] = false;//是否显示时针 auto color = widget["hourMarkColor"]; oRes["scaleHourColor"] = color.isString() ? color : Tools::int2Color(color.toInt()).name(); color = widget["minMarkColor"]; @@ -503,12 +523,17 @@ QJsonObject GenTmpThread::convertAClock(const QJsonObject &json) { oRes["pinMinColor"] = color.isString() ? color : Tools::int2Color(color.toInt()).name(); color = widget["secHandColor"]; oRes["pinSecColor"] = color.isString() ? color : Tools::int2Color(color.toInt()).name(); - + oRes["pinHourLen"] = widget["hhLen"].toInt(); + oRes["pinMinLen"] = widget["mhLen"].toInt(); + oRes["pinSecLen"] = widget["shLen"].toInt(); + oRes["pinHourWidth"] = widget["hhWidth"].toInt(); + oRes["pinMinWidth"] = widget["mhWidth"].toInt(); + oRes["pinSecWidth"] = widget["shWidth"].toInt(); oRes["showMinScale"] = false; oRes["scaleStyle"] = 0; oRes["showScaleNum"] = false; oRes["pinStyle"] = 1; - oRes["showSecond"] = true; + oRes["showSecond"] = widget["showSecHand"]; //下同Video oRes["entryEffect"] = "None"; oRes["exitEffect"] = "None"; @@ -564,26 +589,32 @@ QJsonObject GenTmpThread::convertTimer(const QJsonObject &json) { Tools::saveImg(dstDir, metric, font, color, imgs, tr("hour"), "hour"); Tools::saveImg(dstDir, metric, font, color, imgs, tr("min"), "min"); Tools::saveImg(dstDir, metric, font, color, imgs, tr("sec"), "sec"); - auto innerW = json["innerW"].toInt(); - auto innerH = json["innerH"].toInt(); - auto rect = metric.boundingRect(0, 0, innerW, innerH, Qt::AlignCenter | Qt::TextWordWrap, text); - QImage img(qMin(rect.width(), innerW), qMin(rect.height(), innerH), QImage::Format_ARGB32); - img.fill(Qt::transparent); - QPainter painter(&img); - painter.setFont(font); - painter.setPen(color); - painter.drawText(QRectF(0, 0, img.width(), img.height()), text, QTextOption(Qt::AlignCenter)); - QBuffer buf; - if(img.save(&buf, "PNG")) { - QCryptographicHash cryptoHash(QCryptographicHash::Md5); - cryptoHash.addData(buf.data()); - auto md5 = QString::fromLatin1(cryptoHash.result().toHex()); - QFile file(dstDir+"/"+md5); - if(file.open(QFile::WriteOnly)) { - file.write(buf.data()); - file.close(); - imgs.insert("text", md5); + if(! text.isEmpty()) { + auto innerW = json["innerW"].toInt(); + auto innerH = json["innerH"].toInt(); + auto rect = metric.boundingRect(0, 0, innerW, innerH, Qt::AlignCenter | Qt::TextWordWrap, text); + QImage img(qMin(rect.width(), innerW), qMin(rect.height(), innerH), QImage::Format_ARGB32); + img.fill(Qt::transparent); + { + QPainter painter(&img); + painter.setFont(font); + painter.setPen(color); + painter.drawText(QRectF(0, 0, img.width(), img.height()), text, QTextOption(Qt::AlignCenter)); } + QByteArray data; + QBuffer buffer(&data); + buffer.open(QIODevice::WriteOnly); + if(img.save(&buffer, "PNG")) { + QCryptographicHash cryptoHash(QCryptographicHash::Md5); + cryptoHash.addData(data); + auto md5 = QString::fromLatin1(cryptoHash.result().toHex()); + QFile file(dstDir+"/"+md5); + if(file.open(QFile::WriteOnly)) { + file.write(data); + file.close(); + imgs.insert("text", md5); + } else emit onErr("convertTimer file.open false"); + } else emit onErr("convertTimer img.save false"); } oRes["imgs"] = imgs; return oRes; diff --git a/LedOK/wProgramManager/gentmpthread.h b/LedOK/program/gentmpthread.h similarity index 91% rename from LedOK/wProgramManager/gentmpthread.h rename to LedOK/program/gentmpthread.h index 0b83e3e..73e1bde 100644 --- a/LedOK/wProgramManager/gentmpthread.h +++ b/LedOK/program/gentmpthread.h @@ -12,7 +12,7 @@ public: protected: virtual void run() override; - QJsonObject cvtPage(const QJsonDocument &jProg); + QJsonObject cvtPage(const QJsonDocument &, const QJsonDocument &); QJsonObject cvtEle(const QString &type, const QJsonObject &json); QJsonObject convertText(const QJsonObject &json); QJsonObject convertPhoto(const QJsonObject &json); @@ -23,7 +23,7 @@ protected: QJsonObject convertTimer(const QJsonObject &json); signals: void sProgress(QString, int, bool = false); - + void onErr(QString); private: QString prog_name, dstDir, srcPageDir; QString zip_file, password; diff --git a/LedOK/wProgramManager/pageeditor.cpp b/LedOK/program/pageeditor.cpp similarity index 76% rename from LedOK/wProgramManager/pageeditor.cpp rename to LedOK/program/pageeditor.cpp index 6cc6447..5cedf72 100644 --- a/LedOK/wProgramManager/pageeditor.cpp +++ b/LedOK/program/pageeditor.cpp @@ -2,19 +2,19 @@ #include "cfg.h" #include "globaldefine.h" #include "tools.h" -#include "wProgramManager/eaclock.h" -#include "wProgramManager/eaudio.h" -#include "wProgramManager/ebase.h" -#include "wProgramManager/edclock.h" -#include "wProgramManager/eenviron.h" -#include "wProgramManager/egif.h" -#include "wProgramManager/emultiwin.h" -#include "wProgramManager/ephoto.h" -#include "wProgramManager/etext.h" -#include "wProgramManager/etimer.h" -#include "wProgramManager/evideo.h" -#include "wProgramManager/eweb.h" -#include "wProgramManager/pagelistitem.h" +#include "program/eaclock.h" +#include "program/eaudio.h" +#include "program/ebase.h" +#include "program/edclock.h" +#include "program/eenviron.h" +#include "program/egif.h" +#include "program/emultiwin.h" +#include "program/ephoto.h" +#include "program/etext.h" +#include "program/etimer.h" +#include "program/evideo.h" +#include "program/eweb.h" +#include "program/pagelistitem.h" #include #include #include @@ -30,7 +30,7 @@ PageEditor::PageEditor(QWidget *parent) : QWidget(parent) { toolBar->setStyleSheet("QToolBar{spacing: 2px;}"); toolBar->setIconSize(QSize(18, 18)); toolBar->addSeparator(); - auto actScaleUp = new QAction(QIcon(":/res/ProgramManager/EditProgram/ScaleUp.png"), tr("Zoom In")); + auto actScaleUp = new QAction(QIcon(":/res/program/ScaleUp.png"), tr("Zoom In")); toolBar->addAction(actScaleUp); //放大 connect(actScaleUp, &QAction::triggered, this, &PageEditor::onScaleUp); @@ -43,11 +43,11 @@ PageEditor::PageEditor(QWidget *parent) : QWidget(parent) { fdScale->setAlignment(Qt::AlignCenter); toolBar->addWidget(fdScale);//当前视图比例 - auto actScaleDown = new QAction(QIcon(":/res/ProgramManager/EditProgram/ScaleDown.png"), tr("Zoom Out")); + auto actScaleDown = new QAction(QIcon(":/res/program/ScaleDown.png"), tr("Zoom Out")); toolBar->addAction(actScaleDown);//缩小 connect(actScaleDown, &QAction::triggered, this, &PageEditor::onScaleDown); - QAction *actScaleOrg = new QAction(QIcon(":/res/ProgramManager/EditProgram/ScaleOrg.png"), tr("Original size")); + QAction *actScaleOrg = new QAction(QIcon(":/res/program/ScaleOrg.png"), tr("Original size")); connect(actScaleOrg, &QAction::triggered, this, [this] { curScale = 100; fdScale->setText("100"); @@ -56,22 +56,22 @@ PageEditor::PageEditor(QWidget *parent) : QWidget(parent) { toolBar->addAction(actScaleOrg);//1:1恢复视图 toolBar->addSeparator(); - QAction *actDelete = new QAction(QIcon(":/res/ProgramManager/EditProgram/Delete.png"), tr("Delete the secect media")); - QAction *actClean = new QAction(QIcon(":/res/ProgramManager/EditProgram/Clean.png"), tr("Clear all media")); - //QAction *actCut = new QAction(QIcon(":/res/ProgramManager/EditProgram/Cut.png"), tr("Cut media")); - QAction *actLayerUp = new QAction(QIcon(":/res/ProgramManager/EditProgram/LayerUp.png"), tr("Move layer up")); - QAction *actLayerDown = new QAction(QIcon(":/res/ProgramManager/EditProgram/LayerDown.png"), tr("Send backward")); - QAction *actLayerTop = new QAction(QIcon(":/res/ProgramManager/EditProgram/LayerTop.png"), tr("Bring to front")); - QAction *actLayerBottom = new QAction(QIcon(":/res/ProgramManager/EditProgram/LayerBottom.png"), tr("Move to the bottom layer")); - QAction *actTileFull = new QAction(QIcon(":/res/ProgramManager/EditProgram/TileFull.png"), tr("Fill the entire screen")); - QAction *actTileH = new QAction(QIcon(":/res/ProgramManager/EditProgram/TileH.png"), tr("Fill the screen horizontally")); - QAction *actTileV = new QAction(QIcon(":/res/ProgramManager/EditProgram/TileV.png"), tr("Fill the screen vertically")); - QAction *actArrayTop = new QAction(QIcon(":/res/ProgramManager/EditProgram/ArrayTop.png"), tr("Align top")); - QAction *actArrayHCenter = new QAction(QIcon(":/res/ProgramManager/EditProgram/ArrayHCenter.png"), tr("Center vertically")); - QAction *actArrayBottom = new QAction(QIcon(":/res/ProgramManager/EditProgram/ArrayBottom.png"), tr("Bottom align")); - QAction *actArrayLeft = new QAction(QIcon(":/res/ProgramManager/EditProgram/ArrayLeft.png"), tr("Align left")); - QAction *actArrayVCenter = new QAction(QIcon(":/res/ProgramManager/EditProgram/ArrayVCenter.png"), tr("Center horizontally")); - QAction *actArrayRight = new QAction(QIcon(":/res/ProgramManager/EditProgram/ArrayRight.png"), tr("Align right")); + QAction *actDelete = new QAction(QIcon(":/res/program/Delete.png"), tr("Delete the secect media")); + QAction *actClean = new QAction(QIcon(":/res/program/Clean.png"), tr("Clear all media")); + //QAction *actCut = new QAction(QIcon(":/res/program/Cut.png"), tr("Cut media")); + QAction *actLayerUp = new QAction(QIcon(":/res/program/LayerUp.png"), tr("Move layer up")); + QAction *actLayerDown = new QAction(QIcon(":/res/program/LayerDown.png"), tr("Send backward")); + QAction *actLayerTop = new QAction(QIcon(":/res/program/LayerTop.png"), tr("Bring to front")); + QAction *actLayerBottom = new QAction(QIcon(":/res/program/LayerBottom.png"), tr("Move to the bottom layer")); + QAction *actTileFull = new QAction(QIcon(":/res/program/TileFull.png"), tr("Fill the entire screen")); + QAction *actTileH = new QAction(QIcon(":/res/program/TileH.png"), tr("Fill the screen horizontally")); + QAction *actTileV = new QAction(QIcon(":/res/program/TileV.png"), tr("Fill the screen vertically")); + QAction *actArrayTop = new QAction(QIcon(":/res/program/ArrayTop.png"), tr("Align top")); + QAction *actArrayHCenter = new QAction(QIcon(":/res/program/ArrayHCenter.png"), tr("Center vertically")); + QAction *actArrayBottom = new QAction(QIcon(":/res/program/ArrayBottom.png"), tr("Bottom align")); + QAction *actArrayLeft = new QAction(QIcon(":/res/program/ArrayLeft.png"), tr("Align left")); + QAction *actArrayVCenter = new QAction(QIcon(":/res/program/ArrayVCenter.png"), tr("Center horizontally")); + QAction *actArrayRight = new QAction(QIcon(":/res/program/ArrayRight.png"), tr("Align right")); toolBar->addAction(actDelete); toolBar->addAction(actClean); toolBar->addSeparator(); @@ -169,7 +169,7 @@ void PageEditor::onScaleDown() { } void PageEditor::onDelete() { auto scene = graphicsView->scene(); - if(nullptr == scene) return; + if(0==scene) return; auto selectedItems = scene->selectedItems(); if(selectedItems.count() == 0) return; foreach(QGraphicsItem *selectedItem, selectedItems) if(selectedItem->type() >= QGraphicsItem::UserType) { diff --git a/LedOK/wProgramManager/pageeditor.h b/LedOK/program/pageeditor.h similarity index 100% rename from LedOK/wProgramManager/pageeditor.h rename to LedOK/program/pageeditor.h diff --git a/LedOK/wProgramManager/pagelistitem.cpp b/LedOK/program/pagelistitem.cpp similarity index 91% rename from LedOK/wProgramManager/pagelistitem.cpp rename to LedOK/program/pagelistitem.cpp index ebba2f7..8c56443 100644 --- a/LedOK/wProgramManager/pagelistitem.cpp +++ b/LedOK/program/pagelistitem.cpp @@ -1,25 +1,27 @@ #include "pagelistitem.h" #include "cfg.h" #include "tools.h" -#include "wProgramManager/wplanlist.h" +#include "base/ffutil.h" +#include "program/wplanlist.h" #include "base/lodateselector.h" -#include "wProgramManager/ebase.h" -#include "wProgramManager/etext.h" -#include "wProgramManager/ephoto.h" -#include "wProgramManager/evideo.h" -#include "wProgramManager/eaudio.h" -#include "wProgramManager/egif.h" -#include "wProgramManager/edclock.h" -#include "wProgramManager/eaclock.h" -#include "wProgramManager/eenviron.h" -#include "wProgramManager/eweb.h" -#include "wProgramManager/etimer.h" -#include "wProgramManager/emultiwin.h" +#include "program/ebase.h" +#include "program/etext.h" +#include "program/ephoto.h" +#include "program/evideo.h" +#include "program/eaudio.h" +#include "program/egif.h" +#include "program/edclock.h" +#include "program/eaclock.h" +#include "program/eenviron.h" +#include "program/eweb.h" +#include "program/etimer.h" +#include "program/emultiwin.h" #include "globaldefine.h" #include #include #include #include +#include #include #include @@ -38,19 +40,19 @@ PageListItem::PageListItem(const QJsonObject &attr, const QString &pageDir) : mA auto elements = mAttr["elements"].toArray(); foreach(auto ele, elements) { QString type = ele["elementType"].toString(); - EBase *element = nullptr; + EBase *element = 0; if(type=="Text") element = new EText(ele.toObject()); else if(type=="Photo") element = EPhoto::create(ele.toObject(), this); else if(type=="Gif") element = EGif::create(ele.toObject(), this); else if(type=="Movie") element = EVideo::create(ele.toObject(), this); else if(type=="Audio") element = EAudio::create(ele.toObject(), this); - else if(type=="DClock") element = new eDClock(ele.toObject()); - else if(type=="AClock") element = new eAClock(ele.toObject()); + else if(type=="DClock") element = new EDClock(ele.toObject()); + else if(type=="AClock") element = new EAClock(ele.toObject()); else if(type=="Temp") element = new EEnviron(ele.toObject()); else if(type=="Web") element = new EWeb(ele.toObject()); else if(type=="Timer") element = new ETimer(ele.toObject()); else if(type=="Window") element = new EMultiWin(ele.toObject(), this); - if(element!=nullptr) mScene->addItem(element); + if(element) mScene->addItem(element); } } @@ -160,17 +162,17 @@ QPushButton:hover { } QPushButton#bnAddPlan { - image: url(:/res/ProgramManager/EditProgram/AddPlan.png); + image: url(:/res/program/AddPlan.png); width: 24; height: 24; } QPushButton#bnClearPlan { - image: url(:/res/ProgramManager/EditProgram/Clean.png); + image: url(:/res/program/Clean.png); width: 24; height: 24; } QPushButton#bnDel { - image: url(:/res/ProgramManager/EditProgram/Delete.png); + image: url(:/res/program/Delete.png); width: 18; height: 18; } @@ -238,6 +240,15 @@ QPushButton[ssName="weeklySelector"]:checked { this->fdPlayTimes->setText(QString::number(value)); }); hBox->addWidget(fdPlayTimes); + hBox->addSpacing(20); + + auto fdLoop = new QCheckBox(tr("Sources Repeat")); + fdLoop->setChecked(mAttr["loop"].toBool()); + connect(fdLoop, &QCheckBox::toggled, this, [this](bool checked) { + mAttr["loop"] = checked; + }); + hBox->addWidget(fdLoop); + hBox->addStretch(); vBox->addLayout(hBox); @@ -249,7 +260,7 @@ QPushButton[ssName="weeklySelector"]:checked { hBox = new QHBoxLayout(); auto lb = new QLabel(); - lb->setPixmap(QPixmap(":/res/ProgramManager/EditProgram/Audio.png").scaledToHeight(24, Qt::SmoothTransformation)); + lb->setPixmap(QPixmap(":/res/program/Audio.png").scaledToHeight(24, Qt::SmoothTransformation)); hBox->addWidget(lb); hBox->addWidget(new QLabel(tr("Audios"))); hBox->addStretch(); @@ -261,7 +272,7 @@ QPushButton[ssName="weeklySelector"]:checked { hBox->addStretch(); auto btnAdd = new QPushButton(); - btnAdd->setIcon(QIcon(":/res/ProgramManager/EditProgram/Add.png")); + btnAdd->setIcon(QIcon(":/res/program/Add.png")); btnAdd->setProperty("style","multiTool"); mAudiosList = new QListWidget(); @@ -270,14 +281,14 @@ QPushButton[ssName="weeklySelector"]:checked { int durs = fdTtlDur->text().toInt(); for(int i=0; isetData(Qt::UserRole, QVariant::fromValue(info)); mAudiosList->addItem(item); if(i == files.count()-1) { @@ -292,7 +303,7 @@ QPushButton[ssName="weeklySelector"]:checked { hBox->addWidget(btnAdd); auto btnDel = new QPushButton(); - btnDel->setIcon(QIcon(":/res/ProgramManager/EditProgram/Delete.png")); + btnDel->setIcon(QIcon(":/res/program/Delete.png")); btnDel->setProperty("style","multiTool"); connect(btnDel, &QPushButton::clicked, this, [this, fdTtlDur] { auto row = mAudiosList->currentRow(); @@ -307,7 +318,7 @@ QPushButton[ssName="weeklySelector"]:checked { hBox->addWidget(btnDel); auto btnGoUp = new QPushButton(); - btnGoUp->setIcon(QIcon(":/res/ProgramManager/EditProgram/GoUp.png")); + btnGoUp->setIcon(QIcon(":/res/program/GoUp.png")); btnGoUp->setProperty("style","multiTool"); connect(btnGoUp, &QPushButton::clicked, this, [this] { int row = mAudiosList->currentRow(); @@ -318,7 +329,7 @@ QPushButton[ssName="weeklySelector"]:checked { hBox->addWidget(btnGoUp); auto btnGoDown = new QPushButton(); - btnGoDown->setIcon(QIcon(":/res/ProgramManager/EditProgram/GoDown.png")); + btnGoDown->setIcon(QIcon(":/res/program/GoDown.png")); btnGoDown->setProperty("style","multiTool"); connect(btnGoDown, &QPushButton::clicked, this, [this] { int row = mAudiosList->currentRow(); @@ -339,7 +350,7 @@ QPushButton[ssName="weeklySelector"]:checked { foreach(auto audio, audios) { AudioInfo info{audio["dir"].toString(), audio["name"].toString(), audio["dur"].toInt(), audio["vol"].toInt()}; if(info.dir.isEmpty() || info.name.isEmpty() || info.dur==0) continue; - auto item = new QListWidgetItem(QIcon(":/res/ProgramManager/EditProgram/Audio.png"), info.name); + auto item = new QListWidgetItem(QIcon(":/res/program/Audio.png"), info.name); item->setData(Qt::UserRole, QVariant::fromValue(info)); durs += info.dur; mAudiosList->addItem(item); diff --git a/LedOK/wProgramManager/pagelistitem.h b/LedOK/program/pagelistitem.h similarity index 100% rename from LedOK/wProgramManager/pagelistitem.h rename to LedOK/program/pagelistitem.h diff --git a/LedOK/wProgramManager/progcreatedlg.cpp b/LedOK/program/progcreatedlg.cpp similarity index 80% rename from LedOK/wProgramManager/progcreatedlg.cpp rename to LedOK/program/progcreatedlg.cpp index dca2456..40f36a1 100644 --- a/LedOK/wProgramManager/progcreatedlg.cpp +++ b/LedOK/program/progcreatedlg.cpp @@ -1,10 +1,10 @@ #include "progcreatedlg.h" -#include "gqt.h" +#include "gutil/qgui.h" #include "globaldefine.h" #include #include -ProgCreateDlg::ProgCreateDlg(QString name, int width, int height, QString remarks, QWidget *parent, bool lockName) : BaseDlg(parent) { +ProgCreateDlg::ProgCreateDlg(QString name, int width, int height, QString remarks, QString widths, QWidget *parent) : BaseDlg(parent) { auto vBox = new VBox(this); auto hBox = new HBox(vBox); @@ -33,8 +33,10 @@ ProgCreateDlg::ProgCreateDlg(QString name, int width, int height, QString remark hBox->addWidget(label); hBox->addSpacing(6); - fdName = new QLineEdit(name); - if(lockName) fdName->setDisabled(true); + fdName = new QLineEdit; + if(name.isEmpty()) name = QDateTime::currentDateTime().toString("yyyyMMddhhmmsszzz"); + else fdName->setDisabled(true); + fdName->setText(name); hBox->addWidget(fdName); hBox = new HBox(vBox); @@ -82,16 +84,16 @@ ProgCreateDlg::ProgCreateDlg(QString name, int width, int height, QString remark hBox = new HBox(vBox); - auto lbSplitWidth = new QLabel(tr("打折宽度")); - lbSplitWidth->setVisible(gWidthSplit); + auto lbSplitWidth = new QLabel(tr("每段打折宽度 (用空格分隔)")); hBox->addWidget(lbSplitWidth); - fdSplitWidth = new QSpinBox; - fdSplitWidth->setVisible(gWidthSplit); - fdSplitWidth->setMaximum(9999); - fdSplitWidth->setValue(0); - hBox->addWidget(fdSplitWidth); - hBox->addStretch(); + fdSplitWidths = new QLineEdit(widths); + fdSplitWidths->setPlaceholderText("256 256 256 ..."); + hBox->addWidget(fdSplitWidths); + if(! gWidthSplit) { + lbSplitWidth->setVisible(false); + fdSplitWidths->setVisible(false); + } hBox = new HBox(vBox); hBox->addStretch(); diff --git a/LedOK/wProgramManager/progcreatedlg.h b/LedOK/program/progcreatedlg.h similarity index 81% rename from LedOK/wProgramManager/progcreatedlg.h rename to LedOK/program/progcreatedlg.h index 5db0575..07284da 100644 --- a/LedOK/wProgramManager/progcreatedlg.h +++ b/LedOK/program/progcreatedlg.h @@ -9,12 +9,12 @@ class ProgCreateDlg : public BaseDlg { Q_OBJECT public: - ProgCreateDlg(QString name, int width, int height, QString remarks, QWidget *parent = nullptr, bool lockName = false); + ProgCreateDlg(QString name, int width, int height, QString remarks, QString, QWidget *parent = nullptr); QLineEdit *fdName; QSpinBox *fdWidth; QSpinBox *fdHeight; QTextEdit *fdRemark; - QSpinBox *fdSplitWidth; + QLineEdit *fdSplitWidths; }; #endif // PROGCREATEDLG_H diff --git a/LedOK/wProgramManager/progeditorwin.cpp b/LedOK/program/progeditorwin.cpp similarity index 82% rename from LedOK/wProgramManager/progeditorwin.cpp rename to LedOK/program/progeditorwin.cpp index e10ba54..8c32453 100644 --- a/LedOK/wProgramManager/progeditorwin.cpp +++ b/LedOK/program/progeditorwin.cpp @@ -10,20 +10,20 @@ #include "tools.h" #include "globaldefine.h" #include "base/waitingdlg.h" -#include "wProgramManager/ebase.h" -#include "wProgramManager/etext.h" -#include "wProgramManager/ephoto.h" -#include "wProgramManager/evideo.h" -#include "wProgramManager/eaudio.h" -#include "wProgramManager/egif.h" -#include "wProgramManager/edclock.h" -#include "wProgramManager/eaclock.h" -#include "wProgramManager/eenviron.h" -#include "wProgramManager/eweb.h" -#include "wProgramManager/etimer.h" -#include "wProgramManager/emultiwin.h" -#include "wProgramManager/gentmpthread.h" -#include "wProgramManager/sendprogramdialog.h" +#include "program/ebase.h" +#include "program/etext.h" +#include "program/ephoto.h" +#include "program/evideo.h" +#include "program/eaudio.h" +#include "program/egif.h" +#include "program/edclock.h" +#include "program/eaclock.h" +#include "program/eenviron.h" +#include "program/eweb.h" +#include "program/etimer.h" +#include "program/emultiwin.h" +#include "program/gentmpthread.h" +#include "program/sendprogramdialog.h" #include "progcreatedlg.h" #include #include @@ -42,7 +42,8 @@ ProgEditorWin::ProgEditorWin(ProgItem *progItem, QWidget *parent) : BaseWin(pare gProgEditorWin = this; gProgItem = progItem; setWindowModality(Qt::WindowModal); - if(parent!=nullptr && ! parent->isMaximized()) resize(parent->size()); + setAttribute(Qt::WA_AlwaysShowToolTips); + if(parent && ! parent->isMaximized()) resize(parent->size()); else resize(1280, 720); setWindowFlag(Qt::Window); setAttribute(Qt::WA_DeleteOnClose); @@ -77,10 +78,10 @@ ProgEditorWin::ProgEditorWin(ProgItem *progItem, QWidget *parent) : BaseWin(pare toolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); toolBar->setIconSize(QSize(46, 40)); - auto action = new QAction(QIcon(":/res/ProgramManager/EditProgram/Save.png"), tr("Save")); + auto action = new QAction(QIcon(":/res/program/Save.png"), tr("Save")); connect(action, &QAction::triggered, this, &ProgEditorWin::onSave); toolBar->addAction(action); - action = new QAction(QIcon(":/res/ProgramManager/EditProgram/SaveAs.png"), tr("Save as")); + action = new QAction(QIcon(":/res/program/SaveAs.png"), tr("Save as")); connect(action, &QAction::triggered, this, [this] { auto saveThread = QThread::create([this](){ save(); @@ -112,19 +113,43 @@ ProgEditorWin::ProgEditorWin(ProgItem *progItem, QWidget *parent) : BaseWin(pare dlgTip->exec(); close(); setWindowTitle(progName); - this->mProgItem->mProgPanel->onCreateNewProgramOnOpenEditProgramWidget(progName, QSize(mProgItem->mWidth, mProgItem->mHeight), this->mProgItem->mRemark, this->mProgItem->mSplitWidth); + mProgItem->mProgPanel->onCreateNewProgramOnOpenEditProgramWidget(progName, QSize(mProgItem->mWidth, mProgItem->mHeight), mProgItem->mRemark, mProgItem->mSplitWidths, mProgItem->mMaxWidth); }); toolBar->addAction(action); - action = new QAction(QIcon(":/res/ProgramManager/EditProgram/Setting.png"), tr("Setting")); - connect(action, &QAction::triggered, this, [this](){ - ProgCreateDlg dlg(this->mProgItem->mName, mProgItem->mWidth, mProgItem->mHeight, this->mProgItem->mRemark, this, true); + action = new QAction(QIcon(":/res/program/Setting.png"), tr("Setting")); + connect(action, &QAction::triggered, this, [this]() { + QString widthsStr; + foreach(auto width, mProgItem->mSplitWidths) { + if(! widthsStr.isEmpty()) widthsStr.append(" "); + widthsStr.append(QString::number(width)); + } + ProgCreateDlg dlg(mProgItem->mName, mProgItem->mWidth, mProgItem->mHeight, mProgItem->mRemark, widthsStr, this); if(dlg.exec() != QDialog::Accepted) return; mProgItem->mWidth = dlg.fdWidth->value(); mProgItem->mHeight = dlg.fdHeight->value(); - this->mProgItem->mRemark = dlg.fdRemark->toPlainText(); - this->mProgItem->m_last = QDateTime::currentDateTime(); - this->mProgItem->m_fsize = dirFileSize(this->mProgItem->mProgDir); - this->mProgItem->onSetProgram(); + mProgItem->mRemark = dlg.fdRemark->toPlainText(); + mProgItem->mSplitWidths.clear(); + mProgItem->mMaxWidth = 0; + auto splitWidths = dlg.fdSplitWidths->text().split(" ", Qt::SkipEmptyParts); + int ttl = 0; + foreach(auto splitWidth, splitWidths) { + int val = splitWidth.toInt(); + if(val==0) continue; + if(mProgItem->mMaxWidth < val) mProgItem->mMaxWidth = val; + ttl += val; + mProgItem->mSplitWidths.append(val); + } + if(mProgItem->mMaxWidth) { + while(ttl < mProgItem->mWidth) { + mProgItem->mSplitWidths.append(mProgItem->mMaxWidth); + ttl += mProgItem->mMaxWidth; + } + if(ttl > mProgItem->mWidth) mProgItem->mSplitWidths.last() -= ttl - mProgItem->mWidth; + } + + mProgItem->m_last = QDateTime::currentDateTime(); + mProgItem->m_fsize = dirFileSize(mProgItem->mProgDir); + mProgItem->onSetProgram(); int n = listPage->count(); for(int i=0; i(listPage->item(i)); @@ -136,75 +161,65 @@ ProgEditorWin::ProgEditorWin(ProgItem *progItem, QWidget *parent) : BaseWin(pare auto items = page->mScene->items(); foreach(auto item, items) { auto element = static_cast(item); - if(element->mMultiWin == nullptr) element->fitProgSize(); + if(element->mMultiWin == 0) element->fitProgSize(); } page->mScene->update(); } + onSave(); }); toolBar->addAction(action); toolBar->addSeparator(); - if(progItem->mSplitWidth==0) { - action = new QAction(QIcon(":/res/ProgramManager/EditProgram/Window.png"), tr("MuliContentWindow")); + if(progItem->mSplitWidths.isEmpty()) { + action = new QAction(QIcon(":/res/program/Window.png"), tr("MuliContentWindow")); action->setToolTip(tr("In this window, a plurality of different program materials can be added and played according to the order of joining the list;")); action->setData(EBase::Window); toolBar->addAction(action); toolBar->addSeparator(); - - action = new QAction(QIcon(":/res/ProgramManager/EditProgram/Text.png"), tr("Text")); - action->setData(EBase::Text); - toolBar->addAction(action); } - action = new QAction(QIcon(":/res/ProgramManager/EditProgram/Photo.png"), tr("Photo")); + action = new QAction(QIcon(":/res/program/Text.png"), tr("Text")); + action->setData(EBase::Text); + toolBar->addAction(action); + action = new QAction(QIcon(":/res/program/Photo.png"), tr("Photo")); action->setData(EBase::Photo); toolBar->addAction(action); - action = new QAction(QIcon(":/res/ProgramManager/EditProgram/Movie.png"), tr("Video")); + action = new QAction(QIcon(":/res/program/Movie.png"), tr("Video")); action->setData(EBase::Video); toolBar->addAction(action); - if(progItem->mSplitWidth==0) { - action = new QAction(QIcon(":/res/ProgramManager/EditProgram/Gif.png"), tr("Gif")); + if(progItem->mSplitWidths.isEmpty()) { + action = new QAction(QIcon(":/res/program/Gif.png"), tr("Gif")); action->setData(EBase::Gif); toolBar->addAction(action); - action = new QAction(QIcon(":/res/ProgramManager/EditProgram/DClock.png"), tr("Clock")); + action = new QAction(QIcon(":/res/program/DClock.png"), tr("Clock")); action->setData(EBase::DClock); toolBar->addAction(action); - action = new QAction(QIcon(":/res/ProgramManager/EditProgram/AClock.png"), tr("Analog Clock")); + action = new QAction(QIcon(":/res/program/AClock.png"), tr("Analog Clock")); action->setData(EBase::AClock); toolBar->addAction(action); - action = new QAction(QIcon(":/res/ProgramManager/EditProgram/Temp.png"), tr("Environment")); + action = new QAction(QIcon(":/res/program/Temp.png"), tr("Environment")); action->setData(EBase::Environ); toolBar->addAction(action); - action = new QAction(QIcon(":/res/ProgramManager/EditProgram/Web.png"), tr("Web")); + action = new QAction(QIcon(":/res/program/Web.png"), tr("Web")); action->setData(EBase::Web); toolBar->addAction(action); - action = new QAction(QIcon(":/res/ProgramManager/EditProgram/Timer.png"), tr("Timer")); + action = new QAction(QIcon(":/res/program/Timer.png"), tr("Timer")); action->setData(EBase::Timer); toolBar->addAction(action); } -// action = new QAction(QIcon(":/res/ProgramManager/EditProgram/Audio.png"), tr("Audio")); -// action->setData(EBase::Audio); -// toolBar->addAction(action); toolBar->addSeparator(); - action = new QAction(QIcon(":/res/ProgramManager/EditProgram/preview.png"), tr("Play")+"/"+tr("Stop")); + action = new QAction(QIcon(":/res/program/preview.png"), tr("Play")+"/"+tr("Stop")); connect(action, &QAction::triggered, this, [this] { if(PlayWin::self!=nullptr) PlayWin::self->close(); else { if(isProgChanged()) onSave(); - LoEmptyDialog * msgbox = new LoEmptyDialog(this); - //转换节目 + auto waitingDlg = new WaitingDlg(this, tr("Generate preview data")+" ..."); auto converter = new GenTmpThread(mProgItem, mProgItem->mName, "", "" ,this); - //转换结束,发送信号触发converter释放内存 - connect(converter, SIGNAL(finished()), converter, SLOT(deleteLater())); - connect(converter, SIGNAL(finished()), msgbox, SLOT(unlock())); - //链接转换进度信号到进度条槽函数 - connect(converter, SIGNAL(sProgress(QString,int,bool)), msgbox->mIndicator, SLOT(onProgress(QString,int,bool))); - //链接进度对话框启动信号到转换开始槽函数 - connect(msgbox, SIGNAL(startUp()), converter, SLOT(start())); - msgbox->lock(tr("Generate preview data")+"...",tr("Ready"),tr("Generate TimeOut")); - msgbox->exec(); - + connect(converter, &QThread::finished, waitingDlg, &WaitingDlg::close); + connect(converter, &GenTmpThread::sProgress, waitingDlg->mIndicator, &CustomProgressIndicator::onProgress); + converter->start(); + waitingDlg->exec(); QFile file(mProgItem->mProgDir+"_tmp/program"); if(! file.open(QIODevice::ReadOnly | QIODevice::Text)) return; QString value = file.readAll(); @@ -213,29 +228,25 @@ ProgEditorWin::ProgEditorWin(ProgItem *progItem, QWidget *parent) : BaseWin(pare QJsonObject prog = QJsonDocument::fromJson(value.toUtf8(), &jsErr).object(); if(jsErr.error) return; int www = mProgItem->mWidth, hhh = mProgItem->mHeight; - if(mProgItem->mSplitWidth) { - int cnt = (mProgItem->mWidth+mProgItem->mSplitWidth-1) / mProgItem->mSplitWidth; - www = mProgItem->mSplitWidth; - hhh = mProgItem->mHeight*cnt; + if(mProgItem->mMaxWidth) { + www = mProgItem->mMaxWidth; + hhh *= mProgItem->mSplitWidths.size(); } PlayWin::self = PlayWin::newIns(www, hhh, mProgItem->mProgDir+"_tmp", prog); } }); toolBar->addAction(action); - action = new QAction(QIcon(":/res/ProgramManager/EditProgram/Send.png"), tr("Publish")); + action = new QAction(QIcon(":/res/program/Send.png"), tr("Publish")); connect(action, &QAction::triggered, this, [this]{ onSave(); - auto waitingDlg = new WaitingDlg(this, tr("Convertering")); - auto converter = new GenTmpThread(this->mProgItem, this->mProgItem->mName, "", "", this); - connect(converter, &QThread::finished, converter, &QThread::deleteLater); - connect(converter, &QThread::finished, waitingDlg, &WaitingDlg::success); - connect(converter, SIGNAL(sProgress(QString,int,bool)), waitingDlg->mIndicator, SLOT(onProgress(QString,int,bool))); + auto waitingDlg = new WaitingDlg(this, tr("Convertering")+" ..."); + auto converter = new GenTmpThread(mProgItem, mProgItem->mName, "", "", this); + connect(converter, &QThread::finished, waitingDlg, &WaitingDlg::close); + connect(converter, &GenTmpThread::sProgress, waitingDlg->mIndicator, &CustomProgressIndicator::onProgress); converter->start(); - //msgbox->lock(tr("Convertering")+"...",tr("Converter Successed"),tr("Converter TimeOut")); waitingDlg->exec(); - - auto dlg = new SendProgramDialog(this, this->mProgItem->mName, programsDir()); - dlg->show(); + SendProgramDialog dlg(mProgItem->mName, this); + dlg.exec(); }); toolBar->addAction(action); @@ -322,12 +333,12 @@ ProgEditorWin::ProgEditorWin(ProgItem *progItem, QWidget *parent) : BaseWin(pare } else if(type==EBase::DClock) { if(iNewHeight>80 && (mProgItem->mWidth>=mProgItem->mHeight)) iNewHeight=80; - element = new eDClock(); + element = new EDClock(); } else if(type==EBase::AClock) { if(iNewWidth > 120) iNewWidth = 120; if(iNewHeight > 120) iNewHeight = 120; - element = new eAClock(); + element = new EAClock(); } else if(type==EBase::Environ) element = new EEnviron(); else if(type==EBase::Web) { @@ -337,7 +348,7 @@ ProgEditorWin::ProgEditorWin(ProgItem *progItem, QWidget *parent) : BaseWin(pare else if(type==EBase::Timer) element = new ETimer(); else if(type==EBase::Audio) ; else if(type==EBase::Window) element = new EMultiWin(mPageItem); - if(nullptr != element) { + if(element) { if(element->mWidth==0) { element->setPos(mNewEleX, mNewEleY); element->setSize(iNewWidth, iNewHeight); @@ -378,11 +389,11 @@ ProgEditorWin::ProgEditorWin(ProgItem *progItem, QWidget *parent) : BaseWin(pare toolBar->setIconSize(QSize(22,16)); toolBar->setStyleSheet("QToolBar{spacing: 8px;}"); - QAction *actAdd = new QAction(QIcon(":/res/ProgramManager/EditProgram/Add.png"), tr("Add page")); + QAction *actAdd = new QAction(QIcon(":/res/program/Add.png"), tr("Add page")); connect(actAdd, &QAction::triggered, this, &ProgEditorWin::onAddPage); toolBar->addAction(actAdd); - QAction *actCopy = new QAction(QIcon(":/res/ProgramManager/EditProgram/Copy.png"), tr("Copy page")); + QAction *actCopy = new QAction(QIcon(":/res/program/Copy.png"), tr("Copy page")); connect(actCopy, &QAction::triggered, this, [this] { if(listPage->count() > 0) { auto cur = static_cast(listPage->currentItem()); @@ -397,7 +408,7 @@ ProgEditorWin::ProgEditorWin(ProgItem *progItem, QWidget *parent) : BaseWin(pare }); toolBar->addAction(actCopy); - QAction *actDel = new QAction(QIcon(":/res/ProgramManager/EditProgram/Delete.png"), tr("Delete page")); + QAction *actDel = new QAction(QIcon(":/res/program/Delete.png"), tr("Delete page")); connect(actDel, &QAction::triggered, this, [this] { if(listPage->count() == 1) progEditorMid->onClean(); else if(listPage->count() > 1) { @@ -413,7 +424,7 @@ ProgEditorWin::ProgEditorWin(ProgItem *progItem, QWidget *parent) : BaseWin(pare }); toolBar->addAction(actDel); - QAction *actMoveUp = new QAction(QIcon(":/res/ProgramManager/EditProgram/GoUp.png"), tr("Move up")); + QAction *actMoveUp = new QAction(QIcon(":/res/program/GoUp.png"), tr("Move up")); connect(actMoveUp, &QAction::triggered, this, [this] { if(listPage->count() > 1) { int index = listPage->currentRow(); @@ -429,7 +440,7 @@ ProgEditorWin::ProgEditorWin(ProgItem *progItem, QWidget *parent) : BaseWin(pare }); toolBar->addAction(actMoveUp); - QAction *actMoveDown = new QAction(QIcon(":/res/ProgramManager/EditProgram/GoDown.png"), tr("Move down")); + QAction *actMoveDown = new QAction(QIcon(":/res/program/GoDown.png"), tr("Move down")); connect(actMoveDown, &QAction::triggered, this, [this] { if(listPage->count() > 1) { int index = listPage->currentRow(); @@ -608,6 +619,7 @@ void ProgEditorWin::save() { void ProgEditorWin::onSave() { auto waitingDlg = new WaitingDlg(this, tr("Saving..."), tr("Success")); + waitingDlg->btnAbort->hide(); //dlg->lock(tr("Saving..."),tr("Success"),tr("Save failed")); waitingDlg->show(); save(); diff --git a/LedOK/wProgramManager/progeditorwin.h b/LedOK/program/progeditorwin.h similarity index 94% rename from LedOK/wProgramManager/progeditorwin.h rename to LedOK/program/progeditorwin.h index dd12d82..7b252f5 100644 --- a/LedOK/wProgramManager/progeditorwin.h +++ b/LedOK/program/progeditorwin.h @@ -1,7 +1,7 @@ #ifndef PROGEDITORWIN_H #define PROGEDITORWIN_H #include "basewin.h" -#include "wProgramManager/pageeditor.h" +#include "program/pageeditor.h" #include class ProgPanel; diff --git a/LedOK/wProgramManager/progitem.cpp b/LedOK/program/progitem.cpp similarity index 60% rename from LedOK/wProgramManager/progitem.cpp rename to LedOK/program/progitem.cpp index 02a5258..da97cc4 100644 --- a/LedOK/wProgramManager/progitem.cpp +++ b/LedOK/program/progitem.cpp @@ -1,15 +1,18 @@ #include "progitem.h" +#include "gutil/qcore.h" #include "tools.h" #include "progeditorwin.h" +#include "base/waitingdlg.h" #include "gentmpthread.h" #include "base/loemptydialog.h" #include "usbdetectdialog.h" #include #include "sendprogramdialog.h" #include "mainwindow.h" +#include -ProgItem::ProgItem(const QString &progsDir, const QString &name, int w, int h, const QString &remarks, int splitWidth, LoQTreeWidget *tree, ProgPanel *progPanel) : QTreeWidgetItem(UserType), - mName(name), mWidth(w), mHeight(h), mRemark(remarks), mSplitWidth(splitWidth), mProgsDir(progsDir), mProgPanel(progPanel), mTree(tree) { +ProgItem::ProgItem(const QString &progsDir, const QString &name, int w, int h, const QString &remarks, QList &splitWidths, int maxWidth, LoQTreeWidget *tree, ProgPanel *progPanel) : QTreeWidgetItem(UserType), + mName(name), mWidth(w), mHeight(h), mRemark(remarks), mSplitWidths(splitWidths), mMaxWidth(maxWidth), mProgsDir(progsDir), mProgPanel(progPanel), mTree(tree) { m_last = QDateTime::currentDateTime(); mProgDir = progsDir + "/" + mName; m_orgName = mName; @@ -21,7 +24,12 @@ ProgItem::ProgItem(const QString &progsDir, const QJsonObject &json, LoQTreeWidg mWidth = json["resolution"]["w"].toInt(); mHeight = json["resolution"]["h"].toInt(); mRemark = json["remarks"].toString(); - mSplitWidth = json["splitWidth"].toInt(); + auto splitWidths = json["splitWidths"].toArray(); + foreach(auto splitWidth, splitWidths) { + int width = splitWidth.toInt(); + if(mMaxWidth < width) mMaxWidth = width; + mSplitWidths.append(width); + } m_fsize = json["file_size"].toDouble(); m_last = QDateTime::fromString(json["last_edit"].toString(), "yyyy-MM-dd hh:mm:ss"); mProgDir = progsDir + "/" + mName; @@ -30,20 +38,15 @@ ProgItem::ProgItem(const QString &progsDir, const QJsonObject &json, LoQTreeWidg init(); } -void ProgItem::init() -{ - auto cfg = Tools::getInstance(); - setData(ENUM_PROGRAMLISTHEADERITEM_NAME, 0,mName); +void ProgItem::init() { + setForeground(ENUM_PROGRAMLISTHEADERITEM_NAME, Qt::transparent); + setText(ENUM_PROGRAMLISTHEADERITEM_NAME, mName); setData(ENUM_PROGRAMLISTHEADERITEM_RESOLUTION, 0, QString("%1 x %2").arg(mWidth).arg(mHeight)); - if(m_fsize<=0) - setData(ENUM_PROGRAMLISTHEADERITEM_SIZE, 0, cfg->convertFileSize((qint64)100)); - else - setData(ENUM_PROGRAMLISTHEADERITEM_SIZE, 0, cfg->convertFileSize(m_fsize)); + if(m_fsize<=0) setData(ENUM_PROGRAMLISTHEADERITEM_SIZE, 0, byteSizeStr((qint64)100)); + else setData(ENUM_PROGRAMLISTHEADERITEM_SIZE, 0, byteSizeStr(m_fsize)); setData(ENUM_PROGRAMLISTHEADERITEM_LASTTIME, 0, m_last.toString("yyyy-MM-dd hh:mm:ss")); setTextAlignment(ENUM_PROGRAMLISTHEADERITEM_NAME, Qt::AlignLeft | Qt::AlignVCenter); - for(int i=1; iinsertTopLevelItem(0,this); @@ -69,9 +72,9 @@ QPushButton:hover { m_bnExport->setStyleSheet(R"rrr( QPushButton { border-radius: 4px; - image: url(:/res/ProgramManager/bnExport_u.png); + image: url(:/res/program/bnExport_u.png); } -QPushButton:pressed{image: url(:/res/ProgramManager/bnExport_s.png);} +QPushButton:pressed{image: url(:/res/program/bnExport_s.png);} QPushButton:hover{background-color: #cccccc;} )rrr"); @@ -84,9 +87,9 @@ QPushButton:hover{background-color: #cccccc;} m_bnSend->setStyleSheet(R"rrr( QPushButton{ border-radius: 4px; - image: url(:/res/ProgramManager/bnSend_u.png); + image: url(:/res/program/bnSend_u.png); } -QPushButton:pressed{image: url(:/res/ProgramManager/bnSend_s.png);} +QPushButton:pressed{image: url(:/res/program/bnSend_s.png);} QPushButton:hover{background-color: #cccccc;} )rrr"); @@ -106,7 +109,7 @@ void ProgItem::save() { } else if(mName != m_orgName) { dParent.rename(m_orgName, mName); m_orgName = mName; - mProgDir = mProgsDir + MACRO_FENGEFU + mName; + mProgDir = mProgsDir + "/" + mName; } dRoot = QDir(mProgDir); @@ -116,7 +119,9 @@ void ProgItem::save() { obj["name"] = mName; obj["resolution"] = QJsonObject{{"w", mWidth}, {"h", mHeight}}; obj["remarks"] = mRemark; - obj["splitWidth"] = mSplitWidth; + QJsonArray splitWidths; + foreach(auto splitWidth, mSplitWidths) splitWidths.append(splitWidth); + obj["splitWidths"] = splitWidths; obj["file_size"] = m_fsize; obj["last_edit"] = m_last.toString("yyyy-MM-dd hh:mm:ss"); QJsonDocument json(obj); @@ -133,10 +138,9 @@ void ProgItem::del() { } //设置列表项的值 void ProgItem::onSetProgram() { - auto cfg = Tools::getInstance(); m_bnName->setText(mName); setData(ENUM_PROGRAMLISTHEADERITEM_RESOLUTION, 0, QString("%1 x %2").arg(mWidth).arg(mHeight)); - setData(ENUM_PROGRAMLISTHEADERITEM_SIZE, 0, cfg->convertFileSize(m_fsize<=0 ? 100 : m_fsize)); + setData(ENUM_PROGRAMLISTHEADERITEM_SIZE, 0, byteSizeStr(m_fsize<=0 ? 100 : m_fsize)); setData(ENUM_PROGRAMLISTHEADERITEM_LASTTIME, 0, m_last.toString("yyyy-MM-dd hh:mm:ss")); save(); } @@ -146,36 +150,22 @@ void ProgItem::onUsbExportProgram(){ connect(pDlg, &UsbDetectDialog::acceptData, this, &ProgItem::onUsbExportProgramPro); pDlg->exec(); } -void ProgItem::onUsbExportProgramPro(QString strPath, QString strPassword){ - LoEmptyDialog *msgbox = new LoEmptyDialog(mProgPanel); - QString strUsbProgramName = mName; - auto converter = new GenTmpThread(this, strUsbProgramName, strPath + (strPath.endsWith('/') ? "program.zip" : "/program.zip"), strPassword, this); - connect(converter, &QThread::finished, converter, &QThread::deleteLater); - //转换结束,发送信号触发converter释放内存 - connect(converter, SIGNAL(finished()), msgbox, SLOT(unlock())); - connect(converter, SIGNAL(finished()), this, SLOT(UsbExportFinished())); - //链接转换进度信号到进度条槽函数 - connect(converter, SIGNAL(sProgress(QString,int,bool)), msgbox->mIndicator, SLOT(onProgress(QString,int,bool))); - //链接进度对话框启动信号到转换开始槽函数 - connect(msgbox, SIGNAL(startUp()), converter, SLOT(start())); - msgbox->lock(tr("Convertering")+"...",tr("USB Export Successed"),tr("USB Export TimeOut")); - msgbox->exec(); +void ProgItem::onUsbExportProgramPro(QString strPath, QString strPassword) { + auto waitingDlg = new WaitingDlg(mProgPanel, tr("Convertering")+" ..."); + auto converter = new GenTmpThread(this, mName, strPath + (strPath.endsWith('/') ? "program.zip" : "/program.zip"), strPassword, this); + connect(converter, &QThread::finished, waitingDlg, &WaitingDlg::success); + connect(converter, &GenTmpThread::sProgress, waitingDlg->mIndicator, &CustomProgressIndicator::onProgress); + converter->start(); + waitingDlg->exec(); } -void ProgItem::onSendProgram(){ - LoEmptyDialog *msgbox = new LoEmptyDialog(mProgPanel); - //转换节目 +void ProgItem::onSendProgram() { + auto waitingDlg = new WaitingDlg(mProgPanel, tr("Convertering")+" ..."); auto converter = new GenTmpThread(this, mName, "", "", this); - connect(converter, &QThread::finished, converter, &QThread::deleteLater); - //转换结束,发送信号触发converter释放内存 - connect(converter, SIGNAL(finished()), msgbox, SLOT(unlock())); - //链接转换进度信号到进度条槽函数 - connect(converter, SIGNAL(sProgress(QString,int,bool)), msgbox->mIndicator, SLOT(onProgress(QString,int,bool))); - //链接进度对话框启动信号到转换开始槽函数 - connect(msgbox, SIGNAL(startUp()), converter, SLOT(start())); - msgbox->lock(tr("Convertering")+"...",tr("Converter Successed"),tr("Converter TimeOut")); - msgbox->exec(); - - auto dlg = new SendProgramDialog(mProgPanel, mName, programsDir()); - dlg->show(); + connect(converter, &QThread::finished, waitingDlg, &WaitingDlg::close); + connect(converter, &GenTmpThread::sProgress, waitingDlg->mIndicator, &CustomProgressIndicator::onProgress); + converter->start(); + waitingDlg->exec(); + SendProgramDialog dlg(mName, mProgPanel); + dlg.exec(); } diff --git a/LedOK/wProgramManager/progitem.h b/LedOK/program/progitem.h similarity index 88% rename from LedOK/wProgramManager/progitem.h rename to LedOK/program/progitem.h index ebef519..62a9ff6 100644 --- a/LedOK/wProgramManager/progitem.h +++ b/LedOK/program/progitem.h @@ -13,7 +13,7 @@ class ProgPanel; class ProgItem : public QObject, public QTreeWidgetItem { Q_OBJECT public: - explicit ProgItem(const QString &progsDir, const QString &name, int w, int h, const QString & remarks, int splitWidth, LoQTreeWidget *parent = nullptr, ProgPanel *pWnd=nullptr); + explicit ProgItem(const QString &progsDir, const QString &name, int w, int h, const QString & remarks, QList &splitWidths, int, LoQTreeWidget *parent = nullptr, ProgPanel *pWnd=nullptr); explicit ProgItem(const QString &progsDir, const QJsonObject &json, LoQTreeWidget *parent = nullptr, ProgPanel *pWnd=nullptr); void save(); @@ -24,7 +24,8 @@ public: int mWidth; int mHeight; QString mRemark; - int mSplitWidth{0}; + QList mSplitWidths; + int mMaxWidth{0}; QString mProgsDir; QString mProgDir; qint64 m_fsize{0}; diff --git a/LedOK/wProgramManager/sendprogramdialog.cpp b/LedOK/program/sendprogramdialog.cpp similarity index 92% rename from LedOK/wProgramManager/sendprogramdialog.cpp rename to LedOK/program/sendprogramdialog.cpp index ec3f8f6..cac842e 100644 --- a/LedOK/wProgramManager/sendprogramdialog.cpp +++ b/LedOK/program/sendprogramdialog.cpp @@ -1,273 +1,270 @@ -#include "sendprogramdialog.h" -#include "tools.h" -#include -#include -#include -#include - -SendProgramDialog::SendProgramDialog(QWidget *parent, QString strProgramName, QString strProgramPath) : QWidget(parent, Qt::Window) { - setWindowModality(Qt::ApplicationModal); - setAttribute(Qt::WA_DeleteOnClose); - resize(1024, 700); - setWindowTitle(tr("Publish")+" "+strProgramName); - auto vBox = new QVBoxLayout(this); - auto hBox = new QHBoxLayout(); - - label = new QLabel(tr("success info")); - hBox->addWidget(label); - - hBox->addStretch(); - - auto pushButtonRefresh = new QPushButton(tr("Refresh")); - pushButtonRefresh->setProperty("ssType", "progManageTool"); - connect(pushButtonRefresh, SIGNAL(clicked()),this, SLOT(onRefresh())); - hBox->addWidget(pushButtonRefresh); - - auto txtSearch = new QLineEdit(); - txtSearch->setFixedWidth(150); - txtSearch->setClearButtonEnabled(true); - txtSearch->setStyleSheet("QLineEdit{border: 2px solid #aaaaaa; padding: 2px;}"); - txtSearch->addAction(new QAction(QIcon(":/res/ProgramManager/bnSearch.png"), QString()), QLineEdit::LeadingPosition); - connect(txtSearch,SIGNAL(textChanged(const QString &)),this,SLOT(FilterProgram(const QString &))); - hBox->addWidget(txtSearch); - - vBox->addLayout(hBox); - - wDevicePublishList = new LoQTreeWidget(); - wDevicePublishList->setProperty("ssType", "topList"); - m_headerItem = new QTreeWidgetItem(); - m_headerItem->setTextAlignment(1, Qt::AlignHCenter | Qt::AlignVCenter); - for(int i=1; isetTextAlignment(i, Qt::AlignCenter); - m_headerItem->setData(ENUM_DEVICE_PUBLISH_HEADE_CHECK, 0, ""); - m_headerItem->setData(ENUM_DEVICE_PUBLISH_HEADE_SCREEN_ID, 0, tr("Screen ID")); - m_headerItem->setData(ENUM_DEVICE_PUBLISH_HEADE_ONLINE, 0, tr("Online")); - m_headerItem->setData(ENUM_DEVICE_PUBLISH_HEADE_SCREEN_IP, 0, tr("Screen IP")); - m_headerItem->setData(ENUM_DEVICE_PUBLISH_HEADE_SCREEN_SIZE, 0, tr("Screen Size")); - m_headerItem->setData(ENUM_DEVICE_PUBLISH_HEADE_ENCRYPT,0,tr("Security")); - m_headerItem->setData(ENUM_DEVICE_PUBLISH_HEADE_PROGRESS, 0, tr("Progress")); - m_headerItem->setData(ENUM_DEVICE_PUBLISH_HEADE_REMARK_NAME, 0, tr("Remark Name")); - m_headerItem->setData(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, 0, tr("Remarks")); - wDevicePublishList->setHeaderItem(m_headerItem); - wDevicePublishList->header()->setSectionResizeMode(ENUM_DEVICE_PUBLISH_HEADE_CHECK, QHeaderView::Fixed); - wDevicePublishList->header()->setSectionResizeMode(ENUM_DEVICE_PUBLISH_HEADE_ONLINE, QHeaderView::Fixed); - wDevicePublishList->header()->setSectionResizeMode(ENUM_DEVICE_PUBLISH_HEADE_SCREEN_ID, QHeaderView::Fixed); - wDevicePublishList->header()->setSectionResizeMode(ENUM_DEVICE_PUBLISH_HEADE_SCREEN_IP, QHeaderView::Fixed); - wDevicePublishList->header()->setSectionResizeMode(ENUM_DEVICE_PUBLISH_HEADE_SCREEN_SIZE, QHeaderView::Fixed); - wDevicePublishList->header()->setSectionResizeMode(ENUM_DEVICE_PUBLISH_HEADE_ENCRYPT, QHeaderView::Fixed); - wDevicePublishList->header()->setSectionResizeMode(ENUM_DEVICE_PUBLISH_HEADE_PROGRESS, QHeaderView::Fixed); - wDevicePublishList->header()->setSectionResizeMode(ENUM_DEVICE_PUBLISH_HEADE_REMARK_NAME, QHeaderView::Interactive); - wDevicePublishList->header()->setSectionResizeMode(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, QHeaderView::Stretch); - wDevicePublishList->header()->setStretchLastSection(false); - wDevicePublishList->setColumnWidth(ENUM_DEVICE_PUBLISH_HEADE_CHECK, 52); - wDevicePublishList->setColumnWidth(ENUM_DEVICE_PUBLISH_HEADE_SCREEN_ID, 130); - wDevicePublishList->setColumnWidth(ENUM_DEVICE_PUBLISH_HEADE_SCREEN_IP, 130); - wDevicePublishList->setColumnWidth(ENUM_DEVICE_PUBLISH_HEADE_SCREEN_SIZE, 88); - wDevicePublishList->setColumnWidth(ENUM_DEVICE_PUBLISH_HEADE_ONLINE, 50); - wDevicePublishList->setColumnWidth(ENUM_DEVICE_PUBLISH_HEADE_ENCRYPT, 52); - wDevicePublishList->setColumnWidth(ENUM_DEVICE_PUBLISH_HEADE_REMARK_NAME, 160); - wDevicePublishList->setColumnWidth(ENUM_DEVICE_PUBLISH_HEADE_PROGRESS, 120); - vBox->addWidget(wDevicePublishList); - - hBox = new QHBoxLayout(); - hBox->addStretch(); - - auto btnPublish = new QPushButton(tr("Publish")); - connect(btnPublish, &QPushButton::clicked, this, [this] { - if(mWaitCnt > 0) return; - int cnt = wDevicePublishList->topLevelItemCount(); - int sentCnt{0}; - for(int i=0; itopLevelItem(i); - if(item->checkState(0) != Qt::Checked) continue; - auto row = static_cast(item); - if(row->mIsSending) continue; - if(row->mLedCard->bPassword && row->mLedCard->m_bLockStatus) { - row->setData(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, 0, tr("This screen is encrypted")); - row->setForeground(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, Qt::red); - continue; - } - row->fdProgress->setValue(0); - if(sentCnt>=5) { - row->setData(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, 0, " 等待中 ..."); - row->setForeground(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, Qt::black); - mWaitCnt++; - continue; - } - row->mIsSending = true; - row->setData(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, 0, ""); - auto sendProg = new SendProgThread(m_strProgramPath+"/"+m_strProgramName+"_tmp", row->mLedCard->m_strCardIp, 3333); - connect(sendProg, &SendProgThread::emErr, row, [this, row](QString strTip) { - row->mIsSending = false; - if(strTip=="OK") { - row->setCheckState(0, Qt::Unchecked); - row->setData(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, 0, "OK"); - row->setForeground(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, Qt::darkGreen); - } else { - row->setData(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, 0, strTip); - row->setForeground(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, Qt::red); - } - sendNext(); - }); - connect(sendProg, &SendProgThread::emProgress, row->fdProgress, &QProgressBar::setValue); - connect(this, &SendProgramDialog::stopAllThd, sendProg, &SendProgThread::stop); - sendProg->start(); - sentCnt++; - } - }); - btnPublish->setProperty("ssType", "progManageTool"); - hBox->addWidget(btnPublish); - - auto btnCancel = new QPushButton(tr("Cancel")); - connect(btnCancel, &QPushButton::clicked, this, &QWidget::close); - btnCancel->setProperty("ssType", "progManageTool"); - hBox->addWidget(btnCancel); - - vBox->addLayout(hBox); - - m_strProgramName = strProgramName; - m_strProgramPath = strProgramPath; - - onRefresh(); - - auto timer = new QTimer(this); - connect(timer, &QTimer::timeout, this, &SendProgramDialog::onRefresh); - timer->start(60000); -} -void SendProgramDialog::closeEvent(QCloseEvent *) { - emit stopAllThd(); -} -void SendProgramDialog::sendNext() { - if(mWaitCnt <= 0) return; - int cnt = wDevicePublishList->topLevelItemCount(); - for(int i=0; itopLevelItem(i); - if(item->checkState(0) != Qt::Checked) continue; - auto row = static_cast(item); - if(row->mIsSending) continue; - if(row->mLedCard->bPassword && row->mLedCard->m_bLockStatus) continue; - if(! row->data(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, 0).toString().startsWith(" ")) continue; - row->setData(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, 0, ""); - row->fdProgress->setValue(0); - row->mIsSending = true; - mWaitCnt--; - auto sendProg = new SendProgThread(m_strProgramPath+"/"+m_strProgramName+"_tmp", row->mLedCard->m_strCardIp, 3333); - connect(sendProg, &SendProgThread::emErr, row, [this, row](QString strTip) { - row->mIsSending = false; - if(strTip=="OK") { - row->setCheckState(0, Qt::Unchecked); - row->setData(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, 0, "OK"); - row->setForeground(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, Qt::darkGreen); - } else { - row->setData(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, 0, strTip); - row->setForeground(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, Qt::red); - } - sendNext(); - }); - connect(sendProg, &SendProgThread::emProgress, row->fdProgress, &QProgressBar::setValue); - connect(this, &SendProgramDialog::stopAllThd, sendProg, &SendProgThread::stop); - sendProg->start(); - return; - } -} - -void SendProgramDialog::onRefresh() { - int iCount = gDevicePanel->LedCardList.count(); - for(int i=0; iLedCardList.at(i)); - label->setText(tr("All")+":"+QString::number(iCount)); -} -void SendProgramDialog::onAddLedCard(LedCard *p) { - int iExistFlg=0; - int cnt = wDevicePublishList->topLevelItemCount(); - for(int i=0; i(wDevicePublishList->topLevelItem(i))->mLedCard->m_strCardId; - if(strTempCardId == p->m_strCardId) { - iExistFlg=1; - static_cast(wDevicePublishList->topLevelItem(i))->SetItemParam(p); - break; - } - } - if(iExistFlg==0) new wProgramPublishItem(p, wDevicePublishList, this, m_strProgramName, m_strProgramPath); -} -void SendProgramDialog::FilterProgram(const QString &strtemp) -{ - if (strtemp.isEmpty()) //显示全部 - { - for (int i = 0; i< wDevicePublishList->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = wDevicePublishList->topLevelItem(i); - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),false); - } - } - else - { - QList resultList = wDevicePublishList->findItems(strtemp, Qt::MatchContains,ENUM_DEVICE_PUBLISH_HEADE_SCREEN_ID); //搜索结果 - if (resultList.size() > 0) - { - //QMessageBox::warning(this, "Export", QString(resultList.size())); - for (int i = 0; i< wDevicePublishList->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = wDevicePublishList->topLevelItem(i); - if (resultList.contains(topItem)) - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),false); //显示匹配的结果 - else - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - else { - - QList resultList6 = wDevicePublishList->findItems(strtemp, Qt::MatchContains,ENUM_DEVICE_PUBLISH_HEADE_REMARK_NAME); //搜索结果 - if (resultList6.size() > 0) - { - //QMessageBox::warning(this, "Export", QString(resultList.size())); - for (int i = 0; i< wDevicePublishList->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = wDevicePublishList->topLevelItem(i); - if (resultList6.contains(topItem)) - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),false); //显示匹配的结果 - else - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - else { - - - //QMessageBox::warning(this, "Export", "FilterProgram"); - QList resultList1 = wDevicePublishList->findItems(strtemp, Qt::MatchContains,ENUM_DEVICE_PUBLISH_HEADE_SCREEN_SIZE); //搜索结果 - if (resultList1.size() > 0) - { - //QMessageBox::warning(this, "Export", QString(resultList.size())); - for (int i = 0; i< wDevicePublishList->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = wDevicePublishList->topLevelItem(i); - if (resultList1.contains(topItem)) - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),false); //显示匹配的结果 - else - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - else { - QList resultList2 = wDevicePublishList->findItems(strtemp, Qt::MatchContains,ENUM_DEVICE_PUBLISH_HEADE_SCREEN_IP); //搜索结果 - if (resultList2.size() > 0) - { - //QMessageBox::warning(this, "Export", QString(resultList.size())); - for (int i = 0; i< wDevicePublishList->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = wDevicePublishList->topLevelItem(i); - if (resultList2.contains(topItem)) - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),false); //显示匹配的结果 - else - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - else { - for (int i = 0; i< wDevicePublishList->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = wDevicePublishList->topLevelItem(i); - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - } - } - } - } -} +#include "sendprogramdialog.h" +#include "tools.h" +#include "cfg.h" +#include +#include +#include +#include + +SendProgramDialog::SendProgramDialog(QString progName, QWidget *parent) : QDialog(parent), mProgName(progName) { + setWindowFlag(Qt::WindowMaximizeButtonHint); + setWindowTitle(tr("Publish")+" "+mProgName); + resize(1024, 700); + auto vBox = new QVBoxLayout(this); + auto hBox = new QHBoxLayout(); + + label = new QLabel(tr("success info")); + hBox->addWidget(label); + + hBox->addStretch(); + + auto pushButtonRefresh = new QPushButton(tr("Refresh")); + pushButtonRefresh->setProperty("ssType", "progManageTool"); + connect(pushButtonRefresh, SIGNAL(clicked()),this, SLOT(onRefresh())); + hBox->addWidget(pushButtonRefresh); + + auto txtSearch = new QLineEdit(); + txtSearch->setFixedWidth(150); + txtSearch->setClearButtonEnabled(true); + txtSearch->setStyleSheet("QLineEdit{border: 2px solid #aaaaaa; padding: 2px;}"); + txtSearch->addAction(new QAction(QIcon(":/res/program/bnSearch.png"), QString()), QLineEdit::LeadingPosition); + connect(txtSearch,SIGNAL(textChanged(const QString &)),this,SLOT(FilterProgram(const QString &))); + hBox->addWidget(txtSearch); + + vBox->addLayout(hBox); + + wDevicePublishList = new LoQTreeWidget(); + wDevicePublishList->setProperty("ssType", "topList"); + m_headerItem = new QTreeWidgetItem(); + m_headerItem->setTextAlignment(1, Qt::AlignHCenter | Qt::AlignVCenter); + for(int i=1; isetTextAlignment(i, Qt::AlignCenter); + m_headerItem->setData(ENUM_DEVICE_PUBLISH_HEADE_CHECK, 0, ""); + m_headerItem->setData(ENUM_DEVICE_PUBLISH_HEADE_SCREEN_ID, 0, tr("Screen ID")); + m_headerItem->setData(ENUM_DEVICE_PUBLISH_HEADE_ONLINE, 0, tr("Online")); + m_headerItem->setData(ENUM_DEVICE_PUBLISH_HEADE_SCREEN_IP, 0, tr("Screen IP")); + m_headerItem->setData(ENUM_DEVICE_PUBLISH_HEADE_SCREEN_SIZE, 0, tr("Screen Size")); + m_headerItem->setData(ENUM_DEVICE_PUBLISH_HEADE_ENCRYPT,0,tr("Security")); + m_headerItem->setData(ENUM_DEVICE_PUBLISH_HEADE_REMARK_NAME, 0, tr("Remark Name")); + m_headerItem->setData(ENUM_DEVICE_PUBLISH_HEADE_PROGRESS, 0, tr("Progress")); + m_headerItem->setData(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, 0, tr("Remarks")); + wDevicePublishList->setHeaderItem(m_headerItem); + wDevicePublishList->header()->setSectionResizeMode(ENUM_DEVICE_PUBLISH_HEADE_CHECK, QHeaderView::Fixed); + wDevicePublishList->header()->setSectionResizeMode(ENUM_DEVICE_PUBLISH_HEADE_ONLINE, QHeaderView::Fixed); + wDevicePublishList->header()->setSectionResizeMode(ENUM_DEVICE_PUBLISH_HEADE_SCREEN_ID, QHeaderView::Fixed); + wDevicePublishList->header()->setSectionResizeMode(ENUM_DEVICE_PUBLISH_HEADE_SCREEN_IP, QHeaderView::Fixed); + wDevicePublishList->header()->setSectionResizeMode(ENUM_DEVICE_PUBLISH_HEADE_SCREEN_SIZE, QHeaderView::Fixed); + wDevicePublishList->header()->setSectionResizeMode(ENUM_DEVICE_PUBLISH_HEADE_ENCRYPT, QHeaderView::Fixed); + wDevicePublishList->header()->setSectionResizeMode(ENUM_DEVICE_PUBLISH_HEADE_PROGRESS, QHeaderView::Fixed); + wDevicePublishList->header()->setSectionResizeMode(ENUM_DEVICE_PUBLISH_HEADE_REMARK_NAME, QHeaderView::Interactive); + wDevicePublishList->header()->setSectionResizeMode(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, QHeaderView::Stretch); + wDevicePublishList->header()->setStretchLastSection(false); + wDevicePublishList->setColumnWidth(ENUM_DEVICE_PUBLISH_HEADE_CHECK, 52); + wDevicePublishList->setColumnWidth(ENUM_DEVICE_PUBLISH_HEADE_SCREEN_ID, 130); + wDevicePublishList->setColumnWidth(ENUM_DEVICE_PUBLISH_HEADE_SCREEN_IP, 130); + wDevicePublishList->setColumnWidth(ENUM_DEVICE_PUBLISH_HEADE_SCREEN_SIZE, 88); + wDevicePublishList->setColumnWidth(ENUM_DEVICE_PUBLISH_HEADE_ONLINE, 50); + wDevicePublishList->setColumnWidth(ENUM_DEVICE_PUBLISH_HEADE_ENCRYPT, 52); + wDevicePublishList->setColumnWidth(ENUM_DEVICE_PUBLISH_HEADE_REMARK_NAME, 160); + wDevicePublishList->setColumnWidth(ENUM_DEVICE_PUBLISH_HEADE_PROGRESS, 120); + vBox->addWidget(wDevicePublishList); + + hBox = new QHBoxLayout(); + hBox->addStretch(); + + auto btnPublish = new QPushButton(tr("Publish")); + connect(btnPublish, &QPushButton::clicked, this, [this] { + if(mWaitCnt > 0) return; + int cnt = wDevicePublishList->topLevelItemCount(); + int sentCnt{0}; + for(int i=0; itopLevelItem(i); + if(item->checkState(0) != Qt::Checked) continue; + auto row = static_cast(item); + if(row->mIsSending) continue; + if(row->mLedCard->bPassword && row->mLedCard->m_bLockStatus) { + row->setData(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, 0, tr("This screen is encrypted")); + row->setForeground(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, Qt::red); + continue; + } + row->fdProgress->setValue(0); + if(sentCnt>=5) { + row->setData(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, 0, " 等待中 ..."); + row->setForeground(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, Qt::black); + mWaitCnt++; + continue; + } + row->mIsSending = true; + row->setData(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, 0, ""); + auto sendProg = new SendProgThread(programsDir()+"/"+mProgName+"_tmp", row->mLedCard->m_strCardIp, 3333); + connect(sendProg, &SendProgThread::emErr, row, [this, row](QString strTip) { + row->mIsSending = false; + if(strTip=="OK") { + row->setCheckState(0, Qt::Unchecked); + row->setData(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, 0, "OK"); + row->setForeground(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, Qt::darkGreen); + } else { + row->setData(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, 0, strTip); + row->setForeground(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, Qt::red); + } + sendNext(); + }); + connect(sendProg, &SendProgThread::emProgress, row->fdProgress, &QProgressBar::setValue); + connect(this, &SendProgramDialog::stopAllThd, sendProg, &SendProgThread::stop); + sendProg->start(); + sentCnt++; + } + }); + btnPublish->setProperty("ssType", "progManageTool"); + hBox->addWidget(btnPublish); + + auto btnCancel = new QPushButton(tr("Cancel")); + connect(btnCancel, &QPushButton::clicked, this, &QWidget::close); + btnCancel->setProperty("ssType", "progManageTool"); + hBox->addWidget(btnCancel); + + vBox->addLayout(hBox); + + onRefresh(); + + auto timer = new QTimer(this); + connect(timer, &QTimer::timeout, this, &SendProgramDialog::onRefresh); + timer->start(60000); +} +void SendProgramDialog::closeEvent(QCloseEvent *) { + emit stopAllThd(); +} +void SendProgramDialog::sendNext() { + if(mWaitCnt <= 0) return; + int cnt = wDevicePublishList->topLevelItemCount(); + for(int i=0; itopLevelItem(i); + if(item->checkState(0) != Qt::Checked) continue; + auto row = static_cast(item); + if(row->mIsSending) continue; + if(row->mLedCard->bPassword && row->mLedCard->m_bLockStatus) continue; + if(! row->data(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, 0).toString().startsWith(" ")) continue; + row->setData(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, 0, ""); + row->fdProgress->setValue(0); + row->mIsSending = true; + mWaitCnt--; + auto sendProg = new SendProgThread(programsDir()+"/"+mProgName+"_tmp", row->mLedCard->m_strCardIp, 3333); + connect(sendProg, &SendProgThread::emErr, row, [this, row](QString strTip) { + row->mIsSending = false; + if(strTip=="OK") { + row->setCheckState(0, Qt::Unchecked); + row->setData(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, 0, "OK"); + row->setForeground(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, Qt::darkGreen); + } else { + row->setData(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, 0, strTip); + row->setForeground(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, Qt::red); + } + sendNext(); + }); + connect(sendProg, &SendProgThread::emProgress, row->fdProgress, &QProgressBar::setValue); + connect(this, &SendProgramDialog::stopAllThd, sendProg, &SendProgThread::stop); + sendProg->start(); + return; + } +} + +void SendProgramDialog::onRefresh() { + int iCount = gDevicePanel->mLedCards.count(); + for(int i=0; imLedCards.at(i)); + label->setText(tr("All")+":"+QString::number(iCount)); +} +void SendProgramDialog::onAddLedCard(LedCard *p) { + int iExistFlg=0; + int cnt = wDevicePublishList->topLevelItemCount(); + for(int i=0; i(wDevicePublishList->topLevelItem(i))->mLedCard->m_strCardId; + if(strTempCardId == p->m_strCardId) { + iExistFlg=1; + static_cast(wDevicePublishList->topLevelItem(i))->SetItemParam(p); + break; + } + } + if(iExistFlg==0) new wProgramPublishItem(p, wDevicePublishList, this, mProgName, programsDir()); +} +void SendProgramDialog::FilterProgram(const QString &strtemp) +{ + if (strtemp.isEmpty()) //显示全部 + { + for (int i = 0; i< wDevicePublishList->topLevelItemCount(); ++i) + { + QTreeWidgetItem* topItem = wDevicePublishList->topLevelItem(i); + wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),false); + } + } + else + { + QList resultList = wDevicePublishList->findItems(strtemp, Qt::MatchContains,ENUM_DEVICE_PUBLISH_HEADE_SCREEN_ID); //搜索结果 + if (resultList.size() > 0) + { + //QMessageBox::warning(this, "Export", QString(resultList.size())); + for (int i = 0; i< wDevicePublishList->topLevelItemCount(); ++i) + { + QTreeWidgetItem* topItem = wDevicePublishList->topLevelItem(i); + if (resultList.contains(topItem)) + wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),false); //显示匹配的结果 + else + wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 + } + } + else { + + QList resultList6 = wDevicePublishList->findItems(strtemp, Qt::MatchContains,ENUM_DEVICE_PUBLISH_HEADE_REMARK_NAME); //搜索结果 + if (resultList6.size() > 0) + { + //QMessageBox::warning(this, "Export", QString(resultList.size())); + for (int i = 0; i< wDevicePublishList->topLevelItemCount(); ++i) + { + QTreeWidgetItem* topItem = wDevicePublishList->topLevelItem(i); + if (resultList6.contains(topItem)) + wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),false); //显示匹配的结果 + else + wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 + } + } + else { + + + //QMessageBox::warning(this, "Export", "FilterProgram"); + QList resultList1 = wDevicePublishList->findItems(strtemp, Qt::MatchContains,ENUM_DEVICE_PUBLISH_HEADE_SCREEN_SIZE); //搜索结果 + if (resultList1.size() > 0) + { + //QMessageBox::warning(this, "Export", QString(resultList.size())); + for (int i = 0; i< wDevicePublishList->topLevelItemCount(); ++i) + { + QTreeWidgetItem* topItem = wDevicePublishList->topLevelItem(i); + if (resultList1.contains(topItem)) + wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),false); //显示匹配的结果 + else + wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 + } + } + else { + QList resultList2 = wDevicePublishList->findItems(strtemp, Qt::MatchContains,ENUM_DEVICE_PUBLISH_HEADE_SCREEN_IP); //搜索结果 + if (resultList2.size() > 0) + { + //QMessageBox::warning(this, "Export", QString(resultList.size())); + for (int i = 0; i< wDevicePublishList->topLevelItemCount(); ++i) + { + QTreeWidgetItem* topItem = wDevicePublishList->topLevelItem(i); + if (resultList2.contains(topItem)) + wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),false); //显示匹配的结果 + else + wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 + } + } + else { + for (int i = 0; i< wDevicePublishList->topLevelItemCount(); ++i) + { + QTreeWidgetItem* topItem = wDevicePublishList->topLevelItem(i); + wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 + } + } + } + } + } + } +} diff --git a/LedOK/wProgramManager/sendprogramdialog.h b/LedOK/program/sendprogramdialog.h similarity index 71% rename from LedOK/wProgramManager/sendprogramdialog.h rename to LedOK/program/sendprogramdialog.h index dc12b3e..5bea778 100644 --- a/LedOK/wProgramManager/sendprogramdialog.h +++ b/LedOK/program/sendprogramdialog.h @@ -1,31 +1,31 @@ -#ifndef SENDPROGRAMDIALOG_H -#define SENDPROGRAMDIALOG_H - -#include "wprogrampublishitem.h" - -class SendProgramDialog : public QWidget { - Q_OBJECT -public: - explicit SendProgramDialog(QWidget *parent = nullptr, QString strProgramName = "", QString strProgramPath = ""); -protected: - void closeEvent(QCloseEvent *event) override; -signals: - void stopAllThd(); -protected slots: - void onRefresh(); - void FilterProgram(const QString &strtemp); -private: - void sendNext(); - void onAddLedCard(LedCard *p); - - LoQTreeWidget *wDevicePublishList; - int mWaitCnt{0}; - QLabel *label; - - QTreeWidgetItem *m_headerItem = nullptr; - QString m_strProgramName; - QString m_strProgramPath; - QString m_strUrl; -}; - -#endif // SENDPROGRAMDIALOG_H +#ifndef SENDPROGRAMDIALOG_H +#define SENDPROGRAMDIALOG_H + +#include "wprogrampublishitem.h" +#include + +class SendProgramDialog : public QDialog { + Q_OBJECT +public: + explicit SendProgramDialog(QString, QWidget *parent = nullptr); +protected: + void closeEvent(QCloseEvent *event) override; +signals: + void stopAllThd(); +protected slots: + void onRefresh(); + void FilterProgram(const QString &strtemp); +private: + void sendNext(); + void onAddLedCard(LedCard *p); + + LoQTreeWidget *wDevicePublishList; + int mWaitCnt{0}; + QLabel *label; + + QTreeWidgetItem *m_headerItem = nullptr; + QString mProgName; + QString m_strUrl; +}; + +#endif // SENDPROGRAMDIALOG_H diff --git a/LedOK/wProgramManager/sendprogthread.cpp b/LedOK/program/sendprogthread.cpp similarity index 96% rename from LedOK/wProgramManager/sendprogthread.cpp rename to LedOK/program/sendprogthread.cpp index 4486214..c6eda2d 100644 --- a/LedOK/wProgramManager/sendprogthread.cpp +++ b/LedOK/program/sendprogthread.cpp @@ -1,224 +1,225 @@ -#include "sendprogthread.h" -#include -#include -#include -#include -#include -#include - -SendProgThread::SendProgThread(const QString &progDir, const QString &ip, int port) : prog_dir(progDir), ip(ip), port(port) { - connect(this, &QThread::finished, this, &QThread::deleteLater); -} - -void SendProgThread::run() { - emit emProgress(0); // 进度条归零 - auto fileInfos = QDir(prog_dir).entryInfoList(QDir::Files); - if(fileInfos.isEmpty()) { - emit emErr(tr("Program is empty")); - return; - } - if(stoped) return; - TcpSocket tcp; - tcp.connectToHost(ip, port); - if(! tcp.waitForConnected()) { - emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when waitForConnected"); - tcp.close(); - return; - } - if(stoped) { - tcp.close(); - return; - }; - //发送节目列表协商 - QJsonArray ids; - foreach(auto fileInfo, fileInfos) { - auto baseName = fileInfo.baseName(); - if(baseName!="program") ids.append(baseName); - } - if(! ids.isEmpty()) { - QJsonObject req; - req.insert("_type", "consult"); - req.insert("proName", "program"); - req.insert("idList", ids); - req.insert("zVer", "xixun1"); - auto requ = QJsonDocument(req).toJson(QJsonDocument::Compact); - auto resNum = tcp.write(requ); - if(resNum == -1 || ! tcp.waitForBytesWritten()) { - emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when write 'consult'. size"+QString::number(requ.size())); - tcp.close(); - return; - } - if(! tcp.waitForReadyRead()) { - emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when waitForRead 'consult'. size"+QString::number(requ.size())); - tcp.close(); - return; - } - auto resp = tcp.readAll(); - if(resp.isEmpty()) { - emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when read 'consult'. size"+QString::number(requ.size())); - tcp.close(); - return; - } - if(stoped) { - tcp.close(); - return; - }; - QJsonParseError parseErr; - QJsonDocument res = QJsonDocument::fromJson(resp, &parseErr); - for(int i=2; parseErr.error == QJsonParseError::UnterminatedString && i < 10; i++) { - if(! tcp.waitForReadyRead()) { - emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when waitForRead 'consult' "+QString::number(i)); - tcp.close(); - return; - } - auto resp2 = tcp.readAll(); - if(resp2.isEmpty()) { - emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when read 'consult' "+QString::number(i)); - tcp.close(); - return; - } - resp += resp2; - res = QJsonDocument::fromJson(resp, &parseErr); - } - if(parseErr.error != QJsonParseError::NoError) { - emit emErr(parseErr.errorString()+" when parse consult. size:"+QString::number(resp.size())); - tcp.close(); - return; - } - if(res["_type"].toString()=="consult") { - fileInfos.clear(); - fileInfos.append(QString(prog_dir+"/program")); - QJsonArray ids = res["idList"].toArray(); - foreach(auto id, ids) fileInfos.append(QString(prog_dir+"/"+id.toString())); - } - } - if(stoped) { - tcp.close(); - return; - } - qint64 progSize = 0; - foreach(auto fileInfo, fileInfos) progSize += fileInfo.size(); - if(progSize == 0) { - emit emErr(tr("Program is empty")); - tcp.close(); - return; - } - auto req = QJsonObject(); - req.insert("_type", "proStart"); - req.insert("proName", "program"); - req.insert("proSize", progSize); - req.insert("zVer","xixun1"); - auto resNum = tcp.write(QJsonDocument(req).toJson(QJsonDocument::Compact)); - if(resNum == -1 || ! tcp.waitForBytesWritten()) { - emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when write 'proStart'"); - tcp.close(); - return; - } - if(stoped) { - tcp.close(); - return; - } - //4.发送协商列表应答里的文件 - long long sentBytes = 0; - foreach(auto info, fileInfos) if(info.isFile()) { - auto baseName = info.baseName(); - auto remain = info.size(); - req = QJsonObject(); - req.insert("_type", "fileStart"); - req.insert("id", baseName); - req.insert("size", remain); - req.insert("relative_path", ""); - req.insert("zVer","xixun1"); - auto resNum = tcp.write(QJsonDocument(req).toJson(QJsonDocument::Compact)); - if(resNum == -1 || ! tcp.waitForBytesWritten()) { - emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when write 'fileStart'"); - tcp.close(); - return; - } - auto file = new QFile(info.filePath()); - if(! file->open(QFile::ReadOnly)) { - emit emErr(tr("Open file failed")+" "+file->errorString()); - tcp.close(); - return; - } - while(remain > 0) { - auto readed = file->read(qMin(4096LL, remain)); - if(readed.isEmpty()) { - emit emErr(tr("Read file failed")+" "+file->errorString()); - tcp.close(); - file->close(); - return; - } - if(stoped) { - tcp.close(); - file->close(); - return; - }; - resNum = tcp.write(readed); - if(resNum == -1) { - emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when write file: "+file->fileName()); - tcp.close(); - file->close(); - return; - } - if(! tcp.waitForBytesWritten()) { - emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when waitForWritten file: "+file->fileName()); - tcp.close(); - file->close(); - return; - } - if(stoped) { - tcp.close(); - file->close(); - return; - }; - remain -= resNum; - sentBytes += resNum; - if(sentBytes != 0) emit emProgress(sentBytes * 99 / progSize); - } - file->close(); - if(stoped) { - tcp.close(); - return; - }; - req = QJsonObject(); - req.insert("_type", "fileEnd"); - req.insert("id", baseName); - req.insert("zVer", "xixun1"); - resNum = tcp.write(QJsonDocument(req).toJson(QJsonDocument::Compact)); - if(resNum == -1 || ! tcp.waitForBytesWritten()) { - emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when write 'fileEnd'"); - tcp.close(); - return; - } - } - if(stoped) { - tcp.close(); - return; - }; - //5.发送结束 - req = QJsonObject(); - req.insert("_type", "proEnd"); - req.insert("proName", "program"); - req.insert("zVer","xixun1"); - resNum = tcp.write(QJsonDocument(req).toJson(QJsonDocument::Compact)); - if(resNum == -1 || ! tcp.waitForBytesWritten()) { - emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when write 'proEnd'"); - tcp.close(); - return; - }; - if(! tcp.waitForReadyRead()) { - emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when waitForRead 'proEnd'"); - tcp.close(); - return; - } - auto resp = tcp.readAll(); - if(resp.isEmpty()) { - emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when read 'proEnd'"); - tcp.close(); - return; - } - tcp.close(); - emit emProgress(100); - emit emErr("OK"); -} +#include "sendprogthread.h" +#include "gutil/qnetwork.h" +#include +#include +#include +#include +#include +#include + +SendProgThread::SendProgThread(const QString &progDir, const QString &ip, int port) : prog_dir(progDir), ip(ip), port(port) { + connect(this, &QThread::finished, this, &QThread::deleteLater); +} + +void SendProgThread::run() { + emit emProgress(0); // 进度条归零 + auto fileInfos = QDir(prog_dir).entryInfoList(QDir::Files); + if(fileInfos.isEmpty()) { + emit emErr(tr("Program is empty")); + return; + } + if(stoped) return; + TcpSocket tcp; + tcp.connectToHost(ip, port); + if(! tcp.waitForConnected()) { + emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when waitForConnected"); + tcp.close(); + return; + } + if(stoped) { + tcp.close(); + return; + }; + //发送节目列表协商 + QJsonArray ids; + foreach(auto fileInfo, fileInfos) { + auto baseName = fileInfo.baseName(); + if(baseName!="program") ids.append(baseName); + } + if(! ids.isEmpty()) { + QJsonObject req; + req.insert("_type", "consult"); + req.insert("proName", "program"); + req.insert("idList", ids); + req.insert("zVer", "xixun1"); + auto requ = QJsonDocument(req).toJson(QJsonDocument::Compact); + auto resNum = tcp.write(requ); + if(resNum == -1 || ! tcp.waitForBytesWritten()) { + emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when write 'consult'. size"+QString::number(requ.size())); + tcp.close(); + return; + } + if(! tcp.waitForReadyRead()) { + emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when waitForRead 'consult'. size"+QString::number(requ.size())); + tcp.close(); + return; + } + auto resp = tcp.readAll(); + if(resp.isEmpty()) { + emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when read 'consult'. size"+QString::number(requ.size())); + tcp.close(); + return; + } + if(stoped) { + tcp.close(); + return; + }; + QJsonParseError parseErr; + QJsonDocument res = QJsonDocument::fromJson(resp, &parseErr); + for(int i=2; parseErr.error == QJsonParseError::UnterminatedString && i < 10; i++) { + if(! tcp.waitForReadyRead()) { + emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when waitForRead 'consult' "+QString::number(i)); + tcp.close(); + return; + } + auto resp2 = tcp.readAll(); + if(resp2.isEmpty()) { + emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when read 'consult' "+QString::number(i)); + tcp.close(); + return; + } + resp += resp2; + res = QJsonDocument::fromJson(resp, &parseErr); + } + if(parseErr.error != QJsonParseError::NoError) { + emit emErr(parseErr.errorString()+" when parse consult. size:"+QString::number(resp.size())); + tcp.close(); + return; + } + if(res["_type"].toString()=="consult") { + fileInfos.clear(); + fileInfos.append(QString(prog_dir+"/program")); + QJsonArray ids = res["idList"].toArray(); + foreach(auto id, ids) fileInfos.append(QString(prog_dir+"/"+id.toString())); + } + } + if(stoped) { + tcp.close(); + return; + } + qint64 progSize = 0; + foreach(auto fileInfo, fileInfos) progSize += fileInfo.size(); + if(progSize == 0) { + emit emErr(tr("Program is empty")); + tcp.close(); + return; + } + auto req = QJsonObject(); + req.insert("_type", "proStart"); + req.insert("proName", "program"); + req.insert("proSize", progSize); + req.insert("zVer","xixun1"); + auto resNum = tcp.write(QJsonDocument(req).toJson(QJsonDocument::Compact)); + if(resNum == -1 || ! tcp.waitForBytesWritten()) { + emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when write 'proStart'"); + tcp.close(); + return; + } + if(stoped) { + tcp.close(); + return; + } + //4.发送协商列表应答里的文件 + long long sentBytes = 0; + foreach(auto info, fileInfos) if(info.isFile()) { + auto baseName = info.baseName(); + auto remain = info.size(); + req = QJsonObject(); + req.insert("_type", "fileStart"); + req.insert("id", baseName); + req.insert("size", remain); + req.insert("relative_path", ""); + req.insert("zVer","xixun1"); + auto resNum = tcp.write(QJsonDocument(req).toJson(QJsonDocument::Compact)); + if(resNum == -1 || ! tcp.waitForBytesWritten()) { + emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when write 'fileStart'"); + tcp.close(); + return; + } + auto file = new QFile(info.filePath()); + if(! file->open(QFile::ReadOnly)) { + emit emErr(tr("Open file failed")+" "+file->errorString()); + tcp.close(); + return; + } + while(remain > 0) { + auto readed = file->read(qMin(4096LL, remain)); + if(readed.isEmpty()) { + emit emErr(tr("Read file failed")+" "+file->errorString()); + tcp.close(); + file->close(); + return; + } + if(stoped) { + tcp.close(); + file->close(); + return; + }; + resNum = tcp.write(readed); + if(resNum == -1) { + emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when write file: "+file->fileName()); + tcp.close(); + file->close(); + return; + } + if(! tcp.waitForBytesWritten(60000)) { + emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when waitForWritten file: "+file->fileName()); + tcp.close(); + file->close(); + return; + } + if(stoped) { + tcp.close(); + file->close(); + return; + }; + remain -= resNum; + sentBytes += resNum; + if(sentBytes != 0) emit emProgress(sentBytes * 99 / progSize); + } + file->close(); + if(stoped) { + tcp.close(); + return; + }; + req = QJsonObject(); + req.insert("_type", "fileEnd"); + req.insert("id", baseName); + req.insert("zVer", "xixun1"); + resNum = tcp.write(QJsonDocument(req).toJson(QJsonDocument::Compact)); + if(resNum == -1 || ! tcp.waitForBytesWritten()) { + emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when write 'fileEnd'"); + tcp.close(); + return; + } + } + if(stoped) { + tcp.close(); + return; + }; + //5.发送结束 + req = QJsonObject(); + req.insert("_type", "proEnd"); + req.insert("proName", "program"); + req.insert("zVer","xixun1"); + resNum = tcp.write(QJsonDocument(req).toJson(QJsonDocument::Compact)); + if(resNum == -1 || ! tcp.waitForBytesWritten()) { + emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when write 'proEnd'"); + tcp.close(); + return; + }; + if(! tcp.waitForReadyRead()) { + emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when waitForRead 'proEnd'"); + tcp.close(); + return; + } + auto resp = tcp.readAll(); + if(resp.isEmpty()) { + emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when read 'proEnd'"); + tcp.close(); + return; + } + tcp.close(); + emit emProgress(100); + emit emErr("OK"); +} diff --git a/LedOK/wProgramManager/sendprogthread.h b/LedOK/program/sendprogthread.h similarity index 96% rename from LedOK/wProgramManager/sendprogthread.h rename to LedOK/program/sendprogthread.h index 890cc31..787fbea 100644 --- a/LedOK/wProgramManager/sendprogthread.h +++ b/LedOK/program/sendprogthread.h @@ -1,6 +1,5 @@ #ifndef SENDPROGTHREAD_H #define SENDPROGTHREAD_H -#include #include #include #include diff --git a/LedOK/wProgramManager/usbdetectdialog.cpp b/LedOK/program/usbdetectdialog.cpp similarity index 97% rename from LedOK/wProgramManager/usbdetectdialog.cpp rename to LedOK/program/usbdetectdialog.cpp index d25b739..8d16d57 100644 --- a/LedOK/wProgramManager/usbdetectdialog.cpp +++ b/LedOK/program/usbdetectdialog.cpp @@ -1,93 +1,93 @@ -#include "usbdetectdialog.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -UsbDetectDialog::UsbDetectDialog(QWidget *parent) : BaseDlg(parent) { - setAttribute(Qt::WA_DeleteOnClose); - setWindowTitle(tr("Usb upgrade program")); - resize(240, 220); - auto vBox = new QVBoxLayout(this); - - auto hBox = new QHBoxLayout(); - hBox->addStretch(); - auto bnClose = new QPushButton("X"); - bnClose->setProperty("ssType","progManageTool"); - bnClose->setFixedWidth(32); - connect(bnClose, &QPushButton::clicked, this, &BaseDlg::close); - hBox->addWidget(bnClose); - - vBox->addLayout(hBox); - - hBox = new QHBoxLayout(); - hBox->addWidget(new QLabel(tr("Password"))); - - fdPassword = new QLineEdit(); - fdPassword->setEchoMode(QLineEdit::Password); - fdPassword->setPlaceholderText(tr("Input password")); - hBox->addWidget(fdPassword); - - vBox->addLayout(hBox); - - fdDrives = new QListWidget(); - fdDrives->setSelectionRectVisible(true); - fdDrives->setProperty("ssType", "usbList"); - fdDrives->setProperty("ssName", "usbListName"); - vBox->addWidget(fdDrives); - - hBox = new QHBoxLayout(); - hBox->addStretch(); - auto bnOk = new QPushButton(tr("OK")); - bnOk->setProperty("ssType","progManageTool"); - connect(bnOk, &QPushButton::clicked, this, [this] { - auto selects = fdDrives->selectedItems(); - if(selects.count() > 0) { - for(auto select : selects) emit acceptData(select->text(), fdPassword->text()); - accept(); - return; - } - if(fdDrives->count() <= 0) QMessageBox::warning(this, tr("Tip"),tr("No checked USB device")); - else QMessageBox::warning(this, tr("Tip"),tr("please select usb device in list")); - }); - hBox->addWidget(bnOk); - hBox->addStretch(); - auto bnCancel = new QPushButton(tr("Cancel")); - bnCancel->setProperty("ssType","progManageTool"); - connect(bnCancel, &QPushButton::clicked, this, &BaseDlg::reject); - hBox->addWidget(bnCancel); - hBox->addStretch(); - vBox->addLayout(hBox); - - detectDriver(); - timerId = startTimer(3000); -} -void UsbDetectDialog::timerEvent(QTimerEvent *e) { - if(e->timerId() == timerId) detectDriver(); -} -void UsbDetectDialog::detectDriver() { - auto drives = QDir::drives(); //获取当前系统的盘符 - QStringList movables; - for(auto drive : drives) if(GetDriveType((WCHAR *) drive.filePath().utf16())==2) movables.append(drive.filePath()); - if(movables.size() == lastCnt) return; - if(movables.size() > lastCnt) { - for(auto movable : movables) { - for(int n=0; n < fdDrives->count(); n++) if(movable == fdDrives->item(n)->text()) goto exist; - fdDrives->addItem(movable); - exist:; - } - } else { - fdDrives->clear(); - fdDrives->addItems(movables); - } - lastCnt = movables.size(); - if(lastCnt==1) { - QListWidgetItem *item = fdDrives->item(0); - item->setSelected(true); - } -} +#include "usbdetectdialog.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +UsbDetectDialog::UsbDetectDialog(QWidget *parent) : BaseDlg(parent) { + setAttribute(Qt::WA_DeleteOnClose); + setWindowTitle(tr("Usb upgrade program")); + resize(240, 220); + auto vBox = new QVBoxLayout(this); + + auto hBox = new QHBoxLayout(); + hBox->addStretch(); + auto bnClose = new QPushButton("X"); + bnClose->setProperty("ssType","progManageTool"); + bnClose->setFixedWidth(32); + connect(bnClose, &QPushButton::clicked, this, &BaseDlg::close); + hBox->addWidget(bnClose); + + vBox->addLayout(hBox); + + hBox = new QHBoxLayout(); + hBox->addWidget(new QLabel(tr("Password"))); + + fdPassword = new QLineEdit(); + fdPassword->setEchoMode(QLineEdit::Password); + fdPassword->setPlaceholderText(tr("Input password")); + hBox->addWidget(fdPassword); + + vBox->addLayout(hBox); + + fdDrives = new QListWidget(); + fdDrives->setSelectionRectVisible(true); + fdDrives->setProperty("ssType", "usbList"); + fdDrives->setProperty("ssName", "usbListName"); + vBox->addWidget(fdDrives); + + hBox = new QHBoxLayout(); + hBox->addStretch(); + auto bnOk = new QPushButton(tr("OK")); + bnOk->setProperty("ssType","progManageTool"); + connect(bnOk, &QPushButton::clicked, this, [this] { + auto selects = fdDrives->selectedItems(); + if(selects.count() > 0) { + for(auto select : selects) emit acceptData(select->text(), fdPassword->text()); + accept(); + return; + } + if(fdDrives->count() <= 0) QMessageBox::warning(this, tr("Tip"),tr("No checked USB device")); + else QMessageBox::warning(this, tr("Tip"),tr("please select usb device in list")); + }); + hBox->addWidget(bnOk); + hBox->addStretch(); + auto bnCancel = new QPushButton(tr("Cancel")); + bnCancel->setProperty("ssType","progManageTool"); + connect(bnCancel, &QPushButton::clicked, this, &BaseDlg::reject); + hBox->addWidget(bnCancel); + hBox->addStretch(); + vBox->addLayout(hBox); + + detectDriver(); + timerId = startTimer(3000); +} +void UsbDetectDialog::timerEvent(QTimerEvent *e) { + if(e->timerId() == timerId) detectDriver(); +} +void UsbDetectDialog::detectDriver() { + auto drives = QDir::drives(); //获取当前系统的盘符 + QStringList movables; + for(auto drive : drives) if(GetDriveType((WCHAR *) drive.filePath().utf16())==2) movables.append(drive.filePath()); + if(movables.size() == lastCnt) return; + if(movables.size() > lastCnt) { + for(auto movable : movables) { + for(int n=0; n < fdDrives->count(); n++) if(movable == fdDrives->item(n)->text()) goto exist; + fdDrives->addItem(movable); + exist:; + } + } else { + fdDrives->clear(); + fdDrives->addItems(movables); + } + lastCnt = movables.size(); + if(lastCnt==1) { + QListWidgetItem *item = fdDrives->item(0); + item->setSelected(true); + } +} diff --git a/LedOK/wProgramManager/usbdetectdialog.h b/LedOK/program/usbdetectdialog.h similarity index 95% rename from LedOK/wProgramManager/usbdetectdialog.h rename to LedOK/program/usbdetectdialog.h index 1bb38b8..01fbd46 100644 --- a/LedOK/wProgramManager/usbdetectdialog.h +++ b/LedOK/program/usbdetectdialog.h @@ -1,25 +1,25 @@ -#ifndef USBDETECTDIALOG_H -#define USBDETECTDIALOG_H - -#include -#include - -class UsbDetectDialog : public BaseDlg { - Q_OBJECT -public: - explicit UsbDetectDialog(QWidget *parent = nullptr); - ~UsbDetectDialog() {if(timerId!=0) killTimer(timerId);} -protected: - void timerEvent(QTimerEvent *) override; -signals: - void acceptData(QString string1, QString string2); -private: - void detectDriver(); - QListWidget *fdDrives; - QLineEdit *fdPassword; - int timerId = 0; - int lastCnt = 0; - -}; - -#endif // USBDETECTDIALOG_H +#ifndef USBDETECTDIALOG_H +#define USBDETECTDIALOG_H + +#include +#include + +class UsbDetectDialog : public BaseDlg { + Q_OBJECT +public: + explicit UsbDetectDialog(QWidget *parent = nullptr); + ~UsbDetectDialog() {if(timerId!=0) killTimer(timerId);} +protected: + void timerEvent(QTimerEvent *) override; +signals: + void acceptData(QString string1, QString string2); +private: + void detectDriver(); + QListWidget *fdDrives; + QLineEdit *fdPassword; + int timerId = 0; + int lastCnt = 0; + +}; + +#endif // USBDETECTDIALOG_H diff --git a/LedOK/wProgramManager/videosplitthread.cpp b/LedOK/program/videosplitthread.cpp similarity index 76% rename from LedOK/wProgramManager/videosplitthread.cpp rename to LedOK/program/videosplitthread.cpp index 3253bbb..c15b591 100644 --- a/LedOK/wProgramManager/videosplitthread.cpp +++ b/LedOK/program/videosplitthread.cpp @@ -1,205 +1,212 @@ -#include "videosplitthread.h" -#include -#include -#include -extern "C"{ -#include -#include -#include -} -VideoSplitThread::VideoSplitThread(int sw, int sh, int dw, int dh, int cnt, QPointF pos, QByteArray file) : sw(sw), sh(sh), dw(dw), dh(dh), cnt(cnt), pos(pos), file(file) { - connect(this, &QThread::finished, this, &QThread::deleteLater); -} - -void VideoSplitThread::run() { - AVFormatContext *in_fmt = avformat_alloc_context(), *out_fmt = 0; - AVCodecContext *de_ctx = 0, *en_ctx = 0; - QString err; - char buf[AV_ERROR_MAX_STRING_SIZE]; - int ret; - { - if((ret = avformat_open_input(&in_fmt, file.constData(), nullptr, nullptr)) < 0) { - err = QString("Couldn't open input stream. ")+av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); - goto free; - } - if((ret = avformat_find_stream_info(in_fmt, nullptr)) < 0) { - err = QString("Couldn't find stream information. ")+av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); - goto free; - } - auto outfile = file+"-square.mp4"; - if((ret = avformat_alloc_output_context2(&out_fmt, 0, "mp4", outfile.constData())) < 0) { - err = QString("avformat_alloc_output_context2 fail. ")+av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); - goto free; - } - int vi_idx = -1; - AVStream *out_vi_stream; - for(uint ss=0; ssnb_streams; ss++) { - AVStream *stream = in_fmt->streams[ss]; - qDebug()<<"codec_type"<codecpar->codec_type); - if(stream->codecpar->codec_type == AVMEDIA_TYPE_DATA) continue; - AVStream *out_stream = avformat_new_stream(out_fmt, 0); - if(vi_idx == -1 && stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { - vi_idx = ss; - out_vi_stream = out_stream; - } else { - if((ret = avcodec_parameters_copy(out_stream->codecpar, stream->codecpar)) < 0) { - err = QString("avcodec_parameters_copy fail. ") + av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); - goto free; - } - } - out_stream->time_base = stream->time_base; - out_stream->start_time = stream->start_time; - out_stream->duration = stream->duration; - } - if(vi_idx == -1) { - err = "Didn't find a Video Stream"; - goto free; - } - - auto codecpar = in_fmt->streams[vi_idx]->codecpar; - - auto decoder = avcodec_find_decoder(codecpar->codec_id); - if(decoder==0) { - err = "Could not found Video Decoder"; - goto free; - } - de_ctx = avcodec_alloc_context3(decoder); - de_ctx->thread_count = 4; - avcodec_parameters_to_context(de_ctx, codecpar); - if(avcodec_open2(de_ctx, decoder, 0) < 0) { - err = "Could not open Video decode Ctx"; - goto free; - } - - auto out_codecpar = out_vi_stream->codecpar; - out_codecpar->codec_type = AVMEDIA_TYPE_VIDEO; - out_codecpar->codec_id = AV_CODEC_ID_H264; - out_codecpar->format = AV_PIX_FMT_YUV420P; - out_codecpar->width = dw; - out_codecpar->height = dh; - - auto encoder = avcodec_find_encoder(out_codecpar->codec_id); - if(encoder==0) { - fprintf(stderr, "Codec not found\n"); - goto free; - } - en_ctx = avcodec_alloc_context3(encoder); - en_ctx->thread_count = 4; - avcodec_parameters_to_context(en_ctx, out_codecpar); - en_ctx->bit_rate = dw*dh*6; - en_ctx->gop_size = de_ctx->gop_size; - en_ctx->max_b_frames = 3; - en_ctx->time_base = out_vi_stream->time_base; - - if((ret = avcodec_open2(en_ctx, encoder, 0)) < 0) { - err = QString("Open video encode ctx failed. ") + av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); - goto free; - } - if(out_fmt->flags & AVFMT_NOFILE) qDebug()<<"AVFMT_NOFILE"; - else if((ret = avio_open(&out_fmt->pb, outfile.constData(), AVIO_FLAG_WRITE)) < 0) { - err = QString("avio_open fail. ")+av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); - goto free; - } - qDebug()<<"oformat"<oformat; - if((ret = avformat_write_header(out_fmt, 0)) < 0) { - err = QString("avformat_write_header fail. ")+av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); - goto free; - } - auto sws_ctx = sws_getContext(de_ctx->width, de_ctx->height, de_ctx->pix_fmt, sw, sh, AV_PIX_FMT_0RGB, SWS_FAST_BILINEAR, 0, 0, 0); - auto out_sws_ctx = sws_getContext(dw, dh, AV_PIX_FMT_0RGB, dw, dh, AV_PIX_FMT_YUV420P, SWS_FAST_BILINEAR, 0, 0, 0); - auto packet = av_packet_alloc(); - auto frm = av_frame_alloc(); - QImage img(sw, sh, QImage::Format_RGB32); - uint8_t *img_data[4]{img.bits(), 0, 0, 0}; - int img_linesize[4]{img.bytesPerLine(), 0, 0, 0}; - QImage out_img(dw, dh, QImage::Format_RGB32); - uint8_t *out_img_data[4]{out_img.bits(), 0, 0, 0}; - int out_img_linesize[4]{out_img.bytesPerLine(), 0, 0, 0}; - QPainter painter(&out_img); - while(1) { - if((ret = av_read_frame(in_fmt, packet)) < 0) { - if(ret!=AVERROR_EOF) { - err = QString("Read packet fail: ")+av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); - break; - } - ret = avcodec_send_packet(de_ctx, 0); - } else { - if(packet->stream_index != vi_idx) { - av_interleaved_write_frame(out_fmt, packet); - continue; - } - ret = avcodec_send_packet(de_ctx, packet); - } - if(ret < 0) { - err = QString("avcodec_send_packet fail. ")+av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); - break; - } - while((ret = avcodec_receive_frame(de_ctx, frm)) != AVERROR(EAGAIN)) { - if(ret < 0) { - if(ret!=AVERROR_EOF) { - err = QString("Receive frame fail: ")+av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); - goto free2; - } - ret = avcodec_send_frame(en_ctx, 0); - } else { - sws_scale(sws_ctx, frm->data, frm->linesize, 0, de_ctx->height, img_data, img_linesize); - painter.drawImage(pos, img); - auto apos = pos; - for(int i=1; ipts; - auto dur = frm->pkt_duration; - av_frame_unref(frm); - frm->pts = pts; - frm->pkt_duration = dur; - frm->format = AV_PIX_FMT_YUV420P; - frm->width = dw; - frm->height = dh; - if((ret = av_frame_get_buffer(frm, 0)) < 0) { - err = QString("av_frame_get_buffer fail. ")+av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); - goto free2; - } - sws_scale(out_sws_ctx, out_img_data, out_img_linesize, 0, dh, frm->data, frm->linesize); - ret = avcodec_send_frame(en_ctx, frm); - int pro = frm->pts*100/out_vi_stream->duration; - if(pro > lastPro) { - lastPro = pro; - emit emProgress(pro); - } - } - if(ret < 0) { - err = QString("avcodec_send_frame fail. ")+av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); - goto free2; - } - while((ret = avcodec_receive_packet(en_ctx, packet)) != AVERROR(EAGAIN)) { - if(ret < 0) { - if(ret!=AVERROR_EOF) err = QString("Receive frame fail: ")+av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); - else { - av_interleaved_write_frame(out_fmt, 0); - av_write_trailer(out_fmt); - emit emProgress(100); - } - goto free2; - } else { - av_interleaved_write_frame(out_fmt, packet); - } - } - } - } - free2: - av_frame_free(&frm); - av_packet_free(&packet); - sws_freeContext(sws_ctx); - sws_freeContext(out_sws_ctx); - } - free: - avcodec_free_context(&de_ctx); - avcodec_free_context(&en_ctx); - avformat_close_input(&in_fmt); - avio_closep(&out_fmt->pb); - if(out_fmt) avformat_free_context(out_fmt); - emit emErr(err); -} +#include "videosplitthread.h" +#include +#include +#include +extern "C"{ +#include +#include +#include +} + +static void imgCleanupHandler(void *info) { + delete [] (uchar*)info; +} + +VideoSplitThread::VideoSplitThread(int elew, int eleh, int dpw, int sph, QList &widths, QPointF pos, QByteArray file) : mEleW(elew), mEleH(eleh), mDPW(dpw), mSPH(sph), mWidths(widths), pos(pos), file(file) { + connect(this, &QThread::finished, this, &QThread::deleteLater); +} + +void VideoSplitThread::run() { + AVFormatContext *in_fmt = avformat_alloc_context(), *out_fmt = 0; + AVCodecContext *de_ctx = 0, *en_ctx = 0; + QString err; + char buf[AV_ERROR_MAX_STRING_SIZE]; + int ret; + { + if((ret = avformat_open_input(&in_fmt, file.constData(), 0, 0)) < 0) { + err = QString("Couldn't open input stream. ")+av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); + goto free; + } + if((ret = avformat_find_stream_info(in_fmt, nullptr)) < 0) { + err = QString("Couldn't find stream information. ")+av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); + goto free; + } + auto outfile = file+"-square.mp4"; + if((ret = avformat_alloc_output_context2(&out_fmt, 0, "mp4", outfile.constData())) < 0) { + err = QString("avformat_alloc_output_context2 fail. ")+av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); + goto free; + } + int vi_idx = -1; + AVStream *out_vi_stream; + for(uint ss=0; ssnb_streams; ss++) { + AVStream *stream = in_fmt->streams[ss]; + qDebug()<<"codec_type"<codecpar->codec_type); + if(stream->codecpar->codec_type == AVMEDIA_TYPE_DATA) continue; + AVStream *out_stream = avformat_new_stream(out_fmt, 0); + if(vi_idx == -1 && stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + vi_idx = ss; + out_vi_stream = out_stream; + } else { + if((ret = avcodec_parameters_copy(out_stream->codecpar, stream->codecpar)) < 0) { + err = QString("avcodec_parameters_copy fail. ") + av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); + goto free; + } + } + out_stream->time_base = stream->time_base; + out_stream->start_time = stream->start_time; + out_stream->duration = stream->duration; + } + if(vi_idx == -1) { + err = "Didn't find a Video Stream"; + goto free; + } + + auto codecpar = in_fmt->streams[vi_idx]->codecpar; + + auto decoder = avcodec_find_decoder(codecpar->codec_id); + if(decoder==0) { + err = "Could not found Video Decoder"; + goto free; + } + de_ctx = avcodec_alloc_context3(decoder); + de_ctx->thread_count = 4; + avcodec_parameters_to_context(de_ctx, codecpar); + if(avcodec_open2(de_ctx, decoder, 0) < 0) { + err = "Could not open Video decode Ctx"; + goto free; + } + + auto outPar = out_vi_stream->codecpar; + outPar->codec_type = AVMEDIA_TYPE_VIDEO; + outPar->codec_id = AV_CODEC_ID_H264; + outPar->format = AV_PIX_FMT_YUV420P; + outPar->width = mDPW; + outPar->height = mSPH*mWidths.size(); + + auto encoder = avcodec_find_encoder(outPar->codec_id); + if(encoder==0) { + fprintf(stderr, "Codec not found\n"); + goto free; + } + en_ctx = avcodec_alloc_context3(encoder); + en_ctx->thread_count = 4; + avcodec_parameters_to_context(en_ctx, outPar); + en_ctx->bit_rate = outPar->width * outPar->height * 6; + en_ctx->gop_size = de_ctx->gop_size; + en_ctx->max_b_frames = 3; + en_ctx->time_base = out_vi_stream->time_base; + + if((ret = avcodec_open2(en_ctx, encoder, 0)) < 0) { + err = QString("Open video encode ctx failed. ") + av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); + goto free; + } + if(out_fmt->flags & AVFMT_NOFILE) qDebug()<<"AVFMT_NOFILE"; + else if((ret = avio_open(&out_fmt->pb, outfile.constData(), AVIO_FLAG_WRITE)) < 0) { + err = QString("avio_open fail. ")+av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); + goto free; + } + if((ret = avformat_write_header(out_fmt, 0)) < 0) { + err = QString("avformat_write_header fail. ")+av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); + goto free; + } + auto sws_ctx = sws_getContext(de_ctx->width, de_ctx->height, de_ctx->pix_fmt, mEleW, mEleH, AV_PIX_FMT_RGB32, SWS_FAST_BILINEAR, 0, 0, 0); + auto out_sws_ctx = sws_getContext(outPar->width, outPar->height, AV_PIX_FMT_RGB32, outPar->width, outPar->height, AV_PIX_FMT_YUV420P, SWS_FAST_BILINEAR, 0, 0, 0); + auto packet = av_packet_alloc(); + auto frm = av_frame_alloc(); + + int img_linesize[4]{(mEleW*4+63)/64*64}; + uint8_t *img_data[4]{new uchar[img_linesize[0] * mEleH]}; + QImage img(img_data[0], mEleW, mEleH, img_linesize[0], QImage::Format_ARGB32, imgCleanupHandler, img_data[0]); + + int out_img_linesize[4]{(outPar->width*4+63)/64*64}; + uint8_t *out_img_data[4]{new uchar[out_img_linesize[0] * outPar->height]}; + QImage out_img(out_img_data[0], outPar->width, outPar->height, out_img_linesize[0], QImage::Format_ARGB32, imgCleanupHandler, out_img_data[0]); + QPainter painter(&out_img); + auto end = mWidths.size() - 1; + while(1) { + if((ret = av_read_frame(in_fmt, packet)) < 0) { + if(ret!=AVERROR_EOF) { + err = QString("Read packet fail: ")+av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); + break; + } + ret = avcodec_send_packet(de_ctx, 0); + } else { + if(packet->stream_index != vi_idx) { + av_interleaved_write_frame(out_fmt, packet); + continue; + } + ret = avcodec_send_packet(de_ctx, packet); + } + if(ret < 0) { + err = QString("avcodec_send_packet fail. ")+av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); + break; + } + while((ret = avcodec_receive_frame(de_ctx, frm)) != AVERROR(EAGAIN)) { + if(ret < 0) { + if(ret!=AVERROR_EOF) { + err = QString("Receive frame fail: ")+av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); + goto free2; + } + ret = avcodec_send_frame(en_ctx, 0); + } else { + sws_scale(sws_ctx, frm->data, frm->linesize, 0, de_ctx->height, img_data, img_linesize); + auto apos = pos; + painter.drawImage(apos, img, QRectF(0, 0, mWidths[0]-apos.rx(), img.height())); + for(int i=0; ipts; + auto dur = frm->pkt_duration; + av_frame_unref(frm); + frm->pts = pts; + frm->pkt_duration = dur; + frm->format = AV_PIX_FMT_YUV420P; + frm->width = outPar->width; + frm->height = outPar->height; + if((ret = av_frame_get_buffer(frm, 0)) < 0) { + err = QString("av_frame_get_buffer fail. ")+av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); + goto free2; + } + sws_scale(out_sws_ctx, out_img_data, out_img_linesize, 0, outPar->height, frm->data, frm->linesize); + ret = avcodec_send_frame(en_ctx, frm); + int pro = frm->pts*100/out_vi_stream->duration; + if(pro > lastPro) { + lastPro = pro; + emit emProgress(pro); + } + } + if(ret < 0) { + err = QString("avcodec_send_frame fail. ")+av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); + goto free2; + } + while((ret = avcodec_receive_packet(en_ctx, packet)) != AVERROR(EAGAIN)) { + if(ret < 0) { + if(ret!=AVERROR_EOF) err = QString("Receive frame fail: ")+av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret); + else { + av_interleaved_write_frame(out_fmt, 0); + av_write_trailer(out_fmt); + emit emProgress(100); + } + goto free2; + } else { + av_interleaved_write_frame(out_fmt, packet); + } + } + } + } + free2: + av_frame_free(&frm); + av_packet_free(&packet); + sws_freeContext(sws_ctx); + sws_freeContext(out_sws_ctx); + } + free: + avcodec_free_context(&de_ctx); + avcodec_free_context(&en_ctx); + avformat_close_input(&in_fmt); + avio_closep(&out_fmt->pb); + if(out_fmt) avformat_free_context(out_fmt); + emit emErr(err); +} diff --git a/LedOK/wProgramManager/videosplitthread.h b/LedOK/program/videosplitthread.h similarity index 72% rename from LedOK/wProgramManager/videosplitthread.h rename to LedOK/program/videosplitthread.h index 5280080..d2ea440 100644 --- a/LedOK/wProgramManager/videosplitthread.h +++ b/LedOK/program/videosplitthread.h @@ -6,8 +6,9 @@ class VideoSplitThread : public QThread { Q_OBJECT public: - VideoSplitThread(int sw, int sh, int dw, int dh, int cnt, QPointF pos, QByteArray file); - int sw, sh, dw, dh, cnt; + VideoSplitThread(int elew, int eleh, int dpw, int sph, QList &, QPointF pos, QByteArray file); + int mEleW, mEleH, mDPW, mSPH; + QList mWidths; QPointF pos; QByteArray file; protected: diff --git a/LedOK/wProgramManager/wplanitem.cpp b/LedOK/program/wplanitem.cpp similarity index 100% rename from LedOK/wProgramManager/wplanitem.cpp rename to LedOK/program/wplanitem.cpp diff --git a/LedOK/wProgramManager/wplanitem.h b/LedOK/program/wplanitem.h similarity index 100% rename from LedOK/wProgramManager/wplanitem.h rename to LedOK/program/wplanitem.h diff --git a/LedOK/wProgramManager/wplanitem.ui b/LedOK/program/wplanitem.ui similarity index 100% rename from LedOK/wProgramManager/wplanitem.ui rename to LedOK/program/wplanitem.ui diff --git a/LedOK/wProgramManager/wplanlist.cpp b/LedOK/program/wplanlist.cpp similarity index 100% rename from LedOK/wProgramManager/wplanlist.cpp rename to LedOK/program/wplanlist.cpp diff --git a/LedOK/wProgramManager/wplanlist.h b/LedOK/program/wplanlist.h similarity index 100% rename from LedOK/wProgramManager/wplanlist.h rename to LedOK/program/wplanlist.h diff --git a/LedOK/wProgramManager/wprogrampublishitem.cpp b/LedOK/program/wprogrampublishitem.cpp similarity index 95% rename from LedOK/wProgramManager/wprogrampublishitem.cpp rename to LedOK/program/wprogrampublishitem.cpp index af0e185..d14ce63 100644 --- a/LedOK/wProgramManager/wprogrampublishitem.cpp +++ b/LedOK/program/wprogrampublishitem.cpp @@ -83,7 +83,7 @@ void wProgramPublishItem::SetPasswordItem(LedCard *card) { m_parent->setItemWidget(this, ENUM_DEVICE_PUBLISH_HEADE_ENCRYPT, m_bnLock); connect(m_bnLock, SIGNAL(clicked()), this, SLOT(onVerifyLockPassword())); } - m_bnLock->setIcon(QIcon(card->m_bLockStatus ? ":/res/DeviceManager/Lock.png" : ":/res/DeviceManager/UnLock.png")); //如果已经验证通过密码显示绿色图标 没有验证显示蓝色锁图标 + m_bnLock->setIcon(QIcon(card->m_bLockStatus ? ":/res/device/Lock.png" : ":/res/device/UnLock.png")); //如果已经验证通过密码显示绿色图标 没有验证显示蓝色锁图标 m_parent->setItemWidget(this, ENUM_DEVICE_PUBLISH_HEADE_ENCRYPT, m_bnLock); } @@ -92,7 +92,7 @@ void wProgramPublishItem::SetItemParam(LedCard *p) { setData(ENUM_DEVICE_PUBLISH_HEADE_REMARK_NAME, 0, p->m_strCardRemarkName); setData(ENUM_DEVICE_PUBLISH_HEADE_SCREEN_IP, 0, p->m_strCardIp); setData(ENUM_DEVICE_PUBLISH_HEADE_SCREEN_SIZE, 0, QString("%1 x %2").arg(p->m_iWidth).arg(p->m_iHeight)); - m_ImageOnline->setPixmap(QPixmap(mLedCard->m_bOnLine ? ":/res/DeviceManager/O_Online.png" : ":/res/DeviceManager/O_Offline.png")); + m_ImageOnline->setPixmap(QPixmap(mLedCard->m_bOnLine ? ":/res/device/O_Online.png" : ":/res/device/O_Offline.png")); SetPasswordItem(mLedCard); // //progresss.append(progress); diff --git a/LedOK/wProgramManager/wprogrampublishitem.h b/LedOK/program/wprogrampublishitem.h similarity index 97% rename from LedOK/wProgramManager/wprogrampublishitem.h rename to LedOK/program/wprogrampublishitem.h index 7e2d97a..958b447 100644 --- a/LedOK/wProgramManager/wprogrampublishitem.h +++ b/LedOK/program/wprogrampublishitem.h @@ -13,7 +13,7 @@ #include #include #include -#include +#include class wProgramPublishItem : public QObject, public QTreeWidgetItem { Q_OBJECT diff --git a/LedOK/qss.qrc b/LedOK/qss.qrc deleted file mode 100644 index 6345d43..0000000 --- a/LedOK/qss.qrc +++ /dev/null @@ -1,6 +0,0 @@ - - - qss/00_Common.css - qss/10_MainWindow.css - - diff --git a/LedOK/qss/00_Common.css b/LedOK/qss/00_Common.css deleted file mode 100644 index abd0697..0000000 --- a/LedOK/qss/00_Common.css +++ /dev/null @@ -1,125 +0,0 @@ -QLineEdit,QComboBox,QAbstractSpinBox { - border: 1px solid #aaaaaa; - border-radius: 3px; - padding: 2px; -} - -QGroupBox { - border: 1px solid #aaaaaa; - border-radius: 3px; - margin-top: 1.2ex; - padding-top: 1ex; -} -QGroupBox::title { - subcontrol-origin: margin; - position: relative; - left: 1.4ex; -} - -QComboBox::drop-down, -QAbstractSpinBox::up-button, -QAbstractSpinBox::down-button { - border: 0; -} -QComboBox::down-arrow, -QAbstractSpinBox::down-arrow { - image: url(:/res/ArrowDropDown.png); -} -QComboBox::down-arrow:on, -QAbstractSpinBox::up-arrow { - image: url(:/res/ArrowDropUp.png); -} - -QAbstractSpinBox::up-arrow:pressed { - top: -1px; -} -QAbstractSpinBox::down-arrow:pressed { - top: 1px; -} - -QCheckBox::indicator { - width: 24px; - height: 24px; -} -QCheckBox::indicator:disabled { - background-color: #666666; -} -QCheckBox::indicator:unchecked { - image: url(:/res/CheckBoxUnchecked.png); -} -QCheckBox::indicator:checked { - image: url(:/res/CheckBoxChecked.png); -} - -ExtendedGroupBox::indicator { - width: 10px; - height: 10px; -} -ExtendedGroupBox::indicator:unchecked { - image: url(:/res/ProgramManager/EditProgram/uncheck.png); -} -ExtendedGroupBox::indicator:checked { - image: url(:/res/ProgramManager/EditProgram/check.png); -} - -QScrollArea { - border : 0; -} -QScrollBar:vertical { - width: 12px; -} -QScrollBar:horizontal { - height: 12px; -} - -QMenu { - background-color: #eeeeee; - border: 2px solid #cccccc; -} -QMenu::item { - background-color: transparent; -} -QMenu::item:selected { - background-color: #8FC0D6; -} -QMenu::indicator:exclusive:checked { - image: url(:/res/RadioChecked.png); -} - -QToolBar::separator { - background-color: #888888; - width: 1px; -} - -LoColorSelector { - border: 1px solid #aaaaaa; - border-radius: 4px; - background-color: transparent; - padding: 3px 6px; - max-height: 30px; -} - -QTreeWidget[ssType="topList"]::item { - border-right: 1px solid #dddddd; - border-bottom: 1px solid #dddddd; - height: 40px; -} -QTreeWidget[ssType="topList"] QHeaderView::section { - border-top: 1px solid #aaaaaa; - border-bottom: 1px solid #aaaaaa; - border-left: 0; - border-right: 0; - height: 36px; -} -QTreeWidget[ssType="topList"]::item:hover { - background-color: #dddddd; -} - -QTreeWidget[ssType="topList"]::indicator, -QTreeWidget[ssType="topList"]::indicator:unchecked { - image: url(:/res/CheckBoxUnchecked.png); -} -QTreeWidget[ssType="topList"]::indicator:checked { - image: url(:/res/CheckBoxChecked.png); -} - diff --git a/LedOK/qss/10_MainWindow.css b/LedOK/qss/10_MainWindow.css deleted file mode 100644 index fecc69b..0000000 --- a/LedOK/qss/10_MainWindow.css +++ /dev/null @@ -1,70 +0,0 @@ -QPushButton[ssType="progManageTool"] { - border-radius: 4px; - background-color: #19c; - color: #000; - padding: 3px 6px; -} -QPushButton[ssType="progManageTool"]:hover { - background-color: #08b; - color: #fff; -} -QPushButton[ssType="progManageTool"]:pressed { - background-color: #07a; -} -QPushButton[ssType="progManageTool"]:disabled { - background-color: #bbb; - color: #777; -} - - -LoQTitleBar QPushButton { - border-radius: 4px; - icon-size: 20px; - width: 32px; - height: 28px; -} -LoQTitleBar QPushButton:press, -LoQTitleBar QPushButton:hover { - background-color: #C1C1C1; -} -LoQTitleBar QPushButton::menu-indicator { - image: none; -} - - -QToolButton[ss="MainTab"], -QToolButton[ss="CtrlTab"] { - border: none; -} -QToolButton[ss="MainTab"]:checked, -QToolButton[ss="MainTab"]:hover { - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ddd, stop: 1.0 #8cd); - font-size: 15px; - color: #04d; -} -QToolButton[ss="CtrlTab"]:checked, -QToolButton[ss="CtrlTab"]:hover { - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #eee, stop: 1.0 #ade); - font-size: 15px; - color: #04d; -} - - -QPushButton#bnSelectFile { - border-radius: 4px; - background-color: #19c; - border: 1px solid #888; - padding: 3px 6px; -} -QPushButton#bnSelectFile:pressed { - background: transparent; -} - -QPushButton[style="multiTool"] { - border-radius: 4px; - padding: 3px 6px; -} -QPushButton[style="multiTool"]:hover { - background-color: rgba(226,226,226,1); -} - diff --git a/LedOK/res.qrc b/LedOK/res.qrc index d24f825..a40e718 100644 --- a/LedOK/res.qrc +++ b/LedOK/res.qrc @@ -1,209 +1,201 @@ - - - res/AdvParam.png - res/AppSetting.png - res/AppSettingTip.png - res/ArrowDropDown.png - res/ArrowDropUp.png - res/CheckBoxChecked.png - res/CheckBoxUnchecked.png - res/DeviceManager/Add.png - res/DeviceManager/DeviceNum_All.png - res/DeviceManager/DeviceNum_Offline.png - res/DeviceManager/DeviceNum_Online.png - res/DeviceManager/DeviceNum_Unlogin.png - res/DeviceManager/Equal.png - res/DeviceManager/FlashArrow.png - res/DeviceManager/Lock.png - res/DeviceManager/O_Offline.png - res/DeviceManager/O_Online.png - res/DeviceManager/O_Unlogin.png - res/DeviceManager/Transparent.png - res/DeviceManager/UnLock.png - res/DeviceManager/bnDetail.png - res/DeviceManager/deviceReadbackPic.png - res/DeviceManager_s.png - res/DeviceManager_u.png - res/DeviceSetting_s.png - res/DeviceSetting_u.png - res/GuangYingPin_s.png - res/GuangYingPin_u.png - res/Hdmi.png - res/Logo.ico - res/Logo.png - res/Lora.png - res/ProgramManager/EditProgram/AClock.png - res/ProgramManager/EditProgram/Add.png - res/ProgramManager/EditProgram/AddPlan.png - res/ProgramManager/EditProgram/ArrayBottom.png - res/ProgramManager/EditProgram/ArrayHCenter.png - res/ProgramManager/EditProgram/ArrayLeft.png - res/ProgramManager/EditProgram/ArrayRight.png - res/ProgramManager/EditProgram/ArrayTop.png - res/ProgramManager/EditProgram/ArrayVCenter.png - res/ProgramManager/EditProgram/Audio.png - res/ProgramManager/EditProgram/Clean.png - res/ProgramManager/EditProgram/CleanPlan.png - res/ProgramManager/EditProgram/ColorText.png - res/ProgramManager/EditProgram/Copy.png - res/ProgramManager/EditProgram/Cut.png - res/ProgramManager/EditProgram/DClock.png - res/ProgramManager/EditProgram/DateSelect.png - res/ProgramManager/EditProgram/DateSelect_enable.png - res/ProgramManager/EditProgram/Delete.png - res/ProgramManager/EditProgram/DocAlignHC_s.png - res/ProgramManager/EditProgram/DocAlignHC_u.png - res/ProgramManager/EditProgram/DocAlignHL_s.png - res/ProgramManager/EditProgram/DocAlignHL_u.png - res/ProgramManager/EditProgram/DocAlignHR_s.png - res/ProgramManager/EditProgram/DocAlignHR_u.png - res/ProgramManager/EditProgram/DocAlignVB_s.png - res/ProgramManager/EditProgram/DocAlignVB_u.png - res/ProgramManager/EditProgram/DocAlignVC_s.png - res/ProgramManager/EditProgram/DocAlignVC_u.png - res/ProgramManager/EditProgram/DocAlignVT_s.png - res/ProgramManager/EditProgram/DocAlignVT_u.png - res/ProgramManager/EditProgram/FontBold_s.png - res/ProgramManager/EditProgram/FontBold_u.png - res/ProgramManager/EditProgram/FontItalics_s.png - res/ProgramManager/EditProgram/FontItalics_u.png - res/ProgramManager/EditProgram/FontUnderline_s.png - res/ProgramManager/EditProgram/FontUnderline_u.png - res/ProgramManager/EditProgram/Gif.png - res/ProgramManager/EditProgram/GoDown.png - res/ProgramManager/EditProgram/GoUp.png - res/ProgramManager/EditProgram/LayerBottom.png - res/ProgramManager/EditProgram/LayerDown.png - res/ProgramManager/EditProgram/LayerTop.png - res/ProgramManager/EditProgram/LayerUp.png - res/ProgramManager/EditProgram/Movie.png - res/ProgramManager/EditProgram/Office.png - res/ProgramManager/EditProgram/Photo.png - res/ProgramManager/EditProgram/RadioChecked.png - res/ProgramManager/EditProgram/RadioUnchecked.png - res/ProgramManager/EditProgram/Rss.png - res/ProgramManager/EditProgram/Save.png - res/ProgramManager/EditProgram/SaveAs.png - res/ProgramManager/EditProgram/ScaleDown.png - res/ProgramManager/EditProgram/ScaleOrg.png - res/ProgramManager/EditProgram/ScaleUp.png - res/ProgramManager/EditProgram/Send.png - res/ProgramManager/EditProgram/Setting.png - res/ProgramManager/EditProgram/Temp.png - res/ProgramManager/EditProgram/Text.png - res/ProgramManager/EditProgram/TileFull.png - res/ProgramManager/EditProgram/TileH.png - res/ProgramManager/EditProgram/TileV.png - res/ProgramManager/EditProgram/Timer.png - res/ProgramManager/EditProgram/Weather.png - res/ProgramManager/EditProgram/Web.png - res/ProgramManager/EditProgram/Window.png - res/ProgramManager/EditProgram/check.png - res/ProgramManager/EditProgram/preview.png - res/ProgramManager/EditProgram/previewStop.png - res/ProgramManager/EditProgram/uncheck.png - res/ProgramManager/bnExport_s.png - res/ProgramManager/bnExport_u.png - res/ProgramManager/bnSearch.png - res/ProgramManager/bnSend_s.png - res/ProgramManager/bnSend_u.png - res/ProgramManager_s.png - res/ProgramManager_u.png - res/RadioChecked.png - res/Warning.png - res/WndClose.png - res/WndMaximize.png - res/WndMinimize.png - res/apk.png - res/bnBrightnessAdjustMent_s.png - res/bnNetConfig_s.png - res/bnPowerControl_s.png - res/bnVerifyClock_s.png - res/borders/M1_0.bmp - res/borders/M1_1.bmp - res/borders/M1_2.bmp - res/borders/M1_3.bmp - res/borders/M1_4.bmp - res/borders/M1_5.bmp - res/borders/M1_6.bmp - res/borders/M1_7.bmp - res/borders/M1_8.bmp - res/borders/M2_0.bmp - res/borders/M2_1.bmp - res/borders/M2_2.bmp - res/borders/M2_3.bmp - res/borders/M2_5.bmp - res/borders/M2_6.bmp - res/borders/M2_7.bmp - res/borders/M2_8.bmp - res/borders/M3_0.bmp - res/borders/M3_1.bmp - res/borders/M3_2.bmp - res/borders/M3_3.bmp - res/borders/M3_4.bmp - res/borders/M3_5.bmp - res/borders/M3_6.bmp - res/borders/M3_7.bmp - res/borders/M3_8.bmp - res/borders/M4_0.bmp - res/borders/M4_1.bmp - res/borders/M4_2.bmp - res/borders/M4_3.bmp - res/borders/M4_4.bmp - res/borders/M4_5.bmp - res/borders/M4_6.bmp - res/borders/M4_7.bmp - res/borders/M4_8.bmp - res/borders/M5_0.bmp - res/borders/M5_1.bmp - res/borders/M5_2.bmp - res/borders/M5_3.bmp - res/borders/M5_4.bmp - res/borders/M5_5.bmp - res/borders/M5_6.bmp - res/borders/M5_7.bmp - res/borders/M5_8.bmp - res/borders/M6_0.bmp - res/borders/M6_1.bmp - res/borders/M6_2.bmp - res/borders/M6_3.bmp - res/borders/M6_4.bmp - res/borders/M6_5.bmp - res/borders/M6_6.bmp - res/borders/M6_7.bmp - res/borders/M6_8.bmp - res/borders/M6_9.bmp - res/borders/M7_0.bmp - res/borders/M7_1.bmp - res/borders/M7_2.bmp - res/borders/M7_3.bmp - res/borders/M7_4.bmp - res/borders/M7_5.bmp - res/borders/M7_6.bmp - res/borders/M7_7.bmp - res/borders/M7_8.bmp - res/borders/M8_0.bmp - res/borders/M8_1.bmp - res/borders/M8_2.bmp - res/borders/M8_3.bmp - res/borders/M8_4.bmp - res/borders/M8_5.bmp - res/borders/M8_6.bmp - res/borders/M8_7.bmp - res/borders/M8_8.bmp - res/borders/M9_0.bmp - res/encrypt.png - res/ledset.png - res/loop.png - res/next.png - res/previous.png - res/reddot.png - res/splash.png - res/success.png - res/test.png - res/tip.png - res/video-pre.png - res/volume.png - res/ProgramManager/EditProgram/DateSelect_e.png - - + + + res/signal-0.png + res/signal-1.png + res/signal-2.png + res/signal-3.png + res/signal-4.png + res/signal-5.png + css.css + res/AdvParam.png + res/AppSetting.png + res/AppSettingTip.png + res/ArrowDropDown.png + res/ArrowDropUp.png + res/CheckBoxChecked.png + res/CheckBoxUnchecked.png + res/device/Add.png + res/device/DeviceNum_All.png + res/device/DeviceNum_Offline.png + res/device/DeviceNum_Online.png + res/device/DeviceNum_Unlogin.png + res/device/Equal.png + res/device/FlashArrow.png + res/device/Lock.png + res/device/O_Offline.png + res/device/O_Online.png + res/device/O_Unlogin.png + res/device/UnLock.png + res/device/bnDetail.png + res/device/deviceReadbackPic.png + res/DeviceManager_s.png + res/DeviceManager_u.png + res/DeviceSetting_s.png + res/DeviceSetting_u.png + res/GuangYingPin_s.png + res/GuangYingPin_u.png + res/Hdmi.png + res/Logo.ico + res/Logo.png + res/Lora.png + res/program/AClock.png + res/program/Add.png + res/program/AddPlan.png + res/program/ArrayBottom.png + res/program/ArrayHCenter.png + res/program/ArrayLeft.png + res/program/ArrayRight.png + res/program/ArrayTop.png + res/program/ArrayVCenter.png + res/program/Audio.png + res/program/Clean.png + res/program/CleanPlan.png + res/program/ColorText.png + res/program/Copy.png + res/program/Cut.png + res/program/DClock.png + res/program/DateSelect.png + res/program/DateSelect_e.png + res/program/DateSelect_enable.png + res/program/Delete.png + res/program/TextAlignHC.png + res/program/TextAlignHL.png + res/program/TextAlignHR.png + res/program/TextAlignVB.png + res/program/TextAlignVC.png + res/program/TextAlignVT.png + res/program/Gif.png + res/program/GoDown.png + res/program/GoUp.png + res/program/LayerBottom.png + res/program/LayerDown.png + res/program/LayerTop.png + res/program/LayerUp.png + res/program/Movie.png + res/program/Office.png + res/program/Photo.png + res/program/Rss.png + res/program/Save.png + res/program/SaveAs.png + res/program/ScaleDown.png + res/program/ScaleOrg.png + res/program/ScaleUp.png + res/program/Send.png + res/program/Setting.png + res/program/Temp.png + res/program/Text.png + res/program/TileFull.png + res/program/TileH.png + res/program/TileV.png + res/program/Timer.png + res/program/Weather.png + res/program/Web.png + res/program/Window.png + res/program/preview.png + res/program/previewStop.png + res/program/bnExport_s.png + res/program/bnExport_u.png + res/program/bnSearch.png + res/program/bnSend_s.png + res/program/bnSend_u.png + res/ProgramManager_s.png + res/ProgramManager_u.png + res/Warning.png + res/WndClose.png + res/WndMaximize.png + res/WndMinimize.png + res/apk.png + res/bnBrightnessAdjustMent_s.png + res/bnNetConfig_s.png + res/bnPowerControl_s.png + res/bnVerifyClock_s.png + res/borders/M1_0.bmp + res/borders/M1_1.bmp + res/borders/M1_2.bmp + res/borders/M1_3.bmp + res/borders/M1_4.bmp + res/borders/M1_5.bmp + res/borders/M1_6.bmp + res/borders/M1_7.bmp + res/borders/M1_8.bmp + res/borders/M2_0.bmp + res/borders/M2_1.bmp + res/borders/M2_2.bmp + res/borders/M2_3.bmp + res/borders/M2_5.bmp + res/borders/M2_6.bmp + res/borders/M2_7.bmp + res/borders/M2_8.bmp + res/borders/M3_0.bmp + res/borders/M3_1.bmp + res/borders/M3_2.bmp + res/borders/M3_3.bmp + res/borders/M3_4.bmp + res/borders/M3_5.bmp + res/borders/M3_6.bmp + res/borders/M3_7.bmp + res/borders/M3_8.bmp + res/borders/M4_0.bmp + res/borders/M4_1.bmp + res/borders/M4_2.bmp + res/borders/M4_3.bmp + res/borders/M4_4.bmp + res/borders/M4_5.bmp + res/borders/M4_6.bmp + res/borders/M4_7.bmp + res/borders/M4_8.bmp + res/borders/M5_0.bmp + res/borders/M5_1.bmp + res/borders/M5_2.bmp + res/borders/M5_3.bmp + res/borders/M5_4.bmp + res/borders/M5_5.bmp + res/borders/M5_6.bmp + res/borders/M5_7.bmp + res/borders/M5_8.bmp + res/borders/M6_0.bmp + res/borders/M6_1.bmp + res/borders/M6_2.bmp + res/borders/M6_3.bmp + res/borders/M6_4.bmp + res/borders/M6_5.bmp + res/borders/M6_6.bmp + res/borders/M6_7.bmp + res/borders/M6_8.bmp + res/borders/M6_9.bmp + res/borders/M7_0.bmp + res/borders/M7_1.bmp + res/borders/M7_2.bmp + res/borders/M7_3.bmp + res/borders/M7_4.bmp + res/borders/M7_5.bmp + res/borders/M7_6.bmp + res/borders/M7_7.bmp + res/borders/M7_8.bmp + res/borders/M8_0.bmp + res/borders/M8_1.bmp + res/borders/M8_2.bmp + res/borders/M8_3.bmp + res/borders/M8_4.bmp + res/borders/M8_5.bmp + res/borders/M8_6.bmp + res/borders/M8_7.bmp + res/borders/M8_8.bmp + res/borders/M9_0.bmp + res/encrypt.png + res/groupbox-checked.png + res/groupbox-unchecked.png + res/ledset.png + res/loop.png + res/next.png + res/previous.png + res/random.png + res/reddot.png + res/splash.png + res/success.png + res/test.png + res/tip.png + res/video-pre.png + res/volume.png + + diff --git a/LedOK/res/128_128.png b/LedOK/res/128_128.png deleted file mode 100644 index 5cc7e8d3287acf1b15b2520997180fe7f1491037..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6983 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 P89?oYwo;XXMd<$kt$ZY~ diff --git a/LedOK/res/CheckBoxChecked - 副本 - 副本.png b/LedOK/res/CheckBoxChecked - 副本 - 副本.png deleted file mode 100644 index 45877e14d7fbaa84024ba58f7a4122ed0f700386..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 617 zcmV-v0+#)WP)=Pw`-o%_!GS4ud2fHrFf1d^xe|aTfDXykA`(Cc zK+`!_5&+Gjpmnk(B)cS6&1_l<3NxEd!LDR_QCJqgo&Vs!00!RsDKoq5y+0d<;aHJi z;Ju$B`2av0z%x~yC<+YB>^RB$B!7_X0eJ4cpDY3lNFGbE@9E!V(adI?bEVA&1MmGL z$$J?_a!FNZGi)eWE|<5Cs;TM(fV;WM-U67*hGi(2B*|%2oh5lxM79jV;y6A6V1eYf z6nmE>$p!EI_O)mGf&g9uXp?*bpxh5t)x!Yp09Z-C@gBgXFbsFDcYYA~20)MGPXLdT zBssMf1#l>j0r+5MS5$SpUpM-KB+rw4kwYH=I4L55h=}+80D#*hzovITlDt~2R(JL7 z{UET>Xlx^C0A7>K(1&pxpQzXC2hHpj$uH@>Pb9C^>-F7(uz_HPn%NA1#k6HB0GQk1wr^ByWKcvTilQB=dXeNSlFI;Ys_OoYU>gEOL{xPgKxk&?Hd@&qftwM373`)D zXNtnIH4#8ZNVaklSo|XFoGY1GD_3a|*(KR>&Xs-v{X||9JG-VA00000NkvXXu0mjf D<8BX2 diff --git a/LedOK/res/CheckBoxChecked.png b/LedOK/res/CheckBoxChecked.png index 3293681290fc6fc5378640b46662fad63e3df44a..45877e14d7fbaa84024ba58f7a4122ed0f700386 100644 GIT binary patch literal 617 zcmV-v0+#)WP)=Pw`-o%_!GS4ud2fHrFf1d^xe|aTfDXykA`(Cc zK+`!_5&+Gjpmnk(B)cS6&1_l<3NxEd!LDR_QCJqgo&Vs!00!RsDKoq5y+0d<;aHJi z;Ju$B`2av0z%x~yC<+YB>^RB$B!7_X0eJ4cpDY3lNFGbE@9E!V(adI?bEVA&1MmGL z$$J?_a!FNZGi)eWE|<5Cs;TM(fV;WM-U67*hGi(2B*|%2oh5lxM79jV;y6A6V1eYf z6nmE>$p!EI_O)mGf&g9uXp?*bpxh5t)x!Yp09Z-C@gBgXFbsFDcYYA~20)MGPXLdT zBssMf1#l>j0r+5MS5$SpUpM-KB+rw4kwYH=I4L55h=}+80D#*hzovITlDt~2R(JL7 z{UET>Xlx^C0A7>K(1&pxpQzXC2hHpj$uH@>Pb9C^>-F7(uz_HPn%NA1#k6HB0GQk1wr^ByWKcvTilQB=dXeNSlFI;Ys_OoYU>gEOL{xPgKxk&?Hd@&qftwM373`)D zXNtnIH4#8ZNVaklSo|XFoGY1GD_3a|*(KR>&Xs-v{X||9JG-VA00000NkvXXu0mjf D<8BX2 literal 479 zcmV<50U-W~P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!~g&e!~vBn4jTXf0dz@3K~y+TrIWv| z0Z|afzuiP=NxXwfs}L$1QF#H;OVk?Kf)&Ml?-yPZxa>~=dz{tJuS?Ka}^IO_E}0)c?^fDwaGD1=6%fqXuX z#bO}`cRHO8EXzV7kwB}}@^*g_1HOeqp@3*Kib|z|`Ft*iqtOV1!2ro*64h!|Dt#lJ zPRrw9Tp{IhIVu*5lbi^Wi@)v(!Yq~noD1kGj>;c(c? z_=o2T?o6jsGEI{l$MJUFxmWQ0Q|75!tyXXc1c$@n5y#{4W&IqSyId}1BEKAG9X~3d VriD(_KtTWi002ovPDHLkV1ji@&^7=7 diff --git a/LedOK/res/CheckBoxChecked24.png b/LedOK/res/CheckBoxChecked24.png deleted file mode 100644 index 2c70eccb33b09726a44bf364f92216bad2fb9da0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 698 zcmV;r0!96aP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!~g&e!~vBn4jTXf0#8XqK~zXfwU)n2 za$yw5zlsuSqM57i(wdWtLxPDv@CPY`2>u5yx(Lp-)X)$FVxi*V?$ke^f|g>6LQvo& zE@Fe?eLJUX;G6Q=+wB8)xX<(O{hsHX^E~&;-rnAXv$HeQYBekt3rK-nF2~{FAyTOn zWSLAxs8*{uI5>b(se~X1;Ma)Q~1=%jxB(X<5folMQ|o$qXJI9#ATkFc=K@or+CJV$kh&ad~-(LZN{B`+FXf z%%Ih3;rjX-udlB#7z{9*%{(qi4IUpKaeI47?vjYb56LD=nfp8K%@9i+RvJMMLb zLV-vm0+-8$ot+(V#Rn?}lgR|lW)tJ_SR7do6*8C0u?gk+LZJ}!dOa5|o6UZjP+D$oZdiP8Zx6@E$1JW=sd#=9D+U^k z20ot;e!rjdNjc8v^QcrRC>D!+n09w};cz%uoOb&!zU+;Vu3(_Pbc*_b(dPL z7FTS?MgxMx!r?H|=``Z;IGcVKHdtOv>mU=8$@FdU&&!SqNyU>I`Yx09?|<~)yMupQ g>h=0B{I;a<2PjDO(p&lw4*&oF07*qoM6N<$f=)|8{Qv*} diff --git a/LedOK/res/CheckBoxUnchecked - 副本 - 副本.png b/LedOK/res/CheckBoxUnchecked - 副本 - 副本.png deleted file mode 100644 index 8fffceb07955b3cc886e5b6633846fd674c5f358..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 177 zcmeAS@N?(olHy`uVBq!ia0vp^G9b*s1|*Ak?@s|z6`n4RAs(G?uWjT#V!*@fP&)7B zW=8Evvu}3aQhqYq;>V-a3|^{CIw7)G3>i#3V=rx~O$)g+$v zH&JBLan^M=s>HSxTeFHqBs4+@JLc=9HJdir3ag&oU>hfUh(YS)$IqE=)88^KsAaT~ Wo5-BG@{AVH4Gf;HelF{r5}E)EdOq?1 diff --git a/LedOK/res/CheckBoxUnchecked.png b/LedOK/res/CheckBoxUnchecked.png index 5a5b64c1c4307fe7de8b24b603d8de0f84c06a29..8fffceb07955b3cc886e5b6633846fd674c5f358 100644 GIT binary patch literal 177 zcmeAS@N?(olHy`uVBq!ia0vp^G9b*s1|*Ak?@s|z6`n4RAs(G?uWjT#V!*@fP&)7B zW=8Evvu}3aQhqYq;>V-a3|^{CIw7)G3>i#3V=rx~O$)g+$v zH&JBLan^M=s>HSxTeFHqBs4+@JLc=9HJdir3ag&oU>hfUh(YS)$IqE=)88^KsAaT~ Wo5-BG@{AVH4Gf;HelF{r5}E)EdOq?1 literal 241 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sDEfH31!Z9ZwBV4J6lV~B8@GxnvK*+^w@jZ|?3Mj?m4$b^ z-kjo1@%O#=H}l1w-F!Xj`Ht!r7p^YTAmwW5G jHZPsxuk^pC_yBWb)PXa{_I;@Vx`@Hk)z4*}Q$iB})yi8~ diff --git a/LedOK/res/CheckBoxUnchecked24.png b/LedOK/res/CheckBoxUnchecked24.png deleted file mode 100644 index 219e2441377488c89f0a3b36b343c4c33e1b3392..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 280 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sDEfH31!Z9ZwB;95@?#}E(ix6=%{jwlGY?r&-rj4tLrFYNvL zNtW8u3gKXt7w=k@L<^MpZvL^W@uB_3pNF^QYF{=t52w3SD{x=j>~ZyC-#ONsiy)_4hw@ zT7MR?@e~hv*`yU4u#|h%pU#G?b*AOdcF(u$du-7@EkHl`+vlb8gRIU^D~*-6h}MZ~ X;tsgP>LMKrbU1^jtDnm{r-UW|1a4}U diff --git a/LedOK/res/DeviceManager/Lock - 副本.png b/LedOK/res/DeviceManager/Lock - 副本.png deleted file mode 100644 index 82eded84e15270aff169d686409c3433793c5f89..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30357 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 diff --git a/LedOK/res/DeviceManager/Transparent.png b/LedOK/res/DeviceManager/Transparent.png deleted file mode 100644 index c6c491e4f823d63cc3cbe6b66cd7c2e56f32a179..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2821 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 XK(qrrp>d_B00000NkvXXu0mjfup3>B diff --git a/LedOK/res/DeviceManager/UnLock - 副本.png b/LedOK/res/DeviceManager/UnLock - 副本.png deleted file mode 100644 index 5d8e51c0bcb898e64c903a2fa05bcfb8491b38ce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24287 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 diff --git a/LedOK/res/DeviceManager/图层 4(1).png b/LedOK/res/DeviceManager/图层 4(1).png deleted file mode 100644 index d042c5400394b76ea0b1ca47bb1329886ac9af8f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 627 zcmV-(0*w8MP)3c(4I)^Gq7lVPZA8$3QLs={T(I*SsD+3hLNSF)BQA*Gieh1* zph+P%f*T^Z1UCq7BZ6=BxnFfVq+Xny`iuHI^a3nrOf4(P=fKeV95x z{Owvii^98w&ax00MxYtHLSu$-yDUVOMHo5XiRTzB8;ME)BGk3xSR?jHWOyXRWB{VA z7N858&^?BAVH+;uM^Q~IL)~NnT5tyMLR{XDV{h?Aa?=WkYv`y1;3VEm;PBA^E@Mt5 zDQK6p+F0T5#s+M~g_0C>PC5leAQLIVrcsKpw%{boHf+Qmi58^ahT|OGgx!)+tolL} zexLduQtaPd@CbKCJv=Lb@Y{^V62Z!c)mIIm%eojocS>`@9Z9V3&LZizYnN1jlb9Y}8g z>)+iJlKg=rbHMWY=C`BGE&1>EV?fqVfaNbFy#gfDKspI5M}Ty4O=^AvNoJAtI4(#%A()Uvk}0ZfquBEbBwSdKy@-fs6NNOZA~e z088ELAc<@&S-s2G;$V!{6P}R{#@+>Ehw)!!aMPO z#`Bii+%tfQsX<$+ZOH|-yh)OjNs^SAI6v5uyq5q)r@N4J7D$d_P}^aWB-Q?hy#Yvp zlM!V79!ML&dJIa@18pICRe@}&J_Lch*xWGjWSzGhw?cFT5Qgcji?$bBwA%*JQw1khY8?<47@=5qOIH6iPd$od6Yy^^*kag~VSwzJ^hLPmV!n5o5 zDo%lu5g?7h$%z${_YlBjOH)I6U+za2Z8u?tNI!f}swNQ{?HIT&oMohw;N%E8`2tDL z0!af%E+fk`#+zEVRG%&GeUJhJ`*B=2TR^}_NdjfUxB>D0YI v@&>S+K-Nl^PW0KPJ_nLF^JTr~-?sc8Z&++B;`NIj00000NkvXXu0mjfS;X4{ diff --git a/LedOK/res/DeviceManager/图层 5 拷贝.png b/LedOK/res/DeviceManager/图层 5 拷贝.png deleted file mode 100644 index dad1e82a182f57166fb24a1e8c6ef83dee88969d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 206 zcmV;<05SiGP)Y)Cphq|s`9z~0`ZI{5C+Nx>sP)-`@*A zzy_E+%6}#G9r#c$>bLsYG|hNOj);iNEPx5{)ieDs-vCHJjGmZsQ6K;S002ovPDHLk FV1j{gR7d~- diff --git a/LedOK/res/DeviceManager/矩形 20.png b/LedOK/res/DeviceManager/矩形 20.png deleted file mode 100644 index 70cf53a4ca4c6fc1e5b1541ad043c4f0e1102b15..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 114 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbBEInNuLn2z=o>OFGFyLX{@UuKL zb$8ohK9-jBNpDmy^Ko!;a&BdI0)n><6DCXuuvSn}QMtm$@we(%dA*?8%9^P_Ll`_= L{an^LB{Ts5U9uq~ diff --git a/LedOK/res/Logo2.png b/LedOK/res/Logo2.png deleted file mode 100644 index 6b133169207dc2decfec7cfb868d79178008935c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5152 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 Ifo4)=8 zFmwfF1o9D`z4FA4mBj%#d3JSM(q5G<%`X5Po`}mE!PQ2gl%QMXlSL8!k2!vYFU4h? zO$pHqTBL4wZNYVP-ctd_5w7j}RWm81Po2BKbnDe$42gW-ZpxQ-ku_Ym*uolY-u-&! z|3c}&+$D{1JA01nIXQ+{9}>iwRnT~OP7?8=C1yIeD<`Roro+PYvf~)k!G74pP3gbuq_|qt!(0 zYNjqNDc&XHWJU;j7C1lV!$T3H9?-duL;`qCe(2d}yqM3gB0XaVa&h;;+)@oPu~(EK zjbgjZV#DtQD#`LnEMu~a8|7nG89l9?iUf;Qe(uV~o8$EojH))h9h2SUl%zogx_3)e z0(3QCIlelLaS6`?7~hvHQzroid04;6=kRg?YS!>--XTrCR?3k@n(8 zwfRSw9H~8*Rn8>G4!c+KxN6ZUv2`X6ejD#<{$i2jJ*sIViTUIUt|)t3n6*mwVw2M8 zs1!2@{dD-?e&2Q?Z!{j8dDXy3cCqO#2jxPPo$mfN+@RsB36qLySL$TL)!2rD^eada zN#EsHwK`yp@ZSKR(>rcBa+-ljFHZVGLuv#!$mdJ93yK-#`KjJpA9U1T_AsxDUJg?pIy{qs4h?Aw7RFXJ?>||g zC&RDNpQ(y^9?!()<+W2WcHM*a>IRPj$mG;^Ee&RUg7r%#nrz!FZFR51URUc8!sKIw z=j>d`<84630t#P+!Vi+6np~b2K&QFQyYGfuoVrClOz1|19<0%I3MLC2Uy4F}%g4KY zlx4dz`nHzVIuuI(QwzvHf>nF67X(phM*WJkT zxExi@Yrgkdx8G}`;kE+9#8oo0Yl0T>15}7PWtMwxO#0ibI3C7e-H>IaQLnoiV!kzV zB0_0SXHm?o;uIg#3`bu=NlH*W^nc~#|GCP(-ewROfG6F>?Q0D;{gW_2QBFm+TH5se F{{blpv}^zX diff --git a/LedOK/res/Logo3.png b/LedOK/res/Logo3.png deleted file mode 100644 index a13e3ae3a4c825a5c6438f1d1af55589ab3fe734..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5873 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

w0>@J7LmQ`^1I4|?oon&mG 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 diff --git a/LedOK/res/Lora.psd b/LedOK/res/Lora.psd deleted file mode 100644 index 96abe524c2715ea2a930a070b6c420e85236ca34..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 50845 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 hE06Q%3Zy8bma%l)pQp;m}Fr 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 diff --git a/LedOK/res/ProgramManager/EditProgram/AClock/AClock/Aclock2.png b/LedOK/res/ProgramManager/EditProgram/AClock/AClock/Aclock2.png deleted file mode 100644 index 75095687b0224de056626b0b087402c3e85fd91c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 323913 zcmYIvby!q!w>2e_lF}e8B{_6AGXetAJ#?oajUe5f0@5JTFoc8--NMk_jYvy>hwr}k zy?-D$&olF!IcNXYUTf{OBh^$Daj__{kdTmY!Af!(NJuEXz)v>@I`9hi*UJvz7p9An zo;&bAqNg8Zq^vJwz>BozN*XFiNIpzRNS{6VFv`fUNIE@ip8?2;DChtm55?#WO9kHyp({SVnEw| zF83t)u=vVq&Ya6z{5sZp0CsqCc1F}UU6(F29m8M5!LFVnm*|i*GK#z;$M8XBwA^jU z>-1PK@NTsIr5aL}1NhyV(|7$QHIEJ9(mzX`{+Az}^HU0KA#Ga!U%$rU%U#aE3GwFo#>N^iQY`roV>!yji?8R!qhdg}6 zE$;V+*JNe``#<3%@*G2OH!88QE)Q|4zDyoR`+3kvrcB3q6qHN_n#q@DIfAj!9%DIT zs)xWp?!DwJ|MNfB{Qqw&7s}?QFDf_*2OVl3SfM4kXfvJbBw$YzWb#_oFM%!!t(<-W zBvbwgq>{)h%^G?{%vUV9SJtLKHv@kq|N$FyY2A$yPr;@qwlyv?K!Rx z!*q#y+rhzGM1%X%6lZ9I$W>*E%!GD@d^nkPeA!C}l2peO`HD2VA7N0_Eaot%9Xz+4 zFeuVeZ#MU>MBeK>uB4$Y7bDW4x{d^)!p8>Z<_e*YKp0Yb~7Wg&>${q=##faD-3-rvFbtq0zO8u%CEETN8t%3?IB10!DnMe-{g4&p6 zew*e!kiEUiVx;Kzii{dAa9g+}5Z#{Mn#N>GCx8yM%JZ~(^4r=Ew^m^qq#pJ38Vr}3SpdHX>vvc7#+bB0ZRR=vRyo0u;l=VaE*3&`wpNip>;JuqmCW^JX*we4P{7_%}_nI5W zcA8WPks@>%xsd_F1S1+`ao(0B6UbM7r(h-vgY!NMV^xO`StMY{qBtG|b%4HmWeVzI zG{%roMvZP{mP9%(=%!84mC88%Mwlq^8knH(;x zJXSNmYQi@44RSGYs{zR`=&-DAstg%Qv24-_wnS@-wKAhE-WB8O;;vDC=lr~jPMvUJ zFmY&$WpilkC8Q_)?D|f9>`Zm*=D2fFeE;bHaPmCW*24|`9rwFKXXi%!+l{X+k{1Y59><&zfY>MeWKb!FXXcqWe`EStK6h8D=Up}DkJP2IQ7VY;8V+t1d;tqN@;+py{5iCl zDam(cHtda%Aluyq)@QCbu-_|hF>Ryl3|`M)t6*7+ncMaRZd<*4av| zV6#Ykk`nXvS#QQDMr}qg${@U$PjWXgefsYOiMa9%{=zygmZOa0!SxO?WZ)mH=5pV2IC~QZ-_k}J=b6f{8 zd883VBkWwm($yY};uxw6QArB@BsBO((I$yqmvIn`;;m!yTIIqqCdQ&7rD3j{BMn5L z4KY!K+)srWO?18`jG(v3vYYs0(M@q~9-iM}lpP|f>iN9BOo$l+#c$>HDQbZd9z9zz z21*`Kv5op6P>fGI-kWFMM|`Rj)CE*wbhZWfa2Z_`Ss~&frULG%D{|D#@Rmx6=P`r=cAWJGEys;s3XZ|5TC&UGv50gO&N(*@*VhUgjL- zZQ<-|EQ%0lG$XE(Wr#-kIxb8@*f~z5DCbb5 zSFHDUc-)2OS&3<-nKMNkWeF2+B&>Mw;7FOlP&-Ql2)B7!JPr)}(JEW1z`<9J5vo*Z zYz>75=~spw-wHj%z?@j}Nf}_;dxeZlSntKg7~;%>S?Iuoj6=!%`rCeRW~a`M^)t!c71(4akTu6FMG<6 z<>_@Bj6Z`U4EohatdhilgpBhB*-(YpTqzj8%Y~bR)PbvBTo->x`InI<)G`U5$(3ZG zB(m&iJE9=svc`m-NgDsRg8)z>hGOo)jNlrhaBdt?IT*nW23>}M?(ea=A&yrp_kNBB z?2F$r^#pK&X}?a{(S>}~WK-u%7e#f|fG8s-yBu?8T2vOlt8tLHQiaRpO9eU?n|rgQ zLe90>I5;?d8?f5uW;4!Si}Ctal~f$3U#3GEiy0Vp)5eXtYrLrG&Pk=XD@f6xF@u^L zR`uY@@uDfbxLzD5>H7M!w`UzT%1p4(tMb=6f++rVj4j@I7qFNCg_AAl?B?zkrBE2uPrTsM zUY<Dk1tVC7r&=6w zl=32|n;U1a7^Ui9LT3*;lEuGyMuSwG`$i~ERwA!dmqUYXb71Ri)jQK!kLW(mU$&V2 zJJWQ54`;FV;v4%D_DH%Y8-5DS3M~>6lCqhD`IRq>y4qiupu3xRvU}#e9`3;BjE-1W zOa7S^MZ$T8g6%*w!g; zCe;%4YB|2G5|Xm@dJLE{X5l|!h`*?AIBQ`RQ zAI3j=Z^R0U*tvcqF4l~yYXu6Nqr<41#S*vLdm-G(!)4|m#&#sw_# zGDVtm2!;)tLAznXJ_?aB>c0E{ceRX|13o( zACdMo)ctBnn48nnK)-k%{98Mst*M#IaK>_Jp2w|)%0Cs$-{1fILYsv+8faW3A>|zn zN5i5y*Ez{(MU1gb>hU5Z$#9jeLP?? zy7$s7L^;808M-CWP|;>5!+}L6q-0A=oKX^e zAUvBEzVY&;4aJyKv36FrL+$6K7z)?>7;4fQQ45|6)B!_E9+EUDdBl*QCz3+Zme@z$* zJN|8<4vydt(gX)%sl@nk!74Dhq`$tBv@c{(=1GC`@$qK9{J2RizpO2lN;6|=dM0o$ zW}w27`c(w4(%Id72_*U0^gy?zfm~rYJ!TC>HcWT13TycqdVCAO8#f(twW| zTeecWtD1k82PZ5njEw5=b^1_kz`ajzZ!a0upRO~p8}ys9b7Gc@v|l`p7c#7W9csid zuq?O~l9xaX-AB!hLL(eh+v^wez*&` zE$uu~ITmJJ_{U$!`gg`9_jHu^5Jwh|JGy=kbXw3m4UK+@mUFAzg_(0NHO~LA z#O{W^R*^+VR(OZ^=P!3*zh!keXiAPBD*-H1p$>HRtP2WkZ0zBYQC>m8J~&)V(0O_D zU+A$FjQA+^4<(hUmsf^cON8Ts!;)tn%r>PF%h7t-ZtM&n!^UzNXF;KvGZc~tmwGm# zd&^WnauG`Y4ci?}`m@mFgA+p~)OW_~MuZsJir^sG@o->HR3fl+aaBb}=v@Pl)6X~M$8SxG#4YWIZHSU40S z!7XI3NcwX8mgg(&0rp=~Qqml7FEUeYVhvnSXy~(GS}9ifVhy^yF~rKs*ze!??(Xgw zbY6SK>0~P%;g7dm_ir^)6V9T1{=LAq)EDy1WjU$G5X60NA^eN&Y&a@dJ7B@p@$I{7 z_GfSu^5kwG0@GOmQxp*odi}DqiML!Q6^|#9NhPd}3OTj4JP#L-H=W!P5^*`jD*cC? zOke8-(NLt>KFcS4!EJcs*i_Hks70?+nVL4(LnxrWDAg-r+<^qeHH==lJxy=O24PUeEduJ_9?9lGS7^|$PGPACV}wyxR`deL!wu)#l+qKarp-iKx}s}tv^#D%?0 z3So&lM`G}f3Z?P6@!2~f7t&|B2QNQ@byJok3z7vGK(H9WfBjz}K&YE3YxTc}A>~2L`~LCLP1El!8D{ZwoxfaQ*Jz33GgUvfbTi zcoP3;QBhIPFE4p{c!Dy=>>0k?uY?YAv)39bfyH)ep^*j<~cMbUc; zwD%vdI6mNHCnkC_G1*dmB<>R!w@cP0@B6uaycC2Cb6n^J-Yxv`4^`Yo4RG?=QU~j> zwgt*lA&K9JGYQnK!F1c537kv%d772IB z1qZEUC2#2&^r1uu)wCt+*AUzwIvgAv#v~<$p}O2R2sk(HDNMdt7rGSYL5878NXYNM zUK5#b>SPx+aG>+|Kr628Qe@?N^kWS!(L{(_%kXcQQA~V1VqsxuzR{k1_oz^f<@akQ z+oavu9gq=+I+##-#?rcR#&KqtOBUDF<0wRLNfwxXvEb|05^pt}{96mXu<*t2J`9+M8 z21do)BX+Tg2>t^3e0Pzvyv z>EX+xWtz0kIRJe?k?z(Fp*@{xXlPJzx%cI8^rzG zU@9I!t%iDXA65>_&jWcRe^aj?{I>=sOmF5X^YXG=uenM~oE@FDcQEfn*j`90G{f?f zUvgxFrUr0O+rvE`IW={0r*nc#{-<=VgoESfqU^0TypQ%&(iO!BObT45 zrPiL}x9Lw0KRG$surnYBIO^24+8n$fQ1|RC+3n?#xs6RkVj=5x7HL;A2W6H zqU^tjmug2ZiJU?dYHbK9oL|;`JT^8CIMQ-jZX4K5dm}V~q=+{#z*wS=$C5rozUM$R zh&GV|sz=dj6X61g<>~2wnuey7ZZ$_M@pD49rJ2ic0EWSP~T@5{wkW(ioOMJK5xfT8n%9j zd}9Fnq(PQy{FC1HMmJU@62+2&MfQVRsQhJy874SgPcAE;IE*fxb;i*?SUcloSqLar zsgO)QDzv*nMUFFEhlQJ$7ykDzx8%cys8hlJ0RkEAg1Hr8t?Q0E2t*c&U|*2Hwp5x!_e?m_eIBLD zucp&|eV=y_xs0V^c^xwSg+BDA^3fa>T-n4 zIZC_?CTIu+7{&06-{2N6Oe>_J2Yx3et{rE1jQ?##HnqMfbcVefNf=g*@X~|& z@!xGHe}2N@i}lj=m%}3i8}D8RDB;5ZV;wbz)sQWfTP2y>j;^@-%3qGH)-l_yMY*`Z z-3Rac()W7TBTuT#mJCvd1^uZnUp5azqrXT7<^o_*W!M7W8cMeXQ5=f@!;qDgr4n-a zlq33aKdAmY$*e0?PQq`Rj<@eE@NJ5xVZY9l4Bi-F<_tkCJ)galN4pSlr2=SAD&*Oa z2i+;=XQ`RjqQW;fA5P`S!d6?ogfXiM*}sb8E%4FCso6rP&{|pG&K_=lV2vu14rTEQ z;Y~ND8ys+%nwaC@B zjIfNdA9YQ?j#}7yeT0$%Qc1s#UzhMAH4JN>NX+Qa&)z>3{B8i~S1AG|I6pg-- z4R3iLbaZlq`WIYzT_D3#R3FN1w-#0YMu1(kP?-`=k%Gvb*>ApHspBV?VA_(c5mRXrCo-M=d4M< zY0<9GP3sB6rEGSd;dELSk|zsm&_@Q?q&Y*9-WS8*oMI!E;)wbljfyE5Okd`y}Y|c)s;r-Zoy3acS-Z0A`D5ty%@)HLfYL zEcjHFc^O$_ANf0rGJw-ctUM0k04V~X<^KL&C{)ICzXPfK_qcA_bCmTtiXE=Jwcc3D zr&=j5XLVX?Q*G3@4Digd;xilj<9Iic_YX{Sea?6DP+ua%&LC#dvD7fWf4BUB3TFnM zP?tPlj}-(Vv}o{a9%|$e>ys`iXSS7=s?U&rFCG#N1nwNg!QOcta5u1le*d`pCrNlzidI3Z`nZ zuXyigQffI_Q7@<7y}6023{ZckD3t|IUA|a?2gl;FN z!Y>X3r55z>L^O)aCVvv6r)|*J^$Wl3ix8rVF*EE!>7tMQpmOzZ9+O$XVLegtRpFdN zQoXWqz_lf(QEN9Gj^f;LEdX2<4lb@b2MIYP<;Lo-&p@?BL*Bj0V6Htz*fsvWj|h4o zFw)C;^I_g&CH8v`SDdUGp<=OaNw?{^k6Bhy%f22wOwsX|x6j~!d8cHbh&_vs2`MJra?1psTvU%)_+hkXRV{urs;i6? z#|5o!Jb{nLkNyGMb9vjz@5GBS8ytxQ zi4J9?t=X*w(m-Htckh&AhGb%dt5RVEOH{)}H%Q&~TR3xah7d-Lc>E0<<@LK<3s29q z%uI6CFGA8ujDUTfk_0J+qvDDE{Im2!w45%qZd@;-Azm_-x)7Y?a)0Adz_R~EIsx43 zKroA=g0uFCPKhWYkqrK8^rcG<3d6=h$KnFtzn))>&yDvwvOUJ-(*da}Pb!IIaglQ$ zpeFf6;o*V1OuTU2g*GNDq!L~FH+`&rKSwWnLJ~^~OMYQ92LiBO!)CriZTt*NX}ofs zUcDuhk`jpdaJH>d!ez8ES^nP7WuG|K=aUWxHwZL1kK4*(ZgwOh&LX%Nk0leV9UFM% z{P4zjbooB}ugE}oygifhT?bf>f7jJ5!7hRp51%n=AoQ4b)QE0v@egr+B z*-BM&;D9)1W(MZA42p3shqF9@DO)vh-7v`QawygV$z1*gy+MD@LekKhJ+xJ(30kX6 z!P3N%#|jlo+mX(9_TKNpGV5R?H@fsqThgv%yh`)FS}5)96V(+-bU8A#Y8fQ@topi% zH|>ef7s)!N-tvlYq>}wZMPg0>^WOln)_D^~y=Ct1=OB`tg%?Evzw?*en`z>f@;z z8N5e~%DP8A(Uyst6^89TFX_+_2n3a|TL|D5@CXY7ozogoq5^#O-~PgQUI__R6K7}G zSK@g$qTQY#^ZlFSG?PN(YN8uyt5TZ@2LUigPEme;Rt*#25pOkn1RZG;8x}CtLmm;t50~r1-()xOiNV71^VQoPBwQB1KYJs?j2t#u+WUC$xYOx!G0*fc@OUmM?JWg3 zl5xKu>?&LUub%O(N6oy%wg7S?$DM%=25&Y1nli6<{;l^!1E(-?Y^QwYK#A2OCL6!V z76PCa(8n(r?)3+#XsoYo&#v!FY}m8NCUR%3TU{$oyNcBQ`W|CiRY^ zoJqqR&5urj)gR4v%&Q7E`xtsFuY0zC!1UiRS$ykI-$T}Xog>Qx?sHnbl}I1W9lTsn zu>vUllpP=?vfemCU5&D3@_#Pg;UExaVrRppvz>vGqMnCe16}YJnXr?K9RrX0g`l*2 zw@O(hy71juHKdp?Gr|l6)@aKfMyH`Nr77|l(!}y2VJ<#dIwt<9kEbRNfn?}0ReGOo zvo!0FJ8q9xdH{Uc(nt&nLbhUd2EMeb_^H%*KgZhkr(BG0lakTs95k3B;KY$X z@dXlzXVYd_b88*ab0Lz28-*r-&3dg<{BXbY;VFVbxbZZwjQx5uIF?j|s!psbrw&RS z{A)|s=wp?*{u~#FJh`8k{CSxsdr??<>ip>{2_!X&xl39q3VseT#VC43REnv%EH*e) z-989tRE#bq_CW@FGIH{@wWI9WI!o+Sj{_v^z31Jmj1asGfJ4f$sq^+Wp!J84c3yjQ z+*UgO#qRuzP24A#XcaKyS%3y>Hx!REw@^rYQ>U_|%6MvP3$zQGK`W$7Y<%Acir z*{{zjy>k0j)g+xvUiG_`PR!Og*1XxT=a0(~8jajIc0KHN-RFPR1)FWKCBhS{$php? zos$`A=(2Iyh)rE`30h?Yv2>MMFAMR-*k=;55@w|${BT1F_b8Klc<09Jfc4k2SDT0| z3(GDKT@od53Tsp)hv&gW@ms?mp0Nf^PCSBwGv&UVWUM8&8Z5+QG&ELbW-@|bad8rc zw#cZcx>-^|b8!W#sUX*w6^A7DtNj!-MqqM@y%?o#6l*4Wv8lJ zcex8fm+Gox*4A+ErtKMo-pxxmoUW*PjzR>~vLczO~!c zG8WahQ-{wDrDN*j0=HQ>@PPv;(V{6k0Fnoav(K8V-qz|C0l1%-5AE&i11Q{66Y$vB z7^)O0m$RD2W@R$2EsBpm9R76fFYZMl4^%clHbs|jS)$6$FHf^gZV0Q}PO%>E@*ds8 z6a=^>#YbYZXEHJ~*Y4)(+fI5ZhliKVfYHQ}LDO#N9Bc%zNKNOW6MbYbaJYuUu0Y7n zAPP;=ERM-<|0*;5B;I8O6B7=d*Kizty!`x$7UL8D`Q;1lI;($O`M>xd&wiGKcTV{0 z9RA0->b$Y>Ptb9#5s!pN0?{rF@^?z)m0cJx_TtN?_n7@=)$=s#3hhxl-sdS0pZ<{{ z{q2cMDFd2MHO3pC@g!EKbWFC|KT66KknO&Ln%(Qe9F|A@MPYm(p{NZZ>PB{8WICPV zVQz%g?9I)w&O!%iklAS!V1txt?eza(HeN=iyVmLa8&6I}wb}W&^BB#n-AI9bcBcI9 zojY*Ao)j!_z^q5V?BSs6r)e+D?~wu4g2NK5BKfT-H}@wN58HoRU2JyG7P zQR}V4$H+UoPs(5-`IPP=%pA=)(9|~pwjNFLa?}vtAF1oNbTFQ2YUdyGM?H=)Qx9Iw zn;KlinhU|~^C=!Z8}zpJh+d7V&IUc_y;T!WG0(WSBnJiQCDyY}S**iYsf>)Z%kN4K z_Chh|WJ)$zr?E@-&)+33XuT-!Rg*a(oyT)X*efEPX?mdC;L z_{xGJ5FI)Z^LIdUEgYY_Jc5dLdC-Av__H_Ngxh})i}gSL+X>9|lNgh{FMTAI^*+Ll zJn}AMTtDAKd=YYuX=xGWG;05OaWJE&n_+EcMxA#(TUBl4fzU? z0JPSraZrPx_h~OKK$a@gRIObdh=%G!z$~+zGP7hrWX-oZl)hd3GY(E{K+7WEU3JW0 z2i_0o-2Vv86CJGayC0}vLI)l2zq&z+nFdmjbcVjGU7vHNjHOoN4eBK8%Y;f2S9}|L zX$c1Sls9k_s@pwNKCbwu^X-hSwQ>T6+j>W(=xl=}Um=72-ciMB%FR#wZjU@hFzDCl zpYZ*Q7*ij${UA*Okbeqy|4S^;ffkmNs-%g**X>ep7fI*c+ebVgtl+ha$g>3QZMI-z zpJs*W2l@feKa1tzwam;J85w~3el>P>UhXvZncIlbLR~H;=Mu(&&G)tm2}JHGUKx5L z!Hcs1at7Of!7T}b%M~P)@8Sy=TaeT;HJoPhOfq8qfy5kJMkkc`-a4j{MNeTJc{1^6 zzv2@{sGXVPH7qKSM_Rj3Mz$Z zdmmlS^ch>0$}DDB?TRhA@9CL@5(WEcQc%+;Dd zCn6$>iQAuuJ2`P(%%#!PhMSS0+h*+-;dHG6Qx?GEe>ww_x7Lp_c{k;G>yPK}C425P zsmIPDi2N5{MvLTf4aPxMUq9`M-4ZIX+ z%Emu>2a;b4`<%0oav2x3a2Kb}R4&Z^_{g=;bZlX2V^iBY=T?WGx0SNvFtgJe#O-X%lnee9k6)wF&!sfZcXIh^=hgIatBv7cCTL8zED|aR3T#w4bT7 z93l~LoPSba{(z51;)jtR-ny=v%s52P{gxccpI%WBmdLsh&EpJC<6j79gRv?3?s5?@ zvfy+n%#xI>*;O~D^n*sf#Wqf477_45$~3==mTEK{lpmuH8S#8=TK8qr;a%H$yw4~n zE*NoJC=&RQ!v3#~)*w3aP`4k$!7eS0=>Dbf;L&VnF%!d4=qIOh#HM6Iz-v7?KZhe< zLR3o1m(iWm$$Oo zCa0k;(kQPn?|T7rURfS6r2$&qiP-)WTXBa3Nl7W7xBX6{O*XH0@^)U`7Y24;9xc#m zr?9_N!&Yv` zxcI#wI7vZacsLM;CgZ2 zp|%>V%HoaAy88L4yNLNPm$R6!zuV?k_NwE&am(4vvgFU;U#GCM+C z0F%=!$9R@c$(E>!(1=9&PSznf{)<5nK73-Zye`2a`bC48LnirJ8V{SQ^t6sn_`=G{ z5QD>PMa8h)%Yt?+o`-+s#N&O;y>GLxvtR@UEmy`7+RdZP z(Z$@4J_9K>)^GGaEhcpR`d(|%M#C4uXMhH7-DPk#u$y0@L=PcwM<5J4{4xO}chpE| zER)aYH&>iF5Fw%za4-diKLE$%6%go6dt(3uoPgBR%C%_Vb2_xgb(1@609zsr=IaR1 zkmEMg_E{54ST9Pno2kcoulx&Gy3fQQ;y!e)_q|$G#_fXxP1Wvzn`vcTx(7IJ6Yq;O zIBM-@1Zd_1KgqBv9zG9&63N=W1}8Cs>^%U1eRiUCf675AI~!6W_&4dtzi!$|iSZtTaGoBvT7|DrLjm(kQgQiYcdF&n>xFq;(B8(wUB_PM$k zJqPO5@(Y1UVo&>RHh<&7pVYTlyIiL zrvbd$e!pa7X|nZJ&W(+Y!{zquCEu$W&m;XoafYG(2_tM#?Q02e@(-tFUvEEuSt8p7 z-Wr|++YktfvMfjM$ee&{VPq1s>N~vdD60y2i9E$_l^XG21Hr$&)BB=1S;2|O7=GB>Qf4XIMseH!?APTv}yq8us1vGL|`us(6%B&yXSg?mE1^BGrHl{HUZW9|b2kJ`f;ors=G4G_6>m12-_qL@b|)xH`ve05m*7W5TYne@hG~j;BX<)U>jl^KlvK-?E2+juj_dmGY-hH$Lp@1_;C+*suEV4Iibi7T+;i zE)8pKY}9QH{%kq$(O<&rkyy}a@vE^j;5v0z8ZM*Vc3ktBc1zX+AtK8lsex)8~Qo{Wkf{~bLsr_OV!)Gk!xthE}UKmwdS zJwcvdHx~y_^IKgGv)MFlucL|mr~?R!d-z%d@kMQf>tVCLr9u)qfi0m~k||4M0%Qif z;HgmVKwVuzi;2=MX_&lwgR4pv`276@c)UOLtf2sZFQY;KO_F9)Z*e6)gKDI`2b_EJ zW)k=2=B8|hw1G+C>w7_Z`9d0o;?Is-8Dsir_hr%@s|iICarS29qeN7(zFMfYSN&EUcVGGinq2g%eL7&>e>@v8iV!J%FSoaatrVZkXcC>Puk8RU17X zS^0@3;4LqBu1>=0S3ksTiMiMDWvfce)alB{xae1($hhtg?KDaMis6aoJ*SIE>qZ_O z8F2+HK4Y)7XHLss;2sz74_#rnVyFEKF>!Hq-UxIc9M-SJ)=z5+7?#|V`!1a6<^cf` z(OQT;Z_&;>V>*D;XJ_5$|YP4*& z#KpTG$N#ONow%X^H#lC_ErM2mCi(p}BTit;(sr25Egym-UaLY4=6HbjfzBh<(O_<5 zr^S04=e6pW)%L69jl;|{ApQ$*vAKF{yn`9%uZEmwc@Kzcfi+do)*k2smq*zKu;r$Em2v-LW+w#yw5pqIPCG>} z#@*oNR)ELYcBh|s8#eJh?Itc=OpuP$;O{&PuZvqmC7KK!8-eiqw-zo^{qNK=?v>6o9xQfq2tBqnfDT&PM5=}EDk1rJ}=esJAsb%Nb1`}Sy~$y3icHrH}jn+wAz{HT|7we1eP#~kEGzTo?jCS$)Y=_L~ zE_FSPUlU|pL+r~64u8&<>nMafNO?MR*yOUwDCwDS>8lLe`@>(aY|Ix&Qx~{i>}!3C z6>%*p6QrCU%7i#AWtC`pM(7jtv;jP!h{s`;TXjY4)dc=|HFd9tQCr(vAkIKUB5q8h zgE^Wb+9%j?_C`Tb(R)2o_Hdyoe!P|-MMLbWlJxrM@lva#qynv@U@GbSd=qnn#NroO zJoWO><7MdM>y#lw-z(zB{q#p%YY8#M!d%aP7QQ4Squ4;;dT8bLRbZS-_6$+)n{}a* zfVaL-^YZL9IA|j6MLB|i?H*M(t?%E>#X0Wxsc3X2X|K!&ibapxW%j-~T}aGA_s6-1 zv4>6>o zUx1*q`}M>#K=T3_JirDA2zXx*>T}@!cEKE}@2$S~e;aim9%w4IHLwmsY&_>GAqcNJ00zTP z86a0GKEUsATzFc%umP#%s$^kkl&ekra^;s^ZnnK0!*%pKj9&V91my8|Yg)6vMsrG_ z1mm5tIUUBsd)GkUB$G>iL6vH7YjC9Np#T9=70{ffp?{l%CJS*h-}vp2B#=#=^bvT% z#{Nf^9artg>J?LDfPN%;7Z7!O+?fY3u>JQt3JOX_=?!xhK*1K-4hnW&s|1{u20%>u zSif3CB_#muyd~SQ5fbh2mkrE zhEp|xuwFNq44xIwU5{nF0Ox)a!irBWoJg*2{B5<8YSRu6@diq=GPB)j{YwEKYVd+M zIs=;ewv_Adl5;@#9J$eN+G2|UPm&?Gegn?RhM?ma{4nVrkBrP{d=$emy0j#~bNSo! zFuJl8`A#yf4rjO^y2h~~9p-QQDMh*MLBu5R#8SU@J-;u{qHDR`2N|k={z`Ia(jk^M zh?}4Y{U4^Bp0wdFKHW}RO6j7%F1yrZC2D)JuuPEK7cA+C~DGVcam02YIQqXWzwhDTN0 zw+3IT=86qu@>%~I{g}7odrV~s*n@xucrAGio~|~j*1G2|O65OD^<^W5$Xld!=htaQ z7iTWP9Nhtd3;^YOGkPj$V1&la?;jl$)HK)P{`xr{jRk-cDMRAa z@9LSmWH--xRQX%AYu@8@q3HFE>Qfb#feSr9-@v^|NK_x^`y0(WVOAr()i~$z_hSmj z%T6?Iz|O(b^01%ZqFZ=*jLwyuYf%BLFj%+_ zZ_Zquczna2ITmIQJ#d4HcDIzw^7!qiflVtgBE_#mX|=EIVVkn;FC5$OheWZnGi7(J zh21v=LMi8#s*MeFbhQh%IlFLubL2kP2m=*J8n!F^$8iVX9$Nsk7trJp=2q3l#eoPb zA0MCHgM*Em5%Q4Vw~E$U_KML^GQjp--8%cq7@A81*vIK#{C@}gbH6gvGxhe-Wd{>d z=UZnH``-L=wo(buE9R@K_YcL_v+FTq%-IkUGREZody0v9j?U#*NK zzmpgMTo)lA{|gAJ)u+&1yH6_7Yt<*W0x;$VfP5a{(VkyjeT*_k`ykd;l6n23-ds}U zJRfbGM=6y5c3X5eL~fzC{~V05702?+I=sB!Xr3y<5%l)cGiw6*eS*43yuRNg8{#{{!TwD-HL0Xd3aK7A5;AzJDNaInFx21j}f z8*LBapX}9b@I(eh0JK%I1y0Wq@7#eTA&-E7LTxo3uYo*OSaT{(|JK*>uM+(7wYt3^ z+zG3nvssOIO)EFlaqaHGim&{MrGZs5_lM7TUbjb0-pB1%&3@PPz((#YOa+)zo^6jj zDbUZ)@#+8t%JCL&1QQV=hs^9sX0Atj>fJ9q`%m9OIbVWrNm%R9OP;$?|Jy_gBbev= zk94!|kl?h2%B6)aAH4mPF=&4VH-?L2^kDCWm{Zp@~qMYv?k2ov|KsxhFI0Eh)_(-vPm*9VX2m4 zqR$E@rLe*o6O?4vo6$E1hivSuwvULT`!$Ii4Q4Y)iokM&Fm46 z_=h8^>-z@Qf^`C=sXzGxoxWtgNjv+n{D9 zoZ_PVZ4YxJ*g73zZ5x?+dmTeSxZ){c(WCf2!dg|8QQAI`STG=uu|SQRAP4>#jgB!a zUyBt7mFP8P0Iw){`hCe)l~frv4d{4eV|!+ z5rR?wO+n~0Wkiu?d4e2xM;4}0zAE%$<^In{ARun#=9W|)aDM>kEQSyMd`OSLD-96$pqhN#quNkMjzZ<>~Ob_Rle*Z9-tpf)3a(2PlS6;DcBQT}v*_T}{+ZqxmjQ`&SHE3IyVd zh({Da>LsoR-q~r1U)G*_C-7_mZyT*ss&`lhsnk;6XTe$Wr|ggcX0(yw!787xMjJ_) zz}hR^w~OP}n2ht?kcR31@$}XKQEuJ)w?T;@ozmSc9n#$h(heaa4bmmuAt@jr-7Q_x z%?OAzLw9%c+jE}p`~L4aIy3jZ_gdHbT-Wk8OZ^FuYKz;7YKpLI6vg)_Lp{}BaKEn$ z5;3+Ve|2M5o_gxA2P;92dubIsyQtQE9s%2p}?r zqR}=kw47B=TiI%&U;tL-k9~swqF^iobjb}_pEX%9!vzQE(Q*j6iH20>y{UenfK!x0vSHaRx+iur4sc zhorEJm&*x@L@lJ{DfTB^zn*g6Evt9GUQcfHIA_YYblmzw>9RN70XU;K1Ch?plPpue zM@Q)oV6m`ZYFhzIg7s8STpWXf95(sX0HxAvCOlziPP=bx{o)PTRQUqHXM?+A;SG-M z!Z5IX&43{Q7=27&JL&Dk5XU3)Opu=SaLxFpX~(U=oc; z`8KN|jCm5@K2KWgUlA|fE}`+2D_4D-qnkGfqd_0=6uELp{IQ>HlIcVMb=bHgx)6K7 zO?;r_z~x7B!2Hn61}@rM2zLI9Z#*bnfnIG=xO`#M@e>m5BSig)2O%<;#Yn~axdmCY3~q|Gi4TSpMMnpg1CwSW}nS;S1`9VnHs$rL(xh-?^jyVFr_}RFw_HWy@=G$Neev8w zLBPv5iT`^S4{6-=1|VjKM@b)R7r9|Kwdj|J*Y-bs*NoS1nxZ`ZPuP1J2x(x8UNw&9 zW;bENt>X}vQ=$YmXg$(eme^Uo?+8z|v%W6CFoJ}WRWsJ|l8sj2+Ty=5d7v#_&2NhK z<-~|80OzwB!;(ivxnxq4pRxiV2!3U3F5^YS(sV;YEmPM#J!@%m7FVV(+xkGg%sfQB_cLtukF z`H82}x&stA{i({UJY96xEzh_7n9Th9*THPR!+`|!<6kByI8pq{(7V6GGek(uTU$y0 z#&z`YM-wm?)cCQsDo>~kc4`dC-@4beHhGBM)9Q!%WLnCZ;0=v%oxAsNEPft5Q|N5j z^Eq_r&EChey-ilk!}h$`gMhmV=!wx}0-bYq?IXzKUcZ5S_5abOp!x3T5C?t0C*HJf z2c?>szj-XtUAqmWujl4%rh58zSeM2Fjz6DgvpSM;J7lv2D- zNA|%mxc!%{$#NeOa_^&EW1C2Fb0+Hlx`n$pk_JMYSb=5tT#-`(7i(f~a=Y;)k{KvC z(DX}62J`=L%L&4|D|q|Y6%vB!zno3fTEcxYI&BYgKvcuI!U71Y*F{a{`ory^g}vJ5 zBXN-b1!ld!O1w63E`Kq!rYIfVEna2lsI%G25Jiz(6!T~??P&lf+_?u%7sq?>bi+UD zpRB%LTn4{*wt1D~c78u{<%o0C6cgU zNX|isZnu2I)%A$t@h!*Msv_ho7eQDvmteOZ6Jnj8)-&1<_HLp3mv*b2lZyPoCBB)2 z6w1VtNcn0c?x)IR0(Y1$i=8|?$9Qsa{1Smr>0`)g!@PK{XLGG8R;4U9XI(<}1fv7| ze&hD8aAa$tmG0VH3_=jPLk16}F&q_53x+`o`Wm zd|{lw7k)v8e*)b?4vl;#X#b&nZO7;jYpM@{hhCdPz`;=sv~bXALP1BM>gy{Oy~-gXG6L%5 zt!;;yN(goI>N9^0d3`cEdU_$>%xf<{Ri6`062UV<3uwlE?2*`Ye8p*P#r+GRI?>6aYMy%L#Obq)FigsPfI!%B;q-N%H$tHo z23KCNrI{h>E*!DdSEPH|Dz5+W@y9x(BiE*L<|Ji`6JIbX+s%k&WWQPC2(FpXRVm@g z#4V+=HA+0SPR`X^FRNc%5rSQ_0mY0G7yT8PaDTk2SKR(wz2?sT$WFTHopwaS7^qT~ zJ&Y_+7^10GK5`EUj6jlyD3&+!6n|X(t9Ju6J-_b(6}RreXV0ZgcsC8M@O)uGR0oOi z&yYk%8gSqm7BFrR@*$hZ8%?BYyit^Qo^z!%t_~zQ<5~m-a&Uu@1BsVdn~ia; zmH(W>2c(&lukB0W$DgmeU{n5u-WybNKFsaIo|yBKqx>u)Mw;%I3VRGSS}Y?xwui`1 z_>xUMJcua~fOuebxY#-jrU0N|S#;kdg^TymBm$lA2L;{*0(}dBneagpTs?xPVB}j` ze5iZRvSNOS2jJI&X&z;`^eTxV^51yo;d&EZY`Cu{>hL@7;D(Tkbx%OOQkTDpZfxYo zGJPCMVl`-Y2m|dl2QRNetI;NyzySUeLWl$yQ6Rvny{grV0_XObflao0OuN8rxKFvA z_mt8972L)mf#hpp{`-(={?fY*pTuCOpd8Cwze-NCqDr1(AO|OUx)ueCpUo~$z%{_D zGrYn8i5V47uWB;Ko91e}F_C$V0G}e8d6D4t0VVKf0#zn-)!jD49{A*5|NZk#r7oU2 zQ)fxf!0k~I{yhNh0saKH9cr?j!wW$m@ppjxbEeL-UPU_;C+>3;2sT=Gi5yfIpm4*k@(_IzCT z-mTwi(@`Y+xz0|t>6lKZ!y|==!veLQG7=&Q@!CRi3o5P$TDg|*u|9| zX`WjUBGF`#y)AS9M&@>OYE-eZY$=20Vd=TxS8P@ z4SU=nX8vhk7{bI+vk97physp zDKiX}ai_It>m35 z=2qxRNQWt3v7PT=OrB+;nb~9i*^5bSTA}36DLX&%9rA^rsl&ae06|zfS+@dK*+?3$ zNl{};1d#m!w|(4Vkajze085QLUhGi^GWmx&UJT)*C)bXML_yQ#ins`=vBWY3T<;fM zirdScltdE)7P}w#uE4Z!rcQ^nx|N4sXuxZy7d!LH7^&y|LLTp(QGI*7s~atrk#b6V zN%%e162FRUnH`KboGNvM?g`@DwwY)BeSf~COB=jI1sc5DMv8^o=?I^I_YDtFs3!@LQd4(+T!V7xIT(9`S_Q~=K!FDbDEJtFw}78tfUDs5-eG}? zJqjB?oFrfO^0jrqZz|CLH2Ojhte>bAjDe}x*hEQ~Lz%Ye&CRp?ZHi&(UG>!Tr<{9% z;IDdADF6G|qu_P-vgg58UhaQ6dcKxpdi-taGzJ97lLf3aby%ixCf_-!qSO>H_+B(3 zz2soc3Mm{<*x7r=XKQEynkGA+-Q5-dJEKsWKR(>=&DNxW@en7-Q{a&_`>w`vv4yt8 zPY1lIsc)31iqgHR>3mG>JZ0;jO$kJ#RU zxSe&}ET#Q|HXH6@^YQjJIj(g6ZHC^B%m9-XV#@o%wO_534XZ~#;_B1W8`Ao&Zjbq% z^P~xmj?~!zJu(=ADc$7KY-qSZ*RlU^DDQbv)Ud)EVc}u8;EAIu+yM$`cuNcyJ|Az4 zABDi}HEJPts|y!Wfadw6ts)J5PSUx@q^jnVm6%JBR`z(ZdeQSxWQ8YNt^X8uUnuIF!n`3wt_>mF$!CPo zmrn|s^`8nS{4H=eO+@u6>uq!@_)omNT)S0LQK8Dacq3N%`1Ils1_dwLFEIi2TwOun zYF@j&`7}C8b@$b)5iLI~g%SA22tO7P1&iV_t!m34*(eXshL<;ary47SaZTC;IyWLa zHOe~WB}&j%uW}n*JHN&UiRXYF>VQp*vYJTe^w0HJV@7@RtBk4IM?aUq$>7aS9_ac1uh) za!cWZdBra;`y9Y(;*rTcz5)*sjePfACl5Gk!5M{5>;z&~GX9tUUbO~l-ak>(eu_DFylDnPgd3xc|AlpReg?(69?2& zj__QF9F-}{kVLAeO4eI%ND}<-hP#v^2-vZEu^L;t-d4qMpy`TL5lQm@v^MBl-AODd zg|(y<5-&C4*8zfB)G}MYSZRm?O>#8DEgAlw!^cP5+yUmg;7oMp3b{O(gSpdMCYY_` zBIR3t5a5+BiB6lKrQ#ZUffGzSOWMpY19@Tkr{{~}H@dN%ow7eZQ|o-6`o6NBusKQl zcMndRR5|k7_Aovq&eSl!sBVbZe2?O%FfLR)_GIwPR;M&*XX~dtNqj#_*PC;zHweXA z`EQKZAHW!I&i5AjL-0)qg2qdw$-ceeXZO?rO0ZD=>kWCbhDTAyd<+E+=XGMAH!EWn zK7?JV6w$&h2Covk-E3cIgo-f2{x zLbt=Ac^`Bk$hkw&$$#IsRUpn1l&KMFKnNwsxr0?EII0o#<^Te$sm)|qWv^I+Xf#Kh zby$D}k6ydifWs0)t;Ny^qkWux`&A4ghZ0ukSiQZm&7E_ zMt06wKCu%+k^?Q9ro)ls-Wol?qb6*>iARssddeKu<~>mP7!SEmZ(C4yQ`0?)4 zda)%1JdpMP5&)pELY~HULTp3%T$S5d^xlW2f1oK-Y5U57;4~tCGv#*o7xqB;O1L_V zpzRj*FvBgT1SSl_CCAjL6n@d5@DTO7z2T|-UCZr zdRHw88bqvYJg9(Pb>YsOe$#tvI?oPYMyCC16^NEv_`muIm#4z;Ryyx*jY1wNULVg$ z7uQ&q?Fd7*7L%Xa-;#IZ3;=Rp!i{*sV$j@C1OQTaBM10a(5V7S$9?Iy5BykVGi)2S zyZ>i*43vP=t(=&Z5XvZ-05G^3FP;qbzHb0v?2*aTVF>`&@ zEP%Nk?Fc}Ij~(Fyf!Cz8DJjj|+xm`7ZssE=CQmyv%RamD1s&#~jV`#P;~~s6NG5*S zv`DJ;SU8Hq4w*|mPm0|)|6GzlN_D{hD&MjiOvcI$Jrf!JLa6p(wfCFAyO^z8roo_4 zNeZX%0GkCudSch5UQ%LedseDeunw2Xcuoe1U$o2(AbqDJyt&EPG%vG>xbEAZ8Y4TB zAk>quXSw>`{1|gkGnBE777kW%EpkbTN&RHx8KkC_Aj>1!C5&VJinzUXdL^r z<+U!C`HoXrb83*eOi3u(NQqq7E%vzT+`w~1u%g{35T`Ht)T;f$YHz+S08G6SpxzfD zVWycWjh3B-(phmJ5-eMbc@2C(2J<*MITPtPrg0w9(Cn>BrGT!n;o(Trbhq+9BVq^t zyUl!!yUQ?6iqPm$Me=mwk{+!IKOPLwjA1EiWImh;$AGb4JOXsc6a(LRuse|%{xI_` z3dZ4CC;?;!U-UEuS_#rlKo%1xT0rgYzvG2NpJaHg5C4aWVC+opCbM2&&!YkRL@v zy`u2CoR}%aOcWQ2FHk7eE-5xjdOKOYy_qv%gHtu*yp>!R%vK+pb+imT=jy_K?ekCP z4+O-JZA8_>Amy{2m8@|*J%cmdmi}QQ&4=FoDNY14uJ*4drtBPV?xay&g3iZHn}YP=d6!1nImKC@#h=Jk_?NqV(9g}6D;u}J zL{YfjHF#@CZhi>GyHzbxDzhmFDfMFAr|cPh7`-^PA%i%`Ru>;=JUG-7w#G=<9==h! zQV*-!bWd;k1o{YI-2-GS{Fs2F$9#)!0l?~ZeE4|ZZUNeTc#i}oP~#I5l3aZ_SpN3Hu$W$@GxuTq2KLH zwKGn+6?Wd!Hsd}X1HihRp6d1p;s@JvC?gN?a0dFxD|p-POlee{OH;eAHX5{@arGE- zFQ^v4L%%_u){n8`HlbLWF)605L&h1J7oAGWHG4*nme5ow9l_)H^0>X zjr#xGvkq1s;Q+2V$`QNC5kC7P39?e+^BL8#T|+No9bUO?S$wnUyGFQOk9sp%kz6Vq5r<_gNKJ-h0l2j!Wd-Heb*C+xc_XYe{YZqQ3x5fmG-`8RE`ZAQ;(F^ zKB`Jcpp}=vM7V0JxQA-62}v)CUI<3Sp%_53jVdH%MeZjUwy$b1B(#}XUJV7Ws+Gjg z;03tsKQ4y#7YnV?RNQ$srD=Gvo7}47@U~?F*u7d%bmgLIsflf_&c<~2Uzyjxhl#E2 zt3C&Qw<8MJ^+g0ovT|DPL@zhEAvN;2ZnmCn@dGMb<>7BK85ty$9DH~Tmxt#sZ^h|Z zg<$zql>K@Y)4)~CzGEmaaa1O{{}nlLRDF!LOw&5W|Ea_?z72JY(1NUXG2k?a=b2`E zcUL1*{0UJs7-H6#jg%Y5FOQ-rg0L>Y7QKrV^c0SAsf&y6Xdl zRZ>&5MmUh6D#2`p%=ga0WpCl7Wq711NEY;v8*&~Xh@e1lz?@IoZJtHGT?oy=^sVdO zh^7%qdv#k#v!nvmSPUR6u$*o9Ze; z48?W$v4RpWMTd~}b~e1?Vfhpgkj?W=Z=^XhO<|H4;zde4hJD++6LbCJk{SJ4?Rxqc zdaUo}@)AC<=phN3ljgse`Kg_y_M6A~pEEXSNKJq9ys+g>n=P3u-@*6gBo>{8cJ}-8 zAw&>$*u1VR5@frGZfY548q+mnXk0lD!|VIjKuy`EIkYes7c2B_p}DB{QX@fU5!QMU zL%xHko0S`r$RAzA=j>_jNlp%a>st)6CE!zQxjPwx4??FF-O>+Rof69Qd4Wdb9esa$ zsa`RalAcLj$AUoTNG*<<6|a*JmS}FFFB7i88rL9=oziX+*vQV;nS9|Hv?x}I zbZ|J!{6ClTRgDB;@LW8Fn}CW$Zn$_ZA@<<9BYnS^Ja**XFDi*mhku{nlp8kp>f4bn zNAWFw`0N-5ug;eOkimnGj7%(AAKxDzqVylLrQ%8EbHUy6V)v z_f{(D?kh8B+jY{_V7>Ro+M|UPC<=F$6tyWrpM6tUX#oeE0Ot2#}ZX{ zcOHye+;;aPq{MOVr1N;AO{GY13heK$aM!u`wY!1FND*z1>T#s55LUFdvMTo?Y0Q#c zKVRizMQdwC4#Rl8yk==BPj)L|ti~Mkng3gQEClhN#+jBb)+ppo+o#?ScgRA)33~Gv z%rTeEjJ=Ai_{{gKmxFvp3T%f`+B$lMK5G76?9$h^pE3nLc?Qi@S?61F2?;5}qbPu8 z|9S@8AK-0nx!EacxtO(Txmr;NN?d$AAAH;kprETZRcx!;EAS^l^r!*7YSH_pn-TqA zdS&K^qyYiuNH-wna@F{Bwr@< z!3)9U7C1=^x0&}47_Y%ytbh~)j=AMN^3CHuatja=HeEL|!aN01o12P8M*!(P5=5-< zb=L#9X(hmy3~26V_x1I9x7)HqkjZo^jC70SzLgaM`aaPP@T+qu*WhewvEYZTHk|rR zi5eCsjK>HFD+$-zzjimcdD_N<^qENfPLqZeR^i_g=j8Kux8m%!oQAoir?pDK4`oOL z*%n%g$83~2EO#^*6qtZLF;L_AD0wF48W`je`AJ5~;Va}ds8ui(Zf=|ct5n+(3VhAJ zFCRN2lpz_JqYzoFvugOqMFa{({QZpar#qQm$&8f9v6 zlUza9M%~VD?2cuR(I4Hvt@I4K2qsS0Kpj%^Bcq~#X$**HdS&@ACnV%+_!k1uSb@{U zW;hmi*Y2|(A$+xTFATU25DKcIYA5#mzH1GY7Hzpw&E~5dzwa^X=_Fkk7iG}(=TKdY z?UDxTCOhVPZxJO`*viOMjKf~K>vj7>jF>9GAp-87yCJ@&M3l$IxqV^z=|c)KdA)BxXaiCuO5Bh zFT+b>gr^@#c6YX$b2Un3Sdx9%A0un5bu=TBeXk;7^4?c?DNCS;#MVpU87Tx$hOT5m;DtY2Jr4kiB_BF~|!;yG;q&;riikQs!PlF*_7h>lAjfKOOo_|(2W3vf-AcUXe zGD#oFFVpWvZ)MAv+8&=E|5;fdx8K0I|_%iB=*5B(-e*aNNUK> zZ^+HHKWs~=liM{pmmA`UaC1+n%#K~84yPHh;Lo(UbK~St3*T(zwA^;wg2N%=F68lu zoRE~%{Lv42rUCMDm(PYKli33AgcjI-1-V~oDEuqkE|@9i0k4G4%DXPA4DJk+s z9?Nq-gnUzdZ|xp+08BjGagPk=yaK!fX6rs~J%?5k5O^0RXuUu{>ck`rKDKT(^8Hu2 z>Py%wdzx5vzo57Mzgp489M1m02WjTFgJ_qb$G?sG2$lpIE1yX2`^id|Dw$J3g zXEP;20`f7P@%5k%ztaX<#wI5xXGeyJr`z2CJ#aU_lpC0zCwXGaCQBGh>OVe;Qg(Je zX8qUw5~Ql`)<3=mt|&7{$LNfVXF@LfD?k-D14?eB&AitrWR5%SqKOY z2>E`NDY*<9DO4;@RSrsv_s`E%5DAKLbn2Qm-PYIBTa!n#$qP(S*KV( zsd*aV%e@lq13C6~TN3*$a(*cpewfcw-ySoI$S1MIVn$g>f}Chh`Ep{oJoZrNBO*#dHi$g$E?T>39Te9ez8AJ#Iesb_57r&tr(dZ#XQ}T%~VC z2_?yGIprp-2t9ZvY6gZ-KO*ZCemYnQpE(Y=$8fK z?3*!Hk`1S5QT3%*Gc^QacJVE1i5tpa=9_%{9RASp;)$r+p~%Bk%;R@z*+np?g;yEC z#_fJGKwsOFWsohvEtxa+6O2%s%In^AGp;KH@mnQ23dewk_NdSIVf-+iv%VVE;0`bzgo&W@%8)3r*E zWKLtD3lL?-E8SL^Y|etl;y~-(cBQX33)4uH{fw z1ujz4Mfm^Dl!M=)F?JZbnIaiSUI`X@1Y#Cuk|37q=)r8*OL2ikU4WFN4J&&`>RMiTAC#JMuP*~ zFov1(mqz8|GU~q~2{%u#Uva9eh2N}377o!gZvI)%B;zzv_;xt|i9t)qM;W;?Yud_Ry1)H3&z^#@hLQIwAJg5G&Y_9t~ia1SHMFn}DMt(s- z5$_IwP)>%qq4q~h;)?&PC?AJ!7u!4gua}!=7&DEZOaI33UdB@q%!55ep0cC&Hez(v*WC2F6Vs|?_SM`r`6*aaChbMnERjcfvwjf{m zSSemFC%jS#Aop0o;;oCn2Vc`vb^h+=F<8-h&?96R|8rBF((>?QM)Nv+e}9kn|K9pB z8K;Z>iC`t9yaZz|wC8|4O`$MXV9{h5`i(&i$g3kObUF|o>Sm3W1zOWP^S1NOQ_$ayI2R@^qXU7NZW#r0LmEA0yHnRIzBj7y8M0s( ze>g*u;(zUW3i%Bsn3n`hO$1oiemDMph#T@N=a=?7h2$%J9nEhb^ZL>kf9)y*k&HZ^ zpEXKTe}v6}or)^yJ*zGCq;_N4ZWoNi=a5c{%9}&;BU9fK#mpXwW?7=;x$HSrhVGYZT1z4K{1v=^V7N+7bwF z+f+&V_%p8L1bSCY*+>p#!jrw*$8YE4pI$%U&6+p%u|PSEuIqoz>ZW+6lQvHLoWJCL zd$}ncXPyMC1a3BBbr+q@;H9ND&kpel0vb<4`4E^xOXg5pFMc8495q~8Pc~ZZ(zHN% zwzca7?=}FiO)Za|dah@I(&&9RQ>QGt>2i`-4~$2!TTkDZ5Hi7DMfTQiAQ2xPk6tc< zXhyQ-FXW^**J9<`e7VL;o=Opw*?-q=uJnitw(93k($`}@+$FB%khAx!a?^(OU zcl#6-SPopS9dPSC4W3V&Q^-$yK6>LuAeB>EzLO+TjQ#L|DU?c{quX^c{0=MLMt2wFIoU*@jq3$7%p>6#tEmd=yj+8FOxdUBGH(IQCV>K~ zPY$#WQ&r*7e}+Q*fFo$XoNI?3`kY&N9d^rS_}o~!9Lz>Tgm~`hKKsOh1wKlqa${J* z(E*m`FFSIhQ;^!@dTTd}JN7~Z!0I9uU%tgM_@1_v3d->y5WdMV&9=IvQ@Yosl;3ne zfNPl)QB=cuiX*9%-X6Kxz!UIQ?2g@drO{4Q6}JZ-_U_{*rYd?(1L82L&?Gm?4YGjq zj{zS*4B1*mmB5$E915J-b9Idl`^4;RXV~oRcU1+ydCX`@>|iA&C3xc5XlB!&nR1)j(K_e2f$P)FnM!9?ikf-r zqCSSa(J>eMSq8dY-#d__D{DId;_6{!47%iP-( zy)44|cgHb~GG?{@(RC)J+BZcy+ETs+?oA15nw@c$8gb3nq z^E94j+3-f)JYy1y2J5><^~8721px+HO8VO3@j1rvyc5&`jK14W67AHAgrV?>z36$7 zDzKgl&g=p_iv=Hk^J;)r`sPSDgaQRT5%AIOw+?k9k8N5b_jPGDqn3Waq6Mq^-b|dG zZCx(xRp0_!avitiR*wlupPPFOgHq;&_v1D{mtNypx;CV+gzP^W@$QXZs;?M1J(ytG z3fuN?5sdJ3a#7qdc$TfiV5G;TJ0k;gHaas=u* zrrVMq@)=J9`MBmbHOjNWM5Anm&daXSLTXr%y>cAN1n+?Yv38Bxy!_<-1Pw?u=&HD zX%ZG{tqAg#$;8Kl3D9-{Ig~2`hvw#Cg5`5bd|w)k$9L|bd^`!4{zwR6ZVGz#KBq0t zjhAQz>}O3@35ZqL8sb1Zf06;YE5cljQ8+mG#La=w8z&<~smr2{MNVmcO+8DTFxXN{ z>d0(I-K>~1bHL+uqn@xFqjz|>DIT4dklte)M8Yv24OXF25N{Xle=Nm1l#>eUFy z5CkF9^KqjSV1D>5@{!P*@sYuNG5Ve*d=M&?I0zZ z`CO6%Oh6OpK$6yuk76I@EdB_`hlvZrNSo>5y4%a6C_A4hJFiRq>R}!c6~6boEyo-Bfsp>CCAj0x>!Bvo9Bc&x!7whf1#kOI)=%C28UAWc zrBoC3ajN55z7fi#2f$;UTbWF#FJ|Ha+weyD&RMJ0T8v`kq4cL&Ns08$rtC(Q1xgE- zH_~pCH5ivigub~6PZ{5c*IR?3=&QFyS~N$mfp?%0Bw6(qX%>8`t^Z55%A-!o+|7lZ zp-Z2XuYr;!pBw!{Uk@ie@vB)8?#+Adq(en~O-8|((*h363-#!MX7oZL#g)^u-J6cg ziPpQ{3Pmco^Mk9UHt((*ig01j>{IA-%T$*Kq-=(4?Gg}PlcyoS`NHBQgXAZ3Fp&I7 z{G!g11DK)JEH|f1wU~Ypi-Of_{yG%Vram_XzNv6v5O&=PTXprlM2v3tjFTl39nK%o z*KKxTEgF}W*>5>=k!i-hDee9HSBswB=RUYr_;G*J?cv()_+S8M-uLm|>n2`x#huK( z;_VOGJCK%JWdpWAwrmQjyh@NvC^oj{O`GWGIb7#FmA(D9zx8V4zfSKCPXdIU5Lv6H zP8R5o%yMhU?2_m(lWNcbrEaYJkHP!jBb#9S**f#Vegxs=Y0cfJ-J>Yf`&Ov?n@QG- z=+$pB&mK2OT32@)x%Bhmp7$~OhkrtPTE4roj!KHSJ)d$4pVt597Z-1-s$CU6?#6+a zd>_qLIY4~UPb{1lh#&D|XlO?YgDmA^IW6O`>9L~Mmm8#G$(X*%m^R@&YJ)YKs}?YV zh#qq@%SrD05;y+#OeM%m=RO$$+R5sP$`an8FkVaj41_WD?}y)fVs(}5>OX%;9ZG8J zom`o=wJXuD^E)u_X&AZy>vKJ0spsnCS5Ss(<@7~y()hTlT_U#!1jWaH8aNiQ@oY0+ zn#>}OX0-LDvA1?DtBQgRKEGAGQM^cSen>>~ps6K2*BG1P>rZVnQlVp2hz^5=%LU0N zFzqRXU2Dr(HKEo%nZW)a+n^$sRa!Wi+RfGJj0%D{-ny${90!FrZWGDyMt%+F6r+>3 zVqQ#F{%4tL#fQi?!>91nF{PM2ac4e20~L*9T`E+YfWOq>e=hKDnxv#*(X3Y7afg;1jTtM@_>l#Z7W&I#qv}zMQy-e)8L)qxy`f z__RQ54X#1~LlhF+J^kD7x%GTg5WtQ)->&ebfu(L=Bu)6irp4^sa49O`0e|wPM%qD_ zZ=adp@{@LkWo=2I3HsMqNJoQE;CaHqX zd3y{C<5MR@`(;PmV%L0bW{=|Vyp=_tTbuG9%^j;TVxwIcViJu8G88CXp)OewrZexS zrNm$6r9S#zJP3_O?~0xVwim37q&JU6k;q|EJf#YwdHWTC`ZrBjf|(+hNL_DDwadR6 zW~hb5g`p=b=Dx3a@iP5>_*3t0mAQP98M7L0!1sv zPXA4z;6m<&%6HM~T%z($WK#fo=q_gwC&$=s+9<-1<@0Ap=rlabB2y#k%$BP}b<{}9 zVvdC)!=`;wdG?~y3$nETr-lPP(V!d)>dFYh>WN|p%qkW0Jg^O^5)q{QFS5gYL zwhsz?KVZJ&RDXvEyL1r7m`DH~vZkh{{>#G(Ro$t#AGi`%x{p`?6BWV40Yqy8+gVvz z6fpk7TWLUX$}lBnH#ZA?^sS*8M$?diOk}X-zm!izs1jn&()T0q9X5_2 z#CnGKAksGAc~l*0^-5w_~NLIDv%(i3;jv8|t`0(b2E)*^P#QY&}zJMF17K z1ovZ$QjyjQ@SeiM>Aa%e2+eK|*5^UQl=|722NNjz)8D zKgY{Ri@Ac?zwLKJ?LQV!YxXs*4wm%iyqdjQ^Mm!)kEB%E%}b7B7J))Rp`++m)N$ikN3&T5rPTm0uI4MpL~LX8&D0 zt;LMzHAQ(Okvf-#1?kZM|kEvfIsf%$F6cEWg*L(m0Dy^xBy4J#oZWO^$U${dbdLDJ#ULyd$nE^<-JNn&r2jh&lpG&-=Ow9gFwrqzsE47VBcx zN&L|Md=VLsp#I~Co`4iQ(|Brwo2AY&%fnZ%#(Y2zjdy{udxR)X(M4o zGMUsS?4|-8mr*H-M9=NJUJ%YZ@!IA%_vRd`riAkc^&M*^*=eFnSqRG!p4P~w2@P=y zQN<6e+&=9O%`&X~fCb1xi3tR6?}fd2r#MOSJwLU)sw_NZ#cxBku|sb(i})K{-V#a$ z4dHYQKauL8dMBsRlfOn+C{!VoCxzvf$-)#y^h<+N&N9IEbmFzpTg;PoliPB_Fj}cZ~7JD{bo}Adu!)to$d$WIiC_e=MPX+Xqge- z&4I6@!Arw;9B8BqfBra^y;3NdWI|#pDra+Pyp zY&HPD=JfI3Rhsx0VCp2xmIknlIF$nMZi9uh^}DHe{(^X)GBW(oyPSyko1&eGIRtOG zCFp#7^3kfzK7U{_+26|@>eCWXMUL!K(3Np#>5C|q6?CO#qrySa@bCw3b6Qr1upFZD z8+#Fq2_DXP;zR{M=5jsRsTFff0;s(D>rX$r-bfVhdF`W%UM-i*?ycPzcZNo2)#L|BKn2)i9lxB`8-$jx2ay7w>24 z{uDy18M~De9biAanp)vOC=;-sl%x$m**b$FzVq3Ug)cj-NbxnhwnD3NLO|p&kl4q! z5p4EZ8K|Vx5jA8q(BFMR!F?w7EI%9@&+Fe=8yIpJPFa5boLy29VO8Fk3U)1KxS7xc zW)6SGI>~$}2_9gUr~oeUJ^u1}4m6D-o_tGy$AY0r(uOwB;Us1INZ@f*05JgC1Hyn= zoFZFeuBd&P7PI;<4<;;K{6V>Fzij`%u^QGdo;$cQ^aOmgJt&$f*|SbV?5)}7YeQVW z)W07eU{yKZA{}R*7yoqM$Yc|jAHJ&>*cOn_bX6|ds3rAmWMt&b$pw z8J4=`Oi4%}P^yIbg&s-9B<|(IaDJ4z65c;ek3N`=)cu3h5WPC)8_nJ;;SXpZcHXaZ zedLWop-nXL`&aHxvgjN89QhSw>je_B>>rc4Hs%;zs^o+b4$t#mgzw6PI7A|ih9h)x{7cJxUf+$z?Vv%H^Yu`w&Mt>& zCG73>)`JISPnya6Z_B$)B^MSI7i&YgxBc!yZv%0-df(`33&wXkKLv}Y z8;%3TAQ{7Y`EL<-%jKdjnA>z^Ns^x|SJ@6q%WwV&Qm5e-%wVo6;Vs|I+VvnYGo4Iv zp5T$Ei?8BVMTpba*Ka%-WCs0=066);#sO}4l9U{yrKKfh@{o*lp}3h&;V#nl7hu!_ z8E3y^P(nvXRlrFYp3SfaYtPJ)jR9HepKL$Vrj2C1)>|9fZ#@1OW`gZ(DETgXpE6ID z;ojd^v{_B?o^d%^E79!M+F{Z9wtKd;*R9UmWQ6&^aI5LS|94d;nisP4P2r$G%;ARF&><&^6*3kALz*kaPZGN^pS!DZLCn#($5Eo5}~1C z6edb%f!LgV-}zO(+Puro#x#r?-j?imxW9EjEt_%&?w@TTAt`+;A>edb1}Ccd_0Bra zn>SgzW4Iq!e}bho;D9FF6)!M}%)b!G7|eO!jq-&FQ+QI^g9~F?^_MpiXVb(hnOB2~X%?MQW@~d=kD?26VoL(au zN3Z^s;rnTMe%TC|vZoqlV!X;Y(0B(uqa&+@I_~oayqwJBocek*>~QBnXkt9g*5niW zGJd-+#^vsBjXxP@?C`13)m***={9^z-!}5G=BkanrWtj>3|mt5@2!@T6L+$q3lZ`q z`SNg4Iv`a*u;BI46~Ha$2QoyGYfi>#OJVjzPMag*l!APSK3`Y)b8b@k2AzbS)qn~} zf>MK(#klQ9&`W}oi#fZ~y&C9AP3C>10b3u~)cWA5r>FPH$_k{I0hj&u{ytcaG&VUI zRGtD7IZzoPV98#oL1P?{&J+5;iXYE|YrMXgjHRaCa?|tFq5gG8{tOUqBg6e>eEaOX zC>|8kYwo4Uvlrzk^_!_~pD$2_=RW!!Ti=dA!qUCVjNF&f#$B}o{XFZBp5tz3QL4Qd zQ{Ot=&Z(_UR2qD%$t9OHKDRJZ0~LjWMkg|hn5Vw363jUlRQcp_`9lPE#&0xA1q`S<`Gu+R z+U(yO!hg3@PeKbkjlOMKCz`XKAKayjtZ%CPg^l|CNkRYG8?a(YJ;wgzO0}hppl)H* z_}JmFgu8Fk_T@D;gfMP^Csrx{&tHU$O|`Nnns~-nWP+W3lJpD-6j>=W*e`HtbKh$< zJhmk_o-J_(hlCq6I-p13e=+$km}Q)&R}?E}CP#y98V)1rE4my}q61yjc}g9K705_r z);R$>>@hrhk-+zuVBUQ*-N19dmLc4~eD_za^eZNS+ZHPP&5R$=GSsVcKi%LTydihH zA8}>WVLm%^u5nyf5ZrWmvNX$^n*9}fI|olWMuXPjn+EL>rPS?4{~xER!f^NTKbp-r zDKj5pXL#ZLgvGoU%&x}f_7OKLgywA+PIF*s)yF@LAD&X*-=n;v{U&z=I`4VU!&VYe zukhet8c?47hX8~0X)HN4t-wE~x)R+7sWR};9mfIM8HU0d))9a}CtSpAzNyRB*S|46#Zu&BB%Og9pOf`X)!bR#`9(lFB9 zNQZPvcc*j@0@5YjA}s>a4bmkbb@zPtm+?HJIOpuW)|+;A44KmY4s2k&7#IMnt9YT$^Z$oCCVZ`kp*Mvn|@SJ=(8Su{N|voZcneXA1jxRY#CquL>P0qCM*$0^r< znbqOq>_nji_9YpmGl6jg#7sF4vhXQ(JeoY?%Ctzmesv9t+m|;ZlYM&GjzIOAI%n!V zl!rBSs;1Y)IY5?49od)3s&jez+T-sL4Pv(wbB&nKCVtHC#%$QJzut*I)!=3+!5m02 z1tX0aXG9hK(9XHm4AP!!Vo3=d+Q@78VYD}mT;EXa#Pn7|qL=n5UAac&*qC%{Tbn09 zwgs-c+w|&gW={ z&DwUr>GyD+dp03~R|DcKMILX)>-_F_PJDCK$|b22!i&!n_WQt^muk)dGL4Ip;r7g# znZA4p8Gh$Y4BbY((Z9M5B_LvBHp=IKr#HMuAvg$Dc3J+3e{+j8U|TF<9+@ ziI^b`71i*dWisH(@f7A^PLS=(D+wZ9_%f5e_yQZ$-T;HU&1sVuh1I z-XD+6l`LtnpD`QVvhdZMO%>PI*H64HB`?)5F)Ql(T!pGZULg{L0brGQ&dj46W+M}3 z6==z~u2{5R>e|(c7s9H9c^_XHkz^Bw7AR?HajOS>iPh@19W9B7eNaLX;1 z8;V0ors0wQ$wwH0GRIq`x%Fc{Nu$z+*|KavoSX`hq*1{;Kfqnx`S)3Ar)%O(nqCkD z0T$_?yE{xYvu3QO=rUx+dEF6bZ8J16i1~WB$N;?|)m%z-3YQc^0$eo(mjTV;3O`F* zK2erkz4>f&LF)WM+BGvE8S|@8yJ2jCgu>s`hKDycU-$}Ld&TgnWkLderrQ(9W0)^( zc-0~Z%Bg6)93e+#+79cMqI8UY4##NN0P8h=eG#)+v|e18pT<+FE%_%e}9TG z{m5zx;IdRoV6Qv)eJ*0@jg3O3@dY0VHA1@PVB+UoY{AVOjpvkg%+<2sSfKBqw(re| ztyWViQ1T@zSnPMsb1N!Le_7C_OB(i4QL|h4c?85yz&z>?famYd`fC5hlKxi~L;r&hJ8ZQ*5t?caJfp$Pm2!7FgdsGcVfJhV08zr^*rpJuekXC zBRl)+^WAM_)y|g_-$y}NAjqK0-z(x|{0xKt^(?qCW?A5QJ)*Nt|MqZDC-k@;1&%(P zawafa<$S1WPldaqex`50y;Moo+dncS^0lZjkT^5QI*yZu&G>z;*#$oe_3JvcOBL%C zx3?$o?9V#&;_`iUG(ZQ3=T3lq11NoQ8?8=G3=9n9Q1?kSpLtrunSlceP`=gOLV@#` zF_uCw1V2c?MMtaFj0)TYj|qQcp9zUFA-Jv|gN+spnBpHzDME;IelVJp9BA;fY9HNU z-~L=4<~kM0IVdnZ&&ZDFxQo7zk*O}+=O-AN=Ee^K^X$~hiZWeN-%sK*nrA8U;Z>ik zZLY;-Tl9=ULoyez`}psvA?@WZumw`!T9K9J5Iu`#vPgP*Sg4hzH$C+07YhzZM$wu2 zyyK}}+w^>3PWcChKM|To!QhT{+m=9EQ>L_^iJh>z^xN^|hII9qhjB7j=I-?z}#y zz3j1p3s-v4gSmtq2YJ?wM)XFqph`IB=-R=`YBltwJseb{&-F>%$@R|x`*+k!`{uxL z|A%uTY$*VVfcp~6vmoGK^llArzWrAJ;j;4qnYE31>Y1VQurt`YMxP44+Sn2GPal~* z+R$D3_g?==>EHrLuO38^jQu6x0+PWS4%Uz{H-Ps?bQevjc> z`2qTXdV{3ifk9A1z88#ZpfXK@<`agEl!Hjlj^k<?b*I7*d$H&D6gb%m(i7Cs(`*F+t=a(3Jh~c0TnPQ$H4$)Ibu)H?A2aB{Y%J+uPIV zwDi6Z6Y7t4(p|b}(+CJ0Pw=8#Bs1`Reqj<5ps5w??yyUeyr5SiE3K|ZpT#{9LWL63 z63XLfbWc3RkWyn#769+SOFjqbnZgs?r3vxxZ})ZIlvK={D{^;X1{vY7^Wqd%8OA&l zK;!-uDI+@C-Gk~HFpTILrsq_Q8H}lj<=q>&Z;@a@sMh4ecu4$<_rHQO?V-d~8 zQlA4m-UiLHxuUjHE`*$&1SK9xoN{7M)P+U~-i7bopB&DPyk!`5^Ip)U)W%h4ahtnf zkgC;$X*sLX8{SP-ep&b$v=;bIyTydV`|4=xBp+|C(?9&!|MB*}Y0Igf*lnay2dAOL zI*D_;!GZ)0Oa*|hKd1LUqXz*4-f+_wJiq|@nY=k_@Pmc53~NGT;rWVC0LENpk76{%JP2TjkUdfp+*fn+Doy; z>@2=U+^+p`r{h6dxs{J)D1{`qCJK2T>#l<1=#bEUGsEXNdt)ZL# zvd;^!JTL%{TBs7e{=4{PVs1`WLic599Qj6hY0f(Ol;$iMY>TkE z;~&$kVN*f{pF=ovcyfGjxlD*khjN3?>l7tJd|jbw?#lB*%R$btLJ?2t=Lgt{^wIyG zxMh}KXW$`>v9aELA%F9SUP4h~62+h&^12A5*AJc&K=QS4Wa$-O5UQT4%$yBvxhhO| z)fNWo7HiQ8m*T$0A%I05w_3F#213BRgKoX-xyr^=g-vbeOD18EHC2UZN+9!bwlNBMqyo*+&`7Oi$PQLFE}!iV5&h>A6ly zkqP?*FSWV5T5GXmbP_9Iet?vmo5?u8;1cUazuQCbk?*uzihvC-J3AYYV}|BOi!E?`V2BP>`AJ7XO`Kf?No=~E-T#J{h@@&7H8Hp`9OoEW`>5#nyV zds}IfWU>R>9G8Lw8_@; zq2RR#r&*EKYohoc+hrQquA|v6i7n=MU3T10H`=Rw`Y9my*4_+a^^tjzN()@w07ZZEGf=aUJ)Dbi1FA9$Vb z=CsE?zsggIj^s7RNU06cphb$22z%lLx>Mgb@k&M49)mDcZIp1UzoxFXrylt4<2+&m zokkNsT!^R<6&uXKU^d*@Lh724)-(x&xXS~0Rwaifs0I!$mRPjh1;$(c%omgahe`rbZS zZAFVc97Glpr_LvkM~60LbXu`~;A1YVkt){uL*uBYP?!*E8_JXBV02m#<+$j=L)fq` zC>4Pf$ujbGJj&PSTqq6*v8wg~S!KGwdU$vUZ*K>i38tNtj^5xdV{{<0Sl@=F9xMR*FeM!qWR z`;(=B`UI(&*RXs_qLW|=5}n|D%8N@;wkr|OrYZ}A$)x$x`zhldBRe`+yu6@eJj+>>s?&MzJH!Gv11e+J*ahiKw}VivvGK6!LvYN{`6 zP^Qf4S!QaVx(~QzVF6%y%kkVMW!0`pui&eUiOQ#bS0LYCP*X!N{*g7jMtJ4M*k-`v z?c>iqhNkk8AbKP!^_qwzq{3mQX39i*1(b05)6#o4KB?(~c~nx9k|}`x#Y=?6)|j0V zcAUmIOsr_G9zXmI1G*Ih@NbH&N*LE9NL6G_Gcz)ZZ}+}(KK=8KV|~s-D&k;?Nd09$ z$so>G&eYeJzK@^NoJfKQYkp8Gp?+o?0HKES>(hSe6}3( ziXo;}u)$wCkAbZPtHbZ#zo{E_BsYWU3M8TV z(z5~ha`-5^K@; z_6tSbN093cP&H>D%g*sW5`dd9BBgSn6{)qh^PEEC8^fAcMzpR(#wyJG;bNxC-#nXh z6dnBWIuuU(VlB06%?Plck5gfgxq|R&O$Kc!p^1gsr{QmrY?}pw1lZ)EXF-pC+$8Zn z+WENSf{L|L(-*1S$%#)6M;7N@t!0%c5XluiAeaO4V_EzK&h(2;3$@c#wX{GNgQ1URf};nAMZ) z^M(0(bKK#2GoxKvLUasAUt9^E@?<-o+0yDxG2Sex*~>Cn?nbkUz-1e^KSlz8ma?+? zFMmb&9lq>aLBUD4Z1qy5$;HJV@Z${-GO9Qm;-IYPrqur*J!|`g8XRu=5gcn@M&gA8 zveMF+YBr>hK{fA)Gr&ddnDxI!lM8-4SwCl+a%l_$-qvg&p-|ne#K)o-cbdcvOvISv z4ul0K=*VC}_SRd+_B zNc$PjHYgs`fmDWg*3H`1b`?%Y0m!-(uyG0bKJAd!R0B;0B9-90h6dt=h#)-M+t0t6 zpWPg^vcmgR<3u0$9XdP%%s^`Mx6knP2{?Nve*ca418ZF3dVQ{NS z4TKjp43EMB=#_1G-_d0tDE6{w%32wa9dX(&Ci{X9Nn+pqqoD2d!U}jdon6b)-!u zs+At;5h$4@2_QTuF=6nlxpso(H|t+fM>Ytaux-y*0FBaMBKB^Qi4~1VM+9{N3Us|7 z7U3F1E6~8@Nx;1#0M5J^Fw*&qT*4d7KF|RHh*_Qd(h(<9S*%d|Y^ClX2<`v^*IUoM z;xu?bIat##-&9AV#dL)2e9C9Q$j>jE^n((ou%m#v?o8sAm4&^LKHWU_{~987o*gkP z+>>u1_OClfYu@N`2f2Qam+hB<`Y0%tYShS1ZLTHeg;dWfP6~PimT;JIZPPAkX3Ihk#rbD0OM;2f+1lU z8q6l~!(QHcZ~!JujEPB2wul-dgjUQ%n>aBhCODAq^)y>4>cF4fQ`PKljlMbYWJ(Lq z{qYc|R(;2#IP(KVvJX)bv}Kc(7&3?kh-wi}o)GYx{_RYrswv=q#UE{+DC12U_t2ii z(LIej)We?s5&!MwU+hw|sB!WSPwRgA-3dZ7#4r`Yufn=e*8={iFkB`MnGL1s8O-0X zI#BFV<%K}z2h^!gayWcHPZSDlsFDRf-n?wuc#=(7zDIk>eT0uf9g!cV#Yrn0ym?QJ znQzke3=$&wJvuHEU+O8!6n(t9raKnqUNeHg6hvmQa6`*V$F+k|^9-TBf$uDYZTWlu z$n$eJ@4@$YPk-Qdi+j|(@r2iQPOL?5pi#cYf)qCOIz@iN)7;Ao-P+b>_2uI~`?qa6 z@Z6!5$L-@n2Y&wPHO1(_8!3iAyOX=83~7a*Bg)6|&W5J4)l~?inSX zg!ST?eEts4P=5R;Tp6JHlmh+YuGyUOJy5w&rT3=sZfIo(TNXU%vNck7F z@La0t$$xGy>i$G)&kQ#NpFOpNmLg+sbXxkDT}U2h{g}SosM_&-XnY!jk_Z#WB9cwhZl;ihVn0WByL!Z_ybP}%(RTnNLr=;xTJrhny+Z=Xq%-q7uqa-EvI z66Mbtnlvv#4pi>*-Jq%cMbYq@5Yu)X_)^f&!+@lCXOcTcttPU-N=!pbkNIyxB;A|q z0lvmq%&Qx>s$%dF0#Y;D5wBAvydey1}~j(?0_(8yLu72a$mCfW8BI5Y`Ty zR9jnVD+9Gg_XDpN-DdS|m+MhiJ~C*ATG`n`pr{fO!n8?pWaHwn_#bqWiY%EOb@H3< zB)F}#b++9&=axpFDvJ(`>9@fl2o<6jP{xu7z-Evuc0H`@KL(N*YnaiYGl2nSoO0B~ zH6QP{;7;D74w+LV>_O)tvzI46*uu#e1S+ghkF}7rW}9B7#+7=^Tzo18{09S>|1|f^=J0pJ!LnPpvjEna;~^&}&Z&7oa?sO3W#{!iIh`Gzn1VWF?olylgPgYh z9(r?XOngmm7>fGzB+7L#1IHVBvw(QSDLf24ycMVJ^MvoN!;$I^gQp6oo?Whs=kj{A znlFDx3?n#`1TH%!qP!gtFjClN;Fu1`h{K8(Wm)Cl5F@l1)Fc_Fj`+76uZC#2K2KQQ zBiOdGlf6XGt}aJp;_JC;yo+QQ_iuQrAN%@y+A$>fNoy5>hX{KDSy7{*s6NGMCQ21= znL0EjHT4-7beLvoTPyw|`t*-I)fIu-?v+=oGNN7>Qh~4E>9m}? zclH1$wt}fC4N$wdRj(@0J$+3NgaHfhTwJgz{I03|&-wg&AMTNTj$E)?HWS}9Uq&@e zPfXx@yGc(66{}%FV2{mY7z#DFun4Btv=v*QD=JhtExS?QnxzJ z)!LU7ntip=B%ubP3F z^MZ^`Yph`<;dRj3nlTvR3wsnsAj-uU`Y-$0wOX8Cg9ZQLfm$4)k$f+VM|jHg@6~@b zej-h$oF@fAj3)1I$UX?2I+UY-?E9_T%l;>)RxPsC$LPYy{P&#Q^(Dt(VZ(kBad!;* z&_+(~6Ah)GhJ&JfNj=|`lRy}1YS>dx`q?5{o~H2pHDd$68*>C0G)lqZ$&E866uL3r zKsLoz3(ijW4( zz?6fNSJL3LoTx>w>c~(p%Nz(B0g6(%|29tKAH&s>JH?iB3c!++EIC%eQnN;H#J%x}|< zz&A}2n&)5yDqy=7TU;^(-B|;ZcO!%FvC3XVJ!3KH?qMDKeAEjSc2(?W*FXZ_b@s`wL~Va={UoIj-X2pjN~Ex^E~>hV}8 z%OkBBb9eP8Wf4!9e!dd3pJu|jtrZ%6+NIIMpo?iU(aF0?`f`^8i$5+&Z3t6qYY$0? z&fBge?>Y%(h+@Zu*oI3<1d$hscw$|#h#Iy(DPtYS!bHCnhzA~&}W zeH;z#2UgvI6iq1|eTkS);*zwxsZRHWC_mXb(IfsomcA*T;I3rFh24CdJy;FK2Qv~t zSD^Ij{}F2-1=K;$eaTJFZ3YTfC1u7+4JM!vE`-6Q5R@3~JaZmfUa5xl>2M8`;oY6M zd;~#^pxOLKSn^bU#T6la4k9l2-1{A(H;Apzk^zVN&PEpc849M>0`^ND) zpox?>=r}@H1IdsX(InWj{ca#QKbCMCd>r8=*37!Ux>=eQdjOF(3Q~n{zOw^ONRdkh z2Bl^NEpDB`iH~6 zig1`V)53XD>Uqt1EF=)?BGxW{^`>0=0v~d|& z@NgtbbuK58nc!P=uCBiTOJz*%oRph$?uIqSG^5%@$uyqw#qy~?R}Nzi#;zZcm=JkD z%YJy2 zva}O!F%#-#8c0SaWrHWvKE1xzZ0D2d?oi3oh4f+vWA zOG{5w+INLMMLt2k_)qSq)Nl)_-qnSCmCl#~{iN?F-JjSU@E zK-u$uOgTETCzMVEVnAtY`BXeuXh9Lbi$!|VvQO4v?ji`eq1SG!4Q%t<8L{o$vH;I8 z=xa`9l2VwaolTdTEm)6Bd6V{3-oxS8zH!Nw%Yr%rW)*-dOV%m*cBYG^2`+Vrr=cIq zi$EBiI1xhEz@@d44!uWLKCK8d+ywr-5wlF2ROvM>3$5TCu0E%J0X4z6)4MW}!D;$ zs0FX`Tb1La8F*o4xCV7U5Gb(Z={Ut>CUt2#W(PcUP{HLhP5#CNwI)>3HRegU3_f_U z6f6|udX^Ac<6V;0pc1tvS&d-H)lWDWzHC#mXjJ()gHO!Hd?%wLpZB}|HX&8&;)uht z6kxkyZ4{4MS&zfMDD(HzGEJvfs?G|RdUYtv(NX5+tit5Kp}kS2jDqi=T`r4Mj>Obo z(7#`OyxH}Tgo5ZHk{%jJF;|v}X&h3L4Edmotf^lU+EvHy7Fb;tT&2t}*R@$)Ayl{B zDV!h}o16&1450c{lLrlT@Q$6msbaWX1TbS!;7YP@*?I=}eq6~Zpy3SL@dR!V9E!NA zDpqh2wX{TtK5RS&TITwu!UL?1eINM^@7DF1^_t_y1Y8IpMhi1msj|>hA3S{ztH@9o zR`A6s^KDkj^6WD@!o4M%jm%GVWyWwe!+(3U_6u>W`aRd)f|ZxX;%XSDk|yCPCi7GS zIY|41qxX-#p!4~wqu}}fC@8fg7-RZ>Ks6QS-0!~AG#zQ!#DB3W^{TuO z3Bn5C^$Igg{7=kY;Ml&Q%#I}_CZ8>Cp&BVs%-TITDAFMn>!-?=TSayLjrmF0TQJ(< z`U5k^XY59f%OR?=65%n6y84EOnf5q;5EgXOOYsm7pJKrDPZ%L7tX-X-kJt}X06=;1 z8UraaOSk#3aRIEO7NGyv=h$0xD^}3nXkoM|eq;;W86G(@U_v(&uvq|YR(y#bu4t@X@4w5mvn{sACz|>V5r+#700ur@t<-m@vpn|Z-pu^U zl4jFSck=qUvnjXp#{VG|5EnV2p+vw0w*wD0=3DYXjwljuQIjOhD{J`4{d61}pD)fi z8D3IS1EXprHnIXBi=9^LcN)C*uE*oY2i9?sCiIcO&`_oAal`T74Ou5Xh$Lp5qX5Ob z4lK&ANmxrDP@xUH7&cRP{m47Lu<&0Al3hMi5aq>$D=MlulXYIX$gG|Vs-}JmmRX2` zbax|!kdC1>6ngoU4BspE_)b)m`h?i_jhK3p#&_0C3(4Q+5F*r`iMUT4nFThG5^x?tfT#1!IyeP5O3rwtwN~o@8x{GDwv)Jo$4DQf?N5 zIIM<75*kVv<^iPXfd!Oe(^M&(C&=jIP4ONmRJ);(Ff7}J{&S=gBqAzRlk9pzHi#^W z@qsXzLVL7D_{NUet^_{YB{`||JABl8{C}r}h0`7c;rtU4KYI;`oE{!X*&@;zWnXqa z7URToB0!38);Cymg1VwCoqPW67gETKEBe`vf{|{9gXe*yjHApg4b6DUn9c#xfUc?cTJm6I?%w!4-(SL4pXo zXW$hQ5*86n-e`WeqWp`Auu`6?gW_hl4f`kp>sOo2QD09Unhc}@7tOXZsKEkn)@C3& z(1nOzBQ7m10p(?$^@~*V{Bov9{Pa-q9&RV*mu)sRXNkmj3l8^j%sLYTIZMYU8x;59 zPY2@)nXqE*WP*oI*!PmVhaB-@^=Y%;B`O7-$jdf0S5DpkUaI|C?eeFW{0q+&tDcr*hh*@yyXTizi>-LpfVPKREHP_Z)O5u1O zmg%Pig@WS?2K%*w4rmb%@RhFD@cf73{O?Tv9*ag8lK>Tr*Csgf&wyoemQ5jcW8&w} z;QdxNypi9>Q*OdjD=h@rh5KGhqPz*RDwXfc-&cUhk?pbU5ir_9BqWe?p0isjWwHlD z@=4lI#qw2FSGzw6{hc%A=H^ymN&#?HPvfCiH+0m_=o|McBn{i#i&f*fz*~EdyL)BR zdyDUcekRO%I9(dh$`Agh-*$OM)Z_C9I}1I={cTL4oV;8gHKsrFo3kKX3* zzXezz(DWJJ&luK#TPMfULKIK*j=j+i%)7gXhy7RgURo&y49POmf2u!Z{sj^yzxCFm z9&MCUw$gI{n>2rcHsXhjCP%CB$nUG&qKc&A6(y~F9!jK)?Q!E ztigd}prN7zppxf#3cv!h;f(_==Wm@BtzhqF-3T#}86||qQE5@=GBnUcF@|=qNm|8C zO`k3;`3l`0VBhuP`S%1Ohm~uISa8PdFyh2C6TN%26*)M(A+!6rEnXlS`xHrz1WQ9v zrVL4H8sm?^@BZ|^t`e}k9%vku{3g2A~kQ?A1cgKe}tQB)Mz9?KdjS04l^ z_p~gEq>-;*&Y~{;#E=LPv(bRDZY3bHcKVQ4vXHClRc|GXS~%)GFXPBncbz6}D z<2e!TVHcYrGINR_r0@*pvTSWRuUaX#JMzIm3QC`xPDD$Q=V6`0lw*3~&~Zlhu{ipI zSm<@&z6S%WZ$gZLDsX3F`Ioe}<@4a6Gy|U)z{*n>cYPENqLfsnN|8@|hn>o--3OM& z5KYDn&38m+G(uMgbweuaEv%f$C>^xMFsn@3EIF`!;?}e2-~>`|)I#!@up-q==TRd$ zpT^XX6w*91c2treJ6!ucPusypS{RjPk}PROCYDM_HCW3I$w{KaMp+{YHQ}l=#4bho zHXXKf_YckbDbM&vj(QX|NGnwsh3o{O26I^M{ek%317QW~$(|Dx)LvQYWCl_dRbQgL zuYcB2?@syrbBhqGbYEvpGp0n*DhMxAF<}&sg+%;52q5e$IEl07yW!v)cNMPJW34kA zCWMP7j7bib+R}jEYVB48z!}tOqw6iN8qEtaLV`0Oc>x*|JV|%5fyM7q!RO5-xbnOI zLv@FAkHQ3xC2LFzUF&U|T!|W>y%{BN6eS1+CE$RfZb;&1$Rm9K@tXx1?bUfZ4gM(C+rq$s#I3~#pdx+wW_B~9L(F;yNk zohD{TAALJlT3&Gve^^E;PZonpZZ1+$7hb!*9R-!B&5sYaH=-a>cLONsH!e8%wlpha%JBxlFscbnlJE9BQCiroVDzT>Lzp^ z%jC@3986bPtKv`H9#d?dto2%D0z;&S0e8L;2^tKoxOQ|(D#qt##IOX|&!#P7ljO6C z)U<&M4kSVWi;JDF5dDUAl%eR>AwVv{$wrr<;0)C76F_nS9BLy`Y#l>z2SDe2Zif_8 zN)LN#-A{%;3j4Fq+*>iwch-;|T@q{DV87+-?TI(o$kQH8mA<{LXfe zDq9I3Z7tU`FpOf(N^L$qaH(#0J=Y;CMeWYTJmTGPla4Q&|3aPjgD6V7f36ag@tKk; z^Mw&DN~VH0#g7Yi1V+R*McvTu+6s+I z!iXYix~#sBOu4eKuv<1_*&L@8`6hut!d%-;TbwuRbprd>Ls=N*20pUlvzFE85W&t}maI>d|LYT>&q`@sUAF5BrCb5IeD)w?D+~oB!`B%0a>q6B^~5_q7FL?FrOFs0xMs@Cj24!o z?=Xr(N90OiQqaV?Qbj@=_z*d`A1yk3nYD*{9rVjksa<9ITPWcj0wjWoNJ9!0rCnG! zIZ`T>)j-np!@KMmO>SJNSxmh&Go}z6A)ghgSvR;bY3iqnRDihv7)lb9EJ;b7%HDT3 zQk_VkU^NmGllD8+14|rXjRvqvLhytZ5C{8NG#%y5x%1=Y(@|cfzqN`KQ}1#oN1E+* zA&aDua=df7rNW`YN$7~X@P&-ioLDH?N3e?}tT6QmE9t&MBP`)fo85^5Vq{grO}WxPUkK zO#k7qsiPY<^XBUp0`5^sD*3l(zPW&SeJhx?d-Q4zSXa$vU{G1o7KERAoVD}JKn=4w zVlFfepVaUEbd!JP=K-fdnN1Nf6qe9bvNcbe_!h1Tg)8c>7&t0EE0xxK`I8=1ogSZ( z{qTnydeX1q*GJLdOVsF5dwE-?a6X7DAb`FJ2`->C;X{{FRpG|%!LL?Z12@mW)&0Rf$LRhhVaOL!q}f_O3k(AvlR8CJC17VRx$N4!P1vYSPHGYk&{}9!k8} zoK+B#Llgzo)9kGkdaEO7Qrj(6HZhq1&mWM&2sGCQdI0p7`%yt#}UBS_SRY-b!v zbtyg>{Ym5xTeW4;Cf*8;2g^Aaa@(x;*a@GcmVPw@vBuiEfK+Xa9FY{KkY1k?5|Z-9 zJ@TN(W)1nblb^cWe8t)wcP0;`oi`L(-#j=ZKK1I=+miaW-&=W^X{L;FgB5BBM5=ji zXOv!Vu^pS6^{u@zY>xs=Ssl0?WnomkbD>O37|wcvsVw-#xc#bQ9mnhZyp8JHpYZ;k z|EP;Q|M!wDNddO#y#L<5%~$Zbetoc_Zd3el5&z#c%-HN*X(lR*w;=`PWvzMqYDL90 zpKOYIBA&L-DTU~n#@f<-vWHQ2og@Dw2`774Wv5rVsCDcnOJ(aMDYrq%r%e`b|E>=u zR_HC#DKDVM;fC&9WYmFAO+#W3PmGT+SdH2)%#~>n2>SO94hjkj+aCnPcL&31-b1lS z_g2CQXM*t=^hnwSi4igtngpk3>5<5$5m`JDo%$%G=!Jc;Nh*BF+paspU?1`@AS)88 zD3Do4yQuDNL_fE20c>&KI@7r=r%4v|`79 zCsSg+Ncy3IZU9F?S~W^dY4rp1p9qga@fvEgArNdx$=ZJ_XvZ+&9!>7!*_zoO`t3f+fO|($RgZ!t*KH;cz?9P`Iz6`p8@< zYJg`}uebBxrRm&1vq-o*;}9)UNu)DQ59; zIV=ltD@Ktfv8YhfPnTt9I^jcg&a(?`@XX7(hJF5u_bgj@537bXps1;K zo-AkoeC-sk<)W77hvCeGZ>_M@koxAcTvn&8eO8DJ*t!$t9>opZrJm zY#^bgQ$>yNL_)8Ofa5BEHn1wTeY7*{w$KjFR|c-kVzmTFzL@4LXs*Ii!}wL%9wb3Q zR@l~tN0j~WfK{%+2@81AZiT{|%vNYB#FB zhv<{$&ln_eO-?V5p9>1JzZaRg%zEf~d+FM|-@03Z36tOTOyCNsGEEr)3;)RvQ@qKE zi7rjQor>Tjf1PE27cH3^;ht=W8|?(a_H~YjH_b`vr}0*k4Ye-P}>8>YF#;;!u3MVrA>NrgrFT zN7vUp^^GX7qD?CISdipmae1q|_h(m3`Sn=cX2me6#kMK)m^b%FqrPDKr$)FMk!Lw_&qbQho(qP~Qx}8*T856eP zfc#vOm5wVbJNx_!mnV>*jX5{=DyA2(Dr77JeEjP~mG6i7L=G?JQR^}{{>y&a&^f(q z8>V;&6?Xn7h`F{n^D|lc?UNKph8gv{8l%Dwq(ljMT3Wj?Gij8=O0@XAU*o` z-A>PaqoK%!Q982MDm2vok1SO@gq>UHM^Fg1=Z9I{yUUe3o>C<|r_-~LMK7>E>a}H< zy%lHhh3pmDAm!uVh780aoDzMcCJ5ZOnJH*#2?0h0pt0C|KtJkb$EoTx<}$qQ(P!57 z;%MC1Xics?cW#~-O7rD{CW4OxLn>#wAU3u6WqXVt(1MZX6sLp z?ec7bw-j4yvWy6ud&{|bhO@f!D>e(sc4h@{yaFFJM2^YWB;}3P3|5Q6GgQYfSiwjV zGrLxH+e6)-a4!B9qD&+smg-53zW&;afRnW5L&}Gv)nw0tJF4w73t@obyr#XVVDO-= zCz?VYCoEHwVB$?Y(X%B{P45*TSe+Z(Fs#@sqt`7#&Uv~QC9{$%JH;-YM#f089~EDi zh7V=m`v3`TrY?F=9;#_N6=gKL_#7{bS`Kz?><_nL%31Oc5qgNTz4e2RqRVCK_SdmMEq`Sf~x??ULj|Q=af?~&E^a9SS z2;M86aisu+347%koYZc~Fvn{Fi_R#^V}hzNst`}O%33PK=JI!Avk6CSq{tPCP1@r0 zQf1%_6;Wj;?#hQ-?|!~Jp>^mueb%=8dvu;lnDz%sCX*~3520LO$&FQOT#20XJT3A) z^0$BAE66;(=^a2I^B^ACY6H;9>^>lqiG0nSHSoy@ww~Z{7q3@~#DYN>G>}kOSLG%? z(aPeI!YCW&HYKEjkq8FzIPep;vV(PcOk=d^a0;}kkszc2(RV>17y~xGrx?XDly(q3 zvt2^@G%@Kh!i{_1!kr+F#z56b{ZVon8+oBoa>n8DdkN`rR6l%*_d7XJ_NcNd12ZhK zhCPmdNHHBLm1rda{vJmHaavyJFLQezEcT9wA-Qds=cDtkqv*7c5J6&+ znbcqe3v8ti5kZWp)@W$z*;&E(!IFE4Ni47`$vUh;EOZDG1c^vdr5wj;II z{?F96?YXgCE0-ivD(`(dvmZHG~txi-bR^#TA zk-h|}^cyvUuOuc{fsbLQb>F_ri3|iofrv2()D;a44Gge|Th19B9U=gbA86{lw}TtL z&aXEdl16*F!qsOnbW=n27c^jrSIf5n$G*qjcgstL#3wFzd;DRZ}`wMS2_wz=zIt_zEtyi@wfM1!)yVnOIOk=WO8dG)_NQXo`au z`DQiR#U6BM5D216Vk$S<6*5`_CeXDzw_BtmUUn-Zlu&_);Y_=zNO6!_d0*yb=*DM~ zo|-Sk)`ZC;Wj8`S?D16+Kp6;cL(??yG>>+72Xa+QFJ+oy+U!wyXs=yMuyOeF>meX; z;C5vJZtr}c9hQ;y>I436&Wt{G99RA7(pf29haH3<7|ab#L6s;GW?^qn0Ggo1$OUw)4aHK6q7}+4$^X@u zLB8M-llJTZ|96Uj|mORM~2iPP;5Q$lF|3#K!dRzr$d{eIhB zxa*{blvo3PecAU)A8Z@FG=#lB`s|5b+1Y6$H3gT5dwVBlIdqWDx(%Cg@{8XX^2Sec zgSNAgG`5`r^R$z*k?Qjcb+%Jwnny|SjnxWu{B2m6tG71Qz(#Oe`L}yl1wb!nI5G$C z`tUpXly%_G>H6Y&9?(XiAl#uR_P1i<1xBb-t~J+~W1PdPRHO`g zEC4f|fr}jmKnQvMXw`@sOErt|aySJsj3y6J8Wn?7Wb_GBNczCuY4vN$(mQ7~44v6j z^z^8xcRtX9cZzHYOI*n8T5tPjk~w=YjUuQ}B=EJhM}N&Zwf|y*0duEXH)3#x(y?fx z`y}BvrPZ}C$oN5_Ls##RvTiabS6lu^964@dS?!lKCnfZ6l~_S?q(Wa0r`h*pj8xbg~>`M~l7uF@h^jz+HB!;07goLZ@qyi(IVHtc96 zWNm81rHf1Dc;13U1pmc;_*~8tp{9rxAL97rj@2m=4`mMz?E$({6@Q|nSr%B6MaTiW zwwi@tYmr0>pe9K$5l?Rnq`oW~_}4qj-Nx>feopct)7xHrA*4?XE`#4(g=%}v;F;4R zp*3B>NN!(~nz1as9$R`~L4hWE#Z(uC%86uRV$YoO-0+wjJbSMrFGPOqlu3}2?)c$8vwXFCsr~)CCSq8Unh=fwe1Y5*ApP$d`7a_d z4Z?SrPnjTFy8T#Ml2P;&j7sUdrIE!b*vj)&sk4%&&Q=mYy-=fFtOVMkoDeXIiemwJ z6}VQ0FX72RF(T;TROVLR2aG{zl_%MKV7^9$1Zx&`+UNkGxJUO7IZic&`hjL zCD9us$(K=I?DYJvkX7_yb=u;2+YXN=YZNFBQtuV%6A}`*dH3uhs!YEtPs^pq3hxt50DA~-X}f9DsHpSYR{?>D7%ZX= z)}tvA8wqd;0RF3(p(ljc^=rM$gKo9X49<~l0L$Mm#=;Kalc~l~5XA#0RoCCeT94gx z6t5>Zk;ijMur3z{0q6L{ch$gYG_#OfQeTk)7&55}G7-t?A7F|hpcS}n2Hk@0h}xO; z^~v?_+ggAzB8XCGHmIHsB#H{7!i6U^w*Arb=~p~hCa9(>;LXVi zDMMwCyE9IV-BByvE#POYw7QbRE@?quG9XOt{Rq6AGy)ipPf&eZ?_+}n`_x%4<0PJN zkNDtbI#Y&>xY=|M&X~%|5w!(U;^H*5jww81Py(lmjoQ@Q+F*5P5%otH4fB>O^;V9K z()_5+N3M+NLKs;x!$aHSZiP@t)%xB#%kyAGK0oN1LXj0R4y~$*pDVTCL)VfgIHmz~ z$f3cA5vHD$#_3Et`J+P9+Ufp^!VX#2=VIROUjOX zF>NoQ<+!j`99lKy-e?u*g|KhPuR+(6f(LFR7CMJ{+Wis2Wgq{Gw@C}h97?5j^l>X-Yut070B4Azft5nI6?y8Lj-kW9 z?&iUnAtJW%7lHWjYz9hixZ!w616T%>;IzV+b(0g{Tq8)ooO~fIsjD3U#cspkL`Jrn zBrMZGtSl-_WE!$)a>K1)C}fb+eyL48!woM@tHuMborI50jr{qouXLr$%LoNItugYS zj{(x?%YndS$8Z?>#ipT zb*l|MFvvFJ^Gvc)4W{fofe@MG)m0{PX;_Vn3d3lGI2B`k73<|Mo3_iiwYI-U=vrgc zyAARr!xHMEWbAl>OEyD4n|gdJFOw@jue5~k-`iD^VWuNavM4j_H$*qus(RjyP>$_U zfyEqUn*2^1uN->rH==I!ATgc#p^|DE4CLdUev{Nm!^T$$pz5Ew9v0#Yl_ zI_-$;`ed=;IIqr-5vH>?7htP|uDUzCUr4WUnk?K5Od(dDUVvg+1- z8R={T&D26dO282NI?E_x2L#W^hFc`PjAh57qZP|E>Unaf&(E>$e~JeLOxK+~eT(0f zwVNPx`f7m?MR-5g6w%E#PI4(o}X*1<*yih_eT7 zZkvmstc@I!<7}9Zk!DaCwXc=i)T!6Re1gDL)h@7e)OL}(Og7@t-t0aNUM2PcxU-FFmxs#xU z)o`Oj3BleSMa+igLp9Hm-g2+^kOH&A8rPEU>vLEcY5JaHO z7CA$U)>MU0>L1)#LjgwNc`*IBV2bz6KLIv!}1X19H${dsm0|*qD8(4sM zv=^Y~?VKil`m+L1KSL}LZ5~}3G9>}wD3|Z45kRy`6(!p)Pd$Ni4q;|>RURaS5_h)v zRd5&H$ktKgeo*VhT-p9;(Rx1i>UzN`@c&KGCRL}7*NVd}4@)EKb8P?G6T_KUkd2!@ z8N2;J#oF$`fZ>!5ZS&2}-Vf_{n^W@r@FT6#t(M_K>zk3)PWLDv ze^$WlC+3)dpI6%A#{f8IIYyAu^Ad=(CvqPQkgH*ouMscNAp7~d!h~t@1*J9(Q3s^g zodQiO0@8CMu@PX4Ijn*{zpx~>db!f(!?S9Hp*`>R1OY(!1Xe`ExukNQ5_XK`W?(`v z_iIZ6ZgS>v`XYK1gcxY$feidKdP-5DM)Se%qf(&BPA=5_hhak%CSk>g|FV#O9)7JN zw2I)RlL$(SpMY6V(Ok@7s5=F2DOGZ8^p7`MFN-Sbzl9rwxbzKIN_<9*NM^VwW}0Q` zlclCv`;-7L$RsV%`5|>?MoVqZo&mqty~k55B{~8Qiqt`b&W=EC{yD{k&$^f{mBHpq z%C(V1c`Q^Redg7)v;ePo^9M~<4aRsi#`qb}BN}ROk6zuTo}F2j)@J?OAd3p zDZFKVTDK)QIxgbo7PGeteH0@vD}wvohpbW-VXK{-AAW9}PL#t;eUrlO;Y^8qbR3CR zGV+!E#dKmWPWp=o)!o9aqB~ZHtsxC8HUq1ZrG#9O(j+W6c+u@}Ypi!6STc-sR8p^Z z-=P{Za4?dhJKz>kU?WQl`*y4N4u^N3gq}1pU)Z5w{q%qGzVeuwwXmQNs&|cfhgHn5PeSQ%R?)avv}M&gSd#QrO7)E51EThSnR+NO#ZvpL?Rku#$hJpY z*C^5XEyekT5b^xNMR<}e{jGc0#W0ys^lQ`S+5O_4TM+7$qLRmwVh-ZXkwg{;b%@o~ z8H#Mi@{402YkW4p=KBdOJm)qx#sC)>Kq4&s{35`bjCC0+MKM+a*vP@S7ZElNELyNM z2ylTFAGvv)S3uzeScgHKsQmjR;) zMG&#^>)8lUhAlMRpCLZr#f0s)-u=wb{kX^WF32W=#}UtcCxLINpO5M7>v`_tHws(B zC$ zYHIW<*k|x3YA&<=r!b&k%L!ym0cn9eD9~qs+=13#2+U?6ECTR`!0Rg;MRaeTgg_n` zZE4>o9S7Wh`yai0d_1-nKJvRnw!BL~!$41)#uuX@ARs7oba@4>SXTX0S-I_B&lOn- zOT$!X^>S;d&;FE)0gDmQ?WfyBx0co{t+`Tz`W5pS|6NJUZ@ zPmk~ISlNiN85F-@v?-Nbdi%lMh*8A;Hukb-#LnmLkxw-+q%yAgOcJZunlpuwS&b1_ zj=n_C1}7#uMf;^z6euAT2|WJA9VU%N%1K2-z0v)IAm(e z8_N?cQ@u*o61th$uig)Q-&6m77o%|kJ+3W?d^3Kqc>#mfJYKq{DEx=m_2ul@h&68C zkN^o#jT%9MPDVz?&PmSvUfk$+75fm+uBn+~`8*i33yb|^M8M9pCOy~d2H@r-3G)fa8LoF5is8zv2p@I3^tGtllsnVY)k=Y$mG1L zD4@`Qyg&^_*0?l=Lc;8|l2ljv=gL^N-pj9N{K3~r^X$i-kA@2awk(hWXD;!9R~n0t zJ$&AShI&jGA%+oT$}H$xtAG_%%z)bR=I!uZ*yQPYCn#|@1#!XEfOQ*Q*9|2@Lt>zd zSQNz{Bkg+VGg%Xld%%z&U1xu`!ZH60yirY6ptU$|ItGLX@Gr^EOKY;nQO>{LQ@MuZ zy5Fx3Oe7?|6!V-n!uTyX1ej8yf2K~K7#uP+2FtbF!>nFDt8v-Y}eyi>&7uYI3w> z`w1+h4{6_MGg)&b&&0?R5(py<_ClVMo?jO{Z}a~4!0y+oQ+#UxDVD&Zt_Wt9(T(Ri z=vEsYu#<5rUM@GxI?S(KO-i_xtvM6D%ryxro~|N%bcFb*$f*5yPBba^vG-tXTyMWh zYPa+(-16rduTHyCy&jDz0TfJEem02X4I}#>3BhVzZ*;gNBv`mcS3#bFHjE8f5;^eP zQa&{KpTFim9{ph}>BN%ONPMJy<=Z4Sx-a(+OD5zjq!sPOi!Tb*GXCDghI(DCa8uhR zD6xWAFBfpRf~F3E?}np$9^9=>;NC>8xN4{BA#&4^2|J)b+^l6ZQ?tU^c1y7{dt*56 zuflDZK82-+H}YbUT}V1=1cW}1!1-~kv{*YV8}B=4K)xJ+f?*6 zlRC(XKf_U;??2auOkOX$4m6G-(+;R<2@MaJXv zh9tTrhS;ua({@zLBPnxv#H~I}vBGe3%vEEPfSHLe5~3@#(hSR005Yr+on`@ca~>18 z@_^$PMiklZV1-qWw*lrqXiD;G;+8t)8^v8!qGlj^yC#X6Ak}d{{hxL>ONz@s`;MS> zX0d#0u$ZNv{h?qTRHSyNV#({_UH2a=LQs$$)t6z*%rWWG^smjA%3ul1K{EU+)6fN` zYJ;+zSm!mcYD`v=%H#pUj1x3vX~_qO(teK@vi?AJuy=F>yn#D-Aneit$2UN(0$W>) zv#R|utvM?1<<9-dRH=32YRB{i7}D<3MDO1OyHD4yTP@6;OaGoul3tq2Ik=u5vBDIB6e8LIMfxgqx z6jU*FT+;^Y<2;J1dI~f-WN|D+@JM-OS`yaK#2f()BMW~w-OrlAuqO+YxIn*c0-)_% zm`4PPsJ5#WYB8x-WV(^O8mykgmBQaryYr?nItJx#dm8Et5?2{D;@PwNk$h^u+#L>EZP3^qj(+H>X@ ztifVBja4wmQ^&7qSXgj!k6ojJ;oAT=^~o13M1S9j&_Z7RibY(k+N}MK`Y6G_Ct#3X zWJk_(ApMLau4engaV3;E#B|6`CGykkF{OGjhe3Kd5t9v;dLFVtr;26|cYD6JR6aZk*-N9BU5& z;ZP!NZI~^k{j95;ad-TG9!a21gEcs~RV9!CISvf0rSr4#Qy>Rb=bTgU{J8&kRW3Sw zDOA&WD&SOwJ6SkXqY|kRX{7ldaP4&U7Cp}^?YfcdzvZZVHmf|DJNiuq@ig+r8i0*o77nD>Dxz}5iX4u>T%h2xJqfYU|U$a9jXRMQ^y z9#sN4HHI0~udIl~&d8T}%!-Ezt=as~^inbap1|@)KG`$mGogef|TY{NHH+A79q|(x#tOmb0 z8%dmErE#Cab{eDJtT(W4W~iPP0+CwAwK~8?G8amy-g=L9$13rbMky~MW%n0x?e5@y z{%$yCz$`j~v?6D2ZR*5_V?-M5@LLRE^({Bqu3_7dpcEC8RV04;76j5*>fQ?TF2mVh zc~}2sPXUGi{O)Mzpx+CA0|hnPct;NuinTc`|H}Zf8c)`(;u{lfZS2?qcI^lUsYH~n zq!TSF-glx>Wg0N_F}PhonDy}Z*wW4IlLljl-F=toD}!b%d}(#LL-|S_vB~P9A(?S? zj#YC8s^W#Do^ofXpm>nlubMb&qHByx7u9ztu1Ul~bE^a1lBli?NG?)~|>`prP- zSGwL25IAdT0k+=W+!__2h7N!AzXT_rjI%M8ym}y}5&oe}p^>_{t~PRDlNJuk8;fiQF>n+uwDeajIU*YL|moVnIR ztn!l#(lAr1;y%BZ8Tnb4XS$gDPX+QK2S4)+wNNT}68v9Hjz9d?W$-2(CA5vSu#02c zW;6)Y;SRir4njDT6FWtuT5I;hUnuLk3FlaG_5z95jU>n89wk5Uk9R5VkAUN9!0|I$ zuEzJ5<&wbwGc{5oaH2Oh{J|!H|A# zybmYH@T|*N{c8TCQDpdk3OBcrQN`h2S zM3o(X6+LKCU-O;>eT0?!g#{D2@jLsAk0i>>D&HMYyc5t9aAlleRYlu_araM~&q0+L zq3iEA%C#6RX}pO%6CwtM-VRIJVRtUC8}HJK-lMesXvpJnWb40l`Y=PkJkv9yhOMbP z{FvBtyYqSRbNXlCwFA~QK!trGh!XGGomohSf;+*9c z*2E-(204ESVqg5%uD0aI>El#v|9s(rLWx*uuM$;9J=CUE*{wU@G!pEP{)Ou5Ye!UT z<`_RWH;fwx9#uybZ}c*y!Kvm=y>4AP&U1t>pgcdMw7eYZK@eqyGy5gbqZoWJ3$1EAH&wOWTGsONKjHn7_6288^+-+FcE8}|} zz_mJuo(JrQ?iYjjFow!^!!^0Gc{8a84(5y<`IF?HhGb4LMH;mDArrOt!GI_uK+-O@-N z;*BxHjXKGAS(Z=BXqncOxujxN-0$w({oli8Ainba-CS1p2*^+{;9Y|E6h}kq%(pMq zK$9c9>D--*(F)G4zSqF~!bcAL-?JR$whXWEV4h?$BTh z(A0h_jJ?`>2#GN-WmkIBFDEk`V^K^qwK}*MyW=3T$wR^SmVKyzj3DV%0uL5iG8_Ij zzr7&pP)w^b)|y^S8~?KR?~y8=rSHpPKAh%T55d9~5cX6ZyMV7Mi1m5Jc$i~5XNeEW zh0+N7-vwxu@|Ko#eodbggIoT;nzj$XZ3Q9n*hdnEASEUkS5u|NToPPdJh^hakpUyu zsZ|gSeXK!Fw0c+FYx|~u12`m7YFWReUg*%Ci(}K(yh)wpZnPZc`f+*r{+;Ld;#4^e zCjHWRx>!VHIighUES4Q09iBA=4hm_J7%fX=m_g)|nevIr9b-i)M{?a?Bt6E*-40y& zyw`Mnz9f8@jjyjc2KpgRjMg`P1MNiy){Y}iPK|9Cx8|_ilrjzb@xI{s9T36?8<^?` zv8x1GE%>uo7pjSqzHY8yLIlR*9knVJgevYWH4~aK_MxA1snmexTR_*6d%v zDsS#KQ{Jdq4nzzsror=b3effozS#tl!1Rz!11xS^`R{{=#Gcvt09*m2iP6Ejo_^_H zHdLR@5B`YJi_4sv-XfyhLYThWZS=K8yzw%qYce-f$2I{wMr!Jm{43Bm2VBJWs0LJ% zn$ulUXNCBxuBfGzi{15Uc>M80zFo*%v&~wwewURb^!_2`l}~L(fJzhzvoChB3)1HeH$x?r|>n zQ4bzP#-vn_&g|?pO(nF*-UiVtQoPIHohmAOmz&E~kLQF_OnS6fKHt`-5q0xoc&=z9 zKWs}9xHSr!5eZQR53er@k6-cqKdz-1g1ta5cxwLly=#g=j5LZ;oZ#sjk>h95;h5!a z9WOk%pAto&Y36fz7$pK2tOyT|rM0#5{kBm6y{X;q5C;g*10P<#J~%o8FY&U)_1MGp z!%nS-Jtz0y&9A@q4tPC1Nc?^BO4;4-c^o)C;>Q@3LQ>{I2?xAw5Nx=*F|acjuwzm{ zoOu&Nv*>_Aon{64ykR7M>H70rx%^^O+7=JZBa}RHU27qh^T%}Wi2`16d_*{?Jz&GF z$5!KkK&*~_of#asUfyJC|18Ve_z4Q{3D;U(ZTH3$XSjji7F0BO#}qlQfm91v!k_|I zO6^6`^Bn~+6uqF94FBQ3ypQrEN3`($JI>obJlqruM5{Dz#FI9Kv4h`7=k7tfOFoart{?q$P*6;T$X|C}6IAFr}Rkv;=)*N45=K*0e0klYg zG?F84KRaE*US49t9lwtmeorle+Q=FJ`XCT3YLI0lE6GTzll+NHWA6MMIlbBOGNRuT zI6-ET0nUV2;cE||_8Y7b0dUFJ$0Il*qSO83u`_m8m-o1bRZPfQfcMXhUJ}tjG=pM| zLIXSwdrm)^!i+mHHJii#;(k4gduyWPV|oG$Xqn3^J)HfnZ$bbe^9MaaWxH?GIu_6~3Qc z?--tF4*~0%ps(!kpJKEIW~A2)=&`U7aLZOIXbc30UhG_iix{iZSuH!>YKH_Q99wm` zFw)YN(@CcsNF-x5-^vyWri=6?X)eFO9{VKTLgnmUMj~8ulI0Nw-gSemLIK*3s)tqg zb9$_LSr;W0FDZI*=^OQfkB%AjI}F$CXtU{dGYdafq(Xf8%2i1u6@XV1P{jLSmpn+s z$5t;7BBWVqC6`yKmj+EZEKfxB}t@d9}7louL*n0$?q9*gj)|}<^+YGdBWe4 zYZH8q6~_ud=K1u^PsPpnbF%@K_QJ4mY5a#uTxnSN7? z%xu_#Hk}lBrC5fOzh7@PO69a>V`df#tFo(o4(8f?*tqpOT;#KJb+vtpTC~z2D%)o7 z+TZ$)8bt;w=e>Y&2Mh6~&~T?BMpuSHv&sF!ZxI*-%9#r4xBD$J)4Dpj>(*IPdqx{@ z4Kxd*py~{`#Sa0v%a5R44-F-7hj??#^SE}aeLo*&0sILJy@k!yF+ka5=fv^nq)U?r z()QrD+l}#*{&nzvaSe;?d2eokKL8T+hi7NCjcyRAbcf>d({tnPes8MrUN+mKq2sjR zewuBKe~pHGSrH941zbY}mYg01LIa17si(7@>822q_)Mm(UQGu?d1man2uaMb- z#T6G~Au|qYq!V)H z0ZWY=xBl#CJ0D(rT88V|kW2o`@SiRrgM}_rZm!UfSn~(~R>>xkP^!#*DdA7a{baBe ziGMSDqspNXRpfbYmN%B|75I27()Sm=N`5E44Bz;M5>3(~g(ZcRQ^uTt zleZ-b1St!2eV%-yK8}+JajaHrI%-y~ctOajGq<;T<-t3ceDFgTCc7{&_cpN|=Ncu> z4G_EMPrr=cI~3?IKVHgL#Mechs}b@3W?~x<02v*XheDxtyg4)Zhb()ykdqD&j6FiN z<@yjuE1GGIjl==1F#pc0@reO0%EfZu=!+5dcne1^Nz1Vr5vxMl`c)QHWSB<#>4VK# z_2K$-xpxLSVs=nNx}5n3x|F^H0f@aT-*vK6Cc2RP!e%bKV=rDL7g8_zmLy z)joMX-^9Q17S!LWfAr~`?E4{f9YAW%%!{ATc?vhvnP`@$@{wDaL-`FT1}zQ+{uPhM zJ9i+Cnf{ydg&~!}lLJ<~0Ze2!G<00vNY5W|9BmPP4U)w-60UpNlbEtLGEU7YnJ{M@ zDoahNx0D|1C-_#kgdS_%jj9Is{p|O|Mg5>7i9N82`0l_@xH%Ej-MTMo>!wJtM6@t$ z+EBcaCKy6y8Jw{;&Dh4VsF#&tlrB>1X&|w&u|fV2O1on%ke3Vu2ruJlExJbx(WgUI znBd=2@U&V`Z?VS-nWQr(xWZ+{%Yc9=+|%Fdz$49qZO{&Y{cq2dj5dp}{e+ay=14VC zqUCR;7uuwl*Ep^wEpq?)ba>mk`>R8Q9n+$NWrF9*f!}-~KXMDY``rOG-YnRKmAH-M zqd|2hOP)N4VhP>vron3c%JrE4^dMl?fn3Pkso2f-Yqm?#f5W1UPWl-k58cn?>8~me zI;LubJO2kv|Mjcm`BVfmfhWn>fd|>IA_oDmhki5?R ziSyBotY~*UP){XMT2Ei2r3^Fopp;;7aCDMHmMXtMrGri&YIS@n#VxUy?R8t{)!o4<0=rpsP( z$t%JP^!UTT#YOl!n09UN18vdx zQtXJAX>AU%fkF!fvmbLZ>wDvd^TKq$86u@Dek$+qLE3rG+asK_Cyc%jY=A7z)Eslk zBK(@t0Rmmbb2U9^4PuNh)2Q?)dPvvEn19Y6%-87%{adT@D#~6jMEP>9o#+|wENO=y zVd(YiCIgnoAr4^toz*LxwVQF^iFpjwiX5S-`oWe1-q!m|y-<&W2Ol5Fh)}#GGguksqeQHVQ$q%&=LutTks_+o#&e{oG_LiCK88 z&*HzJ?{qajRva<0`>L!3Igo2902|rgWG3eYL5DI?$GU+jW-QT)|b*VI3S^3`uOD)g{E9!S*NEV4h}Y(An?>9UFs!qs>}Rs5-} z=!jRxU;MM?*r-*m9HremUM9}!8!5Wr<#~*-6a3=t)w6ouln`sfe{t9LaURl}Pp7{A z+cEU89z%dq#0S3SVRsVLK@z~OAFB8K`uK;H%zw8)uhoaK`{82K7JM{Y$n}5mNlBjj zuHWK7OWfP}r3MT`E>Ew^?^&68)2{453;Fn3pQxM6EO6)~?uF%=k3DZrsXS6BCYjL0 zzR2yn{6G)Pb`lbYuwy*rH8@UnT+*Dv#olJKOYQOd%jaeC#(RkNz}UFd*2j;Z7aa3bpJf1rNEDA-Nu{s*5Fv|paCC@sWx?6l;az>PNR{TUZ6c)tYm"l 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%0D(azs`@eaurdK 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 c^h1%vfTV6fEUA*xF>(f;?49MW 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

LOsan(R8lCc|b&AwDT!Ge3?#n$(Xs8GJ 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 Gs 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%0Dik`LH59_et3!ot-MU^ohFZYb&JG;<}fu1oM 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 diff --git a/LedOK/res/ProgramManager/EditProgram/AClock/AClock/Aclock3.png b/LedOK/res/ProgramManager/EditProgram/AClock/AClock/Aclock3.png deleted file mode 100644 index 193e467df92177c9da29106681f20885c3cbecc3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 84814 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 BQ|JHy diff --git a/LedOK/res/ProgramManager/EditProgram/AClock/AClock/Aclock4.png b/LedOK/res/ProgramManager/EditProgram/AClock/AClock/Aclock4.png deleted file mode 100644 index c63501b55430b6ad5c9b6697fdd123a8a2dda3de..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 114215 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 cb0;YgJ3=`?!VX1OF$msYT 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 !O+w4^yuQYj- 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�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

y-Tr>nw!Mk1J+4;}GAnR8(BP{CU<+ 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 SX1gK)0000 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/LedOK/res/ProgramManager/EditProgram/AClock/AClock/language_zh-cn.xml b/LedOK/res/ProgramManager/EditProgram/AClock/AClock/language_zh-cn.xml deleted file mode 100644 index 3c8f2d2..0000000 --- a/LedOK/res/ProgramManager/EditProgram/AClock/AClock/language_zh-cn.xml +++ /dev/null @@ -1,907 +0,0 @@ - - - 简体中文 - 0 - - 屏幕配置 - 发送卡 - 屏幕控制 - 工具箱 - 硬件信息 - 设备已连接 - {c #F0F0F0}检查更新{/c} - 帮助 - {c #FFF0F0}设备已连接{/c} - {c #F0F0F0}未检测到设备{/c} - {c #F0F0F0}版本:%s{/c} - 多功能卡 - 校正 - 修改语言设置后请重启软件 - - - 设备列表 ( - / - ): - 设备列表 ( %d / %d ): - 发送卡参数 - 发送卡名称 - 编辑 - 保存 - 分辨率: - 自定义 - - 位置: - 修复 - 大屏位置信息 - DVI截取(左) - DVI截取(上) - DVI截取(宽) - DVI截取(高) - 窗口位置 - 窗口大小 - - 网口1位置信息 - 网口2位置信息 - 网口3位置信息 - 网口4位置信息 - - 网口5位置信息 - 网口6位置信息 - 网口7位置信息 - 网口8位置信息 - 网口9位置信息 - 网口10位置信息 - 网口11位置信息 - 网口12位置信息 - 网口13位置信息 - 网口14位置信息 - 网口15位置信息 - 网口16位置信息 - - 偏移X - 偏移Y - 位置(左) - 位置(上) - 位置(宽) - 位置(高) - - 音频使能(注意:当需要使用音频传输时,开启音频使能。): - 启用音频传输 - 失败,请在尝试一次. - 修复完成 - - 双卡备份 - 通过选择备份卡,然后进行配置,可把当前主卡的配置数据拷贝给备份卡. - - 缩放设置 - 缩放配置可实现全屏播放时画面自动拉伸到屏幕大小.(分辨率不能超过2K分辨率范围内的自定义) - - - 缩放参数 - 启用缩放参数 - 显示屏(目标)宽度: - 显示屏(目标)高度: - - - 设备ID:xxxxxxxxxxxxxxxx - 设备ID: - FPGA版本:xxxxxxxxxxxxxxxx - FPGA版本: - MCU版本:xxxxxxxxxxxxxxxx - MCU版本: - 型号:---- - 型号: - 名称:---- - 名称: - 分辨率:----X---- @ --HZ - 分辨率: - 接收卡数量:--;--;--;-- - 接收卡数量: - - - 显示屏配置 - 显示屏配置可以设计和配置您当前的显示屏,根据用户使用习惯我们准备了如下显示屏配置方案 。 - 向导调屏 - 用于T-75E接收卡对常规显示屏的快速调试。 - 常规调屏 - 支持所有类型接收卡对各种类型显示屏调试。 - 复杂调屏 - 支持各种不同大小的箱体连接显示屏。 - 巡检 - 支持接收卡数据巡检和发送卡修复。 - - - - 芯片CPU程序升级,切记升级过程中不要断电. - 选择一个发送卡(升级相连接的芯片) - 选择一个发送卡进行升级相连接的芯片: - 选择发送卡: - 检测发送卡 - 升级参数: - --系统文件-- - 浏览... - 升级列表: - 自动配置 - 手动配置: - 起始地址: - 数量: - 加入列表 - 删除选择 - 注意:升级过程中切勿断电. - 仅升级选择的芯片 - 升级CPU0 - 升级CPU1 - 升级FPGA接收卡程序(如果不勾选,默认升级T6接收卡程序) - 升级FPGA - 升级 CPU - 快速模式升级 - - - - 生产专用 - 选择发送卡 - 刷新列表 - 配置接收卡参数: - 箱体文件: - 箱体CRC: - 重载箱体数据 - 重置误码率 - 监控信息: - 网口连接信息: - 校验错误数量: - 误码率故障数: - CPU0 - CPU1 - 数据包 - 错误包/次数 - 箱体CRC - 运行时间 - 未检测到发送卡,请刷新设备!!! - 请加载有效箱体文件!!! - 发送数据失败!!! - - - 参数出厂设置 - 选择一个发送卡进行出厂设置: - 刷新发送卡列表 - 网口1卡数量: - 网口2卡数量: - 刷新接收卡数量 - 网口芯片数量: - 发送卡出厂设置选项: - 发送卡出厂设置 - 状态:-- - 接收卡出厂设置选项: - FPGA出厂设置 - 字库出厂设置 - gamma出厂设置 - 动态配置参数出厂设置 - 恢复不可更改数据 - 不可更改数据包含生产日期/维修记录/产品类型/产品名称等信息. - 不可更改数据授权码: - *只有当授权码正确时才可进行重置不可更改数据. - 产品名称: - 产品描述: - *默认生产日期为当前系统时间;*默认卡类型为0;默认重置维修记录. - 一键恢复出厂设置 - - 公司代码 - 解除加密支持功能 - 寄存器参数出厂设置 - 厂家代码设置 - - - 发送 - 黑屏 - 刷新 - 固化 - 确定 - 取消 - 设备列表 ( - / - ): - 设备列表 ( %d / %d ): - 水平: - 垂直: - 刷新频率: - 提示 - 序号 - 地址 - 网口 - 芯片地址 - 芯片类型 - CPU0版本 - CPU1版本 - --用户文件-- - 重复 - 错误 - 升级 - 网口 - 添加 - 移除 - 设置 - 状态 - 备注 - 时间 - 编辑 - 浏览 - 删除 - 清空 - 全选 - 日期 - 星期一 - 星期二 - 星期三 - 星期四 - 星期五 - 星期六 - 星期日 - 每天 - 加载 - 每天 - 恢复默认 - 成功 - 失败 - 完成 - - - 芯片调节 - 亮度: - 所有通道: - 实时调节 - 红: - 绿: - 蓝: - 自定义 : - Gamma编辑器 - 断线显示: - 待机图片 - 最后一帧画面 - 在线调试: - 关闭 - - 绿 - - - - 横线 - 竖线 - 左斜线 - 右斜线 - 系统上电时间 - 物理地址 - 失败,请在尝试一次. - 保存成功 - 发送完成 - 手动调节 - 自动调节 - 当前屏幕亮度: - 当前环境亮度: - 启动自动调节 - 亮度映射表(环境亮度|屏体亮度) - 环境亮度(Lux) - 屏幕亮度(%) - 自定义 - 预设 - 快速分段 - 提示:没检测到光感探头 - - 定时调节 - 时间1 - 从: - 到: - 显示屏亮度: - 时间2 - 时间3 - 时间4 - 时间5 - - - - 预设1 - - - 启动误码率调试 - 重置误码率 - 地址 - 总包数 - 错误包 - FPGA版本: %X.%X.%X.%X - MCU版本: %X.%X - 电源状态 - 运行时间 - - - 出厂设置 - 升级接收卡 - 升级发送卡 - 数据调试(芯片) - 数据调试(发送卡) - 升级分线器 - 升级发送卡 正在建设... - 数据调试(芯片) 正在建设... - 数据调试(发送卡) 正在建设... - 已成功升级 [ %d ] 个芯片. - 升级失败,在执行步骤[%d]时,错误码:[%d] - 升级状态 - 升级结果 - 名称: %s -- 型号: %s -- ID: %s - 无效的发送卡设备,请尝试‘检测发送卡’ - 请选择需要升级的条目!!! - 升级条目为空!!!!!! - 至少选择一个CPU进行升级!!! - 未检测到接收卡存在. - 准备升级!!!!!! - [0]准备升级 - [1]关闭千兆网写保护 - [2]关闭芯片图像显示 - [3]关闭FLASH写保护 - [4]配置数据CHECK - [5]升级数据到SDRAM - [6]固化数据 - [7]检测数据 - [8]检测固化数据 - --处理中 - --查询状态 - --未获取状态 - --完成 - ---失败.错误码:[%d] - 升级完成 - 正在升级... - 中断升级... - 发送卡设备: %s\n - 接收卡卡数: 网口1卡数:%d ; 网口2卡数:%d\n - 是否确认恢复以上设备数据? - 状态: ... - 状态: 开始恢复出厂设置... - 状态: 完成 - 错误: %d . 请重试. - 失败. 地址:网口%d接收卡%d. - 状态: 开始重置不可更改数据... - 读hub数据完成 - 请移除掉多功能卡后进行升级. - 打开文件失败 - 接收卡数量: - 状态: 开始重置寄存器参数... - 升级中...请勿断电. - 通信失败. - 正在MCU写入升级数据,..请勿断电. - 通信失败,中断MCU升级.. - 中断MCU升级,错误码:%d - 检测P%d-%d升级状态. - P%d-%d->MCU升级写入升级数据,..请勿断电. - 升级FPGA固件程序,..请勿断电. - P%d-%d更新标记. - 通信失败,中断FPGA升级. - FPGA升级,写入数据中... - FPGA升级,配置CRC检测数据... - FPGA升级,镜像数据... - P%d-%d镜像固件数据. - P%d-%d查询镜像结果. - P%d-%d查询升级结果. - 开始校验[P%d-%d]请勿断电. - [P%d-%d]通讯失败,中断升级. - [P%d-%d]校验失败,中断升级.请勿断电. - 未检测到接收卡. - 升级:%d 失败: %d. - --用户文件-- - 接收卡数量:%d , 成功: %d, 错误码: %d" - - - 自定义EDID - - - 自定义Gamma调节 - 通过参数调节快速生成Gamma曲线及Gamma表 - 编辑Gamma表的值来进行微调 - 灰阶数: - X轴区间:: - Y轴区间: - 标准 - 增强 - 发送失败.错误码[%d] - - - 电源管理板时间 - 读取 - 将系统时间设置到多功能卡 - 电源控制 - 继电器名称备注 - 全部打开 - 紧急停止 - 电源自定义控制列表 - 电源路数 - 无DVI信号时电源指令 - 无千兆网信号时电源指令 - 关闭所有电源 - 传感器控制 - 传感器自定义列表 - 传感器 - 触发值区间 - 触发持续时间(S) - 板载监控数据 - 电源管理板时间: - 外接温度: - 板载温度: - 外接湿度: - 板载湿度: - 烟感: - 环境亮度: - FPGA版本: - FPGA升级 - BOOT设置 - 启动 - 停止 - 手动控制 - 定时控制 - 外接温度 - - 板载温度 - - 外接湿度 - - 板载湿度 - - 烟感 - 亮度 - - - 设备ID - 发送卡设备ID - 发送卡型号 - - 发送卡名称 - - 网口 - 串联地址 - 多功能卡名称 - - 正常 - 断开 - 状态 - 确定要移除选中选项吗 - 请等待继电器命令执行完后再操作 - 写入数据失败,升级中断,请检查连接线! - 升级失败 - 读取数据失败,升级中断,请检查连接线! - Gloden 升级成功 - 请等待设备初始化 - FPGA 升级成功 - 写寄存器失败 - 固化失败,请检查连接线! - 该卡已经存在 - - - 添加多功能卡 - 选择发送卡: - 网口: - 串联地址: - 名称:%s 型号:%s ID:%llX - 提示:请选择发送卡 - 提示:请选择发送卡网口 - 提示:请填写多功能卡串联地址 - 提示:请填写多功能卡名称 - - - 电源自定义编辑 - 电源自定义控制列表 - 开启时间: - 结束时间: - 自定义编辑区 - - 第一路 - 第二路 - 第三路 - 第四路 - 第五路 - 第六路 - 第七路 - 第八路 - - - 设备备注 - 第一路备注: - 第二路备注: - 第三路备注: - 第四路备注: - 第五路备注: - 第六路备注: - 第七路备注: - 第八路备注: - - - 传感器设置 - 选择传感器: - 下限 - 上限 - 注意:当传感器处于两个阀值限定的区间时触发命令 - 触发持续时间 - 满足条件持续 - S执行命令 - - - - 基本设置 - 启动退出 - 开机时自动启动(隐藏到托盘) - 关闭主面板时 - 隐藏到任务通知栏区域,不退出程序 - 退出程序 - 系统设置 - - - 测试工具 - 出厂设置 - 开始准备修复数据.. - 加载修复数据失败 - 请连接出厂发送卡设备! - 请连接有效的出厂发送卡设备! - 未连接发送卡! - 修复: 发送卡数量->[%d] , 接收卡数量-> [%d],是否正确? - 修复完成,重启发送卡生效. - 修复失败.错误码:%.8X? - - - 校正文件 : - 请加载校正数据文件... - 快速校正 : - 快速校正 - 颜色/补色 - 补红 - 补绿 - 补蓝 - 亮度校正 - 色度校正 - 关闭校正 - 固化数据 - 发送数据 - L1值必须小于L2 - 启用修缝 - 关闭修缝 - - 保存到灯板存储 - 从灯板存储加载 -自动启用 - - 联机 - 网络连接 - 状态:未监听 - 开始监听 - 校正系数文件接收设置 - 浏览 - 校正系数 - 高级 - 灯板FLASH数据管理(仅用于目标数据管理) - 数据写入 - 按照箱体 - 按照大屏 - 状态:--- - - 开始写入 - 数据读取 - 自动校正 - - 低灰校正补偿配置 - 启用低灰校正补偿 - 阈值: - 范围: - - 快速校正-高级配置 - 箱体批次 - 编辑批次数据: - 颜色 - - 绿 - - 补红 - 补绿 - 补蓝 - 发送当前批次 - 保存所有批次数据到接收卡 - 发送 - 固化 - 保存批次数据到本地 - 加载 - 保存 - 锁定布局 - 重置列表 - 刷新列表 - 保存 - - - 完成 - 提示 - 写入成功 - 失败 - 校正系数文件目录 - 状态:正在监听 %s:%d 已经连接 - 状状态:正在监听 %s:%d 已断开 - 停止监听 - 状态:正在监听 无连接! - 开始监听 - 状态:未监听 - 固化完成 - ccd 文件(*.ccd)|*.ccd|dat文件(*.dat)|*.dat|vu3文件(*.vu3)|*.vu3|| - - 成功 - 温馨提示 - 失败 - 补色 文件(*.clist)|*.clist|| - - - 哎呀,您的硬件数据 - 读取失败! - 插口没插稳? - 版本不正确? - 更新到最新版本 - 其他问题? - 重新连接后重试 - 帮助文档 - - - 快速分段配置 - 屏幕亮度: - 分段数: - 环境亮度上限值小于下限 - 屏幕上限值小于下限 - - - 接收卡数据巡检 - 发送卡修复 - 注意:根据发送卡中的数据来修复接收卡箱体的配置,需确认接收卡保存配置是否正确。适用于更换接收卡或者模组后的情况。 - 接收卡修复 - 固化 - 注意:根据接收卡中的数据来修复发送卡配置,适用于更换发送卡的情况。先进行接收卡自测, 观察屏幕显示是否正确 - 接收卡自测 - 修复发送卡 - 固化 - 巡检日志: - - - 获取发送卡巡检数据失败,当前发送卡可能没连接 - 获取箱体配置数据失败 - 获取箱体基本信息失败 - 发送卡与接收卡数据类型匹配 - 发送卡与接收卡数据类型部分匹配 - 发送卡与接收卡数据类型不匹配 - 获取箱体坐标数据失败 - 发送卡中没有该网口上连接箱体的坐标信息 - 发送卡保存巡检数据个数少于接收卡个数 - 正在修复箱体坐标 - 修复箱体坐标失败 - 正在修复箱体GIG坐标 - 修复箱体GIG坐标失败 - 箱体坐标及箱体GIG坐标正常 - 获取箱体数据CRC失败 - 发送卡中保存的箱体数据CRC错误 - 接收卡卡中获取的箱体数据CRC错误 - 箱体动态配置数据正常 - 正在修复箱体动态配置数据 - 修复箱体动态配置数据失败 - 当前发送卡下箱体巡检结束 - 巡检结束 - 正在从接收卡中获取巡检数据 - 从接收卡中获取巡检数据失败 - 接收卡中获取的巡检数据错误 - 异常 - 正在修复千兆网配置参数 - 修复千兆网配置参数失败 - 正在修复发送卡控制参数 - 修复发送卡控制参数失败 - 正在根据箱体坐标信息修复发送卡参数 - 巡检结束,请查看实际效果 - 巡检结束 - 固化成功 - 固化失败 - 提示 - 设备[ID:%s][型号:%s] - [网口:%d] - [接收卡:%d] - - 绿 - - - - 横线 - 竖线 - 左斜线“/” - 右斜线“\\” - 显示系统上电时间 - 显示接收卡物理地址 - 显示灰阶 - 正在显示 - 接收卡自测:%s - 完成 - 提示 - 接收卡自测结束 - 确定 - 正在巡检 - 确定要固化吗? - 提示 - 固化成功 - 固化失败 - 开始巡检,请确认接收卡自测正常! - 取消 - 正在修复发送卡 - 正在进行接收卡自测 - 确定要固化吗? - 正在固化数据... - - - 当前HUB列表: - 发送卡信息 - HUB地址 - 选择升级文件 - 升级失败 - 升级成功 - 请选择需要升级的HUB板 - 请选择升级文件 - 设备ID:%s,类型:%s,名称:%s - - - 升级发送卡固件 - 发送卡型号: - 升级FPGA: - 升级MCU: - 升级EDID: - 设备ID: - 发送卡列表: - FPGA版本 - MCU版本 - MCU升级状态 - FPGA升级状态 - 模式 - 注意:升级过程中切勿断电.升级按钮仅升级处于升级模式下的设备. - 进入正常模式 - 进入升级模式 - 参数错误或没有可升级的项目. - 没有可升级的设备.请连接设备或使设备进入升级状态. - 升级完成 - 升级失败;错误码:%d. - FPGA升级完成. - 升级FPGA... - 升级FPGA失败. - 需要进入BOOT模式升级. - 可升级. - 未在升级模式. - 型号与参数不匹配. - 升级完成. - 擦除升级标志OK. - 开始擦除升级标志... - 升级标志擦除失败... - MCU升级完成. - 升级MCU... - MCU升级失败. - EDID升级完成. - 升级EDID... - EDID升级失败. - ID升级完成. - 升级ID... - ID升级失败. - 重启OK. - 开始重启... - 重启失败... - 正常模式 - 升级模式 - 开始升级FPGA固件程序...,升级过程中请勿断电. - 开始升级MCU固件程序...,升级过程中请勿断电. - 开始升级EDID固件程序...,升级过程中请勿断电. - 开始升级设备ID固件程序...,升级过程中请勿断电. - 升级中...,请勿断电. - 自动重启固件程序. - 开始升级固件程序 - - - 请选择一个设备作为备份卡. - 设备失效了,请检查设备. - 配置成功 - 配置失败 - 备份卡(辅卡)配置 - 选择一个备份发送卡进行配置: - 提示: 选择的卡作为备份卡,进行配置后会把主卡的配置数据保存到备份卡中,同时把备份卡的网口设置为辅网口,同时删除备份卡的巡检数据. - 配置备份卡 - - - 不能为空! - 导出成功 - 制作厂家授权文件 - 管理员密码: - 显示 - 厂家授权码: - 生成 - - 一键解密 - 设备列表: - 输入解密密码: - 显示密码 - 资源无效 - 已解密%d个发送卡和%d个接收卡. - 时间: - 型号: - 名称: - 设备时间: - 状态代码: - 01. - 00. - 未初始化. - 工作状态. - - 索引 - 地址 - 运行时间 - 支持状态 - 执行状态 - 数量: - 支持 - 不支持 - 已过期 - 未过期 - - 加密配置向导 - 选择一个发送卡设置到期日期: - 到期日期: - 启用到期时间1 - 启用到期时间2 - 启用到期时间3 - 启用到期时间4 - 启用独立密码 - 设备授权 - 更新设备时间 - 读取到期日期 - 写入到期日期 - 请选择一个发送卡! - 设备未初始化! - 设备未加密! - 设备已无效! - 未授权! - 更新成功! - 未授权设备! - 时间密码%d不能为空! - 通信失败! - 设备未正常初始化! - 配置成功. - 授权状态: - 已授权 - 未授权 - 型号:---- - 名称:---- - 加密状态:---- - 接收卡数量:--;--;--;-- - 时间:2012-01-35 20:30:05 - 授权状态:未授权 - - 设备已经失效,请更新列表! - 请选择需要加密的设备! - 密码不能为空! - 密码长度不能超过32个字符! - 两次密码输入不一致! - 确认需要加密 [ %d ] 张发送卡及[ %d ]张接收卡 ? - 加密失败: 错误码: %d - 请先解密设备,在进行加密. - 加密成功,可以进行设置到期时间. - 加密配置向导 - 授权文件 - 授权文件: - 使用授权文件 - 设置加密密码 - 密码: - 确认密码:、 - 即将过期提示 - 过期提示 - 设备即将过期,请联系供应商... - 设备已达到使用期限,如需使用,请联系供应商... - 下一步 - - 控制系统加密 - 锁定系统 - 解除锁定 - 设置向导 - 系统状态 - 加密此设备 - - - - 密码不正确,请重新输入! - - - 设备状态 - 设备列表(选择设备查看状态) - - - diff --git a/LedOK/res/ProgramManager/EditProgram/AClock/Aclock1.jpg b/LedOK/res/ProgramManager/EditProgram/AClock/Aclock1.jpg deleted file mode 100644 index 47640cbf43255f2cdf7e2e9597d2a4493e490896..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30634 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ξ+C2_1{_BF2~mI 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 diff --git a/LedOK/res/ProgramManager/EditProgram/AClock/Aclock10.jpg b/LedOK/res/ProgramManager/EditProgram/AClock/Aclock10.jpg deleted file mode 100644 index b88288056fa0958f602769e2bb950d88126b3a70..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24229 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

XSL?PYEcX}N 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 Apa1{> diff --git a/LedOK/res/ProgramManager/EditProgram/AClock/Aclock3.jpg b/LedOK/res/ProgramManager/EditProgram/AClock/Aclock3.jpg deleted file mode 100644 index fa72acc904d7a5976d2bce4159562250ba94ba1d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26021 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 D0`T>z diff --git a/LedOK/res/ProgramManager/EditProgram/AClock/Aclock4.jpg b/LedOK/res/ProgramManager/EditProgram/AClock/Aclock4.jpg deleted file mode 100644 index 8d963593c11d8cef3e284b9c624d18a049e1c8c9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 182501 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 qxblOh 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 CUhpRX diff --git a/LedOK/res/ProgramManager/EditProgram/AClock/Aclock5.jpg b/LedOK/res/ProgramManager/EditProgram/AClock/Aclock5.jpg deleted file mode 100644 index 8c2ef708666965295356c5be3a3a49a5986db178..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 80020 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 diff --git a/LedOK/res/ProgramManager/EditProgram/AClock/Aclock6.jpg b/LedOK/res/ProgramManager/EditProgram/AClock/Aclock6.jpg deleted file mode 100644 index ef628a4b6c61287107fff8a0a82dfe97dc20ac0f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45110 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 diff --git a/LedOK/res/ProgramManager/EditProgram/AClock/Aclock7.jpg b/LedOK/res/ProgramManager/EditProgram/AClock/Aclock7.jpg deleted file mode 100644 index 0ab0ec09172ca9ea62e1f6569d18040dcb90c3e5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36848 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 WdI)%1GFX4C2zF%3^#l;N_4+R~`8cHj diff --git a/LedOK/res/ProgramManager/EditProgram/AClock/Aclock8.jpg b/LedOK/res/ProgramManager/EditProgram/AClock/Aclock8.jpg deleted file mode 100644 index fada9e91d5104bb977550cf0befbea5da128e1b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17762 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 diff --git a/LedOK/res/ProgramManager/EditProgram/DocAlignHC_u.png b/LedOK/res/ProgramManager/EditProgram/DocAlignHC_u.png deleted file mode 100644 index 52f2ab3c82feb362b0a526f060038e783d9f5c25..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 148 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbBqCH(4Ln2z=UfIZbz<`G}Q2#ye zom44bG5rT_2OZmYJo?2RpW$-EJ1c~lg;Pjnh13U5lk3Gx_bJ>-X)^j-Xuj8B$4QpC whiu(sILv1*@Y!*^gZZJFaL8N*$F~mB_Ix&+8GGkl1zN-4>FVdQ&MBb@0LDZyUjP6A diff --git a/LedOK/res/ProgramManager/EditProgram/DocAlignHL_s.png b/LedOK/res/ProgramManager/EditProgram/DocAlignHL_s.png deleted file mode 100644 index fd7574a78eb69befef414bd9e44d788173d17a35..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 140 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbBf<0XvLn2z=Ub@K1puppNknhox zzNb!BO#w{2Z@HiRSLob&zBDU@nSqgsWrfrPrj?h(Q_Lk5zP3MWe51zvWwlnVW7%ZJ np!y8C6M04seyl7jWM44Wc~|rB*p=M?8qeVA>gTe~DWM4f4*M)> diff --git a/LedOK/res/ProgramManager/EditProgram/DocAlignHL_u.png b/LedOK/res/ProgramManager/EditProgram/DocAlignHL_u.png deleted file mode 100644 index 2d422a164853f6cf8c1a2ebb05b22afdbdca8e3d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 144 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbB!aZFaLn2z=UOC9gpulr9V0t-o zzTf4OB`l6yytAC&@z-T`cet(!WoF?NQduEY!1^kA*%v(y^O+0YNdMw*neB5y^G@=S s#)8S5r}i!U@37+}%S0iS7nT>;{umdKI;Vst0OKMtJOBUy diff --git a/LedOK/res/ProgramManager/EditProgram/DocAlignHR_s.png b/LedOK/res/ProgramManager/EditProgram/DocAlignHR_s.png deleted file mode 100644 index fee2858b9cfe3bbec533f92ce8431152868085e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 141 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbBLOfj@Ln2z=UOLFhpdi5P$i1=X z^d`l(igWHLNuQ`!kSu=d{OSc8hmeX#fVl!w=+k(CJR`@|k1|%Oc%$NbBLOop^Ln2z=UOC9gV8C%SVETKu zy`@s>+2sNU1By=kJt(ehtiN&w8;6jJ#|4uGEK$F=e9`AHpSd7whxDPwg2|k#?sd(t qsxflBT43J7{7_9;#bd&PHo1noHk>gM3(|oWFnGH9xvX|k1|%Oc%$NbB0z6$DLn2z=UOLFhpuod&P$cQ; zv{dI?4f7LJj&E%I%O8_;X6w|hJO%}a28L2*21X_o&Q(_N6Yium82$Yrtq)@4h0fLY h$TM>AVr2Sqi?QKJgvj<}X%nE?44$rjF6*2UngE7HE6)G` diff --git a/LedOK/res/ProgramManager/EditProgram/DocAlignVB_u.png b/LedOK/res/ProgramManager/EditProgram/DocAlignVB_u.png deleted file mode 100644 index f7a6999f3adf18db19afbaf1d927ad89f7e05967..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 140 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbBf<0XvLn2z=UfIaWpuoc#IK7R=NE?)jwoWp$P og3ukuJD4A;3A=brSa4ab`G9BPl=_n8K;s!aUHx3vIVCg!0RDY0CjbBd diff --git a/LedOK/res/ProgramManager/EditProgram/DocAlignVC_s.png b/LedOK/res/ProgramManager/EditProgram/DocAlignVC_s.png deleted file mode 100644 index c6a5a091188f2b3b1da5fb1d28d5612a3078659e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 137 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbB0z6$DLn2z=UOLFhV8FrR$nE)5 zQ=3G#FGAKASF!(YvY;9O|PF%%Ya)FO*{bSZivw1G8U-g;w jq%WI?CQt$6tapr6-y=k}#5Gp~&1Ud)^>bP0l+XkKg7GN{ diff --git a/LedOK/res/ProgramManager/EditProgram/DocAlignVC_u.png b/LedOK/res/ProgramManager/EditProgram/DocAlignVC_u.png deleted file mode 100644 index e49e1c8fa3b646f9602c98ae2de267588cb4e6cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 141 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbBLOfj@Ln2z=UfIaWpuppDQRh8d znP2hbmrQ0&itay-zL$^j@VMpYYRVv>;Lxy&u_4GId7b`O)|bP0l+XkKJfAH^ diff --git a/LedOK/res/ProgramManager/EditProgram/DocAlignVT_s.png b/LedOK/res/ProgramManager/EditProgram/DocAlignVT_s.png deleted file mode 100644 index f93312a0e07d95b902102544d0f8dcf04763b1e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 136 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbB{5@S9Ln2z=UOLFhpuod&P$cQ; zv{dI?4f7LJj&E%I%O8_;X6w|hJO%}a1{KH9=iHNK^8_rDuYb%6WL#Lg>ND#}Up5a- ihXw}5S9}5suJe_0MTj^kmevD}X7F_Nb6Mw<&;$UH9xIvv diff --git a/LedOK/res/ProgramManager/EditProgram/DocAlignVT_u.png b/LedOK/res/ProgramManager/EditProgram/DocAlignVT_u.png deleted file mode 100644 index 8e2c8b5b860ecc9a37ef479232b6823c3332114a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 140 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbBf<0XvLn2z=UfIaWpuoc#IK7?YQkH%zDpD; n+(~Kj;1p8v2qmMPgb)YL&#Q zq$UlvNt6B^#D_sDB$&Jm@8G7p;m2|Bl2p3TM3OQ^8^Aye#6XD$ZJc!QS19@jd$)be z@82Z@^c|XMBU={Z1r0tX-~<_*AR}K>z)QLhRqq<{g8D=ISAFL~C3V-EB2#M71uY(k zz9}sP+@*g9jO{B8nrV}|<9b-Fw&^Z)rqsfXYLTAHo=F#!E;Ny^DWqrQc=SQ*RsWt* z2W{0KNza?*&;>0YNqDs!(j&C>_&}EJV)y!)OnWug*#HuT3Zy^^G<#4=b6DzjXEp~6n7l)Iz0L#l6V38~73H*`N7IEkqY!5lq9g?rkQU0s zr)fc&<^8Ll!${Ou27;=p<$`!wwx-l~mu?QqId4szxBR zFQx@`v2W2^H?UQs6`TY9rFrHMq(BO!K(g}<-Xku5$Yi3Q P00000NkvXXu0mjfV`iQ1 diff --git a/LedOK/res/ProgramManager/EditProgram/FontItalics_s.png b/LedOK/res/ProgramManager/EditProgram/FontItalics_s.png deleted file mode 100644 index 82c3565004fe765d8fb4db8d2e8ddd04dc1961a2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 340 zcmV-a0jvIrP)8=4T(sDOSsfv6h_f-1Ia&k$V|C%Il%?J zT&XPM+jd3=J@(w;9QZ9~c=&Lh=i#I_PM%3pQqlkmvLFkxAZdVckmD*Aon{cry-+iV z0cZ@OWVGx(o&j+95XgfvrH*dX-eq4Nv|H7xV6a`>j-m2(ORmf22g*1u_NfTj6P=Eq9$&;N9RNh*t#MRB<;Vd4kPxnW6(6%l5 zlmRy&fC4Ch0*D*n6{KXIL1taWXw>H|Nh zK7KmT#aMpO$EJdigvV*r`7bY^C@t>Zs(%5Ezc=hHEBXN%zC;j`P;4uH(AgL_(EH|CS||ufP`Ty@HBEzu@f<=DHoKY! zbh;R*Ttnp=GnKi4o+hb#H}?MX@n_K47!>91*Ralz?*vc)1yBHS=L^V0W21qC6o3E# N002ovPDHLkV1jgGhUowR diff --git a/LedOK/res/ProgramManager/EditProgram/FontUnderline_s.png b/LedOK/res/ProgramManager/EditProgram/FontUnderline_s.png deleted file mode 100644 index b9e98c5639e8377cf8ea78fe2d12088870351dcf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 333 zcmV-T0kZyyP)3y=Gs$FM{3@aExE~p_N()C z6mOn>)N|z~FToT8)IA+(b}Z0F(WN&Ue?e`Yw6JW&?s=EHVG!1KBL1IPAj?*4RoeJ( zlknp2nY_;^Tn{48jSaGFMYiN}c-5!c8R7UE$JaDGO`-M}zSvShNoD;(QP2MarEX;c fT6F{@pugq=!LM%IFl8Iz00000NkvXXu0mjfL#&K^ diff --git a/LedOK/res/ProgramManager/EditProgram/FontUnderline_u.png b/LedOK/res/ProgramManager/EditProgram/FontUnderline_u.png deleted file mode 100644 index a05de36533ed3d3ae399297b43d3aec5ad212ba7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 305 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 diff --git a/LedOK/res/ProgramManager/EditProgram/勾.png b/LedOK/res/ProgramManager/EditProgram/勾.png deleted file mode 100644 index e04b74436a390ca96f7a524ca3820ca4335aef5c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 491 zcmVU7>tO5EU1kbKiJsJ$gY|gH@@ZN@Nmw#CxrE9B*u8e-OtAuPbNt+_Fq6r zcYrSN$jm0z1-koTNw+0^lhgwq#~3Gv1|=P;z^{^)fq8eI%Cc;9C@{u2Dd|=XN?I_p z=>f3OXlz`oXl4_@&Atv_0y6_2RF>rlGngDK2{yC+zztxj8u>MFE=iKDzZC;7fS#o9!2Pl;kN*k-`}#rPjk{kkv++NU zB11!8%!%jaFB%P$9j( zvw83CSJE`yxn{6Vk|blmjHJbC++|50f!TJuz3ZRBI%%42F|)Iho=I8+uA15Ip}{(4 hHV!22erlKwe*lp0%>tQ+w7&oV002ovPDHLkV1oGo;;R4v diff --git a/LedOK/res/ProgramManager/EditProgram/图层 11.png b/LedOK/res/ProgramManager/EditProgram/图层 11.png deleted file mode 100644 index b2a1323e15a8d24f52fd65642742bce0f1cfbd3a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 385 zcmV-{0e=38P)g z&i6&em>m(lPbQP6sN+kLD-g(sq`FBUN%q1ky$QtC00000NkvXXu0mjfa8a?; diff --git a/LedOK/res/ProgramManager/EditProgram/圆角矩形 3.png b/LedOK/res/ProgramManager/EditProgram/圆角矩形 3.png deleted file mode 100644 index 8fffceb07955b3cc886e5b6633846fd674c5f358..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 177 zcmeAS@N?(olHy`uVBq!ia0vp^G9b*s1|*Ak?@s|z6`n4RAs(G?uWjT#V!*@fP&)7B zW=8Evvu}3aQhqYq;>V-a3|^{CIw7)G3>i#3V=rx~O$)g+$v zH&JBLan^M=s>HSxTeFHqBs4+@JLc=9HJdir3ag&oU>hfUh(YS)$IqE=)88^KsAaT~ Wo5-BG@{AVH4Gf;HelF{r5}E)EdOq?1 diff --git a/LedOK/res/ProgramManager/EditProgram/圆角矩形 30.png b/LedOK/res/ProgramManager/EditProgram/圆角矩形 30.png deleted file mode 100644 index dc9779c9787a741aec32fb173476e7cb55ccd85d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1124 zcmeAS@N?(olHy`uVBq!ia0y~yV9WrrH8|LSUK@~NNifs0r`%NECNLd>TE}(Hyh4SWUF;} zes%NJ9qXd=)SXxMJLj!;&XfpA~5lTha0nrhd> zKh!m^AI>SB5qB$do25_iI`;g3=QrDbef>Q8$=Vn4e;3y)|KnXMyVudJsHJb->sMSi z&OclB=AGW#E6@Li=fB&yBqsbsG}P?fOdS^;+|Pe)H~${->y8{q&9?_-+!T>&5kc|08M@A$MVwU|BLz4>hCcq zDHN6P9kB~!Zz@?-|Hc2beLjPrfTb0C()<<7j#fY`mp`3v-oVizGnaXz|CL6Cxj@%m z{&Zg2fyJfoT;mP(R}K^WzV!dg{P~<$fl0~zxx*XbQUwonU?^<)^O;S6apK})g>Ri! z0!xH}o{SoG)-VmNwo85Y1fKWbi<`K3c})1bH_AITcklMLzPqNp{N9~p&zjjwn2`~Q|W_0QzVuSuug$-M<8cKN^7@9*ayy<_1UZnm)&Sb8vcy85}Sb4q9e E06nQFCjbBd diff --git a/LedOK/res/ProgramManager/EditProgram/矩形 17.png b/LedOK/res/ProgramManager/EditProgram/矩形 17.png deleted file mode 100644 index db71ad0df8e2fc04a0ecd1aff6f83e48d510880f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 89 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`3Z5>GAr`&K96UUK{5jJW%wptG lX$oX^J{`m8yDTFIC Yum+h`YPn>00c9CHUHx3vIVCg!0Qx`=kpKVy diff --git a/LedOK/res/ProgramManager/EditProgram/矩形 51 拷贝.png b/LedOK/res/ProgramManager/EditProgram/矩形 51 拷贝.png deleted file mode 100644 index e363ce4b217f6676e55d32507da7daf8fbda4aec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 407 zcmV;I0cie-P)4aC0#g+q5}vaTsGe17ls#m{z? zT9zTV3n+8%{gzr&V0q6V&y-SYF+rJ2-T{(NAn|}aZzC3#$3XH0Bpyhpm$)IhUJ^Wz z_%>I7a?`|=$TlgS=hXm6Zkt4ih+6B+pxg%rNY0b4wbmIB-$kx2VvIql0&&aJUg9a@ z#JM4$JOu{Go%R&x$Dl1F0kIb6moOJOPKr;Q8ye#0z?J2b$iN7Y7h%sGB*mR`Lm+vL z!U~AGszwI+J;d-~kG8B5OO&FC*|&DvkbHy_B?k#%Jpz)qD9kb`JnImy`y95SL_YfI zi&{jx!*lgyEV?p?pT9D02Kg-Y;m&cZw@)6Tl&3MqP(0@y3!=5o05`nSd0q`ljE|7~ z{RkQSr?Y9OdFZ9}(8KH(hh8bA3OgSI@zth&P2bpx0On#KFGm0X002ovPDHLkV1iYa Bu@e9Q diff --git a/LedOK/res/ProgramManager/EditProgram/矩形 57.png b/LedOK/res/ProgramManager/EditProgram/矩形 57.png deleted file mode 100644 index 70cf53a4ca4c6fc1e5b1541ad043c4f0e1102b15..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 114 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbBEInNuLn2z=o>OFGFyLX{@UuKL zb$8ohK9-jBNpDmy^Ko!;a&BdI0)n><6DCXuuvSn}QMtm$@we(%dA*?8%9^P_Ll`_= L{an^LB{Ts5U9uq~ diff --git a/LedOK/res/ProgramManager/EditProgram/组 37.png b/LedOK/res/ProgramManager/EditProgram/组 37.png deleted file mode 100644 index 6ca23a2e7a70877997faa888ad9b4b27807633ed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 109 zcmeAS@N?(olHy`uVBq!ia0vp^;y^6Q!3HGPJ}O-eq)a?r978O6lM@`6jW+B3J>GWl z>O@vIUU}0wyV@qdZ3sN<4rJFDNc)9euuA<_AC)*uijU#GiwU=*!m+tP{S2P2elF{r G5}E)Z>mZ{5 diff --git a/LedOK/res/ProgramManager/EditProgram/组 41.png b/LedOK/res/ProgramManager/EditProgram/组 41.png deleted file mode 100644 index 1db60ea89a3c624a6be54e5dfc8d3cad5243d209..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 809 zcmV+^1J?YBP)x;i_059s|kPAwB}+CXmFM_;`vW@ez>3b!vYtOx{#$0wnPw0)X-cB%wpR zn*~m)7Xr!aDp&`DgCyagnw$F$B>j9mO+3;lPjg9Gz23Twq5(N_NM4f3^8{>{4-<0I zp7m*D4@ly)vSqNExC$h(gTX;YAURIMY>p=~hMGyr%()9Ursf#kJ_01#gS zNenKZ&c_I&~SrIfNPYc0uXz8Fd=rRwheo|W6?MFceRPauhH zl*+8nMyZ$vd?<@`-0l`2N8klbrIfO6{T_yb7Bj@#Y3_WezBq#H{m|Gx+*W%|aGnnpgedcE}|4mW`K@7{e=y@#;-ywNP|1WMj z8_BLo?JtHKfE+DNK&fooVxXXtHWpCONyk>j<}JOM9pare_h;kHde(>uOAGG9&9$=Rg40?nlH@X-kE8V^ZZ#WvgFYvSAcRgTd7ZB-R>56 nQmec7dkbRin%DAW`mFc^k!d#mN-~6300000NkvXXu0mjfvzBkx diff --git a/LedOK/res/ProgramManager/EditProgram/组 57(1).png b/LedOK/res/ProgramManager/EditProgram/组 57(1).png deleted file mode 100644 index 5bb72703eaa51cb4f3f6d6846def579da59cb26f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 182 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbBYCT;XLn2z=UN+=9puoc#pdYV4 z!7B98B<~Krc{+Kmd`-SNTpT{bzW<%6{qfdjjSAY6{lBZ`<+NjP1+4&!-ufI20NfZmBRZ cez6Q-RoN70S6Ke~5zrwFp00i_>zopr0E?4A=l}o! diff --git a/LedOK/res/RadioChecked.png b/LedOK/res/RadioChecked.png deleted file mode 100644 index 2fd260e9cc61e9782464e18989a87ba2bdb531fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 343 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 diff --git a/LedOK/res/ProgramManager/EditProgram/AClock.png b/LedOK/res/program/AClock.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/AClock.png rename to LedOK/res/program/AClock.png diff --git a/LedOK/res/ProgramManager/EditProgram/Add.png b/LedOK/res/program/Add.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/Add.png rename to LedOK/res/program/Add.png diff --git a/LedOK/res/ProgramManager/EditProgram/AddPlan.png b/LedOK/res/program/AddPlan.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/AddPlan.png rename to LedOK/res/program/AddPlan.png diff --git a/LedOK/res/ProgramManager/EditProgram/ArrayBottom.png b/LedOK/res/program/ArrayBottom.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/ArrayBottom.png rename to LedOK/res/program/ArrayBottom.png diff --git a/LedOK/res/ProgramManager/EditProgram/ArrayHCenter.png b/LedOK/res/program/ArrayHCenter.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/ArrayHCenter.png rename to LedOK/res/program/ArrayHCenter.png diff --git a/LedOK/res/ProgramManager/EditProgram/ArrayLeft.png b/LedOK/res/program/ArrayLeft.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/ArrayLeft.png rename to LedOK/res/program/ArrayLeft.png diff --git a/LedOK/res/ProgramManager/EditProgram/ArrayRight.png b/LedOK/res/program/ArrayRight.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/ArrayRight.png rename to LedOK/res/program/ArrayRight.png diff --git a/LedOK/res/ProgramManager/EditProgram/ArrayTop.png b/LedOK/res/program/ArrayTop.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/ArrayTop.png rename to LedOK/res/program/ArrayTop.png diff --git a/LedOK/res/ProgramManager/EditProgram/ArrayVCenter.png b/LedOK/res/program/ArrayVCenter.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/ArrayVCenter.png rename to LedOK/res/program/ArrayVCenter.png diff --git a/LedOK/res/ProgramManager/EditProgram/Audio.png b/LedOK/res/program/Audio.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/Audio.png rename to LedOK/res/program/Audio.png diff --git a/LedOK/res/ProgramManager/EditProgram/Clean.png b/LedOK/res/program/Clean.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/Clean.png rename to LedOK/res/program/Clean.png diff --git a/LedOK/res/ProgramManager/EditProgram/CleanPlan.png b/LedOK/res/program/CleanPlan.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/CleanPlan.png rename to LedOK/res/program/CleanPlan.png diff --git a/LedOK/res/ProgramManager/EditProgram/ColorText.png b/LedOK/res/program/ColorText.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/ColorText.png rename to LedOK/res/program/ColorText.png diff --git a/LedOK/res/ProgramManager/EditProgram/Copy.png b/LedOK/res/program/Copy.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/Copy.png rename to LedOK/res/program/Copy.png diff --git a/LedOK/res/ProgramManager/EditProgram/Cut.png b/LedOK/res/program/Cut.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/Cut.png rename to LedOK/res/program/Cut.png diff --git a/LedOK/res/ProgramManager/EditProgram/DClock.png b/LedOK/res/program/DClock.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/DClock.png rename to LedOK/res/program/DClock.png diff --git a/LedOK/res/ProgramManager/EditProgram/DateSelect.png b/LedOK/res/program/DateSelect.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/DateSelect.png rename to LedOK/res/program/DateSelect.png diff --git a/LedOK/res/ProgramManager/EditProgram/DateSelect_e.png b/LedOK/res/program/DateSelect_e.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/DateSelect_e.png rename to LedOK/res/program/DateSelect_e.png diff --git a/LedOK/res/ProgramManager/EditProgram/DateSelect_enable.png b/LedOK/res/program/DateSelect_enable.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/DateSelect_enable.png rename to LedOK/res/program/DateSelect_enable.png diff --git a/LedOK/res/ProgramManager/EditProgram/Delete.png b/LedOK/res/program/Delete.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/Delete.png rename to LedOK/res/program/Delete.png diff --git a/LedOK/res/ProgramManager/EditProgram/Gif.png b/LedOK/res/program/Gif.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/Gif.png rename to LedOK/res/program/Gif.png diff --git a/LedOK/res/ProgramManager/EditProgram/GoDown.png b/LedOK/res/program/GoDown.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/GoDown.png rename to LedOK/res/program/GoDown.png diff --git a/LedOK/res/ProgramManager/EditProgram/GoUp.png b/LedOK/res/program/GoUp.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/GoUp.png rename to LedOK/res/program/GoUp.png diff --git a/LedOK/res/ProgramManager/EditProgram/LayerBottom.png b/LedOK/res/program/LayerBottom.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/LayerBottom.png rename to LedOK/res/program/LayerBottom.png diff --git a/LedOK/res/ProgramManager/EditProgram/LayerDown.png b/LedOK/res/program/LayerDown.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/LayerDown.png rename to LedOK/res/program/LayerDown.png diff --git a/LedOK/res/ProgramManager/EditProgram/LayerTop.png b/LedOK/res/program/LayerTop.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/LayerTop.png rename to LedOK/res/program/LayerTop.png diff --git a/LedOK/res/ProgramManager/EditProgram/LayerUp.png b/LedOK/res/program/LayerUp.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/LayerUp.png rename to LedOK/res/program/LayerUp.png diff --git a/LedOK/res/ProgramManager/EditProgram/Movie.png b/LedOK/res/program/Movie.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/Movie.png rename to LedOK/res/program/Movie.png diff --git a/LedOK/res/ProgramManager/EditProgram/Office.png b/LedOK/res/program/Office.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/Office.png rename to LedOK/res/program/Office.png diff --git a/LedOK/res/ProgramManager/EditProgram/Photo.png b/LedOK/res/program/Photo.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/Photo.png rename to LedOK/res/program/Photo.png diff --git a/LedOK/res/ProgramManager/EditProgram/Rss.png b/LedOK/res/program/Rss.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/Rss.png rename to LedOK/res/program/Rss.png diff --git a/LedOK/res/ProgramManager/EditProgram/Save.png b/LedOK/res/program/Save.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/Save.png rename to LedOK/res/program/Save.png diff --git a/LedOK/res/ProgramManager/EditProgram/SaveAs.png b/LedOK/res/program/SaveAs.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/SaveAs.png rename to LedOK/res/program/SaveAs.png diff --git a/LedOK/res/ProgramManager/EditProgram/ScaleDown.png b/LedOK/res/program/ScaleDown.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/ScaleDown.png rename to LedOK/res/program/ScaleDown.png diff --git a/LedOK/res/ProgramManager/EditProgram/ScaleOrg.png b/LedOK/res/program/ScaleOrg.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/ScaleOrg.png rename to LedOK/res/program/ScaleOrg.png diff --git a/LedOK/res/ProgramManager/EditProgram/ScaleUp.png b/LedOK/res/program/ScaleUp.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/ScaleUp.png rename to LedOK/res/program/ScaleUp.png diff --git a/LedOK/res/ProgramManager/EditProgram/Send.png b/LedOK/res/program/Send.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/Send.png rename to LedOK/res/program/Send.png diff --git a/LedOK/res/ProgramManager/EditProgram/Setting.png b/LedOK/res/program/Setting.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/Setting.png rename to LedOK/res/program/Setting.png diff --git a/LedOK/res/ProgramManager/EditProgram/Temp.png b/LedOK/res/program/Temp.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/Temp.png rename to LedOK/res/program/Temp.png diff --git a/LedOK/res/ProgramManager/EditProgram/Text.png b/LedOK/res/program/Text.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/Text.png rename to LedOK/res/program/Text.png diff --git a/LedOK/res/program/TextAlignHC.png b/LedOK/res/program/TextAlignHC.png new file mode 100644 index 0000000000000000000000000000000000000000..ac50ff344fdcc0d949c673e2faed6125ecbb5c57 GIT binary patch literal 384 zcmeAS@N?(olHy`uVBq!ia0vp^av;pX1|+Qw)-3{34>O&e1B!#(ofsG-rY0vO*qmix z@!{j)*;%RT>iEu&OK@T!7mtU6;m#cmjOGa`2|vnsU5pH3uJP(5CLdZXCjCH%DT-r> zJ;O#1s~KlcFeRxw-VjnKtMqi_oUoQTNnKo|@rHxA@duGs7E9)vb`IN|tc0vNJLgV{ zn!}UwoZ;q2j{Q&1rzdRqap=GS8$rcsCcTY`)z-|-M`T-OoN{7g`xnO6mOEWAY5w1X z|58P)LncK9G6{XWT%Mxgq2tBkZQRUcqTAc}@Ny9w+dU69wujt2JTVsq${QH74Gk7} z@~8v7m1t>J;q_pWFVM4`1s;*b3=FbuAj}xMNVpLw=<4a>7~;|S_KG7Hg93+3;OyV? zZ{8An;$-0QBY$O&e1B!#(ofsG-rY0vO*qmix z@!{j)*;%RT>iEu&OK@T!7mtU6;m#cmjOGa`2|vnsU5pH3uJP(5CLdZXCjCH%DT-r> zJ;O#1s~KlcFeRxw-VjnKtMqi_oUoQTNnKo|@rHxA@duGs7E9)vb`IN|tc0vNJLgV{ zn!}UwoZ;q2j{Q&1rzdRqap=GS8$rcsCcTY`)z-|-M`T-OoN{7g`xnO6mOEWAY5w1X z|58P)LncK9G6{XWT%Mxgq2tBkZQRUcqTAc}@Ny9w+dU69wujt2JTVsq${QH74Gk7} z@~8v7m1t>J;q_pWFVM4`1s;*b3=FbuAj}xMNVpLw=;-O<7~;|S_R2v{1_KV~z}bJ( zx5X}yYZ1}y literal 0 HcmV?d00001 diff --git a/LedOK/res/program/TextAlignHR.png b/LedOK/res/program/TextAlignHR.png new file mode 100644 index 0000000000000000000000000000000000000000..2e66817f4d55ea7c1e15f83cabe443c6923a680c GIT binary patch literal 379 zcmeAS@N?(olHy`uVBq!ia0vp^av;pX1|+Qw)-3{34>O&e1B!#(ofsG-rY0vO*qmix z@!{j)*;%RT>iEu&OK@T!7mtU6;m#cmjOGa`2|vnsU5pH3uJP(5CLdZXCjCH%DT-r> zJ;O#1s~KlcFeRxw-VjnKtMqi_oUoQTNnKo|@rHxA@duGs7E9)vb`IN|tc0vNJLgV{ zn!}UwoZ;q2j{Q&1rzdRqap=GS8$rcsCcTY`)z-|-M`T-OoN{7g`xnO6mOEWAY5w1X z|58P)LncK9G6{XWT%Mxgq2tBkZQRUcqTAc}@Ny9w+dU69wujt2JTVsq${QH74Gk7} z@~8v7m1t>J;q_pWFVM4`1s;*b3=FbuAj}xMNVpLw=-}z%7~;|S_R2v{1_d7Hi?jZw zuhUE5YvtmdKI;Vst01}dbO8@`> literal 0 HcmV?d00001 diff --git a/LedOK/res/program/TextAlignVB.png b/LedOK/res/program/TextAlignVB.png new file mode 100644 index 0000000000000000000000000000000000000000..0de9f9877198307a8f0c0eabf396166954f458dd GIT binary patch literal 380 zcmeAS@N?(olHy`uVBq!ia0vp^av;pX1|+Qw)-3{34>O&e1B!#(ofsG-rY0vO*qmix z@!{j)*;%RT>iEu&OK@T!7mtU6;m#cmjOGa`2|vnsU5pH3uJP(5CLdZXCjCH%DT-r> zJ;O#1s~KlcFeRxw-VjnKtMqi_oUoQTNnKo|@rHxA@duGs7E9)vb`IN|tc0vNJLgV{ zn!}UwoZ;q2j{Q&1rzdRqap=GS8$rcsCcTY`)z-|-M`T-OoN{7g`xnO6mOEWAY5w1X z|58P)LncK9G6{XWT%Mxgq2tBkZQRUcqTAc}@Ny9w+dU69wujt2JTVsq${QH74Gk7} z@~8v7m1t>J;q_pWFVM4`1s;*b3=FbuAj}xMNVpLw=;-O<7~;|S_Oc-#g93+h;G4ha zd)CeJP!d%CAFY_0VZhA5a6jwffxFd589i@Hui`k~x#4l-w)ZQpr>YBgNdGaMCwbO^ Vhihfq=NO=244$rjF6*2UngGG?f;0dC literal 0 HcmV?d00001 diff --git a/LedOK/res/program/TextAlignVC.png b/LedOK/res/program/TextAlignVC.png new file mode 100644 index 0000000000000000000000000000000000000000..8b95526d5c1be3b3d870c3da1b130b62faec8c7d GIT binary patch literal 381 zcmeAS@N?(olHy`uVBq!ia0vp^av;pX1|+Qw)-3{34>O&e1B!#(ofsG-rY0vO*qmix z@!{j)*;%RT>iEu&OK@T!7mtU6;m#cmjOGa`2|vnsU5pH3uJP(5CLdZXCjCH%DT-r> zJ;O#1s~KlcFeRxw-VjnKtMqi_oUoQTNnKo|@rHxA@duGs7E9)vb`IN|tc0vNJLgV{ zn!}UwoZ;q2j{Q&1rzdRqap=GS8$rcsCcTY`)z-|-M`T-OoN{7g`xnO6mOEWAY5w1X z|58P)LncK9G6{XWT%Mxgq2tBkZQRUcqTAc}@Ny9w+dU69wujt2JTVsq${QH74Gk7} z@~8v7m1t>J;q_pWFVM4`1s;*b3=FbuAj}xMNVpLw=;Z0*7~;|S_Oc@vg93+3;OyV? zZ{8A9QQ4{SBY$;Ix1%w`58rOKclWgUJZ{|!aJBGjkv+eu)_t#@^-PC55BeD&)G{xO W=iy57wg?BB#^CAd=d#Wzp$Pyw4}m5C literal 0 HcmV?d00001 diff --git a/LedOK/res/program/TextAlignVT.png b/LedOK/res/program/TextAlignVT.png new file mode 100644 index 0000000000000000000000000000000000000000..fc0e4dbac66a19fa96c16685da7b9068c1086299 GIT binary patch literal 381 zcmeAS@N?(olHy`uVBq!ia0vp^av;pX1|+Qw)-3{34>O&e1B!#(ofsG-rY0vO*qmix z@!{j)*;%RT>iEu&OK@T!7mtU6;m#cmjOGa`2|vnsU5pH3uJP(5CLdZXCjCH%DT-r> zJ;O#1s~KlcFeRxw-VjnKtMqi_oUoQTNnKo|@rHxA@duGs7E9)vb`IN|tc0vNJLgV{ zn!}UwoZ;q2j{Q&1rzdRqap=GS8$rcsCcTY`)z-|-M`T-OoN{7g`xnO6mOEWAY5w1X z|58P)LncK9G6{XWT%Mxgq2tBkZQRUcqTAc}@Ny9w+dU69wujt2JTVsq${QH74Gk7} z@~8v7m1t>J;q_pWFVM4`1s;*b3=FbuAj}xMNVpLw=;Z0*7~;|S_Oc@vg93+3;OyV? zZ{8A9QSqGp@3z+CqzgR#TQVNJ+xw_t$y?sgmd7qPKI+^qzw&z1WX>bJ|0Ea~YEl?V X>v*`9ghjppn#SPi>gTe~DWM4f{j7y- literal 0 HcmV?d00001 diff --git a/LedOK/res/ProgramManager/EditProgram/TileFull.png b/LedOK/res/program/TileFull.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/TileFull.png rename to LedOK/res/program/TileFull.png diff --git a/LedOK/res/ProgramManager/EditProgram/TileH.png b/LedOK/res/program/TileH.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/TileH.png rename to LedOK/res/program/TileH.png diff --git a/LedOK/res/ProgramManager/EditProgram/TileV.png b/LedOK/res/program/TileV.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/TileV.png rename to LedOK/res/program/TileV.png diff --git a/LedOK/res/ProgramManager/EditProgram/Timer.png b/LedOK/res/program/Timer.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/Timer.png rename to LedOK/res/program/Timer.png diff --git a/LedOK/res/ProgramManager/EditProgram/Weather.png b/LedOK/res/program/Weather.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/Weather.png rename to LedOK/res/program/Weather.png diff --git a/LedOK/res/ProgramManager/EditProgram/Web.png b/LedOK/res/program/Web.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/Web.png rename to LedOK/res/program/Web.png diff --git a/LedOK/res/ProgramManager/EditProgram/Window.png b/LedOK/res/program/Window.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/Window.png rename to LedOK/res/program/Window.png diff --git a/LedOK/res/ProgramManager/bnExport_s.png b/LedOK/res/program/bnExport_s.png similarity index 100% rename from LedOK/res/ProgramManager/bnExport_s.png rename to LedOK/res/program/bnExport_s.png diff --git a/LedOK/res/ProgramManager/bnExport_u.png b/LedOK/res/program/bnExport_u.png similarity index 100% rename from LedOK/res/ProgramManager/bnExport_u.png rename to LedOK/res/program/bnExport_u.png diff --git a/LedOK/res/ProgramManager/bnSearch.png b/LedOK/res/program/bnSearch.png similarity index 100% rename from LedOK/res/ProgramManager/bnSearch.png rename to LedOK/res/program/bnSearch.png diff --git a/LedOK/res/ProgramManager/bnSend_s.png b/LedOK/res/program/bnSend_s.png similarity index 100% rename from LedOK/res/ProgramManager/bnSend_s.png rename to LedOK/res/program/bnSend_s.png diff --git a/LedOK/res/ProgramManager/bnSend_u.png b/LedOK/res/program/bnSend_u.png similarity index 100% rename from LedOK/res/ProgramManager/bnSend_u.png rename to LedOK/res/program/bnSend_u.png diff --git a/LedOK/res/ProgramManager/EditProgram/preview.png b/LedOK/res/program/preview.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/preview.png rename to LedOK/res/program/preview.png diff --git a/LedOK/res/ProgramManager/EditProgram/previewStop.png b/LedOK/res/program/previewStop.png similarity index 100% rename from LedOK/res/ProgramManager/EditProgram/previewStop.png rename to LedOK/res/program/previewStop.png diff --git a/LedOK/res/random.png b/LedOK/res/random.png new file mode 100644 index 0000000000000000000000000000000000000000..179728e158e58fe253074c6aa60122efaef1ea6d GIT binary patch literal 1695 zcmV;Q24MM#P)V>U4h#&rc_l?b?oJ93kx>c^NFXt}xPSpSU}RwUb`3-_FkIFREMa59 zqZS+BECN~xq(1<$NIIC!$O2*~LD&)?c6mub36QM=VkZ|Af!IJ7Gw>9J1UUoQK0vlY zIubhxiJg*KoD5{=0NL>fzva(oV6gbYz`#5aA(k|afnj?)1B1jJgqX@g1_u6C28L~y z5n`YH!Tx0wJ5-WdQ34Y2(|2SjNGwVOOEZH4G%byR;nQ*k2Hr>p2H^_~3|!F=cYpzF zF)*M>3@1VW0AV>ccuL@sO#lD@32;bRa{vGxh5!H^h5=oo6M+B#1!PG?K~#90?cGa` z+e!>TQR*Q}%Klf7JvoCwfZNZK>O&Skbq|n120>i*HPx0%Z4m$f00000000000C4B< zegFvKkGy{T{kMM`?hgO~e1>^)4)j0I{~W+KUx{)l`Vp;7~?ksfrgIrQ;Ar2 ziSe7xKvTteN*U?SQNHU4G-aHp@R1Vaca4Fjj`I{QQlfm;5NL^0Nul0IgxRLyc`7kE z-?>duq8xKGK}$@|cP?)#!W?(=+?AW0@0Lta!qo9)f|i?{@66v|glVdDoFayS5~jKG zaf%oON|;M*5vPb^poF>1HgSq51WK4TE>0(H6{pBVpoD2-r}La92-C*HCCn}3?3$j0 zX=9gb>mw>$WJs%VSJJj|iZleu)YR9ppL6RtZxN=x&YkdE#~E%PXl0uB5Lt@w^WJTk z5vQircLJ?gtM=WOtE~?9GEVO>J-(RAa?KO#`K9?dX1vE@9cswKd4R9;Q#ZM$Fmb*+ z<5_O))xNL`XO?JJPgku%qHREJZS_PVrmj* zvovv*K$u-p#W^!Q-KQpDc1snfNYK+jJ2QOKrHfOfKTxKo5#x2Gj58I&9F{iD*6Ha! zH7i>5hD#f#NP?d~D^AUYYf2sG6W6IpnA6h78Gd?J;qYclALkXOrXr{Hl!%k*X~^-7 zRwB+%uCZ2{n$Bw}6K7M9oId*QTZ94LWTE$SrW4==9TxDhmx?ppO>4MS=CJNA;N;0} zk2sl{DeV!bHKwMC`f)Nf)2bh*HKwK+;zU@rq{%bOdo4BM3^Fw<@?2kyID@Gctk-(-$H~-O!eg!Z;|!`| zxU1KcJI>%!lR)R>jg!liZdL`FH_jClE>%{Xo+4}3l`~G~soDF&5a^hEaqXFA3A9g+I0H;f5uF!+K-*aR!-~BKko^ z+dHXAYh5uvk$Oexcn#fi@1)iGX4e!ePR~hsb2wi);XER>T;I%ko`3CjphK&N)ra0{ zhx(VuYcx=Phq_3Zsae@bps_y?tw5Mdj69dbiDh~N-8;^QbDG|FA6C>8=)Q5XvBOPk zpnJyI5hl~qMoXZ3#@UHLZ9E0KUz~%7a{{$-7wBGbPX3%ppf;`o-6u|^4?qOE&K_|p ze=;Y~HR{J{bjpZ8?bVLc_*^D|+NvApqLb_dI`8T^eBLsbjl-3nL*!tS$e6n~cdg0k zcuDdQIhdk-o}RB7lQYnD^79F2lHO~1Bj=7YP?VpD^jhl?CTE<1qx?jqKlS|RlPAtZ zL4HG|{bx2}$C*6HZ$4k3U1A;iuz3Fu3jVf@45|gIfA=M}5%s?HTIV?t%ItYx;)Dr} z3lhW$by`=-h!d(bFX0j=)M)Q5AWo>T*z`i2m}a#bi#RdGa+@G=Vwm;*RpP{u6&tIG z6Wvzr_$N+uS$Qi8aiZDkd!&dHO+0SiBThW>x~r5pam({|XX3;q@B8rC2@etZ|898i pFo7Q`e_1R5000000001Z^B3g+TnX(i3zq-@002ovPDHLkV1hm4659X( literal 0 HcmV?d00001 diff --git a/LedOK/res/signal-0.png b/LedOK/res/signal-0.png new file mode 100644 index 0000000000000000000000000000000000000000..5cf83cddcc47a27ca7909af8ae1e57f675d5221d GIT binary patch literal 730 zcmV<00ww*4P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0&ht~K~#8N?UzkX z!!QtqTf`BN*not%1&dyS1$Sh_B`R?b1PeAC0l}EWs2yU@c>dxFe-cXC+B5IHNz$?z z4E{IU`54ZAzyF#~f7$JJ;d)#fE}7Ke5s+y?Yr_;4fv5^Z8?GS@L$s+U@K#=@=Zae$uJsp%bTexBZsic7$SW5s^yp3bH z1}RL6M4Qi8grF+0mT`^-?WZ za{;Fx(>pRO0w8HIj?qq-!nL@@_#vJlxD~cCpYaO8rKq*}j7JFO1-;B?tV1}Pk7jt@ zuTcATJ~bo!7N7#s?3Lg)Eo`J!ymo&VBonoXQfT*gPY(uHxvWa2*SO5X8&VUG4#E6u z@YD!Rn|r@UUIpU{n2%wMXFz9!Ujd1pz6Mt%1;KqV4hDn4z?{wI8+-+NejcJVrvLx| M07*qoM6N<$f~&_sN&o-= literal 0 HcmV?d00001 diff --git a/LedOK/res/signal-1.png b/LedOK/res/signal-1.png new file mode 100644 index 0000000000000000000000000000000000000000..6e0c5f05dfa3eb3704a5065795afb85239e441d0 GIT binary patch literal 740 zcmVPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0(nV9K~#8N?UzAL z12GImTf`BN*not%1&dyS1$P7_E>VelAXu>B2ncLuf~IB?JC2=6nLKGUX(zG&|E2{t zozA-1j`!;9_xrDL`O9v%tFFhj;hf15JOVN;Xli)Joessb=T>?E(}LUE@G6d#=@`;5Bs#Fx zPcd#Y*VNl|3`rOcsnmS#R01{nvKuraw1zo6v?L$qHuN%1vD9S}KrQ1G3w^BcRFe|pw60~XDO_Dq z)42vYf~Aw1L)u5HQEK8G8oc8IiZ1d$fhGvc0FYa_o`z){YvUA&DbyehEGK{@-o`0X zgB&JBYMT#OgiusqDdUuqAk+t2F(1%|pgN>6pDVCN55zS9i_d6AuT!{v4zJ{>1*U|7 z7}4JfIWYayK8hwZC(2^#DQHjVcLleX;Z;7SKcczjwP#CuQY@x*2ZHV;Lg@5TaP_bj z>^Xzw$MB90ivU=1j8jS{%;8$R#P}4?5Znq|nGbk{;8N7ue83|F^MYRH1J)s&jCV6U zKd(^xdR&@O{Ug8yRB~2>+q9^WT=Avnn*dFuCdyHIzSA%la6Q0<)5Qzd_}(f&qro`6 zRuRH<^7O)IRaxSj6^*8-s>%Ehp<`o-03OHt9I0pjhSh%wB4~8AzXm&Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0-#AmK~#8N?U~DM z+%OP^cLR6eLoPND_u$JOwut~qGfoXD#0K2N0M9v?8! zi{#AzQ=+`qZewHJ?8j|$PN&n~arZyRMlI2cxe03t=UCQdVn8e59EW;mLcW6yeb<&8>EwDunP}Km7 zXEY<%6>a_uM{?8!#tNfiM1L#fkjSUjQ8YuoqAX@T2G2?PKGEjKaFox7ajSxhtt}pS za;U{y@m2bq5(kR!6!;E-4>9QH0_PqnzEC6?b6yWe{R7cla4OJe_Fy)1h4T>I5j}z# z^a;|$?Cu6U&psg~A^v{Z13m#3@jx*fd;$<|rN5zYU?1mj&DRI0hEvfY z@T&AJoc9#7!xgW2ey8imH=I}_xDz&(2-bq>f`@&{`mhKf)CuRY3KL?lI$Uc?^`EaE zAT&nPnu`7(ummn)z|*+(5xce+R=)@W2wm-KaARX*W1|mtyEl#TxR~6X9MAv&002ov JPDHLkV1g!FQQ-gp literal 0 HcmV?d00001 diff --git a/LedOK/res/signal-3.png b/LedOK/res/signal-3.png new file mode 100644 index 0000000000000000000000000000000000000000..e1f2bf354d8c93787e7c39e8a6eb63af89c035c9 GIT binary patch literal 826 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 -#include -#include - -SyncTimer::SyncTimer(int inter) { - this->inter = inter; - connect(this, &QThread::finished, this, &QThread::deleteLater); -} -void SyncTimer::run(){ - qint64 curTime; - sleep = inter; - if(sleep <= 0) return; - timeBeginPeriod(1); - msleep(sleep); - qint64 exeTime = QDateTime::currentMSecsSinceEpoch(); - while(inter > 0) { - inter = 0; - emit timeout(); - curTime = inter; - if(curTime<=0) break; - exeTime += curTime; - curTime = QDateTime::currentMSecsSinceEpoch(); - sleep = exeTime - curTime; - if(exeTime > curTime) msleep(sleep); - else exeTime = curTime; - } - timeEndPeriod(1); -} +#include "synctimer.h" +#include +#include +#include + +SyncTimer::SyncTimer(int inter) { + this->inter = inter; + connect(this, &QThread::finished, this, &QThread::deleteLater); +} +void SyncTimer::run(){ + qint64 curTime; + sleep = inter; + if(sleep <= 0) return; + timeBeginPeriod(1); + msleep(sleep); + qint64 exeTime = QDateTime::currentMSecsSinceEpoch(); + while(inter > 0) { + inter = 0; + emit timeout(); + curTime = inter; + if(curTime<=0) break; + exeTime += curTime; + curTime = QDateTime::currentMSecsSinceEpoch(); + sleep = exeTime - curTime; + if(exeTime > curTime) msleep(sleep); + else exeTime = curTime; + } + timeEndPeriod(1); +} diff --git a/LedOK/tcpsocket - 副本.cpp b/LedOK/tcpsocket - 副本.cpp index 2625806..d5feefc 100644 --- a/LedOK/tcpsocket - 副本.cpp +++ b/LedOK/tcpsocket - 副本.cpp @@ -1,128 +1,128 @@ -#include "tcpsocket.h" - -TcpSocket::TcpSocket(QObject *parent) : QTcpSocket{parent} { - connect(this, &QTcpSocket::errorOccurred, this, [this]() { - { - std::lock_guard lock(mtx); - hasErr = true; - } - cv.notify_all(); - }); - connect(this, &QTcpSocket::connected, this, [this]() { - { - std::lock_guard lock(mtx); - } - cv.notify_all(); - }); - connect(this, &QTcpSocket::disconnected, this, [this]() { - { - std::lock_guard lock(mtx); - } - cv.notify_all(); - }); - connect(this, &QTcpSocket::bytesWritten, this, [this]() { - { - std::lock_guard lock(mtx); - isWritten = true; - } - cv.notify_all(); - }); - connect(this, &QTcpSocket::readyRead, this, [this]() { - { - std::lock_guard lock(mtx); - isReadyRead = true; - } - cv.notify_all(); - }); -} - -bool TcpSocket::waitForConnected(int msecs) { - if(hasErr) return false; - if(state() == ConnectedState) return true; - { - std::unique_lock lock(mtx); - if(hasErr) return false; - if(state() == ConnectedState) return true; - auto until = std::chrono::steady_clock::now() + std::chrono::milliseconds(msecs); - auto check = until - std::chrono::milliseconds(10); - do { - cv.wait_until(lock, until); - if(hasErr) return false; - if(state() == ConnectedState) return true; - } while(std::chrono::steady_clock::now() < check); - } - hasErr = true; - setSocketError(SocketTimeoutError); - return false; -} -bool TcpSocket::waitForDisconnected(int msecs) { - if(hasErr) return false; - if(state() == UnconnectedState) return true; - { - std::unique_lock lock(mtx); - if(hasErr) return false; - if(state() == UnconnectedState) return true; - auto until = std::chrono::steady_clock::now() + std::chrono::milliseconds(msecs); - auto check = until - std::chrono::milliseconds(10); - do { - cv.wait_until(lock, until); - if(hasErr) return false; - if(state() == UnconnectedState) return true; - } while(std::chrono::steady_clock::now() < check); - } - hasErr = true; - setSocketError(SocketTimeoutError); - return false; -} -bool TcpSocket::waitForBytesWritten(int msecs) { - if(hasErr) return false; - if(isWritten) return true; - { - std::unique_lock lock(mtx); - if(hasErr) return false; - if(isWritten) return true; - auto until = std::chrono::steady_clock::now() + std::chrono::milliseconds(msecs); - auto check = until - std::chrono::milliseconds(10); - do { - cv.wait_until(lock, until); - if(hasErr) return false; - if(isWritten) return true; - } while(std::chrono::steady_clock::now() < check); - } - hasErr = true; - setSocketError(SocketTimeoutError); - return false; -} -bool TcpSocket::waitForReadyRead(int msecs) { - if(hasErr) return false; - if(isReadyRead) return true; - { - std::unique_lock lock(mtx); - if(hasErr) return false; - if(isReadyRead) return true; - auto until = std::chrono::steady_clock::now() + std::chrono::milliseconds(msecs); - auto check = until - std::chrono::milliseconds(10); - do { - cv.wait_until(lock, until); - if(hasErr) return false; - if(isReadyRead) return true; - } while(std::chrono::steady_clock::now() < check); - } - hasErr = true; - setSocketError(SocketTimeoutError); - return false; -} -qint64 TcpSocket::readData(char *data, qint64 maxlen) { - auto rtn = QTcpSocket::readData(data, maxlen); - isReadyRead = false; - return rtn; -} -qint64 TcpSocket::readLineData(char *data, qint64 maxlen) { - auto rtn = QTcpSocket::readLineData(data, maxlen); - isReadyRead = false; - return rtn; -} -qint64 TcpSocket::writeData(const char *data, qint64 len) { - isWritten = false; - return QTcpSocket::writeData(data, len); -} +#include "tcpsocket.h" + +TcpSocket::TcpSocket(QObject *parent) : QTcpSocket{parent} { + connect(this, &QTcpSocket::errorOccurred, this, [this]() { + { + std::lock_guard lock(mtx); + hasErr = true; + } + cv.notify_all(); + }); + connect(this, &QTcpSocket::connected, this, [this]() { + { + std::lock_guard lock(mtx); + } + cv.notify_all(); + }); + connect(this, &QTcpSocket::disconnected, this, [this]() { + { + std::lock_guard lock(mtx); + } + cv.notify_all(); + }); + connect(this, &QTcpSocket::bytesWritten, this, [this]() { + { + std::lock_guard lock(mtx); + isWritten = true; + } + cv.notify_all(); + }); + connect(this, &QTcpSocket::readyRead, this, [this]() { + { + std::lock_guard lock(mtx); + isReadyRead = true; + } + cv.notify_all(); + }); +} + +bool TcpSocket::waitForConnected(int msecs) { + if(hasErr) return false; + if(state() == ConnectedState) return true; + { + std::unique_lock lock(mtx); + if(hasErr) return false; + if(state() == ConnectedState) return true; + auto until = std::chrono::steady_clock::now() + std::chrono::milliseconds(msecs); + auto check = until - std::chrono::milliseconds(10); + do { + cv.wait_until(lock, until); + if(hasErr) return false; + if(state() == ConnectedState) return true; + } while(std::chrono::steady_clock::now() < check); + } + hasErr = true; + setSocketError(SocketTimeoutError); + return false; +} +bool TcpSocket::waitForDisconnected(int msecs) { + if(hasErr) return false; + if(state() == UnconnectedState) return true; + { + std::unique_lock lock(mtx); + if(hasErr) return false; + if(state() == UnconnectedState) return true; + auto until = std::chrono::steady_clock::now() + std::chrono::milliseconds(msecs); + auto check = until - std::chrono::milliseconds(10); + do { + cv.wait_until(lock, until); + if(hasErr) return false; + if(state() == UnconnectedState) return true; + } while(std::chrono::steady_clock::now() < check); + } + hasErr = true; + setSocketError(SocketTimeoutError); + return false; +} +bool TcpSocket::waitForBytesWritten(int msecs) { + if(hasErr) return false; + if(isWritten) return true; + { + std::unique_lock lock(mtx); + if(hasErr) return false; + if(isWritten) return true; + auto until = std::chrono::steady_clock::now() + std::chrono::milliseconds(msecs); + auto check = until - std::chrono::milliseconds(10); + do { + cv.wait_until(lock, until); + if(hasErr) return false; + if(isWritten) return true; + } while(std::chrono::steady_clock::now() < check); + } + hasErr = true; + setSocketError(SocketTimeoutError); + return false; +} +bool TcpSocket::waitForReadyRead(int msecs) { + if(hasErr) return false; + if(isReadyRead) return true; + { + std::unique_lock lock(mtx); + if(hasErr) return false; + if(isReadyRead) return true; + auto until = std::chrono::steady_clock::now() + std::chrono::milliseconds(msecs); + auto check = until - std::chrono::milliseconds(10); + do { + cv.wait_until(lock, until); + if(hasErr) return false; + if(isReadyRead) return true; + } while(std::chrono::steady_clock::now() < check); + } + hasErr = true; + setSocketError(SocketTimeoutError); + return false; +} +qint64 TcpSocket::readData(char *data, qint64 maxlen) { + auto rtn = QTcpSocket::readData(data, maxlen); + isReadyRead = false; + return rtn; +} +qint64 TcpSocket::readLineData(char *data, qint64 maxlen) { + auto rtn = QTcpSocket::readLineData(data, maxlen); + isReadyRead = false; + return rtn; +} +qint64 TcpSocket::writeData(const char *data, qint64 len) { + isWritten = false; + return QTcpSocket::writeData(data, len); +} diff --git a/LedOK/tcpsocket - 副本.h b/LedOK/tcpsocket - 副本.h index e753bd1..35201b2 100644 --- a/LedOK/tcpsocket - 副本.h +++ b/LedOK/tcpsocket - 副本.h @@ -1,29 +1,29 @@ -#ifndef TCPSOCKET_H -#define TCPSOCKET_H - -#include -#include - -class TcpSocket : public QTcpSocket { - Q_OBJECT -public: - explicit TcpSocket(QObject *parent = nullptr); - - bool waitForConnected(int msecs = 30000) override; - bool waitForDisconnected(int msecs = 30000) override; - bool waitForBytesWritten(int msecs = 30000) override; - bool waitForReadyRead(int msecs = 30000) override; - qint64 readData(char *data, qint64 maxlen) override; - qint64 readLineData(char *data, qint64 maxlen) override; - qint64 writeData(const char *data, qint64 len) override; - bool hasErr = false; - bool isWritten = false; - bool isReadyRead = false; - -private: - std::mutex mtx; - std::condition_variable cv; - -}; - -#endif // TCPSOCKET_H +#ifndef TCPSOCKET_H +#define TCPSOCKET_H + +#include +#include + +class TcpSocket : public QTcpSocket { + Q_OBJECT +public: + explicit TcpSocket(QObject *parent = nullptr); + + bool waitForConnected(int msecs = 30000) override; + bool waitForDisconnected(int msecs = 30000) override; + bool waitForBytesWritten(int msecs = 30000) override; + bool waitForReadyRead(int msecs = 30000) override; + qint64 readData(char *data, qint64 maxlen) override; + qint64 readLineData(char *data, qint64 maxlen) override; + qint64 writeData(const char *data, qint64 len) override; + bool hasErr = false; + bool isWritten = false; + bool isReadyRead = false; + +private: + std::mutex mtx; + std::condition_variable cv; + +}; + +#endif // TCPSOCKET_H diff --git a/LedOK/tcpsocket.cpp b/LedOK/tcpsocket.cpp deleted file mode 100644 index 6892ab7..0000000 --- a/LedOK/tcpsocket.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include "tcpsocket.h" -#include -#include - -const char* socketErrKey(int value) { - static auto metaEnum = QMetaEnum::fromType(); - return metaEnum.valueToKey(value); -} - -bool TcpSocket::waitForConnected(int msecs) { - if(state() == ConnectedState) return true; - QEventLoop loop; - connect(this, &QTcpSocket::connected, &loop, &QEventLoop::quit); - return connAndExec(msecs, &loop); -} -bool TcpSocket::waitForDisconnected(int msecs) { - if(state() == UnconnectedState) return true; - QEventLoop loop; - connect(this, &QTcpSocket::disconnected, &loop, &QEventLoop::quit); - return connAndExec(msecs, &loop); -} -bool TcpSocket::waitForBytesWritten(int msecs) { - QEventLoop loop; - connect(this, &QTcpSocket::bytesWritten, &loop, &QEventLoop::quit); - return connAndExec(msecs, &loop); -} -bool TcpSocket::waitForReadyRead(int msecs) { - QEventLoop loop; - connect(this, &QTcpSocket::readyRead, &loop, &QEventLoop::quit); - return connAndExec(msecs, &loop); -} - -bool TcpSocket::connAndExec(int msecs, QEventLoop *loop) { - connect(this, &QTcpSocket::errorOccurred, loop, [loop] { - loop->exit(1); - }); - if(msecs > 0) { - connect(this, &TcpSocket::timeout, loop, &QEventLoop::exit); - if(timerId!=0) killTimer(timerId); - timerId = startTimer(msecs); - } - auto res = loop->exec(); - timerStop(); - if(res==5) setSocketError(SocketTimeoutError); - return res==0; -} diff --git a/LedOK/tcpsocket.h b/LedOK/tcpsocket.h deleted file mode 100644 index 6a266ee..0000000 --- a/LedOK/tcpsocket.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef TCPSOCKET_H -#define TCPSOCKET_H - -#include -#include -#include - -const char* socketErrKey(int value); - -class TcpSocket : public QTcpSocket { - Q_OBJECT -public: - explicit TcpSocket(QObject *parent = nullptr) : QTcpSocket{parent} {}; - ~TcpSocket() { - if(timerId!=0) killTimer(timerId); - }; - bool waitForConnected(int msecs = 30000) override; - bool waitForDisconnected(int msecs = 30000) override; - bool waitForBytesWritten(int msecs = 30000) override; - bool waitForReadyRead(int msecs = 30000) override; -protected: - void timerEvent(QTimerEvent *e) override { - if(e->timerId()!=timerId) return; - killTimer(timerId); - timerId = 0; - emit timeout(5); - }; - bool connAndExec(int msecs, QEventLoop *loop); - inline void timerStop() { - if(timerId==0) return; - killTimer(timerId); - timerId = 0; - } - int timerId = 0; -signals: - void timeout(int); -}; - -#endif // TCPSOCKET_H diff --git a/LedOK/test.cpp b/LedOK/test.cpp index 3a885ad..ab501b4 100644 --- a/LedOK/test.cpp +++ b/LedOK/test.cpp @@ -1,93 +1,93 @@ -#include -#include -#include -#include -#include -#include - -void testFont() { - QFont font("Arial", 21); - //font.setItalic(m_attr.fontItalics); - font.setStyleStrategy(QFont::NoAntialias); - QFontMetricsF metric(font); - QFontMetrics metricI(font); - qDebug()<<"QFontMetrics"; - qDebug()<<" leading"< -#include -class TestWin : public QWidget { -public: - TestWin(){ - resize(400, 100); - auto hBox = new QHBoxLayout(this); - hBox->setContentsMargins(100,0,0,0); - aaa = new QLabel("Aaaaaaaaaaaaaaaaaaaaaaaa"); - aaa->setAutoFillBackground(true); - QPalette pal; - pal.setColor(QPalette::Window, Qt::darkGreen); - aaa->setPalette(pal); - aaa->setMinimumWidth(10); - hBox->addWidget(aaa); - - bbb = new QLabel("B"); - bbb->setAutoFillBackground(true); - pal.setColor(QPalette::Window, Qt::darkCyan); - bbb->setPalette(pal); - bbb->setMinimumWidth(1); - - auto poli = aaa->sizePolicy(); - poli.setHorizontalPolicy(QSizePolicy::Expanding); - aaa->setSizePolicy(poli); - bbb->setSizePolicy(poli); - - - hBox->addWidget(bbb); - } - void mouseDoubleClickEvent(QMouseEvent *) override { - qDebug()<<"sizeHint "<sizeHint()<sizeHint(); - qDebug()<<"minHint "<minimumSizeHint()<minimumSizeHint(); - qDebug()<<"sizePolicy"<sizePolicy()<sizePolicy(); - qDebug()<<"minSize "<minimumSize()<minimumSize(); - qDebug()<<"maxSize "<maximumSize()<maximumSize(); - qDebug()<<"size "<size()<size(); - } - QWidget *aaa; - QWidget *bbb; -}; -int tttmain(int argc, char *argv[]) { - QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); - QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); - QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); - QApplication a(argc, argv); - QFont font = a.font(); - font.setPointSize(14); - a.setFont(font); - - TestWin w; - w.show(); - return a.exec(); -} - +#include +#include +#include +#include +#include +#include + +void testFont() { + QFont font("Arial", 21); + //font.setItalic(m_attr.fontItalics); + font.setStyleStrategy(QFont::NoAntialias); + QFontMetricsF metric(font); + QFontMetrics metricI(font); + qDebug()<<"QFontMetrics"; + qDebug()<<" leading"< +#include +class TestWin : public QWidget { +public: + TestWin(){ + resize(400, 100); + auto hBox = new QHBoxLayout(this); + hBox->setContentsMargins(100,0,0,0); + aaa = new QLabel("Aaaaaaaaaaaaaaaaaaaaaaaa"); + aaa->setAutoFillBackground(true); + QPalette pal; + pal.setColor(QPalette::Window, Qt::darkGreen); + aaa->setPalette(pal); + aaa->setMinimumWidth(10); + hBox->addWidget(aaa); + + bbb = new QLabel("B"); + bbb->setAutoFillBackground(true); + pal.setColor(QPalette::Window, Qt::darkCyan); + bbb->setPalette(pal); + bbb->setMinimumWidth(1); + + auto poli = aaa->sizePolicy(); + poli.setHorizontalPolicy(QSizePolicy::Expanding); + aaa->setSizePolicy(poli); + bbb->setSizePolicy(poli); + + + hBox->addWidget(bbb); + } + void mouseDoubleClickEvent(QMouseEvent *) override { + qDebug()<<"sizeHint "<sizeHint()<sizeHint(); + qDebug()<<"minHint "<minimumSizeHint()<minimumSizeHint(); + qDebug()<<"sizePolicy"<sizePolicy()<sizePolicy(); + qDebug()<<"minSize "<minimumSize()<minimumSize(); + qDebug()<<"maxSize "<maximumSize()<maximumSize(); + qDebug()<<"size "<size()<size(); + } + QWidget *aaa; + QWidget *bbb; +}; +int tttmain(int argc, char *argv[]) { + QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); + QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); + QApplication a(argc, argv); + QFont font = a.font(); + font.setPointSize(14); + a.setFont(font); + + TestWin w; + w.show(); + return a.exec(); +} + diff --git a/LedOK/tipdialog.cpp b/LedOK/tipdialog.cpp deleted file mode 100644 index 3619c4b..0000000 --- a/LedOK/tipdialog.cpp +++ /dev/null @@ -1,416 +0,0 @@ -#include "QStandardPaths" -#include "tipdialog.h" -#include "ui_tipdialog.h" -#include "globaldefine.h" -#include -#include -#include -#include -#include -#include - -#include -TipDialog::TipDialog(QWidget *parent) : - BaseDlg(parent), - ui(new Ui::TipDialog) -{ - setAttribute(Qt::WA_DeleteOnClose); - ui->setupUi(this); -} -TipDialog::TipDialog(QWidget *parent,int iTipDlgType): - BaseDlg(parent), - ui(new Ui::TipDialog) -{ - setAttribute(Qt::WA_DeleteOnClose); - ui->setupUi(this); - - connect(this, SIGNAL(accepted()), this, SLOT(onAccepted())); - m_iTipDlgType=iTipDlgType; - switch(iTipDlgType) { - case ENUM_IMPORT_DLG: {//Import对话框 - ui->bnOK->setEnabled(false); - ui->bnOK->setStyleSheet("background-color:#8d8d8d;color:#fdfdfd;"); - this->resize(600,400); - setMinimumHeight(400); - ui->bnOK->setText(tr("Import")); - ui->bnCancel->setText(tr("Done")); - ui->label->setText(tr("Import")); - QLabel *pLablePaht = new QLabel(this); - pTextPath = new QLineEdit(this); - pLablePaht->setText(tr("Path")+tr(":")); - QPushButton *pSelectButton = new QPushButton(this); - //ui->verticalSpacer->changeSize(20, 20, QSizePolicy::Preferred, QSizePolicy::Expanding); - - QRect rect; - rect = pLablePaht->geometry(); - rect.setX(rect.x()+rect.width()); - rect.setWidth(this->width()-8-pLablePaht->width()-pSelectButton->width()); - pTextPath->setGeometry(rect); - pSelectButton->setText(tr("browse")); - pSelectButton->adjustSize(); - - //创建一个水平布局,水平布局里左右留12个0空格,中间放入页部件 - m_pLayoutSelectDirPath = new QHBoxLayout(); - m_pLayoutSelectDirPath->setSpacing(2); - m_pLayoutSelectDirPath->addWidget(pLablePaht); - m_pLayoutSelectDirPath->setSpacing(2); - m_pLayoutSelectDirPath->addWidget(pTextPath); - m_pLayoutSelectDirPath->setSpacing(2); - m_pLayoutSelectDirPath->addWidget(pSelectButton); - connect(pSelectButton,SIGNAL(clicked()),this,SLOT(OnSelectDir())); - //创建一个垂直布局 - QVBoxLayout *pVLayout = new QVBoxLayout(); - pVLayout->addLayout(m_pLayoutSelectDirPath, 0);//增加路径选择区到垂直布局的0区 - pVLayout->setSpacing(0); - pVLayout->addSpacing(10); - //增加列表选型到垂直布局的1区 - //创建列表控件 - ctrlProgramList = new QTableWidget(this); - ctrlProgramList->setColumnCount(2); - ctrlProgramList->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); - ctrlProgramList->verticalHeader()->hide(); - QStringList starr; - starr.append(tr("Solution Name")); - starr.append(tr("Progress")); - ctrlProgramList->setHorizontalHeaderLabels(starr); - //根据节目主窗口选中的节目check选型,初始化Tree控件 - //把垂直布局的内容填充到内容区 - pVLayout->addWidget(ctrlProgramList,1); - ctrlProgramList->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); - ui->horizontalLayout_content->addLayout(pVLayout); - connect( ui->bnOK,SIGNAL(clicked()),this,SLOT(OnImportPro())); - connect( ui->bnCancel,SIGNAL(clicked()),this,SLOT(accept())); - } - break; - case ENUM_DELETE_DLG: - { - ui->label->setText(tr("Delete")); - QLabel *pLablePaht = new QLabel(this); - pLablePaht->setText(tr("You will delete the selected solution(s),are you sure?")); - ui->horizontalLayout_content->addWidget(pLablePaht); - connect( ui->bnOK,SIGNAL(clicked()),this,SLOT(accept())); - connect( ui->bnCancel,SIGNAL(clicked()),this,SLOT(reject())); - } - break; - default: break; - } - - -} -TipDialog::TipDialog(QWidget *parent,int iTipDlgType,QStringList *listProgramName,int iTipType): - BaseDlg(parent), - ui(new Ui::TipDialog) -{ - setAttribute(Qt::WA_DeleteOnClose); - ui->setupUi(this); - - connect(this, SIGNAL(accepted()), this, SLOT(onAccepted())); - m_iTipDlgType=iTipDlgType; - switch(iTipDlgType) - { - case ENUM_EXPORT_DLG: - { - ui->bnOK->setEnabled(false); - ui->bnOK->setStyleSheet("background-color:#8d8d8d;color:#fdfdfd;"); - this->resize(600,400); - setMinimumHeight(400); - ui->bnOK->setText(tr("Export")); - ui->bnCancel->setText(tr("Done")); - ui->label->setText(tr("Export")); - QLabel *pLablePaht = new QLabel(this); - pTextPath = new QLineEdit(this); - pLablePaht->setText(tr("Path")+tr(":")); - QPushButton *pSelectButton = new QPushButton(this); - //ui->verticalSpacer->changeSize(20, 20, QSizePolicy::Preferred, QSizePolicy::Expanding); - - QRect rect; - rect = pLablePaht->geometry(); - rect.setX(rect.x()+rect.width()); - rect.setWidth(this->width()-8-pLablePaht->width()-pSelectButton->width()); - pTextPath->setGeometry(rect); - pSelectButton->setText(tr("browse")); - pSelectButton->adjustSize(); - - //创建一个水平布局,水平布局里左右留12个0空格,中间放入页部件 - QHBoxLayout *pLayoutSelectDirPath = new QHBoxLayout(); - pLayoutSelectDirPath->setSpacing(2); - pLayoutSelectDirPath->addWidget(pLablePaht); - pLayoutSelectDirPath->setSpacing(2); - pLayoutSelectDirPath->addWidget(pTextPath); - pLayoutSelectDirPath->setSpacing(2); - pLayoutSelectDirPath->addWidget(pSelectButton); - connect(pSelectButton,SIGNAL(clicked()),this,SLOT(OnSelectDir())); - //创建一个垂直布局 - QVBoxLayout *pVLayout = new QVBoxLayout(); - pVLayout->addLayout(pLayoutSelectDirPath, 0);//增加路径选择区到垂直布局的0区 - pVLayout->setSpacing(0); - pVLayout->addSpacing(10); - //增加列表选型到垂直布局的1区 - //创建列表控件 - ctrlProgramList = new QTableWidget(this); - ctrlProgramList->setRowCount(listProgramName->count()); - ctrlProgramList->setColumnCount(2); - ctrlProgramList->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); - ctrlProgramList->verticalHeader()->hide(); - - QStringList starr; - starr.append(tr("Solution Name")); - starr.append(tr("Progress")); - ctrlProgramList->setHorizontalHeaderLabels(starr); - //根据节目主窗口选中的节目check选型,初始化Tree控件 - for (int i = 0; i < listProgramName->count(); i++) - { - //progresss.append(progress); - wExportProgramItem *topLevelItem = new wExportProgramItem(ctrlProgramList,listProgramName->at(i),i); //创建一个 TreeItem 容器用于后来装载控件 - ctrlProgramList->setItem(i,0,topLevelItem); - } - //把垂直布局的内容填充到内容区 - pVLayout->addWidget(ctrlProgramList,1); - ctrlProgramList->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); - ui->horizontalLayout_content->addLayout(pVLayout); - connect( ui->bnOK,SIGNAL(clicked()),this,SLOT(OnExportButton())); - connect( ui->bnCancel,SIGNAL(clicked()),this,SLOT(accept())); - } - break; - case ENUM_SELECT_NETWORK: - { - setMinimumHeight(400); - ui->bnOK->setText(tr("OK")); - ui->bnCancel->setText(tr("Cancel")); - ui->label->setText(tr("Select the network to connect to the device")); - - //创建一个垂直布局 - QVBoxLayout *pVLayout = new QVBoxLayout(); - //增加列表选型到垂直布局的1区 - //创建列表控件 - QTableWidget *ctrlNetworkList = new QTableWidget(this); - ctrlNetworkList->setRowCount(listProgramName->count()); - ctrlNetworkList->setColumnCount(1); - ctrlNetworkList->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); - ctrlNetworkList->verticalHeader()->hide(); - - QStringList starr; - starr.append(tr("Network name")); - // starr.append(tr("hardware")); - ctrlNetworkList->setHorizontalHeaderLabels(starr); - //根据节目主窗口选中的节目check选型,初始化Tree控件 - for (int i = 0; i < listProgramName->count(); i++) - { - QTableWidgetItem *topLevelItem = new QTableWidgetItem(); //创建一个 TreeItem 容器用于后来装载控件 - topLevelItem->setData(0,listProgramName->at(i)); - //topLevelItem->setFlags(topLevelItem->flags() & ~Qt::ItemIsEnabled & ~Qt::ItemIsEditable); - topLevelItem->setFlags(topLevelItem->flags() & ~Qt::ItemIsEditable); - - //topLevelItem->setFlags(topLevelItem->flags() & ~Qt::ItemIsEnabled & ~Qt::ItemIsSelectable); - /*上面用到的两个枚举中:~Qt::ItemIsEnabled可以保证单击该Item时不会被选中,但是在启用Ctrl + A时,全选操作会导致Item被选中。 - * ~Qt::ItemIsSelectable的使用可以保证全选状态下也不会被选中,但是在单独使用时出现了虚线框,没有真正实现“不存在”的效果。所以必须两个同用。*/ - ctrlNetworkList->setItem(i,0,topLevelItem); - - } - //把垂直布局的内容填充到内容区 - pVLayout->addWidget(ctrlNetworkList,0); - ctrlNetworkList->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); - ui->horizontalLayout_content->addLayout(pVLayout); - ui->label_2->setWordWrap(true); - ui->label_2->setAlignment(Qt::AlignTop); - if(iTipType==0) - ui->label_2->setText(tr("This operation will only set cable network to static IP,are you sure?")); - else if(iTipType==1) - ui->label_2->setText(tr("Do you want set IP of cable network to DHCP")+"?"); - ui->label_2->setText(tr("This operation will only set cable network to static IP,are you sure?")); - connect(ctrlNetworkList,SIGNAL(itemSelectionChanged()),this,SLOT(OnNetworkListSelectChanged())); - connect( ui->bnOK,SIGNAL(clicked()),this,SLOT(accept())); - connect( ui->bnCancel,SIGNAL(clicked()),this,SLOT(reject())); - } - break; - default: - break; - - } - - -} -TipDialog::~TipDialog() -{ - if(ctrlProgramList!=nullptr) - delete ctrlProgramList; - delete ui; -} -void TipDialog::onAccepted() -{ - switch(m_iTipDlgType) - { - case ENUM_IMPORT_DLG://Import对话框 - { - if(iImportAtLeastOneSuccessFlag) - { - emit sigAcceptData(pTextPath->text(),""); - - } - else { - emit sigAcceptData("",""); - - } - } - break; - case ENUM_EXPORT_DLG: - { - emit sigAcceptData(pTextPath->text(),""); - } - break; - case ENUM_DELETE_DLG: - { - emit sigAcceptData("",""); - } - break; - case ENUM_SELECT_NETWORK: - { - if(m_strLineEditText.isEmpty()) - { - - X_UIMsgBoxOk *dlg=new X_UIMsgBoxOk(tr("Tip"),tr("Please select the network to connect to the Led controller"),this,0); - dlg->exec(); - } - else { - emit sigAcceptData(m_strLineEditText,""); - } - } - break; - default: - break; - } -} - -void TipDialog::OnSelectDir() -{ - - QString strDir = QFileDialog::getExistingDirectory(this, tr("Choose Directory"), - "/home", - QFileDialog::ShowDirsOnly - | QFileDialog::DontResolveSymlinks); - - pTextPath->setText(strDir); - if(!strDir.isEmpty()) - { - if(m_iTipDlgType==ENUM_IMPORT_DLG) - { - QDir root_dir(strDir); - QStringList pro_list = root_dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks); - QStringList listProgramName; - foreach(QString pro_name, pro_list) { - QDir pro_dir(strDir + MACRO_FENGEFU + pro_name); - if(pro_dir.exists("pro.json")) { - QFile fPro(pro_dir.path() + MACRO_FENGEFU+"pro.json"); - fPro.open(QIODevice::ReadOnly); - QJsonDocument pro = QJsonDocument::fromJson(fPro.readAll()); - fPro.close(); - QString strProgramName=pro["name"].toString(); - listProgramName.append(strProgramName); - } - } - ctrlProgramList->setRowCount(listProgramName.count()); - for(int i=0;isetItem(i,0,topLevelItem); - - } - - } - - ui->bnOK->setEnabled(true); - - ui->bnOK->setStyleSheet("background-color:rgba(28,154,210);"); - - } - else { - ui->bnOK->setEnabled(false); - ui->bnOK->setStyleSheet("background-color:#8d8d8d;color:#fdfdfd;"); - - } - -} -void TipDialog::OnExportButton() -{ - QString strDestPath=pTextPath->text(); - if(!strDestPath.isEmpty()){ - QDir qDirDest(pTextPath->text()); - if(qDirDest.exists()){ - QString doc_path = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); - if(!doc_path.isEmpty()) { - QString app_path = doc_path + "/" + QApplication::applicationName(); - QString strSourceDir = app_path + "/NPrograms"; - for(int i=0;irowCount();i++) - { - wExportProgramItem *pItem= static_cast(ctrlProgramList->item(i,0)); - pItem->ExportPro(strDestPath,strSourceDir); - qDebug()<exec(); - - } - -} -void TipDialog::OnImportPro() -{ - QString strSourcePath=pTextPath->text(); - if(!strSourcePath.isEmpty()) - { - //查找当前目录下发现的导出节目项,加入到列表, - QString doc_path = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); - QString app_path = doc_path + "/" + QApplication::applicationName(); - QString strDestPath = app_path + "/NPrograms"; - if(strSourcePath.contains(strDestPath,Qt::CaseInsensitive)) - { - X_UIMsgBoxOk *dlg=new X_UIMsgBoxOk(tr("Tip"),tr("The imported directory is already in the working directory, so there is no need to import it again!"),this,0); - dlg->exec(); - return; - } - - if(ctrlProgramList->rowCount()>0)//如果列表大于0,说明有符合的项目 - { - if(!doc_path.isEmpty()) { - QDir qDirDest(strDestPath); - - if(qDirDest.exists()) - { - - for(int i=0;irowCount();i++) - { - wExportProgramItem *pItem= static_cast(ctrlProgramList->item(i,0)); - if(pItem->ExportPro(strDestPath,strSourcePath)) - { - iImportAtLeastOneSuccessFlag=true; - ui->bnClose->setVisible(false); - } - //qDebug()<exec(); - - } - - } - else - { - X_UIMsgBoxOk *dlg=new X_UIMsgBoxOk(tr("Tip"),tr("Please select the network to connect to the Led controller"),this,0); - dlg->exec(); - - } -} - -void TipDialog::OnNetworkListSelectChanged() -{ - QTableWidget *pl = findChild(); - m_strLineEditText=pl->selectedItems()[0]->text(); -} diff --git a/LedOK/tipdialog.h b/LedOK/tipdialog.h deleted file mode 100644 index f69b2e2..0000000 --- a/LedOK/tipdialog.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef TIPDIALOG_H -#define TIPDIALOG_H -#include -#include -#include -#include -namespace Ui { -class TipDialog; -} - -class TipDialog : public BaseDlg -{ - Q_OBJECT - -public: - explicit TipDialog(QWidget *parent = nullptr); - TipDialog(QWidget *parent,int iTipDlgType); - TipDialog(QWidget *parent,int iTipDlgType,QStringList *list,int iTipType); - ~TipDialog(); - -public: - QLineEdit *pTextPath; - QString m_strLineEditText; -signals: - void sigAcceptData(QString string1, QString string2); -protected slots: - void onAccepted(); - void OnSelectDir(); - void OnExportButton(); - void OnImportPro(); - void OnNetworkListSelectChanged(); -private: - Ui::TipDialog *ui; - int m_iTipDlgType; - QTableWidget *ctrlProgramList=nullptr; - QHBoxLayout *m_pLayoutSelectDirPath=nullptr; - bool iImportAtLeastOneSuccessFlag=false; -}; - -#endif // TIPDIALOG_H diff --git a/LedOK/tipdialog.ui b/LedOK/tipdialog.ui deleted file mode 100644 index 774bb7a..0000000 --- a/LedOK/tipdialog.ui +++ /dev/null @@ -1,210 +0,0 @@ - - - TipDialog - - - - 0 - 0 - 378 - 149 - - - - - - - - - - - - QLayout::SetMaximumSize - - - 0 - - - - - - 0 - 0 - - - - font-size:16px; - - - TextLabel - - - Qt::AlignCenter - - - - - - - - 31 - 24 - - - - - 31 - 16777215 - - - - X - - - - - - - - - - 0 - 1 - - - - - 0 - 1 - - - - border-top: 1.5px solid gray; - - - 6 - - - 1 - - - Qt::Horizontal - - - - - - - 0 - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - false - - - border-top: 1px solid gray; - - - 0 - - - 0 - - - Qt::Horizontal - - - - - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - OK - - - - - - - Cancel - - - - - - - - - - - - - - - - bnClose - clicked() - TipDialog - close() - - - 445 - 21 - - - 239 - 159 - - - - - diff --git a/LedOK/tools.cpp b/LedOK/tools.cpp index 71e2528..91aab47 100644 --- a/LedOK/tools.cpp +++ b/LedOK/tools.cpp @@ -1,18 +1,10 @@ #include "tools.h" #include "cfg.h" #include "globaldefine.h" -#include "wProgramManager/pagelistitem.h" +#include "program/pagelistitem.h" #include "base/x_uimsgboxok.h" -#include -#include -#include #include #include -extern "C"{ -#include -#include -#include -} void Tools::timerEvent(QTimerEvent *event) { if(timer_id==event->timerId()) emit sTick(); @@ -43,244 +35,7 @@ QString Tools::addSufix(QString path) { while(QFileInfo::exists(path = prefix+QString::number(i)+sufix)) i++; return path; } -QString Tools::videoInfo(QByteArray url, QImage &img, int64_t *dur, AVCodecID *codec_id) { - AVFormatContext *fmt_ctx = avformat_alloc_context(); - QString err; - { - if(avformat_open_input(&fmt_ctx, url.constData(), nullptr, nullptr) != 0) { - err = "Couldn't open input stream"; - goto free; - } - if(avformat_find_stream_info(fmt_ctx, nullptr) < 0) { - err = "Couldn't find stream information"; - goto free; - } - if(dur!=nullptr) *dur = fmt_ctx->duration; - int vi_idx = -1; - for(uint ss=0; ssnb_streams; ss++) if(fmt_ctx->streams[ss]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) vi_idx = ss; - if(vi_idx == -1) { - err = "Didn't find a Video Stream"; - goto free; - } - auto codecpar = fmt_ctx->streams[vi_idx]->codecpar; - if(codec_id!=nullptr) *codec_id = codecpar->codec_id; - qDebug()<<"codec_id"<codec_id<codec_id); - if(av_seek_frame(fmt_ctx, -1, 1000000, AVSEEK_FLAG_BACKWARD) < 0) { - err = "av_seek_frame fail"; - goto free; - } - const AVCodec *decoder = avcodec_find_decoder(codecpar->codec_id); - if(decoder==nullptr) { - err = "Could not found Video Decoder"; - goto free; - } - auto vcCtx = avcodec_alloc_context3(decoder); - avcodec_parameters_to_context(vcCtx, codecpar); - if(avcodec_open2(vcCtx, decoder, nullptr) < 0) { - err = "Could not open Video Codec Ctx"; - avcodec_free_context(&vcCtx); - goto free; - } - auto sws_ctx = sws_getContext(vcCtx->width, vcCtx->height, vcCtx->pix_fmt, vcCtx->width, vcCtx->height, AV_PIX_FMT_RGB32, SWS_FAST_BILINEAR, nullptr, nullptr, nullptr); - auto packet = av_packet_alloc(); - auto frm = av_frame_alloc(); - while(1) { - if(av_read_frame(fmt_ctx, packet) < 0) break; - if(packet->stream_index != vi_idx) continue; - int res = avcodec_send_packet(vcCtx, packet); - if(res < 0) break; - while((res = avcodec_receive_frame(vcCtx, frm)) != AVERROR(EAGAIN)) { - if(res < 0) goto free2; - img = QImage(vcCtx->width, vcCtx->height, QImage::Format_ARGB32); - uint8_t *dst[4]{img.bits()}; - int dstStride[4]{img.bytesPerLine()}; - sws_scale(sws_ctx, frm->data, frm->linesize, 0, vcCtx->height, dst, dstStride); - goto free2; - } - } - free2: - av_frame_free(&frm); - av_packet_free(&packet); - avcodec_free_context(&vcCtx); - sws_freeContext(sws_ctx); - } - free: - avformat_close_input(&fmt_ctx); - return err; -} -QString trans(int sw, int sh, int dw, int dh, int cnt, QPointF pos, QByteArray file) { - AVFormatContext *in_fmt = avformat_alloc_context(), *out_fmt = 0; - AVCodecContext *de_ctx = 0, *en_ctx = 0; - QString err; - char buf[AV_ERROR_MAX_STRING_SIZE]; - int ret; - { - if((ret = avformat_open_input(&in_fmt, file.constData(), nullptr, nullptr)) < 0) { - err = QString("Couldn't open input stream. ")+av_strerror(ret, buf, AV_ERROR_MAX_STRING_SIZE); - goto free; - } - if((ret = avformat_find_stream_info(in_fmt, nullptr)) < 0) { - err = QString("Couldn't find stream information. ")+av_strerror(ret, buf, AV_ERROR_MAX_STRING_SIZE); - goto free; - } - auto outfile = file+"-square.mp4"; - if((ret = avformat_alloc_output_context2(&out_fmt, 0, "mp4", outfile.constData())) < 0) { - err = QString("avformat_alloc_output_context2 fail. ")+av_strerror(ret, buf, AV_ERROR_MAX_STRING_SIZE); - goto free; - } - int vi_idx = -1; - for(int ss=0; ssnb_streams; ss++) { - AVStream *stream = in_fmt->streams[ss]; - AVStream *newStream = avformat_new_stream(out_fmt, 0); - if((ret = avcodec_parameters_copy(newStream->codecpar, stream->codecpar)) < 0) { - err = QString("avcodec_parameters_copy fail. ") + av_strerror(ret, buf, AV_ERROR_MAX_STRING_SIZE); - goto free; - } - //LOGD("fourcc %s",av_fourcc2str(newStream->codecpar->codec_tag)); - if(vi_idx == -1 && stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) vi_idx = ss; - } - if(vi_idx == -1) { - err = "Didn't find a Video Stream"; - goto free; - } - auto codecpar = in_fmt->streams[vi_idx]->codecpar; - qDebug()<<"codec_id"<codec_id<codec_id); - - auto decoder = avcodec_find_decoder(codecpar->codec_id); - if(decoder==0) { - err = "Could not found Video Decoder"; - goto free; - } - de_ctx = avcodec_alloc_context3(decoder); - avcodec_parameters_to_context(de_ctx, codecpar); - if(avcodec_open2(de_ctx, decoder, 0) < 0) { - err = "Could not open Video Codec Ctx"; - goto free; - } - auto sws_ctx = sws_getContext(de_ctx->width, de_ctx->height, de_ctx->pix_fmt, sw, sh, AV_PIX_FMT_ARGB, SWS_FAST_BILINEAR, 0, 0, 0); - - auto encoder = avcodec_find_encoder(AV_CODEC_ID_H264); - if(encoder==0) { - fprintf(stderr, "Codec not found\n"); - goto free; - } - en_ctx = avcodec_alloc_context3(encoder); - avcodec_parameters_to_context(en_ctx, codecpar); - if(avcodec_open2(en_ctx, encoder, 0) < 0) { - err = "Could not open Video Codec Ctx"; - goto free; - } - en_ctx->pix_fmt = AV_PIX_FMT_ARGB; - en_ctx->bit_rate = dw*dh/150000; //码率 清晰度有关 - en_ctx->width = dw; - en_ctx->height = dh; - qDebug()<<"gop_size"<gop_size; - qDebug()<<"max_b_frames"<max_b_frames; - if (avcodec_open2(en_ctx, encoder, 0) < 0) { - fprintf(stderr, "Could not open codec\n"); - goto free; - } - avcodec_parameters_from_context(out_fmt->streams[vi_idx]->codecpar, en_ctx); - - if(out_fmt->flags & AVFMT_NOFILE) qDebug()<<"AVFMT_NOFILE"; - else if((ret = avio_open(&out_fmt->pb, outfile.constData(), AVIO_FLAG_WRITE)) < 0) { - err = QString("avio_open fail. ")+av_strerror(ret, buf, AV_ERROR_MAX_STRING_SIZE); - goto free; - } - if((ret = avformat_write_header(out_fmt, 0)) < 0) { - err = QString("avformat_write_header fail. ")+av_strerror(ret, buf, AV_ERROR_MAX_STRING_SIZE); - goto free; - } - - auto packet = av_packet_alloc(); - auto frm = av_frame_alloc(); - while(1) { - if((ret = av_read_frame(in_fmt, packet)) < 0) { - if(ret!=AVERROR_EOF) { - err = QString("Read packet fail: ")+av_strerror(ret, buf, AV_ERROR_MAX_STRING_SIZE); - break; - } - ret = avcodec_send_packet(de_ctx, 0); - } else { - if(packet->stream_index != vi_idx) { - av_write_frame(out_fmt, packet); - continue; - } - ret = avcodec_send_packet(de_ctx, packet); - } - if(ret < 0) break; - while((ret = avcodec_receive_frame(de_ctx, frm)) != AVERROR(EAGAIN)) { - if(ret < 0) { - if(ret!=AVERROR_EOF) { - err = QString("Receive frame fail: ")+av_strerror(ret, buf, AV_ERROR_MAX_STRING_SIZE); - goto free2; - } - ret = avcodec_send_frame(en_ctx, 0); - } else { - QImage img(sw, sh, QImage::Format_ARGB32); - uint8_t *dst[4]{img.bits()}; - int dstStride[4]{img.bytesPerLine()}; - sws_scale(sws_ctx, frm->data, frm->linesize, 0, de_ctx->height, dst, dstStride); - auto out_frm = av_frame_alloc(); - av_image_alloc(out_frm->data, out_frm->linesize, dw, dh, AV_PIX_FMT_ARGB, 8); - av_frame_copy_props(out_frm, frm); - out_frm->width = dw; - out_frm->height = dh; - out_frm->format = AV_PIX_FMT_ARGB; - QImage out_img(out_frm->data[0], dw, dh, out_frm->linesize[0], QImage::Format_ARGB32); - QPainter painter(&out_img); - painter.drawImage(pos, img); - for(int i=1; iduration; - } - free: - avformat_close_input(&fmt_ctx); - return err; -} QString Tools::readErrStr(QImageReader::ImageReaderError err) { if(err==QImageReader::UnknownError) return "UnknownError"; if(err==QImageReader::FileNotFoundError) return "FileNotFoundError"; @@ -301,30 +56,33 @@ QString Tools::fileMd5(QString filePath) { file.close(); return QString::fromLatin1(cryptoHash.result().toHex()); } -void Tools::mergeFormat(QTextEdit *textEdit, const QTextCharFormat &format) { +void Tools::mergeFormat(QTextEdit *textEdit, const QTextCharFormat &fmt) { QTextCursor cursor = textEdit->textCursor(); if(! cursor.hasSelection()) cursor.select(QTextCursor::WordUnderCursor); - cursor.mergeCharFormat(format); - textEdit->mergeCurrentCharFormat(format); + cursor.mergeCharFormat(fmt); } void Tools::saveImg(const QString& dir, const QFontMetrics& metric, const QFont& font, const QColor& color, QJsonObject& imgs, const QString& str, const QString& name) { if(str.isEmpty()) return; QImage img(metric.horizontalAdvance(str), metric.lineSpacing(), QImage::Format_ARGB32); img.fill(Qt::transparent); - QPainter painter(&img); - painter.setFont(font); - painter.setPen(color); - QTextOption opt(Qt::AlignCenter); - opt.setWrapMode(QTextOption::NoWrap); - painter.drawText(QRectF(0, 0, img.width(), img.height()), str, opt); - QBuffer buf; - if(! img.save(&buf, "PNG")) return; + { + QPainter painter(&img); + painter.setFont(font); + painter.setPen(color); + QTextOption opt(Qt::AlignCenter); + opt.setWrapMode(QTextOption::NoWrap); + painter.drawText(QRectF(0, 0, img.width(), img.height()), str, opt); + } + QByteArray data; + QBuffer buffer(&data); + buffer.open(QIODevice::WriteOnly); + if(! img.save(&buffer, "PNG")) return; QCryptographicHash cryptoHash(QCryptographicHash::Md5); - cryptoHash.addData(buf.data()); + cryptoHash.addData(data); auto md5 = QString::fromLatin1(cryptoHash.result().toHex()); QFile file(dir+"/"+md5); if(! file.open(QFile::WriteOnly)) return; - file.write(buf.data()); + file.write(data); file.close(); imgs.insert(name, md5); } @@ -336,22 +94,26 @@ void Tools::saveImg2(const QString& dir, const QFontMetrics& metric, const QFont if(! str.isEmpty()) { QImage img(metric.horizontalAdvance(str), metric.lineSpacing(), QImage::Format_ARGB32); img.fill(Qt::transparent); - QPainter painter(&img); - painter.setFont(font); - painter.setPen(color); - QTextOption opt(Qt::AlignCenter); - opt.setWrapMode(QTextOption::NoWrap); - painter.drawText(QRectF(0, 0, img.width(), img.height()), str, opt); - QBuffer buf; - if(img.save(&buf, "PNG")) { + { + QPainter painter(&img); + painter.setFont(font); + painter.setPen(color); + QTextOption opt(Qt::AlignCenter); + opt.setWrapMode(QTextOption::NoWrap); + painter.drawText(QRectF(0, 0, img.width(), img.height()), str, opt); + } + QByteArray data; + QBuffer buffer(&data); + buffer.open(QIODevice::WriteOnly); + if(img.save(&buffer, "PNG")) { obj.insert("picWidth", img.width()); obj.insert("picHeight", img.height()); QCryptographicHash cryptoHash(QCryptographicHash::Md5); - cryptoHash.addData(buf.data()); + cryptoHash.addData(data); auto md5 = QString::fromLatin1(cryptoHash.result().toHex()); QFile file(dir+"/"+md5); if(file.open(QFile::WriteOnly)) { - file.write(buf.data()); + file.write(data); file.close(); obj.insert("id", md5); } @@ -385,34 +147,3 @@ QColor Tools::int2Color(int value) { QString Tools::selectStr(bool f, const QString &s0, const QString &s1) { return f ? s0 : s1; } - -QString Tools::convertFileSize(const qint64 & bytes){ - float num = bytes; - QStringList list; - list << "KB" << "MB" << "GB" << "TB"; - - QStringListIterator i(list); - QString unit("bytes"); - - while(num >= 1024.0 && i.hasNext()) - { - unit = i.next(); - num /= 1024.0; - } - return QString().setNum(num,'f',2)+" "+unit; -} -QString Tools::styleSheet() { - QStringList qsses = QDir(":/qss").entryList(QStringList{"*.css"}); - std::sort(qsses.begin(), qsses.end(), [](const QString &a, const QString &b) { - return a < b; - }); - QString qss; - foreach(QString qss_name, qsses) { - QFile f(":/qss/" + qss_name); - if(f.exists() && f.open(QFile::ReadOnly)) { - qss += f.readAll(); - f.close(); - } - } - return qss; -} diff --git a/LedOK/tools.h b/LedOK/tools.h index 7f4ec12..28d7c08 100644 --- a/LedOK/tools.h +++ b/LedOK/tools.h @@ -2,8 +2,8 @@ #define TOOLS_H #include "devicepanel.h" -#include "wProgramManager/progitem.h" -#include "wDevicesManager/ledcard.h" +#include "program/progitem.h" +#include "device/ledcard.h" #include #include #include @@ -14,9 +14,7 @@ #include #include #include -extern "C"{ -#include -} + const QString str0_9[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}; extern QWidget *gMainWin; extern DevicePanel *gDevicePanel; @@ -25,6 +23,7 @@ extern QTextEdit *gFdResInfo; extern QString gFileHome; extern QWidget *gProgEditorWin; extern ProgItem *gProgItem; +extern QString css; class Tools : public QObject { Q_OBJECT @@ -37,9 +36,6 @@ public: static QRectF centerRect(qreal, qreal, int, int); static QString addSufix(QString); static void mergeFormat(QTextEdit *textEdit, const QTextCharFormat &format); - static QString videoInfo(QByteArray url, QImage &, int64_t *dur, AVCodecID *); - static QString trans(int sw, int sh, int dw, int dh, int cnt, QPointF pos, QByteArray file); - static QString audioInfo(QByteArray url, int64_t *dur); static QString readErrStr(QImageReader::ImageReaderError); static QString fileMd5(QString); static void saveImg(const QString&, const QFontMetrics&, const QFont&, const QColor&, QJsonObject&, const QString&, const QString&); @@ -48,8 +44,6 @@ public: static int color2Int(const QColor& color); static QBrush getBrush(const QColor& color); static QString selectStr(bool f, const QString &s0, const QString &s1 = ""); - static QString convertFileSize(const qlonglong & bytes); - static QString styleSheet(); ~Tools() { killTimer(timer_id); } diff --git a/LedOK/translations/app_en.ts b/LedOK/translations/app_en.ts index da3b515..2228255 100644 --- a/LedOK/translations/app_en.ts +++ b/LedOK/translations/app_en.ts @@ -71,1339 +71,202 @@ Password changed successfully - - ControlEncryptWidget - - - Form - Form - - - - - Entrypt Configuration - Entrypt configuration - - - - Original password - Original password - - - - - - original password - original password - - - - - - New password - New password - - - - - Repeat new password - Repeat new password - - - - - - - Set encryption - Set encryption - - - - - Cancel encryption - Cancel encryption - - - - - Enter password - Enter password - - - - Enter again - Enter again - - - - - - - - - Tip - Tip - - - - NoSelectedController - Please select screen first - - - - - InputOriginalPasswordTip - Please input original password - - - - InputNewPasswordTip - Please input new password - - - - InputRepeatPasswordTip - Please input repeat password - - - - InputRepeatPasswordNotSameTip - The two passwords are inconsistent - - - - Tip Info - Tip Info - - - - After setting the password, please remember the password and record it. If you forget the password, the device will be unable to operate. Are you sure you want to continue with this operation? - After setting the password, please remember the password and record it. If you forget the password, the device will be unable to operate. Are you sure you want to continue with this operation? - - - - - SetControllerPassword - Set password - - - - Readback - Readback - - - - - - Success - Success - - - - - - failed - failed - - - - - Modify password - Modify password - - - - OriginalPasswordErrorTip - The original password is wrong - - - - ControlHdmiSchedule - - - Form - Form - - - - - Add - Add - - - - - Delete - Delete - - - - - Clear - Clear - - - - - Import - Import - - - - - Export - Export - - - - By default, the asynchronous content is played, and the synchronous signal content is played in the fixed time period - By default, asynchronous content is played, and synchronous hdmi-in port input content is played in a fixed time period - - - - - Apply - Apply - - - - Readback - Readback - - - - SYNC HDMI - HDMI-IN video - - - - Start Time - Start Time - - - - End Time - End Time - - - - SUN - SUN - - - - MON - MON - - - - TUE - TUE - - - - WED - WED - - - - THU - THU - - - - FRI - FRI - - - - SAT - SAT - - - - - DeviceItem OnProHttpResponse 解析json文件错误! - - - - - - On - On - - - - SyncSchedule (*.syncs) - - - - - Save File - Save file - - - - Sync Schedule (*.syncs) - - - - - - Tip - Tip - - - - - NoSelectedController - Please select screen first - - - - SetTimingHdmiInTask - Set video source form HDMI-IN schedule task - - - - GetTimingHdmiInTask - Get video source form HDMI-IN schedule task - - - - - Success - Success - - - - - failed - failed - - - - ControlHdmiWidget - - - HDMI Configuration - Video source configuration - - - - Manual - Manual - - - - Schedule - Schedule - - - - - Tip - Tip - - - - - NoSelectedController - Please select screen first - - - - - SyncSwitch - Switch video source from HDMI-IN port - - - - - AnSyncSwitch - Switch video source from Async box - - - - - IsSync - Readback video source - - - - Error - Error - - - - HDMI IN - HDMI IN - - - - Async - Async - - - - Readback - Readback - - - - ControlNetConfigWidget - - - Wire Enther(RJ45) Configuration - Wire Enther(RJ45) Configuration - - - - - DHCP - - - - - - Specify IP - Specify IP - - - - - IP Address - IP Address - - - - Mask Address - Subnet mask - - - - - Gateway - Gateway - - - - - DNS Address - DNS Address - - - - - - - - - - Set - Set - - - - - - - - - Readback - Readback - - - - - WIFI Configuration - WiFi Configuration - - - - - WiFi On/Off - WiFi On/Off - - - - Input Ap name - Input ap name - - - - - 4G/5G Configuration - Cellular Configuration - - - - - Open 4G/5G - Enable cellular data - - - - APN: - - - - - - Get cellular network status information - Get cellular network status information - - - - - Check SIM can automatically match to MCC, and then select carrier get apn param,if not found carrier,you can check the CUSTOM checkbox,then enter custom param. - Through the chcek status button, you can automatically match the country code MCC, and then select "operator" to get the response APN information. If you can't find the operator, you can select the "custom" check box, and then enter the APN information manually. - - - - - Readback APN Info - Readback APN Info - - - - - Set Apn Info,Check SIM can automatically match to MCC, and then select carrier get apn param - Set the APN information - - - - - CUSTOM - CUSTOM - - - - - Check SIM - chcek SIM Info - - - - - - -> - - - - - - Country ID(mcc): - Country ID(mcc): - - - - - Carrier Name - Carrier Name - - - - - APN: - Carrier APN: - - - - - APN(Required) - APN(Required) - - - - - User: - User Name: - - - - - - - Not required - Not required - - - - - Password: - Password: - - - - Set Apn:iot.cargo - - - - - - Flight Mode - Flight Mode - - - - - WiFi name - WiFi name - - - - - - - Password - Password - - - - - - - Input password - Input password - - - - - Scan - Scan - - - - - Ap Mode - AP - - - - Ap name - AP name - - - - OFF - OFF - - - - ON - ON - - - - AP name - AP name - - - - Subnet mask - Subnet mask - - - - Input ap name - Input AP name - - - - - - - - - - - - - - - Success - Success - - - - - - - - - - - - - - - failed - failed - - - - - - - Tip - Tip - - - - - NoSelectedController - Please select screen first - - - - - SetEthernet - Set wire nether - - - - - - - - - - - Attention - Attention - - - - Please input IP address! - Please input IP address! - - - - Your IP Address is Invalid! - IP Address is invalid! - - - - Please input Mask address! - Please input Mask address! - - - - Your Mask Address is Invalid! - Mask Address is Invalid! - - - - Please input Gateway address! - Please input Gateway address! - - - - Your Gateway Address is Invalid! - Gateway Address is Invalid! - - - - Please input DNS address! - Please input DNS address! - - - - Your DNS Address is Invalid! - DNS Address is Invalid! - - - - - GetEthernet - Get wire ethernet - - - - DHCP IP - DHCP IP - - - - STATIC IP - STATIC IP - - - - Error - Error - - - - - - - - - SignalPower - Signal strength - - - - - ConfigurationWiFi - Configuration WiFi - - - - IsPortableHotSpot - Get AP or WiFi - - - - GetWifiList - Scan WiFi list - - - - ConfigurationHotSpot - Configuration AP HotSpot - - - - GetCurrentAPN - Get Current Apn - - - - - GetSIMStatus - Get SIM Status - - - - SetAPN - Set APN - - - - - DeviceItem OnProHttpResponse 解析json文件错误! - - - - - 状态: - Status: - - - - 未知 - unknown - - - - 锁定状态,需要用户的PIN码解锁 - Lock status, need user's pin code to unlock - - - - 锁定状态,需要用户的PUK码解锁 - In the locked state, the PUK code of the user is required to be unlocked - - - - 锁定状态,需要网络的PIN码解锁 - In the locked state, the PIN code of the user is required to be unlocked - - - - 就绪 - be ready - - - - no checked sim card - no checked sim card - - - - 国家码: - MCC: - - - - 号码: - number: - - - - 用户: - User name: - - - - 信号: - Signal: - - - - 信号正常 - Signal OK - - - - 不在服务区 - Not in service area - - - - 仅限紧急呼叫 - Emergency call only - - - - 射频已经关闭 - RF off - - - - 网络: - Network type: - - - - 网络类型未知 - unKnown - - - - GPRS网络 - GPRS - - - - EDGE网络 - EDGE - - - - UMTS网络 - UMTS - - - - CDMA网络,IS95A 或 IS95B. - CDM - - - - EVDO网络, revision 0. - EVDO,revision 0. - - - - EVDO网络, revision A. - EVDO,revision A. - - - - 1xRTT网络 - 1xRTT - - - - HSDPA网络 - HSDPA - - - - HSUPA网络 - HSUPA - - - - HSPA网络 - HSPA - - - - 漫游: - roam: - - - - Yes - Yes - - - - No - No - - - - 数据连接状态: - Data connection status: - - - - 断开 - OFF - - - - 正在连接 - connecting - - - - 已连接 - Connected - - - - 暂停 - suspend - - - - 数据活动休眠状态: - Data active sleep state: - - - - 活动,但无数据发送和接收 - Active, but no data sent and received - - - - 活动,正在接收数据 - Activity, receiving data - - - - 活动,正在发送数据 - Activity, sending data - - - - 活动,正在接收和发送数据 - Activity, receiving and sending data - - - - 休眠状态 - Sleep state - - - - 信号强度: - Signal strength: - - - - SetSwitchSimData - SetSwitchSimData - - - - ContrFlightMode - Set flight mode - - - - GetFlightModeState - Readback flight mode state - - - - ControlPowerManual - - - Form - Form - - - - - POWER - Power - - - - - - Readback - Readback - - - - OFF - OFF - - - - ON - ON - - - - - Tip - Tip - - - - - NoSelectedController - Please select screen first - - - - IsScreenOn - Read power status - - - - - - SetScreenOn - Set power - - - - - - - Success - Success - - - - - on - ON - - - - - - - failed - failed - - - - - off - OFF - - - - - SetScreenOff - SetScreenOff - - - - - DeviceItem OnProHttpResponse 解析json文件错误! - - - ControlPowerSchedule - + Form Form - + Edit area Edit area - - + + Add Add - - + + Delete Delete - - + + Clear Clear - - + + Import Import - - + + Export Export - + It is power off state outside the schedule time period It is power off state outside the schedule time period - + Send command Command area - - + + Apply Apply - + Clear Schedule Cancel Schedule - + Readback Readback - + Power On State Power On State - + Start Time Start Time - + End Time End Time - + SUN SUN - + MON MON - + TUE TUE - + WED WED - + THU THU - + FRI FRI - + SAT SAT - - + + DeviceItem OnProHttpResponse 解析json文件错误! - - + + On On - - + + PowerSchedule (*.pjs) PowerSchedule (*.pjs) - + Save File Save file - - - + + + Tip Tip - - - + + + NoSelectedController Please select screen first - - + + Tip Info Tip Info - - + + Clear schedule task? Clear schedule task? - - + + CleanTimingScreenTask Clear schedule task - + SetTimingScreenTask Set schedule task of screen power - - - - + + + + Success Success - - - - + + + + failed failed - + GetTimingScreenTask Get schedule task of screen power @@ -1411,678 +274,378 @@ ControlPowerWidget - - Form - Form + + + Off + - - + + + On + On + + + + + Tip + Tip + + + + + NoSelectedController + Please select screen first + + + + + SetScreenOn + Set Screen On + + + + + SetScreenOff + Set Screen Off + + + + + IsScreenOn + Read power status + + + Power Configuration Power configuration - - + Manual Manual - - + Schedule Schedule + + + Power + Power + + + + Readback + Readback + ControlTestWidget - + Form Form - - + + Test Screen Test Screen - - + + Line test Line test - - - - - - - + + + + + + + Red Red - - - - - - - + + + + + + + Green Green - - - - - - - + + + + + + + Blue Blue - - - - - - - + + + + + + + White White - - + + Vertical Vertical - - + + Slash Oblique line - - - + + + Horizontal Horizontal - - - - + + + + Speed Speed - - + + ms(>10) - - + + Line Distance Line Distance - + px px - - - - - + + + + + Test Test - - + + Gradation test Gradation test - - + + Only the gray value is displayed Only the gray value is displayed - + (>10) - - + + GrayValue Gray value - + (0-255) - - + + Color test Color test - - + + Gradient Gradient - + 8 8 - + 2 2 - + 3 3 - + 6 6 - + 4 4 - + 5 5 - + 1 1 - + 9 9 - + 7 7 - + 0 0 - - + + Clear Clear - - + + Reset Loop - - - - + + + + Anycast Anycast - - + + Stop Stop - - - - - - - - + + + + + + + + Tip Tip - - - - - + + + + + NoSelectedController Please select screen first - - - + + + StartTest Start test - - - - + + + + Success Success - - - - + + + + failed failed - + StopTest Stop test - + loopback mode loopback mode - + Connect timeout Connect timeout - + Reset loop mode Reset loop mode - - + + success success - - - DeviceItem OnProHttpResponse 解析json文件错误! - DeviceItem OnProHttpResponse json error! - - - - CtrlVerifyClockPanel - - - Form - Form - - - - English - English - - - - 中文 - - - - - Verify Clock Configuration - Verify clock configuration - - - - Verify to Computer time - Verify to Computer time - - - - - Cur time of controller - Cur time of controller - - - - LAN - LAN - - - - (min/time) - (min/time) - - - - Sync identificationCode - Sync identificationCode - - - - - identification code - identification code - - - - - Time offset(msec) - Time offset(msec) - - - - - Brightness - Screen Brightness - - - - - Volume - Volume - - - - - Screen on/off - Screen On/Off - - - - - Slave - Slave - - - - Master - Master - - - - - NTP Server - NTP Server - - - - - - - NTP Server address - NTP Server address - - - - - - - TimeZone - Time zone - - - - - - - - - - - - - - - Set - Set - - - - - Language: - Language: - - - - - Enable Synchronous playing - Enable Synchronous playing - - - - Lora - - - - - GPS - - - - - NTP - - - - - Time zone - Time zone - - - - - - - Sync time interval - Sync time interval - - - - Verify clock configuration - Verify clock configuration - - - - - - - - - - - - - - Readback - Readback - - - - Master - Master - - - - Sync clock to computer time - Calibrate clock to computer time - - - - Identification Code - Identification Code - - - - - - - - - - - - - - Success - Success - - - - - - - - - - - - - - failed - failed - - - - SetNtpServer - SetNtpServer - - - - MasterSwitch - Set as master device - - - - SlaveSwitch - Set as slave device - - - - IsMasterSlave - Read back the identity of master and slave - - - - GetControllerDate - Get date time - - - - SetingSyncMethod - Set sync method - - - - SyncTime - SyncTime - - - - GetNtpServer - GetNtpServer - - - - GetingSyncMethod - Geting Sync Method - - - - - DeviceItem OnProHttpResponse 解析json文件错误! - - - - - SetTimezone - Set Timezone - - - - ControlVolumeManual - - - Form - Form - - - - Volume(0-15) - Volume(0-15) - - - - - - Readback - Readback - - - - SetVolume - Set Volume - - - - - - Success - Success - - - - - - failed - failed - - - - Volume(min:0-max:15) - Volume(min:0-max:15) - - - - GetVolume - Get Volume - - - - + + DeviceItem OnProHttpResponse 解析json文件错误! DeviceItem OnProHttpResponse json error! @@ -2090,174 +653,174 @@ ControlVolumeSchedule - + Defalut volume tip Reminder: the brightness within the fixed time period is displayed according to the timing brightness, and the default brightness value is not set for other time periods - - + + Add Add - - + + Delete Delete - - + + Clear Clear - + Default Volume Default Volume - + (0-15) - - + + Import Import - - + + Export Export - - + + Apply Apply - + Readback Readback - + Volume value Volume value - + Start Time Start Time - + End Time End Time - + SUN SUN - + MON MON - + TUE TUE - + WED WED - + THU THU - + FRI FRI - + SAT SAT - + Default volume tip Reminder: the display screen is the default brightness outside the fixed time period - + Default volume Default volume - - + + DeviceItem OnProHttpResponse 解析json文件错误! DeviceItem OnProHttpResponse json error! - + 10 10 - - + + Volume Schedule (*.vols) - + Save File Save file - - + + Tip Tip - - + + NoSelectedController Please select screen first - + SetAutoVolumeTask Set volume schedule - - + + Success Success - - + + failed failed - + GetAutoVolumeTask Get volume schedule @@ -2265,1187 +828,2504 @@ ControlVolumeWidget - - Form - Form + + + Tip + Tip - - + + + NoSelectedController + Please select screen first + + + + + SetVolume + Set Volume + + + + + GetVolume + Get Volume + + + Volume Control Volume Control - - + Manual Manual - - + Schedule Schedule + + + Volume + Volume + + + + Readback + Readback + CtrlAdvancedPanel - - Advanced parameters - Advanced parameters + + Advanced + Advanced - + Screen Width(pixel) Screen Width(pixel) - + Width Width - - + + Height Height - - - - - - - + + + + + + + + + + + + + + + Set Set - + Alias Alias - + Web Server Address: Web Server Address: - + www.m2mled.net - + www.ledaips.com - + https://www.taxihub.cn:2340 - + https://www.ledaips.com:2340 - + https://www.36taxi.com:2340 - + www.tlzxled.com - + + MCU Uploading + + + + + Traffic screen settings + + + + + Setting protocol ... + + + + + Set protocol + + + + + Getting protocol ... + + + + + Get protocol + + + + + + Port + + + + Realtimer Server Address: Realtimer Server Address: - + + Firmware Management + + + + + update or uninstall + + + + Clear Clear - - Apk upgrade - Apk upgrade - - - + Check Apk Check Apk - + Uninstall Uninstall - + Running check Running check - - FPGA version check - FPGA version check + + Restart + Restart - - Sync FPGA version - Sync FPGA version - - - - Restart led controller system - Restart led controller system - - - + Check Log Check Log - + Start LedSet4 Start LedSet4.0 (Apk Display2.0 and higher) - + Open ADB Open ADB debugging function - + Post Custom JSON Post Custom JSON - - - - - - - - + + + + + + + + Clear Program Clear Program - + www.ledokcloud.com/realtime - - M80 configuration - M80 configuration + + Config + Config - + Refresh Refresh - + Restore to default Restore to default - + Taxi top screen configuration Taxi top screen configuration - + + Service:High Out of service:Low Service:High Out of service:Low - + + Service:Low Out of service:High Service:Low Out of service:High - + Start LedSet3.0 configure LED module Start LedSet3.0 configure LED module (used by manufacturer's professionals) - + Binding *.ic account indentity voucher Binding *.ic account indentity voucher - + Rotate Rotate - - 0 degrees - 0 degrees - - - - 90 degrees - 90 degrees - - - - 180 degrees - 180 degrees - - - - 270 degrees - 270 degrees - - - + Min brightness Min brightness - - (min:1) - (min:1) - - - - - + + + Readback Readback - - - + Send Send - + Max brightness Max brightness - - (max:255) - (max:255) - - - - + + SetScreenSize Set Screen Size - - - - - - - - - - - - - - - - - - - - - - - - - + + + + Success Success - + Compant ID: Company ID - - FPGA Upgrade - FPGA Upgrade - - - + Compant ID Company ID - + InputWebServerAddressTip Please enter web server address - + InputCompanyIdTip Please enter company ID - + Do you want to modify webserveraddress and companyId? Are you sure you want to configure the server address and company ID? - - - - - - - - - - - - - - - - - - - - - - failed - failed - - - - + + SetOnlineAddr Set Web server address - + + ClearRealtimeServer Clear - - InputRealTimeAddressTip - Please enter the realtimer address - - - + + SetRealtimeServer Set realtimer address - - - - + + + + Tip Info Tip Info - - - + + + Can not find LedSet3.0.exe,down you need download and install it Can not find LedSet3.0.exe,down you need download and install it - + + RestartAndroid Restart - - FPGA Version - FPGA Version - - - - + + running running - - + + no running no running - + Check Apk Version Check Apk Version - - + + UninstallSoftware Uninstall - - - IsSoftwareRunning - Check apk running status - - - - apk package (*.rpd) + + + Check apk running status - - CheckHardwareVersions - Check FPGA version - - - - - - SynchronousHardwareVersion - Sync FPGA version - - - - Check Screen untile fpga update finished - Watch the progress of screen upgrade until the upgrade is finished - - - + + OpenAdb Open ADB debugging function - + indentity voucher (*.ic) indentity voucher (*.ic) - - - - - + + + + + InvokeTaxiAppFunction Binding certificate - - Json format is error! - - - - - + + AliIotSetting - - apk package (*.apk *.zip) - - - - + Software Version Info - + Package - + Version - - - UpgradeSoftware - Upgrade firmware - - - - This screen is encrypted,Please decrypt and upgrade APK! - This screen is encrypted,Please decrypt and upgrade APK! - - - - + + Package name is null - + Clearing Program - - - - + + + + Timeout Timeout - - - - + + + + Failed - + Getting Log - - - - - - - - - + + + + + + + + + + + Error Error - + + Setting Timing Reboot + + + + + Set Timing Reboot + + + + + Getting Timing Reboot + + + + + Get Timing Reboot + + + + + totalResolution + FPGA total resoltuion + + + + strCurDisplayResolution + Cur display resolution + + + + File not exist + + + + + Uploading + + + + + + Set Display Mode + + + + + + Get Display Mode + + + + + + Set Screen Offset + + + + + + Get Screen Offset + + + + Open file Failed Open file Failed - + Setting Wallpaper - - + + Set Wallpaper - + System Updating - - + + System Update - + + Getting MCU Version + + + + + + MCU Version + + + + Select File Select File - + Setting player background - - + + Set player background - + Clearing player background - - - - - - - - + + + + + + + + Clear player background - + Setting Baud Rate - + Set Baud Rate - + Getting Baud Rate - + Get Baud Rate - + + Text is empty + + + + + Json Parse Error + + + + + Json isn't an Object + + + + + Setting card work mode ... + + + + + Set card work mode + + + + + Getting card work mode ... + + + + + Get card work mode + + + + + Resolution Config + + + + + Full screen + + + + + Part + + + + + Display Mode + + + + + Screen Position + + + + + Offset + + + + Hidden Settings - + Click right button to hide - + + + Update MCU + + + + + Get MCU Version + + + + Baud Config - + Model - + Uart - + Baud - + + + + + + Get - - - - + + Timing Reboot + + + + + Protocol + + + + + Server + + + + + Client + + + + + SetScreenRotation Set screen rotation - + + SetMinBrightness Set min brightness value - + + SetMaxBrightness Set maximum brightness value - + + GetMinBrightness Get min brightness - + + GetMaxBrightness Get maximum brightness - + + + Card work mode + + + + + SetSpecialResolution Set Special Resolution - + + GetSpecialResolution Get Special Resolution - + + CleanDisplayScreenSize Restore to default relolution - + + SetHighForBusy Set level for busy - + + GetStateForBusy Get level of busy - - install start... - Start installation... - - - + InputAliasTip Please input alias - - + + SetCardAlias Set alias - - Uploadding - Uploading - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Tip Tip - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NoSelectedController Please select screen first - + InputWidthTip Please enter the correct width pixel value - + InputHeightTip Please enter the correct height pixel value - + Password is error Password is error - - - - - DeviceItem OnProHttpResponse 解析json文件错误! - DeviceItem OnProHttpResponse json error! - CtrlBrightPanel - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + Tip Tip - - - - - - - - - - - + + + + + + + + + + + NoSelectedController Please select screen first - - + + SetBrightnessSensitivity Set brightness sensitivity - - + + GetBrightnessSensitivity Get brightness sensitivity - - + + SetMinBrightness Set min brightness value - - + + GetMinBrightness Get min brightness - - + + NeedSelectSensorTypeTip Please select sensor type first - + Open file dialog - + Not found current worksheet - - + + SensorBrightnessTable Set sensor brightness table - + GetSensorBrightnessTable Get sensor bright table - + no sensorBrightnessTable no sensor brightnessTable in controller - + Save file Save file - - + + GetCurrentSensorBrightness Get Current Brightness - - + + SetBrightness Set brightness - + GetBrightness Get brightness - + Brightness Screen Brightness - - + + BrightnessSchedule (*.bjs) - + Import File - + Save File Save file - + BrightnessValue Brightness Value - + Start Time Start Time - + End Time End Time - - + + SetAutoBrightnessTask Send brightness schedule table - + GetAutoBrightnessTask Get brightness schedule - - - - + + Error Error - + Brightness Configuration Brightness configuration - + Auto Auto - + Manual Manual - + Schedule Schedule - + + Adapt to Old Devices + + + + BrightTip1 If the maximum brightness is 64, the minimum brightness can be configured as 1% or appropriate value; if the maximum brightness is 255, the minimum brightness must be configured as 36% or above, otherwise the brightness will be low. - + BrightTip2 When uploading the file, please confirm to select the correct sensor type, otherwise it will be invalid! - + Sensitivity Sensitivity - + Minbrightness Minimum Brightness - - - + + + Set Set - + Upload Upload file - - - - + + + + Readback Readback - + ReadbackTable Readback - + Refresh Refresh - + Cur Brigntness Cur Brigntness - + Brightness value Brightness value - + Default brightness Default brightness - + Add Add - + Clear Clear - + Delete Delete - + Import Import - + Export Export - + Apply Apply - + Default brightness tip - Tip: within the setting time is the setting brightness, and outside the setting time is the default brightness. For example, set the default brightness to 80, set the brightness to 180, and the time range to 8:00-17:00, then the brightness in the time range is 180, and the default brightness in other times is 80! + Tip: within the setting time is the setting brightness, and outside the setting time is the default brightness. For example, set the default brightness to 50%, set the brightness to 80%, and the time range to 8:00-17:00, then the brightness in the time range is 80%, and the default brightness in other times is 50% + + + + CtrlHdmiPanel + + + HDMI Configuration + Video source configuration + + + + Manual + Manual + + + + Schedule + Schedule + + + + + + + Tip + Tip + + + + + + + NoSelectedController + Please select screen first + + + + + SyncSwitch + Switch video source from HDMI-IN port + + + + + AnSyncSwitch + Switch video source from Async box + + + + IsSync + Readback video source + + + + Import File + + + + + Save File + Save file + + + + + Sync Schedule + + + + + + SetTimingHdmiInTask + Set video source form HDMI-IN schedule task + + + + GetTimingHdmiInTask + Get video source form HDMI-IN schedule task + + + + + Async + Async + + + + + Readback + Readback + + + + Start Time + Start Time + + + + End Time + End Time + + + + SUN + SUN + + + + MON + MON + + + + TUE + TUE + + + + WED + WED + + + + THU + THU + + + + FRI + FRI + + + + SAT + SAT + + + + Add + Add + + + + + Apply + Apply + + + + Clear + Clear + + + + Delete + Delete + + + + Import + Import + + + + Export + Export + + + + By default, the asynchronous content is played, and the synchronous signal content is played in the fixed time period + By default, asynchronous content is played, and synchronous hdmi-in port input content is played in a fixed time period + + + + CtrlNetworkPanel + + + Wire Enther(RJ45) Configuration + Wire Enther(RJ45) Configuration + + + + DHCP + + + + + Specify IP + Specify IP + + + + IP Address + IP Address + + + + Gateway + Gateway + + + + DNS Address + DNS Address + + + + + + Set + Set + + + + + + + Readback + Readback + + + + WIFI Configuration + WiFi Configuration + + + + WiFi Mode + WiFi Mode + + + + Cellular Config + Cellular Config + + + + Enable Cellular Data + Enable Cellular Data + + + + Get cellular network status information + Get cellular network status information + + + + Through the check status button + Through the "check status" button, you can automatically match the country code MCC, and then select "operator" to get the corresponding APN information. + + + + Country ID(mcc): + Country ID(mcc): + + + + + Carrier Name + Carrier Name + + + + APN(Required) + APN(Required) + + + + Flight Mode + Flight Mode + + + + WiFi name + WiFi name + + + + + + Password + Password + + + + + Input password + Input password + + + + Scan + Scan + + + + Ap Mode + AP + + + + OFF + OFF + + + + ON + ON + + + + AP name + AP name + + + + Subnet mask + Subnet mask + + + + Input ap name + Input AP name + + + + + + + + + + + + + + + Tip + Tip + + + + + + + + + + + + + + NoSelectedController + Please select screen first + + + + + SetEthernet + Set wire nether + + + + + + + + + + + Attention + Attention + + + + Please input IP address! + Please input IP address! + + + + Your IP Address is Invalid! + IP Address is invalid! + + + + Please input Mask address! + Please input Mask address! + + + + Your Mask Address is Invalid! + Mask Address is Invalid! + + + + Please input Gateway address! + Please input Gateway address! + + + + Your Gateway Address is Invalid! + Gateway Address is Invalid! + + + + Please input DNS address! + Please input DNS address! + + + + Your DNS Address is Invalid! + DNS Address is Invalid! + + + + + GetEthernet + Get wire ethernet + + + + DHCP IP + DHCP IP + + + + STATIC IP + STATIC IP + + + + + ConfigurationWiFi + Configuration WiFi + + + + + IsPortableHotSpot + Get AP or WiFi + + + + GetWifiList + Scan WiFi list + + + + + ConfigurationHotSpot + Configuration AP HotSpot + + + + success + success + + + + WifiName + WifiName + + + + ApName + Ap Name + + + + + GetCurrentAPN + Get Current Apn + + + + GetSIMStatus + Get SIM Status + + + + + SetAPN + Set APN + + + + 状态: + Status: + + + + 未知 + unknown + + + + 锁定状态,需要用户的PIN码解锁 + Lock status, need user's pin code to unlock + + + + 锁定状态,需要用户的PUK码解锁 + In the locked state, the PUK code of the user is required to be unlocked + + + + 锁定状态,需要网络的PIN码解锁 + In the locked state, the PIN code of the user is required to be unlocked + + + + 就绪 + be ready + + + + no checked sim card + no checked sim card + + + + 国家码: + MCC: + + + + 号码: + number: + + + + 用户: + User name: + + + + 信号: + Signal: + + + + 信号正常 + Signal OK + + + + 不在服务区 + Not in service area + + + + 仅限紧急呼叫 + Emergency call only + + + + 射频已经关闭 + RF off + + + + 网络: + Network type: + + + + 网络类型未知 + unKnown + + + + GPRS网络 + GPRS + + + + EDGE网络 + EDGE + + + + UMTS网络 + UMTS + + + + CDMA网络,IS95A 或 IS95B. + CDM + + + + EVDO网络, revision 0. + EVDO,revision 0. + + + + EVDO网络, revision A. + EVDO,revision A. + + + + 1xRTT网络 + 1xRTT + + + + HSDPA网络 + HSDPA + + + + HSUPA网络 + HSUPA + + + + HSPA网络 + HSPA + + + + 漫游: + roam: + + + + Yes + Yes + + + + No + No + + + + 数据连接状态: + Data connection status: + + + + 断开 + OFF + + + + 正在连接 + connecting + + + + 已连接 + Connected + + + + 暂停 + suspend + + + + 数据活动休眠状态: + Data active sleep state: + + + + 活动,但无数据发送和接收 + Active, but no data sent and received + + + + 活动,正在接收数据 + Activity, receiving data + + + + 活动,正在发送数据 + Activity, sending data + + + + 活动,正在接收和发送数据 + Activity, receiving and sending data + + + + 休眠状态 + Sleep state + + + + 信号强度: + Signal strength: + + + + Set APN Info + + + + + User + + + + + Type + + + + + Server + + + + + Port + + + + + Proxy + + + + + MMS Port + + + + + MMS Proxy + + + + + + SetSwitchSimData + SetSwitchSimData + + + + + ContrFlightMode + Set flight mode + + + + + GetFlightModeState + Readback flight mode state + + + + CtrlPwdPanel + + + Set Password + Set Password + + + + Original password + Original password + + + + original password + original password + + + + + New password + New password + + + + Repeat new password + Repeat new password + + + + + + + Set encryption + Set encryption + + + + Cancel encryption + Cancel encryption + + + + Enter again + Enter again + + + + + + + + + + + + Tip + Tip + + + + + NoSelectedController + Please select screen first + + + + + InputOriginalPasswordTip + Please input original password + + + + InputNewPasswordTip + Please input new password + + + + InputRepeatPasswordTip + Please input repeat password + + + + InputRepeatPasswordNotSameTip + The two passwords are inconsistent + + + + Tip Info + Tip Info + + + + After setting the password, please remember the password and record it. If you forget the password, the device will be unable to operate. Are you sure you want to continue with this operation? + After setting the password, please remember the password and record it. If you forget the password, the device will be unable to operate. Are you sure you want to continue with this operation? + + + + + + + SetControllerPassword + Set password + + + + + Error + Error + + + + + Success + Success + + + + + + Modify password + Modify password + + + + + + + OriginalPasswordErrorTip + The original password is wrong + + + + CtrlVerifyClockPanel + + + Verify Clock Configuration + Verify clock configuration + + + + + Verify to Computer time + Verify to Computer time + + + + Cur time of controller + Cur time of controller + + + + + LAN + LAN + + + + + + + + + + + + + + Tip + Tip + + + + + + + + + + + + + + NoSelectedController + Please select screen first + + + + screenSwitch + Switch Screen + + + + + + YES + On + + + + + + NO + Close + + + + volume + Volume + + + + brightness + brightnenss + + + + + identificationCode + Identification Code + + + + + delaySync + Time offset + + + + + msec + msec + + + + + + + OtherSyncItem + Other sync items + + + + + + + lastSynchronousTime + Last Synchronous Time + + + + checkNtpTime + Synchronization interval + + + + Lora identity + Lora identity + + + + (min/time) + (min/time) + + + + identification code + identification code + + + + Time offset(msec) + Time offset(msec) + + + + Brightness + Screen Brightness + + + + Volume + Volume + + + + Screen on/off + Screen On/Off + + + + + Slave + Slave + + + + NTP Server + NTP Server + + + + + NTP Server address + NTP Server address + + + + TimeZone + Time zone + + + + + + + + Set + Set + + + + Language: + Language: + + + + Enable Synchronous playing + Enable Synchronous playing + + + + + Sync time interval + Sync time interval + + + + + + + + Readback + Readback + + + + + Master + Master + + + + Identification Code + Identification Code + + + + + SetNtpServer + SetNtpServer + + + + + MasterSwitch + Set as master device + + + + + SlaveSwitch + Set as slave device + + + + IsMasterSlave + Read back the identity of master and slave + + + + + GetControllerDate + Get date time + + + + + SetingSyncMethod + Set sync method + + + + + SyncTime + SyncTime + + + + + GetNtpServer + GetNtpServer + + + + + GetingSyncMethod + Geting Sync Method + + + + + SetTimezone + Set Timezone Def - - - + Connection Timeout - - - - - - - + + + + + Device replied - - + + + Success Success - - - - Error - Error - - - - Tip Info - Tip Info - - - - + Fail Fail @@ -3453,666 +3333,314 @@ DeviceCtrlPanel - - - + + + + Current Screen Current screen - - + + none none - - + + Clear Clear - - - single screen operation - single screen operation - - - + + Multi screen operation Multi screen operation - + + selected num Selected number - + Brightness Adjustment Brightness Adj. - + Power Control Power Control - + Net Config Network Config - - Time Synchronization + + Time Sync Time Sync - + Video source Video Source - - Encrypt - Encrypt + + Password + Password - - Advanced parameters + + Advanced Advanced - - Current Screen: - - - - + Test Test - - Volume Adjustment - Volume Adj. + + Volume Adj. + Volume DeviceItem - + GetScreenDetailInfo Get more detail info - + ReadbackPic Screenshot - + Input password Input password - + GetScreenshotFull readback screenshot - + cur brightness: Current Brightness: - + android version: Android Version: - + IMEI: - + HardWard Version: FPGA Version: - + MAX Brightness level: Brightness Level: - + Android OS Resolution: Android OS Resolution: - + Firmware Version: Firmware Version: - + Player Version: Player firmware version: - + Detail Info Detail Info - - - - - - - + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + receive Receive - - SetScreenOn - Set power - - - + AliIotSetting - - + + GetScreenStatus GetScreenStatus - - + + Status Status - + Tip Info Tip Info - + password is wrong password is wrong - + GetBrightness Get brightness - - - + brightness brightnenss - - MasterSlaveSwitch - Configure master slave identity - - - - SetBrightness - Set brightness - - - - - SetMinBrightness - Set min brightness value - - - - GetBrightnessSensitivity - Get brightness sensitivity - - - - sensitivity - sensitivity - - - - GetMinBrightness - Get min brightness - - - - SetSensorBrightnessTable - SetSensorBrightnessTable - - - - SetSwitchWiFi - Set WiFi on/off - - - - ConfigurationWiFi - Configuration WiFi - - - - ConfigurationHotSpot - Configuration AP HotSpot - - - - GetSwitchWiFi - GetSwitchWiFi - - - + SetAutoBrightnessTask Send brightness schedule table - + SetAutoVolumeTask Set volume schedule - + SetVolume Set Volume - + GetVolume Get Volume - + SetTimingScreenTask Set schedule task of screen power - - GetControllerDate - Get date time - - - - SetHighForBusy - Set level for busy - - - - - GetStateForBusy - Get level of busy - - - - Service:Low Out of service:High - Service:Low Out of service:High - - - - Service:High Out of service:Low - Service:High Out of service:Low - - - - - - IsPortableHotSpot - Get AP or WiFi - - - - WifiName - WifiName - - - - ApName - Ap Name - - - + TestScreen Test screen - + SetOnlineAddr Set Web server address - + SetRealtimeServer Set realtimer address - - GetOnlineAddr - Get web server address - - - - GetRealtimeServer - Get realtime server address - - - - SetNtpServer - SetNtpServer - - - - GetNtpServer - GetNtpServer - - - - SyncTime - SyncTime - - - - DelPrograms - Clear program - - - - SetingSyncMethod - Set sync method - - - + GetCurrentSensorBrightness Get Current Brightness - + Cur brightness Cur brightness - - SetSpecialResolution - Set Special Resolution - - - - GetSpecialResolution - Get Special Resolution - - - - totalResolution - FPGA total resoltuion - - - - strCurDisplayResolution - Cur display resolution - - - - CleanDisplayScreenSize - Restore to default relolution - - - - SetMaxBrightness - Set maximum brightness value - - - - GetMaxBrightness - Get maximum brightness - - - - screenSwitch - Switch Screen - - - - - - YES - On - - - - - - NO - Close - - - - LAN - LAN - - - + Connect Connect - + timeout timeout - + Anycast Anycast - - + volume Volume - - - - - - - GetingSyncMethod - Geting Sync Method - - - - - identificationCode - Identification Code - - - - - delaySync - Time offset - - - - - msec - msec - - - - - - - OtherSyncItem - Other sync items - - - - - - - lastSynchronousTime - Last Synchronous Time - - - - checkNtpTime - Synchronization interval - - - - Uploadding - Uploadding - - - + Success Success - + failed failed - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + success success - - - Lora identity - Lora identity - - - - Master - Master - - - - Slave - Slave - - - - SetBrightnessSensitivity - Set brightness sensitivity - - - - - + + + on ON - - - + + + off OFF @@ -4121,116 +3649,116 @@ DevicePanel - + All ALL ALL - + Online Online Online - - + + Refresh Refresh Refresh - - - + + + Specify IP Specify IP Specify IP - + Current Screen Current screen - + none none - + Specify IP list - + Search Search - - + + Attention Attention - - + + Please input IP address! Please input IP address! - + Cancel Cancel - + Screen ID Screen ID - + Screen IP Screen IP - + Screen Size Screen Size - + Remark Name Alias - + readback pic Screenshot - + send send - + More Info More Info - + Cur Brightness Screen Current Brightness - + Power Status Power Status - + Security encryption @@ -4407,39 +3935,156 @@ - EAudio + EAClock - + Basic Properties Basic properties - - File - File + + Time Zone + Time Zone - + + Custom Dial + Custom Dial + + + + Select + Select + + + + Select Dail file + Select dial file + + + + Hour Mark + Hour Scale + + + + + Circular + Circle + + + + + Rectangle + Rectangle + + + + Number + Number + + + + + + T + + + + + Min Mark + Minute Scale + + + + Color + + + + + Length + + + + + Width + Width + + + + Hour Hand + + + + + Min Hand + + + + + Sec Hand + + + + + Show + + + + + Text + Text + + + Play Properties - + Play Duration Play Duration - + + s + s + + + + EAudio + + + Basic Properties + Basic properties + + + + File + File + + + + Play Properties + + + + + Play Duration + Play Duration + + + Select File Select File - + s s - + Audio Audio @@ -4447,233 +4092,373 @@ EBase - + Area Area(px) - + X X - + Y Y - + W W - + H H - + Border Border - - + + None None - + Effect Effect - + Rotate Rotate - + Blink Blink - + Speed Speed - + Slow Slow - + Moderate Moderate - + Fast Fast - EEnviron + EDClock - - - - - - - - north - north + + MON + MON - - - - - - - - east - east + + TUE + TUE - - - - - - - - south - south + + WED + WED - - - - - - - - west - west + + THU + THU - - - Temperature - Temperature + + FRI + FRI - - - Humidity - Humidity + + SAT + SAT - - - Noise - Noise + + SUN + SUN - - Wind Speed - Wind Speed + + + AM + AM - - Wind Direction - Wind Direction + + + PM + PM - + Basic Properties Basic properties - - Title - Title + + Time Zone + Time Zone - - Compensation - Compensation + + Year + Year - - Wind speed - Wind speed + + Month + Month - - Wind direction - Wind direction + + Day + Day - - Left - Left + + Hour + Hour - - Center - Center + + Min. + Min. - - Right - Right + + Sec. + Sec. - - Single scroll - Single scroll + + Weekly + Day of Week - - Speed - Speed + + Full Year + 4-Digit Year - - ms/pixel - ms/pixel + + 12-Hour + 12-Hour - - Back Color - Back Color + + Date Style + Date Format - + + Time Style + Time format + + + + Display Style + Display style + + + + Multiline + Multiline + + + Play Properties - - Refresh Cycle - Refresh cycle - - - - min. - min. - - - + Play Duration Play Duration - + + s + s + + + + EEnviron + + + + + + + + + north + north + + + + + + + + + + east + east + + + + + + + + + + south + south + + + + + + + + + + west + west + + + + + Temperature + Temperature + + + + + Humidity + Humidity + + + + + Noise + Noise + + + + Wind Speed + Wind Speed + + + + Wind Direction + Wind Direction + + + + Basic Properties + Basic properties + + + + Title + Title + + + + Compensation + Compensation + + + + Wind speed + Wind speed + + + + Wind direction + Wind direction + + + + Left + Left + + + + Center + Center + + + + Right + Right + + + + Single scroll + Single scroll + + + + Speed + Speed + + + + ms/pixel + ms/pixel + + + + Back Color + Back Color + + + + Play Properties + + + + + Refresh Cycle + Refresh cycle + + + + min. + min. + + + + Play Duration + Play Duration + + + s s @@ -4681,37 +4466,37 @@ EGif - + Basic Properties Basic properties - + File File - + Select File Select File - + Play Properties - + Play Duration Play Duration - + s s - + Play Times Play Times @@ -4719,73 +4504,73 @@ EMultiWin - + Please add media on the right Please add media on the right. You can add multiple different media. The LED display will play in the order of the list - + Media List Media List - - - + + + Text Text - - - + + + Photo Photo - - - + + + Video Video - - - + + + Gif Gif - - - + + + DClock Clock - - - + + + AClock Analog Clock - - - + + + Select File Select File - - + + Environment Environmental Monitoring - - + + Timer Timer @@ -4793,118 +4578,118 @@ EPhoto - + Basic Properties Basic properties - + File File - + Select File Select File - + Image Read Error Image Read Error - + Play Properties - + Play Duration Play Duration - - + + s s - + Enter Style Entrance Effect - + None None - + Alpha_In ALPHA_IN - + Moving to left MOVING_TO_LEFT - + Moving to right MOVE_TO_RIGHT - + Moving to top MOVING_TO_TOP - + Move to bottom MOVE_TO_BOTTOM - + Zoom in ZOOM_IN - + Zoom in to left_bottom ZOOM_IN_LEFT_BOTTOM - + Zoom in to left_top ZOOM_IN_LEFT_TOP - + Zoom in to right_top ZOOM_IN_RIGHT_TOP - + Zoom in to right bottom ZOOM_IN_RIGHT_BOTTOM - + Rotate to right ROTATE_TO_RIGHT - + Rotate to left ROTATE_TO_LEFT - + Enter Duration Effect Duration - + Images (*.png *.jpg *.jpeg *.bmp) @@ -4912,191 +4697,191 @@ EText - + Enter your text Enter your text - + Basic Properties Basic properties - - Font Color - Font Color - - - + Back Color Back Color - + Kerning Kerning - + Line Spacing Line Spacing - + PageCount: PageCount: - + page Page - + Import txt File - + Select File Select File - + Fail Fail - + File Open Fail - + Play Properties - + Flip Flip - + Scroll Scroll - + Static Static - - - + + + Play Duration Play Duration - + Duration/Page Duration/Page - + Effect time effect duration - - + + Tip Info Tip Info - - + + Effect time cannot be longer than duration time Effect time cannot be longer than duration time - + s s - + + Text Color + + + + + Colorful Text + + + + Entrance Effect Entrance Effect - + no no - + random random - + right to left right to left - + bottom to top bottom to top - + left to right left to right - + top to bottom top to bottom - - Head-Tail Connected - Head to Tail - - - + Head-Tail Spacing Spacing - + Scroll Style Direction - + Right -> Left From right to left - + Bottom -> Top From bottom to top - + Left -> Right From left to right - + Top -> Bottom Frome top to bottom - + Scroll Speed Scrolling speed @@ -5104,87 +4889,87 @@ ETimer - + day Days - + hour Hours - + min Mins - + sec Secs - + Basic Properties Basic properties - + Count Down Count Down - + Count Up Count Up - + Time Target Time - + Day Day - + Hour Hour - + Min Min - + Sec Sec - + Multiline Multiline - + Text Text - + Play Properties - + Play Duration Play Duration - + s s @@ -5192,64 +4977,64 @@ EVideo - + Basic Properties Basic properties - + File File - + Play Properties - + Play Duration Play Duration - + Select File Select File - + s s - + Play Times Play Times - + Video Transcoding - - + + Video Transcoding Progress - - + + Error Error - + Video Video - + Flash Flash @@ -5257,17 +5042,17 @@ EWeb - + Basic Properties Basic properties - + Play Duration Play Duration - + s s @@ -5295,10 +5080,93 @@ Secs + + GenTmpThread + + + Preparing ... + Preparing ... + + + + MON + MON + + + + TUE + TUE + + + + WED + WED + + + + THU + THU + + + + FRI + FRI + + + + SAT + SAT + + + + SUN + SUN + + + + AM + AM + + + + PM + PM + + + + day + Days + + + + hour + Hours + + + + min + Mins + + + + sec + Secs + + + + Create json ... + Create json ... + + + + Scan program ... + Scan program ... + + LoColorSelector - + Transparent Transparent @@ -5341,186 +5209,230 @@ MainWindow - + Language Language - + Help Help - - + + Check for updates Check for updates - - + + firmware manager Firmware management - - - Software Configuration - Software Configuration + + + Software Config + Software Config - - + + Info - - + + About About - - + + Setting Setting - - Device - Termianls + + Software Update + Software Update - + + CurVersion + CurVersion + + + + Update + Update + + + + LatestVersion: + LatestVersion: + + + + + Update log: + Update log: + + + + The current version is already the latest version + The current version is already the latest version + + + + Device + Terminals + + + Program Solutions - + Control Terminal Control - + GuangYinPin Lora screen - + Check card Detect - + Tip Info Tip Info - + RestoreLedCardIpByUdpTip This operation will fix all the control cards in the LAN that are not in the same network segment as the computer IP. Please be careful! + + Net + + + Connection Timeout + + + + + Error + Error + + PageEditor - + Zoom In Zoom In - + Zoom Out Zoom Out - + Original size Origianl Size - + Delete the secect media Delete the seleted media - + Clear all media Clear all media - + Move layer up Move layer up(shortcut key PgUp) - + Send backward Send backward(shortcut key PgDn) - + Bring to front Bring to front(shortcut key home) - + Move to the bottom layer Move to the bottom layer(shortcut key end) - + Fill the entire screen Fill the entire screen - + Fill the screen horizontally Fill the screen horizontally - + Fill the screen vertically Fill the screen vertically - + Align top Align up - + Center vertically Center vertically - + Bottom align Bottom up - + Align left Align left - + Center horizontally Center horizontally - + Align right Align right - + Tip Info Tip Info - + Clear all medias? @@ -5528,79 +5440,84 @@ PageListItem - + times Times - + Page name Program name - + New New - + Play times Play times - + + Sources Repeat + + + + Audios - + Total Dur - - + + s s - + Select File Select File - + Duration - + Vol - + Valid Date Valid date - - + + Warning Warning - + Start Time can't be later than End Time - + End Time can't be earlier than Start Time - + Plan Plan @@ -5629,17 +5546,17 @@ PlayWin - + Move to Top Left Move to Top Left - + Set Position - + Close Close @@ -5647,12 +5564,12 @@ PlayerBackSendThread - + Open file failed Open file failed - + Read file failed Read file failed @@ -5673,47 +5590,47 @@ ProgCreateDlg - + Resolution Resolution - + Solution Information Solution Information - + Solution Name Solution Name - + Width Width - + Height Height - + Remarks Remarks - - 节目超宽需要打折, 请输入打折宽度 - + + 每段打折宽度 (用空格分隔) + Each part width (split with space) - + OK Ok - + Cancel Cancel @@ -5721,221 +5638,200 @@ ProgEditorWin - + Save Save - - + + Save as Save as - + Setting Setting - + Text Text - + Photo Photo - + Video Video - + Gif Gif - + Clock Clock - + Analog Clock Analog Clock - + Environment Environmental Monitoring - + Web Web page - + MuliContentWindow Multi material window - + In this window, a plurality of different program materials can be added and played according to the order of joining the list; In this window, a plurality of different program materials can be added and played according to the order of joining the list - + Timer Timer - + Play - + Stop Stop - + Publish Publish - - - - + + + + Select File Select File - + program Program - + Add page Add page - + Copy page Copy page - + Delete page Delete page - - + + Tip Info Tip Info - + Are you sure you want to delete this program page? Are you sure you want to delete this program page? - + Move up Move up - + Move down Move down - + widget properties Widget properties - + Page properties Program properties - + Do you want to save the modifications? Do you want to save the modifications? - - + + Saving... Saving... - - + + Success Success - - + Save failed Save failed - + Convertering Convertering - - Converter Successed - Converter Successed - - - - Converter TimeOut - Converter TimeOut - - - + Generate preview data Generate preview data - - Ready - Ready - - - - Generate TimeOut - Generate TimeOut - - - - + + Error Error - + Rename fail when saving - + Remove Recursively fail when saving - + Warning Warning @@ -5943,155 +5839,177 @@ ProgItem - - + + ExportButtonTip USB playback - - + + SendButtonTip Publish - - + + Convertering Convertering - - - USB Export Successed - USB disk exported successfully - - - - USB Export TimeOut - USB disk export failed - - - - Converter Successed - Converter Successed - - - - Converter TimeOut - Converter TimeOut - ProgPanel - - + + New New - - + + Edit Edit - - + + Delete Delete - - + + + Import Import - - + + + Export Export - - + + Send Send - - + + Publish Publish - - + + Name Name - - + + + Choose Directory + Choose Directory + + + + Tip + Tip + + + + The imported directory is already in the working directory, so there is no need to import it again! + The imported directory is already in the working directory, so there is no need to import it again! + + + + :solution(s) already exist.are you sure you want to overwrite the existing solution(s)? + :solution(s) already exist.are you sure you want to overwrite the existing solution(s)? + + + + Play - - + + Stop Stop - - + + Resolution Resolution - - + + File Size File Size - - + + Last Modify Last Modified - - + + Usb playback USB playback - + Program name conflicted Program name conflicted - + Warning Warning - + You will delete the selected solution(s),are you sure? You will delete the selected solution(s),are you sure? - + + Tip Info Tip Info + + ProgPortDlg + + + Solution Name + Solution Name + + + + Progress + Progress + + + + Done + Done + + QObject - + Setting up the LedOK Express... Setting up the LedOK Express... @@ -6099,18 +6017,18 @@ SendProgThread - - + + Program is empty Program is empty - + Open file failed Open file failed - + Read file failed Read file failed @@ -6118,73 +6036,73 @@ SendProgramDialog - - + + Publish Publish - + success info - + Refresh Refresh - + Cancel Cancel - + Screen ID Screen ID - + Remark Name Alias - + Online Online - + Screen IP Screen IP - + Screen Size Screen Size - + Security encryption - + Progress Progress - + Remarks Remarks - + This screen is encrypted This screen is encrypted - + All ALL @@ -6192,12 +6110,12 @@ SoftConfigDialog - - Software Configuration - Software Configuration + + Software Config + Software Config - + Video compress to Video compress to @@ -6207,200 +6125,31 @@ Video transcoding to - + Text antialiasing Text antialiasing - + TextAntilaTip (Note: this option is suitable for screens with small spacing and large size. If this option is selected, the shadow on the edge of the text will be smooth; it is not recommended for small size screens and single and double color screens.) - + GuangYinPin Lora screen - + + Width Split + + + + OK Ok - - SpecialDlg - - Specify IP - Specify IP - - - Search - Search - - - Cancel - Cancel - - - Attention - Attention - - - Please input IP address! - Please input IP address! - - - Your IP Address is Invalid! - IP Address is invalid! - - - Error - Error - - - - ThreadUpgradeApk - - - Uploadding - Uploadding - - - - TipDialog - - - TextLabel - - - - - - OK - Ok - - - - - Cancel - Cancel - - - - X - - - - - - Import - Import - - - - - Path - Path - - - - - : - - - - - - browse - Browse - - - - You will delete the selected solution(s),are you sure? - You will delete the selected solution(s), are you sure? - - - - - Export - Export - - - - - Done - Done - - - - - Solution Name - Solution Name - - - - - Progress - Progress - - - - Delete - Delete - - - - Select the network to connect to the device - Please select the network to connect to the LED controller - - - - Network name - Network name - - - - - This operation will only set cable network to static IP,are you sure? - This operation will only set cable network to static IP,are you sure? - - - - Do you want set IP of cable network to DHCP - Do you want set the network to automatically get IP through DHCP - - - - - - - - Tip - Tip - - - - - - Please select the network to connect to the Led controller - Please select the network to connect to the LED controller - - - - Choose Directory - Choose Directory - - - - The imported directory is already in the working directory, so there is no need to import it again! - The imported directory is already in the working directory, so there is no need to import it again! - - - - no find program can be imported - no find program can be imported - - UpdateLedset3Dialog @@ -6473,262 +6222,315 @@ Congratulations! You are running the latest version of %1 - - UpdaterDialog - - - Software Update - Software Update - - - - X - X - - - - V1.0 - - - - - Update - Update - - - - CurVersion - CurVersion - - - - LatestVersion: - LatestVersion: - - - - - Update log: - Update log: - - - - The current version is already the latest version - The current version is already the latest version - - UpgradeApkDialog - - - Upgrade apk - Upgrade apk + + Update APK + Update APK - - 口 - - - - - X - X - - - - + Select apk Select apk - - - - + Upgrade Upgrade - - - APK: - - - - - + Uninstall Uninstall - - + check running state check running state - - + Select Fpga Select Fpga - - - success info + + Installing - - + Refresh Refresh - - + Cancel Cancel - + Screen ID Screen ID - + Remark Name Alias - + Online Online - + Screen IP Screen IP - + Security encryption - + Progress Progress - + xixunplayer - + cardsystem - + taxiapp - + starter - + connection - + displayer - + FPGA FPGA - + update - + State State - - - + + All ALL - + + This screen is encrypted + This screen is encrypted + + + + + Select Online APK + + + + + No Files + + + + + Name + Name + + + + Size + + + + + Create Time + + + + + + + Tip + Tip + + + + Is upgrading now. Please wait + + + + + NoSelectedController + Please select screen first + + + + + Downloading Online File + + + + + + Error + Error + + + + Online file is empty + + + + + Uploading + + + + + Upload error + + + + + Install error + + + + + Install success + + + + + Reminder + + + + + Reminder: Uninstalling this program may cause the device to offline, cannot be found, lost configs and have a black screen. Please uninstall with caution! + + + + + Do you want to continue? + + + + + Uninstalling + Uninstalling + + + + Uninstall error + + + + + Uninstall success + + + + + Check apk running status + + + + + Check error + + + + + Running + Running + + + + Not running + + + + The encrypted control card can be upgraded directly The encrypted control card can be upgraded directly - - - apk package (*.rpd) - - - - - apk package (*.apk *.zip) - - UsbDetectDialog - + Usb upgrade program Usb upgrade program - + Password Password - + OK Ok - + Input password Input password - - + + Tip Tip - + No checked USB device No checked USB device - + please select usb device in list please select usb device in list - + Cancel Cancel @@ -6736,7 +6538,7 @@ WaitingDlg - + Success Success @@ -6765,331 +6567,6 @@ Cancel - - eAClock - - - Basic Properties - Basic properties - - - - Time Zone - Time Zone - - - - Custom Dial - Custom Dial - - - - Select - Select - - - - Select Dail file - Select dial file - - - - Hour Mark - Hour Scale - - - - - Circular - Circle - - - - - Rectangle - Rectangle - - - - Number - Number - - - - - - T - - - - - Min Mark - Minute Scale - - - - Hand Color - Hand Color - - - - H - H - - - - M - M - - - - S - - - - - Text - Text - - - - Play Properties - - - - - Play Duration - Play Duration - - - - s - s - - - - eDClock - - - MON - MON - - - - TUE - TUE - - - - WED - WED - - - - THU - THU - - - - FRI - FRI - - - - SAT - SAT - - - - SUN - SUN - - - - - AM - AM - - - - - PM - PM - - - - Basic Properties - Basic properties - - - - Time Zone - Time Zone - - - - Year - Year - - - - Month - Month - - - - Day - Day - - - - Hour - Hour - - - - Min. - Min. - - - - Sec. - Sec. - - - - Weekly - Day of Week - - - - Full Year - 4-Digit Year - - - - 12-Hour - 12-Hour - - - - Date Style - Date Format - - - - Time Style - Time format - - - - Display Style - Display style - - - - Multiline - Multiline - - - - Play Properties - - - - - Play Duration - Play Duration - - - - s - s - - - - GenTmpThread - - - Preparing ... - Preparing ... - - - - MON - MON - - - - TUE - TUE - - - - WED - WED - - - - THU - THU - - - - FRI - FRI - - - - SAT - SAT - - - - SUN - SUN - - - - AM - AM - - - - PM - PM - - - - day - Days - - - - hour - Hours - - - - min - Mins - - - - sec - Secs - - - - Create json ... - Create json ... - - - - Scan program ... - Scan program ... - - mGuangYingPinWidget @@ -7494,68 +6971,55 @@ OpenPort COM failed - - wExportProgramItem - - - Tip Info - Tip Info - - - - :solution(s) already exist.are you sure you want to overwrite the existing solution(s)? - :solution(s) already exist.are you sure you want to overwrite the existing solution(s)? - - wPlanItem - + Form Form - + 1 1 - + Every week: Every week: - + M M - + Tu Tu - + W W - + Th Th - + F F - + Sa Sa - + Su Su @@ -7563,30 +7027,30 @@ wProgramPublishItem - + Input password Input password - - - + + + Error Error - - + + Tip Info Tip Info - + Fail Fail - + password is wrong password is wrong @@ -7594,92 +7058,24 @@ wUpgradeApkItem - + Input password Input password - - uninstalling - Uninstalling + + Error + Error - - - IsSoftwareRunning - Check apk running status - - - - - This screen is encrypted - This screen is encrypted - - - - - Start upgrading - Start upgrade - - - - - Timeout - Timeout - - - - install start... - Start installation... - - - - - SynchronousHardwareVersion - Sync FPGA - - - + Tip Info Tip Info - + password is wrong password is wrong - - - - UninstallSoftware - Uninstall - - - - - Success - Success - - - - Running - Running - - - - NoRunning - Not running - - - - install success - Install success - - - - - Fail - Fail - diff --git a/LedOK/translations/app_ja.ts b/LedOK/translations/app_ja.ts index adc3371..2efe21e 100644 --- a/LedOK/translations/app_ja.ts +++ b/LedOK/translations/app_ja.ts @@ -71,1339 +71,202 @@ パスワードが正常に変更 - - ControlEncryptWidget - - - Form - リフレッシュ - - - - - Entrypt Configuration - セキュリティ設定 - - - - Original password - 元のパスワード - - - - - - original password - 元のパスワード - - - - - - New password - 新しいパスワード - - - - - Repeat new password - 繰り返し入力 - - - - - - - Set encryption - 暗号化 - - - - - Cancel encryption - 暗号化を解除 - - - - - Enter password - パスワードを入力 - - - - Enter again - 再入力 - - - - - - - - - Tip - 提示 - - - - NoSelectedController - 先に大きいスクリーンを選んでください - - - - - InputOriginalPasswordTip - オリジナルのパスワードを入力してください - - - - InputNewPasswordTip - 新しいパスワードを入力してください - - - - InputRepeatPasswordTip - 新しいパスワードを繰り返して入力してください - - - - InputRepeatPasswordNotSameTip - 二回入力したパスワードが一致しません - - - - Tip Info - ヒント - - - - After setting the password, please remember the password and record it. If you forget the password, the device will be unable to operate. Are you sure you want to continue with this operation? - パスワードを設定した後、パスワードを覚えて、それを記録してください。パスワードを忘れた場合は、デバイスが動作することができなくなります。この操作を続行しますか? - - - - - SetControllerPassword - 暗号化の設定 - - - - Readback - 読み戻し - - - - - - Success - 成功 - - - - - - failed - 失敗 - - - - - Modify password - パスワードを変更 - - - - OriginalPasswordErrorTip - 元のパスワードが間違っています - - - - ControlHdmiSchedule - - - Form - リフレッシュ - - - - - Add - 追加 - - - - - Delete - 削除 - - - - - Clear - クリア - - - - - Import - インポート - - - - - Export - 出力 - - - - By default, the asynchronous content is played, and the synchronous signal content is played in the fixed time period - 非同期のコンテンツをデフォルトで再生し、同期のHMI-INポートに入力します - - - - - Apply - 適用 - - - - Readback - 読み戻し - - - - SYNC HDMI - HDMI-IN - - - - Start Time - 開始時間 - - - - End Time - 終了時間 - - - - SUN - 日曜日 - - - - MON - 月曜日 - - - - TUE - 火曜日 - - - - WED - 水曜日 - - - - THU - 木曜日 - - - - FRI - 金曜日 - - - - SAT - 土曜日 - - - - - DeviceItem OnProHttpResponse 解析json文件错误! - - - - - - On - 開く - - - - SyncSchedule (*.syncs) - - - - - Save File - 保存 - - - - Sync Schedule (*.syncs) - - - - - - Tip - 提示 - - - - - NoSelectedController - 先に大きいスクリーンを選んでください - - - - SetTimingHdmiInTask - 同期モードタイミングタスクの設定 - - - - GetTimingHdmiInTask - 同期モードタイミングタスクの取得 - - - - - Success - 成功 - - - - - failed - 失敗 - - - - ControlHdmiWidget - - - HDMI Configuration - ビデオソースの設定 - - - - Manual - 手動 - - - - Schedule - スケジュール - - - - - Tip - 提示 - - - - - NoSelectedController - 先に大きいスクリーンを選んでください - - - - - SyncSwitch - スイッチのビデオソースをHDMI-IN - - - - - AnSyncSwitch - 異ステップモードを切り替え - - - - - IsSync - 同じ非同期モードを読み返す - - - - Error - エラー - - - - HDMI IN - HDMI IN - - - - Async - アシュリン - - - - Readback - 読み戻し - - - - ControlNetConfigWidget - - - Wire Enther(RJ45) Configuration - 有線ネットワークの設定 - - - - - DHCP - - - - - - Specify IP - 指定IP - - - - - IP Address - IPアドレス - - - - Mask Address - サブネットマスク - - - - - Gateway - ゲートウェイ - - - - - DNS Address - DNSアドレス - - - - - - - - - - Set - セット - - - - - - - - - Readback - 読み戻し - - - - - WIFI Configuration - WiFiの設定 - - - - - WiFi On/Off - WiFi機能 - - - - Input Ap name - 入力AP名 - - - - - 4G/5G Configuration - セルラーデータ構成 - - - - - Open 4G/5G - セルラーデータを有効にする - - - - APN: - - - - - - Get cellular network status information - セルラーネットワーク状態情報を取得する - - - - - Check SIM can automatically match to MCC, and then select carrier get apn param,if not found carrier,you can check the CUSTOM checkbox,then enter custom param. - チェックシムは自動的にMCCに一致することができますし、キャリアー取得APNパームを選択し、キャリアが見つからない場合は、カスタムチェックボックスをチェックし、カスタムパームを入力します。 - - - - - Readback APN Info - APN情報を読み返す - - - - - Set Apn Info,Check SIM can automatically match to MCC, and then select carrier get apn param - APN情報を設定する - - - - - CUSTOM - カスタム - - - - - Check SIM - SIM情報の照会 - - - - - - -> - - - - - - Country ID(mcc): - 国号(mcc): - - - - - Carrier Name - 運営者 - - - - - APN: - キャリアAPN: - - - - - APN(Required) - APN(必ず記入) - - - - - User: - ユーザ名: - - - - - - - Not required - 必要でない - - - - - Password: - パスワード: - - - - Set Apn:iot.cargo - - - - - - Flight Mode - 飛行モード - - - - - WiFi name - WiFiの名前 - - - - - - - Password - パスワード - - - - - - - Input password - パスワードを入力 - - - - - Scan - スキャン - - - - - Ap Mode - APエネルギー - - - - Ap name - APの名前 - - - - OFF - オフ - - - - ON - オン - - - - AP name - AP名 - - - - Subnet mask - サブネットマスク - - - - Input ap name - APの名前を入力 - - - - - - - - - - - - - - - Success - 成功 - - - - - - - - - - - - - - - failed - 失敗 - - - - - - - Tip - 提示 - - - - - NoSelectedController - 先に大きいスクリーンを選んでください - - - - - SetEthernet - 有線網を設置する - - - - - - - - - - - Attention - 注意 - - - - Please input IP address! - IPアドレスを入力してください! - - - - Your IP Address is Invalid! - IPアドレスが無効です! - - - - Please input Mask address! - サブネットマスクの住所を入力してください! - - - - Your Mask Address is Invalid! - マスクアドレスが無効です! - - - - Please input Gateway address! - ゲートウェイのアドレスを入力してください! - - - - Your Gateway Address is Invalid! - ゲートウェイアドレスが無効です! - - - - Please input DNS address! - DNSアドレスを入力してください! - - - - Your DNS Address is Invalid! - DNSアドレスを入力してください! - - - - - GetEthernet - 有線ネットワークの設定を取得 - - - - DHCP IP - DHCP IP - - - - STATIC IP - 静的IP - - - - Error - エラー - - - - - - - - - SignalPower - 信号強度 - - - - - ConfigurationWiFi - WiFiの設定 - - - - IsPortableHotSpot - ホットスポットとWiFiモードの取得 - - - - GetWifiList - スキャンWiFi - - - - ConfigurationHotSpot - ホットスポットの設定 - - - - GetCurrentAPN - APN情報の取得 - - - - - GetSIMStatus - SIM状態を取得 - - - - SetAPN - APNの設定 - - - - - DeviceItem OnProHttpResponse 解析json文件错误! - - - - - 状态: - 状態: - - - - 未知 - 不明 - - - - 锁定状态,需要用户的PIN码解锁 - ロック状態は、ユーザのPINコードのロック解除が必要です - - - - 锁定状态,需要用户的PUK码解锁 - ロック状態は、ユーザのPUKコードのアンロックが必要です - - - - 锁定状态,需要网络的PIN码解锁 - ロック状態は、ユーザのPINコードのアンロックが必要です - - - - 就绪 - 準備完了 - - - - no checked sim card - simカードが検出されませんでした - - - - 国家码: - 国号: - - - - 号码: - 番号: - - - - 用户: - ユーザ: - - - - 信号: - 信号: - - - - 信号正常 - 信号が正常である - - - - 不在服务区 - サービスエリアにはいません - - - - 仅限紧急呼叫 - 緊急呼び出しのみ - - - - 射频已经关闭 - 無線周波数はすでに閉鎖されました - - - - 网络: - ネットワークタイプ: - - - - 网络类型未知 - 不明 - - - - GPRS网络 - GPRS - - - - EDGE网络 - EDGE - - - - UMTS网络 - UMTS - - - - CDMA网络,IS95A 或 IS95B. - CDM - - - - EVDO网络, revision 0. - EVDO,revision 0. - - - - EVDO网络, revision A. - EVDO,revision A. - - - - 1xRTT网络 - 1xRTT - - - - HSDPA网络 - HSDPA - - - - HSUPA网络 - HSUPA - - - - HSPA网络 - HSPA - - - - 漫游: - ローミング: - - - - Yes - - - - - No - いいえ - - - - 数据连接状态: - データ接続状態: - - - - 断开 - 切断 - - - - 正在连接 - 接続中 - - - - 已连接 - 接続済み - - - - 暂停 - 一時停止 - - - - 数据活动休眠状态: - データアクティビティの休止状態: - - - - 活动,但无数据发送和接收 - アクティブですが、データ送信と受信はありません - - - - 活动,正在接收数据 - アクティブ、データ受信中 - - - - 活动,正在发送数据 - イベント、データ送信中 - - - - 活动,正在接收和发送数据 - イベント、データ受信と送信中 - - - - 休眠状态 - スリープ状態 - - - - 信号强度: - 信号の強度: - - - - SetSwitchSimData - 4G/5Gスイッチの設定 - - - - ContrFlightMode - 飛行モードの設定 - - - - GetFlightModeState - 飛行モード状態を取得 - - - - ControlPowerManual - - - Form - リフレッシュ - - - - - POWER - パワー - - - - - - Readback - 読み戻し - - - - OFF - オフ - - - - ON - オン - - - - - Tip - 提示 - - - - - NoSelectedController - 先に大きいスクリーンを選んでください - - - - IsScreenOn - スイッチ状態を読み出します - - - - - - SetScreenOn - 電源の設定 - - - - - - - Success - 成功 - - - - - on - オン - - - - - - - failed - 失敗 - - - - - off - オフ - - - - - SetScreenOff - スクリーンスイッチの設定 - - - - - DeviceItem OnProHttpResponse 解析json文件错误! - - - ControlPowerSchedule - + Form リフレッシュ - + Edit area 編集エリア - - + + Add 追加 - - + + Delete 削除 - - + + Clear クリア - - + + Import インポート - - + + Export 出力 - + It is power off state outside the schedule time period 定時の時間帯にはモニターがオンになり、他の時間はオフになります - + Send command 指令エリア - - + + Apply 適用 - + Clear Schedule タイミング指令をクリア - + Readback 読み戻し - + Power On State スクリーンスイッチ状態 - + Start Time 開始時間 - + End Time 終了時間 - + SUN 日曜日 - + MON 月曜日 - + TUE 火曜日 - + WED 水曜日 - + THU 木曜日 - + FRI 金曜日 - + SAT 土曜日 - - + + DeviceItem OnProHttpResponse 解析json文件错误! - - + + On 開く - - + + PowerSchedule (*.pjs) スイッチパネルタイミング(*.pjs) - + Save File 保存 - - - + + + Tip 提示 - - - + + + NoSelectedController 先に大きいスクリーンを選んでください - - + + Tip Info ヒント - - + + Clear schedule task? スケジュールのタスクをキャンセル? - - + + CleanTimingScreenTask スケジュールのタスクをキャンセル - + SetTimingScreenTask 画面タイミングスイッチタスクの設定 - - - - + + + + Success 成功 - - - - + + + + failed 失敗 - + GetTimingScreenTask 画面タイミングスイッチタスクの取得 @@ -1411,678 +274,378 @@ ControlPowerWidget - - Form - リフレッシュ + + + Off + 閉じる - - + + + On + 開く + + + + + Tip + ヒント + + + + + NoSelectedController + 先に大きいスクリーンを選んでください + + + + + SetScreenOn + 画面の電源を入れる + + + + + SetScreenOff + 画面の電源を切る + + + + + IsScreenOn + スイッチ状態を読み出します + + + Power Configuration スイッチパネル制御 - - + Manual 手動 - - + Schedule スケジュール + + + Power + 電源 + + + + Readback + 読み戻し + ControlTestWidget - + Form リフレッシュ - - + + Test Screen テスト画面 - - + + Line test 線テスト - - - - - - - + + + + + + + Red - - - - - - - + + + + + + + Green - - - - - - - + + + + + + + Blue - - - - - - - + + + + + + + White - - + + Vertical 縦線 - - + + Slash 斜線 - - - + + + Horizontal 水平線 - - - - + + + + Speed スピード - - + + ms(>10) ミリ秒(>10) - - + + Line Distance 線の間隔 - + px px - - - - - + + + + + Test テスト - - + + Gradation test グレースケールテスト - - + + Only the gray value is displayed 色の値のみを表示 - + (>10) - - + + GrayValue グレースケール値 - + (0-255) - - + + Color test カラーテスト - - + + Gradient グラデーション - + 8 8 - + 2 2 - + 3 3 - + 6 6 - + 4 4 - + 5 5 - + 1 1 - + 9 9 - + 7 7 - + 0 0 - - + + Clear クリア - - + + Reset ループ - - - - + + + + Anycast リクエスト - - + + Stop 停止 - - - - - - - - + + + + + + + + Tip 提示 - - - - - + + + + + NoSelectedController 先に大きいスクリーンを選んでください - - - + + + StartTest テストを開始します - - - - + + + + Success 成功 - - - - + + + + failed 失敗 - + StopTest テストを中止します - + loopback mode サイクルモード - + Connect timeout 接続タイムアウト - + Reset loop mode ループを設定 - - + + success 成功 - - - DeviceItem OnProHttpResponse 解析json文件错误! - jsonファイルの解析エラー! - - - - CtrlVerifyClockPanel - - - Form - リフレッシュ - - - - English - - - - - 中文 - - - - - Verify Clock Configuration - 検証クロック設定 - - - - Verify to Computer time - コンピュータ時刻の確認 - - - - - Cur time of controller - ディスプレイの現在の時間 - - - - LAN - LAN - - - - (min/time) - (分/回) - - - - Sync identificationCode - 同期IDコード - - - - - identification code - 識別コード - - - - - Time offset(msec) - タイム・オフセット( msec ) - - - - - Brightness - スクリーン輝度 - - - - - Volume - 体積 - - - - - Screen on/off - スクリーンスイッチ - - - - - Slave - から - - - - Master - - - - - - NTP Server - NTPサーバ - - - - - - - NTP Server address - NTPサーバのアドレス - - - - - - - TimeZone - タイムゾーン - - - - - - - - - - - - - - - Set - セット - - - - - Language: - 言語: - - - - - Enable Synchronous playing - 画面を同期させる機能 - - - - Lora - - - - - GPS - - - - - NTP - - - - - Time zone - タイムゾーン - - - - - - - Sync time interval - 同期時間間隔 - - - - Verify clock configuration - 検証クロック設定 - - - - - - - - - - - - - - Readback - 読み戻し - - - - Master - - - - - Sync clock to computer time - 校正クロックからコンピュータ時間まで - - - - Identification Code - 識別コード - - - - - - - - - - - - - - Success - 成功 - - - - - - - - - - - - - - failed - 失敗 - - - - SetNtpServer - NTPサービスの設定 - - - - MasterSwitch - メインデバイスの設定 - - - - SlaveSwitch - スレーブデバイスとして設定 - - - - IsMasterSlave - 主従の身分を読み返す - - - - GetControllerDate - 日付時間の取得 - - - - SetingSyncMethod - set syncメソッド - - - - SyncTime - キャリブレーション時間 - - - - GetNtpServer - NTPサービス情報を取得する - - - - GetingSyncMethod - 同期方式を取得 - - - - - DeviceItem OnProHttpResponse 解析json文件错误! - - - - - SetTimezone - タイムゾーンを設定 - - - - ControlVolumeManual - - - Form - リフレッシュ - - - - Volume(0-15) - 音量(0-15) - - - - - - Readback - 読み戻し - - - - SetVolume - 音量調節 - - - - - - Success - 成功 - - - - - - failed - 失敗 - - - - Volume(min:0-max:15) - 音量(0-15) - - - - GetVolume - 現在の音量を取得 - - - - + + DeviceItem OnProHttpResponse 解析json文件错误! jsonファイルの解析エラー! @@ -2090,174 +653,174 @@ ControlVolumeSchedule - + Defalut volume tip 注意:時間帯の明るさは、定時輝度で表示されます。他の設定されていない時間帯は、デフォルトの輝度値です - - + + Add 追加 - - + + Delete 削除 - - + + Clear クリア - + Default Volume デフォルトの音量 - + (0-15) - - + + Import インポート - - + + Export 出力 - - + + Apply 適用 - + Readback 読み戻し - + Volume value 音量値 - + Start Time 開始時間 - + End Time 終了時間 - + SUN 日曜日 - + MON 月曜日 - + TUE 火曜日 - + WED 水曜日 - + THU 木曜日 - + FRI 金曜日 - + SAT 土曜日 - + Default volume tip 注意:時間帯以外の時間表示はデフォルトの明るさです - + Default volume デフォルトの音量値 - - + + DeviceItem OnProHttpResponse 解析json文件错误! jsonファイルの解析エラー! - + 10 10 - - + + Volume Schedule (*.vols) - + Save File 保存 - - + + Tip 提示 - - + + NoSelectedController 先に大きいスクリーンを選んでください - + SetAutoVolumeTask 設定タイミング音量表 - - + + Success 成功 - - + + failed 失敗 - + GetAutoVolumeTask タイミング音量表の取得 @@ -2265,1187 +828,2504 @@ ControlVolumeWidget - - Form - リフレッシュ + + + Tip + ヒント - - + + + NoSelectedController + 先に大きいスクリーンを選んでください + + + + + SetVolume + 音量調節 + + + + + GetVolume + 現在の音量を取得 + + + Volume Control 音量調節 - - + Manual 手動 - - + Schedule スケジュール + + + Volume + 音量 + + + + Readback + 読み戻し + CtrlAdvancedPanel - - Advanced parameters + + Advanced 上級パラメータ - + Screen Width(pixel) 画面幅(ピクセル) - + Width - - + + Height 高さ - - - - - - - + + + + + + + + + + + + + + + Set セット - + Alias 別名 - + Web Server Address: Webサーバのアドレス: - + www.m2mled.net - + www.ledaips.com - + https://www.taxihub.cn:2340 - + https://www.ledaips.com:2340 - + https://www.36taxi.com:2340 - + www.tlzxled.com - + + MCU Uploading + + + + + Traffic screen settings + + + + + Setting protocol ... + + + + + Set protocol + + + + + Getting protocol ... + + + + + Get protocol + + + + + + Port + ポート + + + Realtimer Server Address: Realtimerアドレス: - + + Firmware Management + ファームウェア管理 + + + + update or uninstall + 更新またはアンインストール + + + Clear クリア - - Apk upgrade - APKアップグレード - - - + Check Apk APKを検出 - + Uninstall アンマウント - + Running check 運転状態モニタ - - FPGA version check - FPGAバージョンクエリ - - - - Sync FPGA version - 同期FPGAバージョン - - - - Restart led controller system + + Restart 再起動 - + Check Log ログを見る - + Start LedSet4 - + Open ADB ADBデバッグ機能を開く - + Post Custom JSON Post Custom JSON - - - - - - - - + + + + + + + + Clear Program 番組をクリア - + www.ledokcloud.com/realtime - - M80 configuration - M 80の設定 + + Config + の設定 - + Refresh 更新 - + Restore to default 標準の値を復元 - + Taxi top screen configuration タクシートップ画面の設定 - + + Service:High Out of service:Low 客がいます:高 客がいません:低 - + + Service:Low Out of service:High 客がいます:低 客がいません:高 - + Start LedSet3.0 configure LED module LedSet 3.0を使ってLEDモジュールを配置する(メーカーの専門家が使用する) - + Binding *.ic account indentity voucher テーピングtaxihubプラットフォームのユーザーID証明書 - + Rotate 回転 - - 0 degrees - 0度 - - - - 90 degrees - 90度 - - - - 180 degrees - 180度 - - - - 270 degrees - 270度 - - - + Min brightness 最低輝度 - - (min:1) - (最小:1) - - - - - + + + Readback 読み戻し - - - + Send 送信 - + Max brightness 最高輝度 - - (max:255) - (マックス:255) - - - - + + SetScreenSize スクリーンのピクセルサイズを設定 - - - - - - - - - - - - - - - - - - - - - - - - - + + + + Success 成功 - + Compant ID: 会社ID: - - FPGA Upgrade - FPGAアップグレード - - - + Compant ID 会社ID - + InputWebServerAddressTip Webサーバのアドレスを入力してください - + InputCompanyIdTip 会社IDを入力してください - + Do you want to modify webserveraddress and companyId? 設定サーバアドレスと会社IDを確認しますか? - - - - - - - - - - - - - - - - - - - - - - failed - 失敗 - - - - + + SetOnlineAddr ウェブサーバのアドレスを設定 - + + ClearRealtimeServer クリア - - InputRealTimeAddressTip - RealTimerアドレスを入力してください - - - + + SetRealtimeServer RealTimerアドレスを設定 - - - - + + + + Tip Info ヒント - - - + + + Can not find LedSet3.0.exe,down you need download and install it LEDSET 3.0 . exeを見つけることができません。ダウンロードしてインストールする必要があります - + + RestartAndroid 再起動 - - FPGA Version - FPGAバージョン - - - - + + running 実行中 - - + + no running 実行されていません - + Check Apk Version チェック APK バージョン - - + + UninstallSoftware アンマウント - - - IsSoftwareRunning + + + Check apk running status APK運転状態監視 - - apk package (*.rpd) - - - - - CheckHardwareVersions - お問い合わせFPGAバージョン - - - - - - SynchronousHardwareVersion - ハードウェアバージョンの同期 - - - - Check Screen untile fpga update finished - 画面のアップグレードの進捗を確認します - - - + + OpenAdb ADBデバッグ機能を開く - + indentity voucher (*.ic) 身分証明書(*.ic) - - - - - + + + + + InvokeTaxiAppFunction 証明書をバインド - - Json format is error! - - - - - + + AliIotSetting - - apk package (*.apk *.zip) - - - - + Software Version Info - + Package - + Version バージョン - - - UpgradeSoftware - ファームウェアをアップグレードする - - - - This screen is encrypted,Please decrypt and upgrade APK! - この画面は、暗号化され、復号化し、アップグレードAPK! - - - - + + Package name is null パッケージ名は空です - + Clearing Program プログラムクリア - - - - + + + + Timeout タイムアウト - - - - + + + + Failed 失敗 - + Getting Log - + ログを取得中 - - - - - - - - - + + + + + + + + + + + Error エラー - + + Setting Timing Reboot + スケジュール再起動を設定中 + + + + Set Timing Reboot + スケジュール再起動の設定 + + + + Getting Timing Reboot + スケジュール再起動を取得中 + + + + Get Timing Reboot + スケジュール再起動の取得 + + + + totalResolution + トータル解像度 + + + + strCurDisplayResolution + 表示解像度 + + + + File not exist + ファイルが存在しません + + + + Uploading + アップロード中 + + + + + Set Display Mode + + + + + + Get Display Mode + + + + + + Set Screen Offset + + + + + + Get Screen Offset + + + + Open file Failed ファイルのオープンに失敗しました - + Setting Wallpaper - - + + Set Wallpaper - + System Updating - - + + System Update - + + Getting MCU Version + + + + + + MCU Version + + + + Select File ファイルを選択 - + Setting player background - - + + Set player background - + Clearing player background - - - - - - - - + + + + + + + + Clear player background - + Setting Baud Rate - + Set Baud Rate - + Getting Baud Rate - + Get Baud Rate - + + Text is empty + + + + + Json Parse Error + + + + + Json isn't an Object + + + + + Setting card work mode ... + + + + + Set card work mode + + + + + Getting card work mode ... + + + + + Get card work mode + + + + + Resolution Config + 解像度設定 + + + + Full screen + フルスクリーン + + + + Part + セクション + + + + Display Mode + 表示モード + + + + Screen Position + + + + + Offset + + + + Hidden Settings - + Click right button to hide - + + + Update MCU + + + + + Get MCU Version + + + + Baud Config - + Model - + Uart - + Baud - + + + + + + Get - + 得る - - - - + + Timing Reboot + スケジュール再起動 + + + + Protocol + プロトコル + + + + Server + サービス + + + + Client + クライアント + + + + SetScreenRotation 画面の回転を設定する - + + SetMinBrightness 最小輝度値を設定します - + + SetMaxBrightness 輝度最大値を設定 - + + GetMinBrightness 輝度最小値を取得 - + + GetMaxBrightness 輝度最大値を取得 - + + + Card work mode + + + + + SetSpecialResolution 解像度を設定 - + + GetSpecialResolution 読み込み解像度 - + + CleanDisplayScreenSize デフォルトの解像度を復元 - + + SetHighForBusy 客レベルの設定 - + + GetStateForBusy ゲストレベルを取得 - - install start... - インストールを開始します... - - - + InputAliasTip エイリアスを入力してください - - + + SetCardAlias エイリアスの設定 - - Uploadding - アップロード - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Tip 提示 - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NoSelectedController 先に大きいスクリーンを選んでください - + InputWidthTip 正しい幅のピクセル値を入力してください - + InputHeightTip 正しい高さのピクセル値を入力してください - + Password is error パスワード - - - - - DeviceItem OnProHttpResponse 解析json文件错误! - jsonファイルの解析エラー! - CtrlBrightPanel - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + Tip 提示 - - - - - - - - - - - + + + + + + + + + + + NoSelectedController 先に大きいスクリーンを選んでください - - + + SetBrightnessSensitivity 輝度センサ感度を設定する - - + + GetBrightnessSensitivity 明るさ感を得る - - + + SetMinBrightness 最小輝度値を設定します - - + + GetMinBrightness 輝度最小値を取得 - - + + NeedSelectSensorTypeTip センサータイプを選択してください - + Open file dialog - + - + Not found current worksheet - - + + SensorBrightnessTable 輝度センサ設定テーブルの設定 - + GetSensorBrightnessTable センサーブライトテーブル - + no sensorBrightnessTable コントロールカードに輝度設定表が見つかりませんでした - + Save file 保存 - - + + GetCurrentSensorBrightness 現在の明るさを取得する - - + + SetBrightness 輝度を設定する - + GetBrightness 輝度値を取得 - + Brightness スクリーン輝度 - + Import File インポートファイル - - + + BrightnessSchedule (*.bjs) - + Save File 保存 - + BrightnessValue 輝度値 - + Start Time 開始時間 - + End Time 終了時間 - - + + SetAutoBrightnessTask 送信タイミング輝度表 - + GetAutoBrightnessTask 取得タイミング輝度表 - - - - + + Error エラー - + Brightness Configuration 輝度の設定 - + Auto 自動 - + Manual 手動 - + Schedule スケジュール - + + Adapt to Old Devices + 古い設備に適合する + + + BrightTip1 最大輝度が64であるならば、最小の明るさは1%または適切な値として構成されることができます;最大の明るさが255であるならば、最小の明るさは36%かそれ以上として構成されなければなりません、さもなければ、明るさは低くなります。 - + BrightTip2 ファイルをアップロードする時、正しいセンサータイプを選択してください。でないと、無効です。 - + Sensitivity 感度 - + Minbrightness 最小輝度 - - - + + + Set セット - + Upload ファイルのアップロード - - - - + + + + Readback 読み戻し - + ReadbackTable 読み戻し - + Refresh 更新 - + Cur Brigntness カールの明るさ - + Brightness value 輝度値 - + Default brightness 標準の明るさ - + Add 追加 - + Clear クリア - + Delete 削除 - + Import インポート - + Export 出力 - + Apply 適用 - + Default brightness tip - ヒント:この設定時間内は明るさを設定し、設定時間外はデフォルトの明るさとなります。例えば、デフォルトの輝度を80とし、設定輝度は180とし、時間範囲は8:00〜17:00とすると、時間範囲は180となり、他の時間はデフォルトの輝度80となる。 + ヒント:この設定時間内は明るさを設定し、設定時間外はデフォルトの明るさとなります。例えば、デフォルトの輝度を50%とし、設定輝度は80%とし、時間範囲は8:00〜17:00とすると、時間範囲は80%となり、他の時間はデフォルトの輝度50%となる。 + + + + CtrlHdmiPanel + + + HDMI Configuration + ビデオソースの設定 + + + + Manual + 手動 + + + + Schedule + スケジュール + + + + + + + Tip + 提示 + + + + + + + NoSelectedController + 先に大きいスクリーンを選んでください + + + + + SyncSwitch + スイッチのビデオソースをHDMI-IN + + + + + AnSyncSwitch + 異ステップモードを切り替え + + + + IsSync + 同じ非同期モードを読み返す + + + + Import File + インポートファイル + + + + Save File + 保存 + + + + + Sync Schedule + 同期モードタイミングタスク + + + + + SetTimingHdmiInTask + 同期モードタイミングタスクの設定 + + + + GetTimingHdmiInTask + 同期モードタイミングタスクの取得 + + + + + Async + アシュリン + + + + + Readback + 読み戻し + + + + Start Time + 開始時間 + + + + End Time + 終了時間 + + + + SUN + 日曜日 + + + + MON + 月曜日 + + + + TUE + 火曜日 + + + + WED + 水曜日 + + + + THU + 木曜日 + + + + FRI + 金曜日 + + + + SAT + 土曜日 + + + + Add + 追加 + + + + + Apply + 適用 + + + + Clear + クリア + + + + Delete + 削除 + + + + Import + インポート + + + + Export + 出力 + + + + By default, the asynchronous content is played, and the synchronous signal content is played in the fixed time period + 非同期のコンテンツをデフォルトで再生し、同期のHMI-INポートに入力します + + + + CtrlNetworkPanel + + + Wire Enther(RJ45) Configuration + 有線ネットワークの設定 + + + + DHCP + + + + + Specify IP + 指定IP + + + + IP Address + IPアドレス + + + + Gateway + ゲートウェイ + + + + DNS Address + DNSアドレス + + + + + + Set + セット + + + + + + + Readback + 読み戻し + + + + WIFI Configuration + WiFiの設定 + + + + WiFi Mode + WiFi機能 + + + + Cellular Config + セルラーデータ構成 + + + + Enable Cellular Data + セルラーデータを有効にする + + + + Get cellular network status information + セルラーネットワーク状態情報を取得する + + + + Through the check status button + 「ステータスを取得」ボタンを使用すると、国コードに自動的に一致し、対応するAPN情報を取得するには「事業者」を選択します。 + + + + Set APN Info + APN情報を設定する + + + + Country ID(mcc): + 国号(mcc): + + + + + Carrier Name + 運営者 + + + + APN(Required) + APN(必ず記入) + + + + Flight Mode + 飛行モード + + + + WiFi name + WiFiの名前 + + + + + + Password + パスワード + + + + + Input password + パスワードを入力 + + + + Scan + スキャン + + + + Ap Mode + APエネルギー + + + + OFF + オフ + + + + ON + オン + + + + AP name + AP名 + + + + Subnet mask + サブネットマスク + + + + Input ap name + APの名前を入力 + + + + + + + + + + + + + + + Tip + 提示 + + + + + + + + + + + + + + NoSelectedController + 先に大きいスクリーンを選んでください + + + + + SetEthernet + 有線網を設置する + + + + + + + + + + + Attention + 注意 + + + + Please input IP address! + IPアドレスを入力してください! + + + + Your IP Address is Invalid! + IPアドレスが無効です! + + + + Please input Mask address! + サブネットマスクの住所を入力してください! + + + + Your Mask Address is Invalid! + マスクアドレスが無効です! + + + + Please input Gateway address! + ゲートウェイのアドレスを入力してください! + + + + Your Gateway Address is Invalid! + ゲートウェイアドレスが無効です! + + + + Please input DNS address! + DNSアドレスを入力してください! + + + + Your DNS Address is Invalid! + DNSアドレスを入力してください! + + + + + GetEthernet + 有線ネットワークの設定を取得 + + + + DHCP IP + DHCP IP + + + + STATIC IP + 静的IP + + + + + ConfigurationWiFi + WiFiの設定 + + + + + IsPortableHotSpot + ホットスポットとWiFiモードの取得 + + + + GetWifiList + スキャンWiFi + + + + + ConfigurationHotSpot + ホットスポットの設定 + + + + success + 成功 + + + + WifiName + Wifiの名前 + + + + ApName + AP名前 + + + + + GetCurrentAPN + APN情報の取得 + + + + GetSIMStatus + SIM状態を取得 + + + + + SetAPN + APNの設定 + + + + 状态: + 状態: + + + + 未知 + 不明 + + + + 锁定状态,需要用户的PIN码解锁 + ロック状態は、ユーザのPINコードのロック解除が必要です + + + + 锁定状态,需要用户的PUK码解锁 + ロック状態は、ユーザのPUKコードのアンロックが必要です + + + + 锁定状态,需要网络的PIN码解锁 + ロック状態は、ユーザのPINコードのアンロックが必要です + + + + 就绪 + 準備完了 + + + + no checked sim card + simカードが検出されませんでした + + + + 国家码: + 国号: + + + + 号码: + 番号: + + + + 用户: + ユーザ: + + + + 信号: + 信号: + + + + 信号正常 + 信号が正常である + + + + 不在服务区 + サービスエリアにはいません + + + + 仅限紧急呼叫 + 緊急呼び出しのみ + + + + 射频已经关闭 + 無線周波数はすでに閉鎖されました + + + + 网络: + ネットワークタイプ: + + + + 网络类型未知 + 不明 + + + + GPRS网络 + GPRS + + + + EDGE网络 + EDGE + + + + UMTS网络 + UMTS + + + + CDMA网络,IS95A 或 IS95B. + CDM + + + + EVDO网络, revision 0. + EVDO,revision 0. + + + + EVDO网络, revision A. + EVDO,revision A. + + + + 1xRTT网络 + 1xRTT + + + + HSDPA网络 + HSDPA + + + + HSUPA网络 + HSUPA + + + + HSPA网络 + HSPA + + + + 漫游: + ローミング: + + + + Yes + + + + + No + いいえ + + + + 数据连接状态: + データ接続状態: + + + + 断开 + 切断 + + + + 正在连接 + 接続中 + + + + 已连接 + 接続済み + + + + 暂停 + 一時停止 + + + + 数据活动休眠状态: + データアクティビティの休止状態: + + + + 活动,但无数据发送和接收 + アクティブですが、データ送信と受信はありません + + + + 活动,正在接收数据 + アクティブ、データ受信中 + + + + 活动,正在发送数据 + イベント、データ送信中 + + + + 活动,正在接收和发送数据 + イベント、データ受信と送信中 + + + + 休眠状态 + スリープ状態 + + + + 信号强度: + 信号の強度: + + + + User + ユーザー + + + + Type + タイプ + + + + Server + サービス + + + + Port + ポート + + + + Proxy + プロキシ + + + + MMS Port + MMS ポート + + + + MMS Proxy + MMS プロキシ + + + + + SetSwitchSimData + 4G/5Gスイッチの設定 + + + + + ContrFlightMode + 飛行モードの設定 + + + + + GetFlightModeState + 飛行モード状態を取得 + + + + CtrlPwdPanel + + + Set Password + パスワードの設定 + + + + Original password + 元のパスワード + + + + original password + 元のパスワード + + + + + New password + 新しいパスワード + + + + Repeat new password + 繰り返し入力 + + + + + + + Set encryption + 暗号化 + + + + Cancel encryption + 暗号化を解除 + + + + Enter again + 再入力 + + + + + + + + + + + + Tip + 提示 + + + + + NoSelectedController + 先に大きいスクリーンを選んでください + + + + + InputOriginalPasswordTip + オリジナルのパスワードを入力してください + + + + InputNewPasswordTip + 新しいパスワードを入力してください + + + + InputRepeatPasswordTip + 新しいパスワードを繰り返して入力してください + + + + InputRepeatPasswordNotSameTip + 二回入力したパスワードが一致しません + + + + Tip Info + ヒント + + + + After setting the password, please remember the password and record it. If you forget the password, the device will be unable to operate. Are you sure you want to continue with this operation? + パスワードを設定した後、パスワードを覚えて、それを記録してください。パスワードを忘れた場合は、デバイスが動作することができなくなります。この操作を続行しますか? + + + + + + + SetControllerPassword + 暗号化の設定 + + + + + Error + エラー + + + + + Success + 成功 + + + + + + Modify password + パスワードを変更 + + + + + + + OriginalPasswordErrorTip + 元のパスワードが間違っています + + + + CtrlVerifyClockPanel + + + Verify Clock Configuration + 検証クロック設定 + + + + + Verify to Computer time + コンピュータ時刻の確認 + + + + Cur time of controller + ディスプレイの現在の時間 + + + + + LAN + LAN + + + + + + + + + + + + + + Tip + ヒント + + + + + + + + + + + + + + NoSelectedController + 先に大きいスクリーンを選んでください + + + + screenSwitch + スクリーンの切り替え + + + + + + YES + 開く + + + + + + NO + オフ + + + + volume + 音量 + + + + brightness + 明るさ + + + + + identificationCode + 識別コード + + + + + delaySync + 時間オフセット + + + + + msec + ミリ秒 + + + + + + + OtherSyncItem + その他の同期項目 + + + + + + + lastSynchronousTime + 最終同期時間 + + + + checkNtpTime + 同期間隔 + + + + Lora identity + ロラの身分 + + + + (min/time) + (分/回) + + + + identification code + 識別コード + + + + Time offset(msec) + タイム・オフセット( msec ) + + + + Brightness + スクリーン輝度 + + + + Volume + 体積 + + + + Screen on/off + スクリーンスイッチ + + + + + Slave + から + + + + NTP Server + NTPサーバ + + + + + NTP Server address + NTPサーバのアドレス + + + + TimeZone + タイムゾーン + + + + + + + + Set + セット + + + + Language: + 言語: + + + + Enable Synchronous playing + 画面を同期させる機能 + + + + + Sync time interval + 同期時間間隔 + + + + + + + + Readback + 読み戻し + + + + + Master + + + + + Identification Code + 識別コード + + + + + SetNtpServer + NTPサービスの設定 + + + + + MasterSwitch + メインデバイスの設定 + + + + + SlaveSwitch + スレーブデバイスとして設定 + + + + IsMasterSlave + 主従の身分を読み返す + + + + + GetControllerDate + 日付時間の取得 + + + + + SetingSyncMethod + set syncメソッド + + + + + SyncTime + キャリブレーション時間 + + + + + GetNtpServer + NTPサービス情報を取得する + + + + + GetingSyncMethod + 同期方式を取得 + + + + + SetTimezone + タイムゾーンを設定 Def - - - + Connection Timeout 接続タイムアウト - - - - - - - + + + + + Device replied - + デバイス応答 - - + + + Success 成功 - - - - Error - エラー - - - - Tip Info - ヒント - - - - + Fail 失敗 @@ -3453,666 +3333,314 @@ DeviceCtrlPanel - - - + + + + Current Screen 現在のスクリーン - - + + none なし - - + + Clear クリア - - - single screen operation - シングルスクリーン操作 - - - + + Multi screen operation マルチスクリーン操作 - + + selected num 選択された数 - + Brightness Adjustment 輝度設定 - + Power Control 電源コントロール - + Net Config ネット配置 - - Time Synchronization + + Time Sync タイマ配置 - + Video source ビデオソース - - Encrypt - 暗号化する + + Password + ひそかに言う - - Advanced parameters + + Advanced 上級パラメータ - - Current Screen: - 現在のスクリーン: - - - + Test テスト - - Volume Adjustment + + Volume Adj. 音量調節 DeviceItem - + GetScreenDetailInfo 詳細 - + ReadbackPic 回読画面 - + Input password パスワードを入力 - + GetScreenshotFull 回読画面 - + cur brightness: 現在の明るさ: - + android version: Androidバージョン: - + IMEI: - + HardWard Version: FPGAバージョン: - + MAX Brightness level: 輝度レベル: - + Android OS Resolution: Androidの解像度: - + Firmware Version: ファームウェアバージョン: - + Player Version: プレーヤーファームウェアバージョン: - + Detail Info 詳細 - - - - - - - + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + receive 受信 - - SetScreenOn - 電源の設定 - - - + AliIotSetting - - + + GetScreenStatus スクリーン状態を取得 - - + + Status 状態 - + Tip Info ヒント - + password is wrong パスワードが間違っている - + GetBrightness 輝度値を取得 - - - + brightness 明るさ - - MasterSlaveSwitch - メインの個人情報を設定 - - - - SetBrightness - 輝度を設定する - - - - - SetMinBrightness - 最小輝度値を設定します - - - - GetBrightnessSensitivity - 明るさ感を得る - - - - sensitivity - 感度 - - - - GetMinBrightness - 輝度最小値を取得 - - - - SetSensorBrightnessTable - センサーパラメータの設定表 - - - - SetSwitchWiFi - WiFiスイッチの設定 - - - - ConfigurationWiFi - WiFiの設定 - - - - ConfigurationHotSpot - ホットスポットの設定 - - - - GetSwitchWiFi - WiFi状態を取得 - - - + SetAutoBrightnessTask 送信タイミング輝度表 - + SetAutoVolumeTask 設定タイミング音量表 - + SetVolume 音量調節 - + GetVolume 現在の音量を取得 - + SetTimingScreenTask 画面タイミングスイッチタスクの設定 - - GetControllerDate - 日付時間の取得 - - - - SetHighForBusy - 客レベルの設定 - - - - - GetStateForBusy - ゲストレベルを取得 - - - - Service:Low Out of service:High - 客がいます:低 客がいません:高 - - - - Service:High Out of service:Low - 客がいます:高 客がいません:低 - - - - - - IsPortableHotSpot - ホットスポットとWiFiモードの取得 - - - - WifiName - Wifiの名前 - - - - ApName - AP名前 - - - + TestScreen テスト画面 - + SetOnlineAddr ウェブサーバのアドレスを設定 - + SetRealtimeServer RealTimerアドレスを設定 - - GetOnlineAddr - ウェブサーバのアドレスを取得 - - - - GetRealtimeServer - realtimeサーバのアドレスを取得します - - - - SetNtpServer - NTPサービスの設定 - - - - GetNtpServer - NTPサービス情報を取得する - - - - SyncTime - キャリブレーション時間 - - - - DelPrograms - 番組をクリア - - - - SetingSyncMethod - set syncメソッド - - - + GetCurrentSensorBrightness 現在の明るさを取得する - + Cur brightness カールの明るさ - - SetSpecialResolution - 解像度を設定 - - - - GetSpecialResolution - 読み込み解像度 - - - - totalResolution - FPGAトータル解像度 - - - - strCurDisplayResolution - 表示解像度 - - - - CleanDisplayScreenSize - デフォルトの解像度を復元 - - - - SetMaxBrightness - 輝度最大値を設定 - - - - GetMaxBrightness - 輝度最大値を取得 - - - - screenSwitch - スクリーンの切り替え - - - - - - YES - 開く - - - - - - NO - オフ - - - - LAN - LAN - - - + Connect 接続 - + timeout タイムアウト - + Anycast リクエスト - - + volume 音量 - - - - - - - GetingSyncMethod - 同期方式を取得 - - - - - identificationCode - 識別コード - - - - - delaySync - 時間オフセット - - - - - msec - ミリ秒 - - - - - - - OtherSyncItem - その他の同期項目 - - - - - - - lastSynchronousTime - 最終同期時間 - - - - checkNtpTime - 同期間隔 - - - - Uploadding - アップロード - - - + Success 成功 - + failed 失敗 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + success 成功 - - - Lora identity - ロラの身分 - - - - Master - - - - - Slave - から - - - - SetBrightnessSensitivity - 輝度センサ感度を設定する - - - - - + + + on オン - - - + + + off オフ @@ -4121,115 +3649,115 @@ DevicePanel - + All トータル トータル - + Online オンライン中 - - + + Refresh 更新 更新 - - - + + + Specify IP 指定IP 指定IP - + Current Screen 現在のスクリーン - + none なし - + Specify IP list - + 指定 IP リスト - + Search 検索 - - + + Attention 注意 - - + + Please input IP address! IPアドレスを入力してください! - + Cancel キャンセル - + Screen ID ターミナルID - + Screen IP ターミナルIP - + Screen Size スクリーンサイズ - + Remark Name 別名 - + readback pic 読み戻し - + send 送信 - + More Info 詳細 - + Cur Brightness 現在の画面の明るさ - + Power Status 画面切り替えステータス - + Security 暗号化 @@ -4406,39 +3934,156 @@ - EAudio + EAClock - + Basic Properties 基本的な属性 - - File - ファイル + + Time Zone + タイムゾーン - + + Custom Dial + ユーザー定義の文字盤 + + + + Select + 選択 + + + + Select Dail file + 文字盤の画像を選択 + + + + Hour Mark + 時間目盛り + + + + + Circular + 円形 + + + + + Rectangle + 矩形 + + + + Number + デジタル + + + + + + T + + + + + Min Mark + 分目盛り + + + + Color + カラー + + + + Length + 長さ + + + + Width + + + + + Hour Hand + 時針 + + + + Min Hand + 分針 + + + + Sec Hand + 秒針 + + + + Show + 表示 + + + + Text + テキスト + + + Play Properties 再生方法 - + Play Duration 再生時間 - + + s + + + + + EAudio + + + Basic Properties + 基本的な属性 + + + + File + ファイル + + + + Play Properties + 再生方法 + + + + Play Duration + 再生時間 + + + Select File ファイルを選択 - + s - + Audio オーディオ @@ -4446,233 +4091,373 @@ EBase - + Area 領域(px) - + X X - + Y Y - + W W - + H H - + Border ボーダー - - + + None なし - + Effect 特効 - + Rotate 回転 - + Blink きらめき - + Speed スピード - + Slow 遅い - + Moderate - + Fast 速い - EEnviron + EDClock - - - - - - - - north - 北の方 + + MON + 月曜日 - - - - - - - - east - + + TUE + 火曜日 - - - - - - - - south - 南の方 + + WED + 水曜日 - - - - - - - - west - 西の方 + + THU + 木曜日 - - - Temperature - 温度 + + FRI + 金曜日 - - - Humidity - 湿度 + + SAT + 土曜日 - - - Noise - ノイズ + + SUN + 日曜日 - - Wind Speed - 風速 + + + AM + 午前 - - Wind Direction - 風向 + + + PM + 午後 - + Basic Properties 基本的な属性 - - Title - タイトル + + Time Zone + タイムゾーン - - Compensation - 補償 + + Year + - - Wind speed - 風速 + + Month + - - Wind direction - 風向 + + Day + - - Left - 左に寄る + + Hour + - - Center - 中央にある + + Min. + - - Right - 右に寄る + + Sec. + - - Single scroll - 1行スクロール + + Weekly + 曜日 - - Speed - スピード + + Full Year + 四桁数の年 - - ms/pixel - ミリ秒/ピクセル + + 12-Hour + 12時 - - Back Color - 背景色 + + Date Style + 日付スタイル - + + Time Style + タイムスタイル + + + + Display Style + 表示スタイル + + + + Multiline + 複数行表示 + + + Play Properties 再生方法 - - Refresh Cycle - リフレッシュサイクル - - - - min. - - - - + Play Duration 再生時間 - + + s + + + + + EEnviron + + + + + + + + + north + 北の方 + + + + + + + + + + east + + + + + + + + + + + south + 南の方 + + + + + + + + + + west + 西の方 + + + + + Temperature + 温度 + + + + + Humidity + 湿度 + + + + + Noise + ノイズ + + + + Wind Speed + 風速 + + + + Wind Direction + 風向 + + + + Basic Properties + 基本的な属性 + + + + Title + タイトル + + + + Compensation + 補償 + + + + Wind speed + 風速 + + + + Wind direction + 風向 + + + + Left + 左に寄る + + + + Center + 中央にある + + + + Right + 右に寄る + + + + Single scroll + 1行スクロール + + + + Speed + スピード + + + + ms/pixel + ミリ秒/ピクセル + + + + Back Color + 背景色 + + + + Play Properties + 再生方法 + + + + Refresh Cycle + リフレッシュサイクル + + + + min. + + + + + Play Duration + 再生時間 + + + s @@ -4680,37 +4465,37 @@ EGif - + Basic Properties 基本的な属性 - + File ファイル - + Select File ファイルを選択 - + Play Properties 再生方法 - + Play Duration 再生時間 - + s - + Play Times 再生回数 @@ -4718,73 +4503,73 @@ EMultiWin - + Please add media on the right 右側にメディアを追加してください。複数のメディアに参加できます。LEDディスプレイはリスト順に再生されます - + Media List メディアリスト - - - + + + Text テキスト - - - + + + Photo 写真 - - - + + + Video 動画リスト - - - + + + Gif アニメーション - - - + + + DClock デジタル時計 - - - + + + AClock アナログ時計 - - - + + + Select File ファイルを選択 - - + + Environment 環境モニタリング - - + + Timer タイマー @@ -4792,118 +4577,118 @@ EPhoto - + Basic Properties 基本的な属性 - + File ファイル - + Select File ファイルを選択 - + Image Read Error 画像読み込みエラー - + Play Properties 再生方法 - + Play Duration 再生時間 - - + + s - + Enter Style 開始効果 - + None なし - + Alpha_In 淡入 - + Moving to left 連続する左シフト - + Moving to right 連続右シフト - + Moving to top 連続アップコンバート - + Move to bottom 連続的下向 - + Zoom in 拡大 - + Zoom in to left_bottom 左下の拡大 - + Zoom in to left_top 左上の角を大きく - + Zoom in to right_top 右上拡大 - + Zoom in to right bottom 右下隅を大きく - + Rotate to right 右回り - + Rotate to left 左回り - + Enter Duration 効果時間 - + Images (*.png *.jpg *.jpeg *.bmp) 写真(*.png *.jpg *.jpeg *.bmp) @@ -4911,191 +4696,191 @@ EText - + Enter your text 内容を入力してください - + Basic Properties 基本的な属性 - - Font Color - フォント色 - - - + Back Color 背景色 - + Kerning 字の間隔 - + Line Spacing 間隔 - + PageCount: 総ページ数: - + page ページ - + Import txt File インポート txt ファイル - + Select File ファイルを選択 - + Fail 失敗 - + File Open Fail - + Play Properties 再生方法 - + Flip 次頁 - + Scroll スクロール - + Static スタティック - - - + + + Play Duration 再生時間 - + Duration/Page ページごとの再生時間 - + Effect time 効果時間 - - + + Tip Info ヒント - - + + Effect time cannot be longer than duration time 効果の長さはプレイ時間より長くできません - + s - + + Text Color + テキスト色 + + + + Colorful Text + まばゆい文字 + + + Entrance Effect 開始効果 - + no なし - + random ランダム - + right to left 左へ連続移動 - + bottom to top 連続して上に移動 - + left to right 右へ連続移動 - + top to bottom 連続して下に移動 - - Head-Tail Connected - 首尾接続 - - - + Head-Tail Spacing 首尾間隔 - + Scroll Style スクロール方向 - + Right -> Left 左へ - + Bottom -> Top 上へ - + Left -> Right 右へ - + Top -> Bottom 下へ - + Scroll Speed スクロールスピード @@ -5103,87 +4888,87 @@ ETimer - + day - + hour - + min - + sec - + Basic Properties 基本的な属性 - + Count Down カウントダウン - + Count Up カウントアップ - + Time 目標時間 - + Day - + Hour - + Min - + Sec - + Multiline 複数行表示 - + Text テキスト - + Play Properties 再生方法 - + Play Duration 再生時間 - + s @@ -5191,64 +4976,64 @@ EVideo - + Basic Properties 基本的な属性 - + File ファイル - + Play Properties 再生方法 - + Play Duration 再生時間 - + Select File ファイルを選択 - + s - + Play Times 再生回数 - + Video Transcoding - - + + Video Transcoding Progress ビデオ変換の進歩 - - + + Error エラー - + Video ビデオ - + Flash Flash @@ -5256,17 +5041,17 @@ EWeb - + Basic Properties 基本的な属性 - + Play Duration 再生時間 - + s @@ -5294,10 +5079,93 @@ + + GenTmpThread + + + Preparing ... + 準備... + + + + MON + 月曜日 + + + + TUE + 火曜日 + + + + WED + 水曜日 + + + + THU + 木曜日 + + + + FRI + 金曜日 + + + + SAT + 土曜日 + + + + SUN + 日曜日 + + + + AM + 午前 + + + + PM + 午後 + + + + day + + + + + hour + + + + + min + + + + + sec + + + + + Create json ... + クリエイトjson... + + + + Scan program ... + スキャン番組… + + LoColorSelector - + Transparent 透明な @@ -5340,186 +5208,230 @@ MainWindow - + Language 言語 - + Help ヘルプ - - + + Check for updates アップデートをチェック - - + + firmware manager ファームウェア管理 - - - Software Configuration + + + Software Config ソフトウェアの設定 - - + + Info 情報 - - + + About 当ソフトウェアについて - - + + Setting 設置 - + + Software Update + ソフトウェアの更新 + + + + CurVersion + 現在のバージョン + + + + Update + 更新 + + + + LatestVersion: + 最新バージョン: + + + + + Update log: + 更新ログ: + + + + The current version is already the latest version + すでに最新バージョンです。 + + + Device 端末管理 - + Program コンテンツ管理 - + Control ターミナルコントロール - + GuangYinPin スクリーン - + Check card ワンタッチ修復 - + Tip Info ヒント - + RestoreLedCardIpByUdpTip この操作はLAN内のすべてのコンピュータIPと同じセグメントにないコントロールカードを固定IPに修正します。慎重に操作してください。 + + Net + + + Connection Timeout + 接続タイムアウト + + + + Error + エラー + + PageEditor - + Zoom In 拡大 - + Zoom Out 縮小 - + Original size オリジナル割合 - + Delete the secect media 選んで削除する - + Clear all media コンテンツをすべてクリアする - + Move layer up 前面にする(ショートカットキーPgUp) - + Send backward 背面にする(ショートカットキーPgDn) - + Bring to front 最前面にする(ショートカットキーHome) - + Move to the bottom layer 写真を最背面にする(ショートカットキーEnd) - + Fill the entire screen 全画面塗りつぶし - + Fill the screen horizontally 行塗りつぶし - + Fill the screen vertically 列塗りつぶし - + Align top 縦位置 上詰め - + Center vertically 縦位置 中央揃え - + Bottom align 縦位置 下詰め - + Align left 横位置 左詰め - + Center horizontally 横位置 中央揃え - + Align right 横位置 右詰め - + Tip Info ヒント - + Clear all medias? @@ -5527,79 +5439,84 @@ PageListItem - + times - + Page name プログラム名 - + New 新規 - + Play times 再生回数 - + + Sources Repeat + ソースの繰り返し + + + Audios オーディオ - + Total Dur 全期間 - - + + s - + Select File ファイルを選択 - + Duration 期間 - + Vol 音量 - + Valid Date 有効期間 - - + + Warning 警告 - + Start Time can't be later than End Time 開始時間は終了時間より後にようにしてください - + End Time can't be earlier than Start Time 終了時間は開始時間より遅いようにしてください - + Plan タイムスケジュール @@ -5628,17 +5545,17 @@ PlayWin - + Move to Top Left 左上隅に移動 - + Set Position 設定位置 - + Close 閉じる @@ -5646,12 +5563,12 @@ PlayerBackSendThread - + Open file failed ファイルのオープンに失敗しました - + Read file failed ファイルの読み込みに失敗しました @@ -5672,47 +5589,47 @@ ProgCreateDlg - + Resolution 解像度 - + Solution Information スケジュール情報 - + Solution Name リスト名 - + Width - + Height 高さ - + Remarks 備考 - - 节目超宽需要打折, 请输入打折宽度 + + 每段打折宽度 (用空格分隔) - + OK 確定 - + Cancel キャンセル @@ -5720,221 +5637,200 @@ ProgEditorWin - + Save 保存 - - + + Save as 名前を付けて保存 - + Setting 設置 - + Text テキスト - + Photo 写真 - + Video ビデオ - + Gif アニメーション - + Clock デジタル時計 - + Analog Clock アナログ時計 - + Environment 環境モニタリング - + Web ウェブページ - + MuliContentWindow マルチ素材ウィンドウ - + In this window, a plurality of different program materials can be added and played according to the order of joining the list; このウィンドウには、複数の異なる番組素材を追加して、リストに追加した順に再生することができます - + Timer タイマー - + Play 再生 - + Stop 停止 - + Publish 転送 - - - - + + + + Select File ファイルを選択 - + program 番組リスト - + Add page ページを追加 - + Copy page コピーページ - + Delete page ページを削除 - - + + Tip Info ヒント - + Are you sure you want to delete this program page? 本当にこの番組ページを削除しますか? - + Move up 前へ - + Move down 次頁 - + widget properties パッケージプロパティ - + Page properties プログラムのプロパティ - + Do you want to save the modifications? 変更された内容を保存してもよろしいですか? - - + + Saving... 保存中、少々お待ちください... - - + + Success 成功 - - + Save failed 保存に失敗 - + Convertering データを整理する - - Converter Successed - 整理に成功しました - - - - Converter TimeOut - 整理タイムアウト - - - + Generate preview data プレビューデータの生成 - - Ready - 準備が完了しました - - - - Generate TimeOut - タイムアウトを生成 - - - - + + Error エラー - + Rename fail when saving - + Remove Recursively fail when saving - + Warning 警告 @@ -5942,155 +5838,177 @@ ProgItem - - + + ExportButtonTip USBメモリで再生する - - + + SendButtonTip 転送 - - + + Convertering データを整理する - - - USB Export Successed - USBメモリのエクスポートに成功しました - - - - USB Export TimeOut - USBメモリのエクスポートに失敗しました - - - - Converter Successed - 整理に成功しました - - - - Converter TimeOut - 整理タイムアウト - ProgPanel - - + + New 新規 - - + + Edit 編集 - - + + Delete 削除 - - + + + Import インポート - - + + + Export 出力 - - + + Send 送信 - - + + Publish 転送 - - + + Name 名前 - - + + + Choose Directory + ディレクトリを選択 + + + + Tip + ヒント + + + + The imported directory is already in the working directory, so there is no need to import it again! + このインポートしたディレクトリはすでにワークディレクトリの下にあります。再インポートする必要はありません! + + + + :solution(s) already exist.are you sure you want to overwrite the existing solution(s)? + 解決策は既に存在します。既存の解決策を上書きしたいと思いますか? + + + + Play 再生 - - + + Stop 停止 - - + + Resolution 解像度 - - + + File Size サイズ - - + + Last Modify 最終更新日 - - + + Usb playback USBメモリで再生する - + Program name conflicted 番組名が重なる - + Warning 警告 - + You will delete the selected solution(s),are you sure? 是否确认删除选中的节目? - + + Tip Info ヒント + + ProgPortDlg + + + Solution Name + リスト名 + + + + Progress + 程度 + + + + Done + 完了 + + QObject - + Setting up the LedOK Express... 初期化LedOK Express… @@ -6098,18 +6016,18 @@ SendProgThread - - + + Program is empty プログラムは空です - + Open file failed ファイルのオープンに失敗しました - + Read file failed ファイルの読み込みに失敗しました @@ -6117,73 +6035,73 @@ SendProgramDialog - - + + Publish 転送 - + success info - + Refresh 更新 - + Cancel キャンセル - + Screen ID ターミナルID - + Remark Name 別名 - + Online オンライン中 - + Screen IP ターミナルIP - + Screen Size スクリーンサイズ - + Security 暗号化 - + Progress 程度 - + Remarks 備考 - + This screen is encrypted スクリーンは暗号化されています - + All トータル @@ -6191,12 +6109,12 @@ SoftConfigDialog - - Software Configuration + + Software Config ソフトウェアの設定 - + Video compress to ビデオ圧縮 to @@ -6206,200 +6124,31 @@ トランスコード to - + Text antialiasing 文字のアンチエイリアス - + TextAntilaTip (ヒント:小さい間隔の大きい画面に適しています。このオプションを有効にすると、文字の端に影がフォントのエッジの滑らかさに達します。小さいサイズのスクリーンと単色のスクリーンは使用を推奨しません) - + GuangYinPin スクリーン - + + Width Split + + + + OK 確定 - - SpecialDlg - - Specify IP - 指定IP - - - Search - 検索 - - - Cancel - キャンセル - - - Attention - 注意 - - - Please input IP address! - IPアドレスを入力してください! - - - Your IP Address is Invalid! - IPアドレスが無効です! - - - Error - エラー - - - - ThreadUpgradeApk - - - Uploadding - アップロード中 - - - - TipDialog - - - TextLabel - - - - - - OK - 確定 - - - - - Cancel - キャンセル - - - - X - - - - - - Import - インポート - - - - - Path - パス - - - - - : - - - - - - browse - ブラウズ - - - - You will delete the selected solution(s),are you sure? - 是否确认删除选中的节目? - - - - - Export - 出力 - - - - - Done - 完了 - - - - - Solution Name - リスト名 - - - - - Progress - 程度 - - - - Delete - 削除 - - - - Select the network to connect to the device - LEDコントローラに接続するネットワークを選択してください - - - - Network name - ネットワーク名 - - - - - This operation will only set cable network to static IP,are you sure? - この動作は,選択されたネットワークを固定IPに設定し,自動で直連のLEDデバイスを同一セグメントのIPアドレスに設定して確認するかどうかである? - - - - Do you want set IP of cable network to DHCP - ネットワークの設定はDHCPにより自動的にIPを取得する - - - - - - - - Tip - 提示 - - - - - - Please select the network to connect to the Led controller - LEDコントローラに接続するネットワークを選択してください - - - - Choose Directory - ディレクトリを選択 - - - - The imported directory is already in the working directory, so there is no need to import it again! - このインポートしたディレクトリはすでにワークディレクトリの下にあります。再インポートする必要はありません! - - - - no find program can be imported - プログラムはインポートできません - - UpdateLedset3Dialog @@ -6472,262 +6221,315 @@ おめでとう!あなたは%1の最新バージョンを実行しています - - UpdaterDialog - - - Software Update - ソフトウェアの更新 - - - - X - X - - - - V1.0 - - - - - Update - 更新 - - - - CurVersion - 現在のバージョン - - - - LatestVersion: - 最新バージョン: - - - - - Update log: - 更新ログ: - - - - The current version is already the latest version - すでに最新バージョンです。 - - UpgradeApkDialog - - - Upgrade apk - アップグレード + + Update APK + 更新APK - - 口 - - - - - X - X - - - - + Select apk Appパッケージを選択 - - - - + Upgrade アップグレード - - - APK: - - - - - + Uninstall アンマウント - - + check running state 運転状態を検出 - - + Select Fpga FPGAファイルを選択 - - - success info - + + Installing + インストール中 - - + Refresh 更新 - - + Cancel キャンセル - + Screen ID ターミナルID - + Remark Name 別名 - + Online オンライン中 - + Screen IP ターミナルIP - + Security 暗号化 - + Progress 程度 - + xixunplayer - + cardsystem - + taxiapp - + starter - + connection - + displayer - + FPGA FPGA - + update - + State 状態 - - - + + All トータル - + + This screen is encrypted + スクリーンは暗号化されています + + + + + Select Online APK + オンラインAPKを選択 + + + + No Files + ファイルがありません + + + + Name + 名前 + + + + Size + サイズ + + + + Create Time + 作成時間 + + + + + + Tip + ヒント + + + + Is upgrading now. Please wait + 更新中です、しばらくお待ちください + + + + NoSelectedController + 先に大きいスクリーンを選んでください + + + + + Downloading Online File + オンラインファイルをダウンロード中 + + + + + Error + エラー + + + + Online file is empty + オンラインファイルが空です + + + + Uploading + アップロード中 + + + + Upload error + アップロード エラー + + + + Install error + インストール エラー + + + + Install success + インストールに成功しました + + + + Reminder + ヒント + + + + Reminder: Uninstalling this program may cause the device to offline, cannot be found, lost configs and have a black screen. Please uninstall with caution! + ヒント:このプログラムをアンインストールすると、プラットフォームがオフラインになり、デバイスが見つかりません。構成パラメータが失われ、黒画面の問題が発生します。慎重にアンインストールしてください。 + + + + Do you want to continue? + 続行しますか? + + + + Uninstalling + アンマウント中 + + + + Uninstall error + アンインストール エラー + + + + Uninstall success + アンインストールに成功しました + + + + Check apk running status + APK運転状態監視 + + + + Check error + チェック エラー + + + + Running + 実行中 + + + + Not running + 実行されていません + + + The encrypted control card can be upgraded directly 暗号化されたコントロールカードを直接アップグレードすることができます - - - apk package (*.rpd) - - - - - apk package (*.apk *.zip) - - UsbDetectDialog - + Usb upgrade program Uディスク更新プログラム - + Password パスワード - + OK 確定 - + Input password パスワードを入力 - - + + Tip 提示 - + No checked USB device チェックUSBデバイス - + please select usb device in list リスト内のUSBデバイスを選択してください - + Cancel キャンセル @@ -6735,7 +6537,7 @@ WaitingDlg - + Success 成功 @@ -6764,331 +6566,6 @@ キャンセル - - eAClock - - - Basic Properties - 基本的な属性 - - - - Time Zone - タイムゾーン - - - - Custom Dial - ユーザー定義の文字盤 - - - - Select - 選択 - - - - Select Dail file - 文字盤の画像を選択 - - - - Hour Mark - 時間目盛り - - - - - Circular - 円形 - - - - - Rectangle - 矩形 - - - - Number - デジタル - - - - - - T - - - - - Min Mark - 分目盛り - - - - Hand Color - 剣カラー - - - - H - H - - - - M - - - - - S - - - - - Text - テキスト - - - - Play Properties - 再生方法 - - - - Play Duration - 再生時間 - - - - s - - - - - eDClock - - - MON - 月曜日 - - - - TUE - 火曜日 - - - - WED - 水曜日 - - - - THU - 木曜日 - - - - FRI - 金曜日 - - - - SAT - 土曜日 - - - - SUN - 日曜日 - - - - - AM - 午前 - - - - - PM - 午後 - - - - Basic Properties - 基本的な属性 - - - - Time Zone - タイムゾーン - - - - Year - - - - - Month - - - - - Day - - - - - Hour - - - - - Min. - - - - - Sec. - - - - - Weekly - 曜日 - - - - Full Year - 四桁数の年 - - - - 12-Hour - 12時 - - - - Date Style - 日付スタイル - - - - Time Style - タイムスタイル - - - - Display Style - 表示スタイル - - - - Multiline - 複数行表示 - - - - Play Properties - 再生方法 - - - - Play Duration - 再生時間 - - - - s - - - - - GenTmpThread - - - Preparing ... - 準備... - - - - MON - 月曜日 - - - - TUE - 火曜日 - - - - WED - 水曜日 - - - - THU - 木曜日 - - - - FRI - 金曜日 - - - - SAT - 土曜日 - - - - SUN - 日曜日 - - - - AM - 午前 - - - - PM - 午後 - - - - day - - - - - hour - - - - - min - - - - - sec - - - - - Create json ... - クリエイトjson... - - - - Scan program ... - スキャン番組… - - mGuangYingPinWidget @@ -7493,68 +6970,55 @@ シリアルのオープンに失敗しました - - wExportProgramItem - - - Tip Info - ヒント - - - - :solution(s) already exist.are you sure you want to overwrite the existing solution(s)? - 解決策は既に存在します。既存の解決策を上書きしたいと思いますか? - - wPlanItem - + Form リフレッシュ - + 1 1 - + Every week: 毎週: - + M - + Tu - + W - + Th - + F - + Sa - + Su @@ -7562,30 +7026,30 @@ wProgramPublishItem - + Input password パスワードを入力 - - - + + + Error エラー - - + + Tip Info ヒント - + Fail 失敗 - + password is wrong パスワードエラー @@ -7593,92 +7057,24 @@ wUpgradeApkItem - + Input password パスワードを入力 - - uninstalling - アンマウント中 + + Error + エラー - - - IsSoftwareRunning - APK運転状態監視 - - - - - This screen is encrypted - スクリーンは暗号化されています - - - - - Start upgrading - レベルアップします - - - - - Timeout - タイムアウト - - - - install start... - インストールを開始します - - - - - SynchronousHardwareVersion - 同期FPGA - - - + Tip Info ヒント - + password is wrong - - - - UninstallSoftware - アンマウント - - - - - Success - 成功 - - - - Running - 実行中 - - - - NoRunning - 実行されていません - - - - install success - インストール成功 - - - - - Fail - 失敗 - diff --git a/LedOK/translations/app_zh_CN.ts b/LedOK/translations/app_zh_CN.ts index 31d6b17..3284c38 100644 --- a/LedOK/translations/app_zh_CN.ts +++ b/LedOK/translations/app_zh_CN.ts @@ -71,1339 +71,202 @@ 密码更改成功 - - ControlEncryptWidget - - - Form - Form - - - - - Entrypt Configuration - 安全配置 - - - - Original password - 原始密码 - - - - - - original password - 原始密码 - - - - - - New password - 新密码 - - - - - Repeat new password - 重复输入 - - - - - - - Set encryption - 加密 - - - - - Cancel encryption - 取消加密 - - - - - Enter password - 输入密码 - - - - Enter again - 再次输入 - - - - - - - - - Tip - 提示 - - - - NoSelectedController - 请先选择大屏幕 - - - - - InputOriginalPasswordTip - 请输入原始密码 - - - - InputNewPasswordTip - 请输入新密码 - - - - InputRepeatPasswordTip - 请重复输入新密码 - - - - InputRepeatPasswordNotSameTip - 两次输入的密码不一致 - - - - Tip Info - 提示 - - - - After setting the password, please remember the password and record it. If you forget the password, the device will be unable to operate. Are you sure you want to continue with this operation? - 设置密码后,请记住密码并记录。如果忘记密码,设备将无法运行。确实要继续此操作吗? - - - - - SetControllerPassword - 设置加密 - - - - Readback - 回读 - - - - - - Success - 成功 - - - - - - failed - 失败 - - - - - Modify password - 修改密码 - - - - OriginalPasswordErrorTip - 原始密码错误 - - - - ControlHdmiSchedule - - - Form - Form - - - - - Add - 添加 - - - - - Delete - 删除 - - - - - Clear - 清除 - - - - - Import - 导入 - - - - - Export - 导出 - - - - By default, the asynchronous content is played, and the synchronous signal content is played in the fixed time period - 默认播放异步内容,定时时间段内播放同步HDMI-IN端口输入内容 - - - - - Apply - 应用 - - - - Readback - 回读 - - - - SYNC HDMI - 同步模式 - - - - Start Time - 开始时间 - - - - End Time - 结束时间 - - - - SUN - 星期日 - - - - MON - 星期一 - - - - TUE - 星期二 - - - - WED - 星期三 - - - - THU - 星期四 - - - - FRI - 星期五 - - - - SAT - 星期六 - - - - - DeviceItem OnProHttpResponse 解析json文件错误! - - - - - - On - - - - - SyncSchedule (*.syncs) - - - - - Save File - 保存文件 - - - - Sync Schedule (*.syncs) - - - - - - Tip - 提示 - - - - - NoSelectedController - 请先选择大屏幕 - - - - SetTimingHdmiInTask - 设置同步模式定时任务 - - - - GetTimingHdmiInTask - 获取同步模式定时任务 - - - - - Success - 成功 - - - - - failed - 失败 - - - - ControlHdmiWidget - - - HDMI Configuration - 画面输入源配置 - - - - Manual - 手动 - - - - Schedule - 定时 - - - - - Tip - 提示 - - - - - NoSelectedController - 请先选择大屏幕 - - - - - SyncSwitch - 切换同步模式 - - - - - AnSyncSwitch - 切换异步模式 - - - - - IsSync - 回读同异步模式 - - - - Error - 错误 - - - - HDMI IN - 同步 - - - - Async - 异步 - - - - Readback - 回读 - - - - ControlNetConfigWidget - - - Wire Enther(RJ45) Configuration - 有线网配置 - - - - - DHCP - - - - - - Specify IP - 指定IP - - - - - IP Address - IP地址 - - - - Mask Address - 子网掩码 - - - - - Gateway - 网关 - - - - - DNS Address - DNS地址 - - - - - - - - - - Set - 设置 - - - - - - - - - Readback - 回读 - - - - - WIFI Configuration - WiFi配置 - - - - - WiFi On/Off - WiFi使能 - - - - Input Ap name - 输入热点名称 - - - - - 4G/5G Configuration - 蜂窝数据配置 - - - - - Open 4G/5G - 启用蜂窝数据 - - - - APN: - - - - - - Get cellular network status information - 获取蜂窝网络状态信息 - - - - - Check SIM can automatically match to MCC, and then select carrier get apn param,if not found carrier,you can check the CUSTOM checkbox,then enter custom param. - 通过获取状态按钮可以自动匹配国家码MCC,然后选择“运营商”可获取到响应的APN信息,如果找不到运营商,可以选中“自定义”复选框,然后手动输入APN信息。 - - - - - Readback APN Info - 回读APN信息 - - - - - Set Apn Info,Check SIM can automatically match to MCC, and then select carrier get apn param - 设置Apn信息 - - - - - CUSTOM - 自定义 - - - - - Check SIM - 查询SIM信息 - - - - - - -> - - - - - - Country ID(mcc): - 国家码(mcc): - - - - - Carrier Name - 运营商 - - - - - APN: - 运营商APN: - - - - - APN(Required) - APN(必填) - - - - - User: - 用户名: - - - - - - - Not required - 非必填 - - - - - Password: - 密码: - - - - Set Apn:iot.cargo - - - - - - Flight Mode - 飞行模式 - - - - - WiFi name - WiFi名称 - - - - - - - Password - 密码 - - - - - - - Input password - 输入密码 - - - - - Scan - 扫描 - - - - - Ap Mode - AP使能 - - - - Ap name - 热点名称 - - - - OFF - - - - - ON - - - - - AP name - 热点名称 - - - - Subnet mask - 子网掩码 - - - - Input ap name - 输入AP名称 - - - - - - - - - - - - - - - Success - 成功 - - - - - - - - - - - - - - - failed - 失败 - - - - - - - Tip - 提示 - - - - - NoSelectedController - 请先选择大屏幕 - - - - - SetEthernet - 设置有线网 - - - - - - - - - - - Attention - 注意 - - - - Please input IP address! - 请输入IP地址! - - - - Your IP Address is Invalid! - IP地址无效! - - - - Please input Mask address! - 请输入子网掩码地址! - - - - Your Mask Address is Invalid! - 掩码地址无效! - - - - Please input Gateway address! - 请输入网关地址! - - - - Your Gateway Address is Invalid! - 网关地址无效! - - - - Please input DNS address! - 请输入DNS地址! - - - - Your DNS Address is Invalid! - DNS地址无效! - - - - - GetEthernet - 获取有线网配置 - - - - DHCP IP - 动态DHCP IP - - - - STATIC IP - 静态IP - - - - Error - 错误 - - - - - - - - - SignalPower - 信号强度 - - - - - ConfigurationWiFi - 配置WiFi - - - - IsPortableHotSpot - 获取热点和WiFi模式 - - - - GetWifiList - 扫描WiFi - - - - ConfigurationHotSpot - 配置热点 - - - - GetCurrentAPN - 获取APN信息 - - - - - GetSIMStatus - 获取SIM状态 - - - - SetAPN - 设置APN - - - - - DeviceItem OnProHttpResponse 解析json文件错误! - - - - - 状态: - 状态: - - - - 未知 - 未知 - - - - 锁定状态,需要用户的PIN码解锁 - 锁定状态,需要用户的PIN码解锁 - - - - 锁定状态,需要用户的PUK码解锁 - 锁定状态,需要用户的PUK码解锁 - - - - 锁定状态,需要网络的PIN码解锁 - 锁定状态,需要网络的PIN码解锁 - - - - 就绪 - 就绪 - - - - no checked sim card - 检测不到sim卡 - - - - 国家码: - 国家码: - - - - 号码: - 号码: - - - - 用户: - 用户: - - - - 信号: - 信号: - - - - 信号正常 - 信号正常 - - - - 不在服务区 - 不在服务区 - - - - 仅限紧急呼叫 - 仅限紧急呼叫 - - - - 射频已经关闭 - 射频已经关闭 - - - - 网络: - 网络: - - - - 网络类型未知 - 未知 - - - - GPRS网络 - GPRS - - - - EDGE网络 - EDGE - - - - UMTS网络 - UMTS - - - - CDMA网络,IS95A 或 IS95B. - CDM - - - - EVDO网络, revision 0. - EVDO,revision 0. - - - - EVDO网络, revision A. - EVDO,revision A. - - - - 1xRTT网络 - 1xRTT - - - - HSDPA网络 - HSDPA - - - - HSUPA网络 - HSUPA - - - - HSPA网络 - HSPA - - - - 漫游: - 漫游: - - - - Yes - - - - - No - - - - - 数据连接状态: - 数据连接状态: - - - - 断开 - 断开 - - - - 正在连接 - 正在连接 - - - - 已连接 - 已连接 - - - - 暂停 - 暂停 - - - - 数据活动休眠状态: - 数据活动休眠状态: - - - - 活动,但无数据发送和接收 - 活动,但无数据发送和接收 - - - - 活动,正在接收数据 - 活动,正在接收数据 - - - - 活动,正在发送数据 - 活动,正在发送数据 - - - - 活动,正在接收和发送数据 - 活动,正在接收和发送数据 - - - - 休眠状态 - 休眠状态 - - - - 信号强度: - - - - - SetSwitchSimData - 设置4G/5G开关 - - - - ContrFlightMode - 配置飞行模式 - - - - GetFlightModeState - 获取飞行模式状态 - - - - ControlPowerManual - - - Form - Form - - - - - POWER - 开关 - - - - - - Readback - 回读 - - - - OFF - - - - - ON - - - - - - Tip - 提示 - - - - - NoSelectedController - 请先选择大屏幕 - - - - IsScreenOn - 读取开关状态 - - - - - - SetScreenOn - 设置电源 - - - - - - - Success - 成功 - - - - - on - - - - - - - - failed - 失败 - - - - - off - - - - - - SetScreenOff - 配置屏幕开关 - - - - - DeviceItem OnProHttpResponse 解析json文件错误! - - - ControlPowerSchedule - + Form Form - + Edit area 编辑区 - - + + Add 添加 - - + + Delete 删除 - - + + Clear - 清除 + 清空 - - + + Import 导入 - - + + Export 导出 - + It is power off state outside the schedule time period 定时时间段内显示屏开启,其他时间段为关屏状态 - + Send command 指令区 - - + + Apply 应用 - + Clear Schedule 清除定时 - + Readback 回读 - + Power On State 屏开关状态 - + Start Time 开始时间 - + End Time 结束时间 - + SUN 星期日 - + MON 星期一 - + TUE 星期二 - + WED 星期三 - + THU 星期四 - + FRI 星期五 - + SAT 星期六 - - + + DeviceItem OnProHttpResponse 解析json文件错误! - - + + On - - + + PowerSchedule (*.pjs) 开关屏定时(*.pjs) - + Save File 保存文件 - - - + + + Tip 提示 - - - + + + NoSelectedController 请先选择大屏幕 - - + + Tip Info 提示 - - + + Clear schedule task? 取消计划任务? - - + + CleanTimingScreenTask 取消计划任务 - + SetTimingScreenTask 设置屏幕定时开关任务 - - - - + + + + Success 成功 - - - - + + + + failed 失败 - + GetTimingScreenTask 获取屏幕定时开关任务 @@ -1411,678 +274,378 @@ ControlPowerWidget - - Form - Form + + + Off + - - + + + On + + + + + + Tip + 提示 + + + + + NoSelectedController + 请先选择大屏幕 + + + + + SetScreenOn + 打开屏幕电源 + + + + + SetScreenOff + 关闭屏幕电源 + + + + + IsScreenOn + 读取开关状态 + + + Power Configuration 开关屏控制 - - + Manual 手动 - - + Schedule 定时 + + + Power + 电源 + + + + Readback + 回读 + ControlTestWidget - + Form Form - - + + Test Screen 测试屏幕 - - + + Line test 线条测试 - - - - - - - + + + + + + + Red - - - - - - - + + + + + + + Green 绿 - - - - - - - + + + + + + + Blue - - - - - - - + + + + + + + White - - + + Vertical 竖线 - - + + Slash 斜线 - - - + + + Horizontal 横线 - - - - + + + + Speed 速度 - - + + ms(>10) 毫秒(>10) - - + + Line Distance 线距 - + px 像素 - - - - - + + + + + Test 测试 - - + + Gradation test 灰度测试 - - + + Only the gray value is displayed 只显示颜色值 - + (>10) - - + + GrayValue 灰度值 - + (0-255) - - + + Color test 颜色测试 - - + + Gradient 渐变 - + 8 8 - + 2 2 - + 3 3 - + 6 6 - + 4 4 - + 5 5 - + 1 1 - + 9 9 - + 7 7 - + 0 0 - - + + Clear - 清除 + 清空 - - + + Reset 循环 - - - - + + + + Anycast 点播 - - + + Stop 停止 - - - - - - - - + + + + + + + + Tip 提示 - - - - - + + + + + NoSelectedController 请先选择大屏幕 - - - + + + StartTest 开始测试 - - - - + + + + Success 成功 - - - - + + + + failed 失败 - + StopTest 停止测试 - + loopback mode 循环模式 - + Connect timeout 连接超时 - + Reset loop mode 设置循环 - - + + success 成功 - - - DeviceItem OnProHttpResponse 解析json文件错误! - 解析json文件错误! - - - - CtrlVerifyClockPanel - - - Form - Form - - - - English - - - - - 中文 - - - - - Verify Clock Configuration - 校准时间 - - - - Verify to Computer time - 校准到计算机时间 - - - - - Cur time of controller - LED显示屏设备当前时间 - - - - LAN - 局域网 - - - - (min/time) - (分钟/次) - - - - Sync identificationCode - 同步识别码 - - - - - identification code - 同步识别码 - - - - - Time offset(msec) - 时间偏移(毫秒) - - - - - Brightness - 屏体亮度 - - - - - Volume - 音量 - - - - - Screen on/off - 屏幕开关 - - - - - Slave - - - - - Master - - - - - - NTP Server - NTP服务器 - - - - - - - NTP Server address - NTP服务器地址 - - - - - - - TimeZone - 时区 - - - - - - - - - - - - - - - Set - 设置 - - - - - Language: - 语言: - - - - - Enable Synchronous playing - 使能同步画面功能 - - - - Lora - - - - - GPS - - - - - NTP - - - - - Time zone - 时区 - - - - - - - Sync time interval - 同步时间间隔 - - - - Verify clock configuration - 校准时间 - - - - - - - - - - - - - - Readback - 回读 - - - - Master - - - - - Sync clock to computer time - 校准时钟到计算机时间 - - - - Identification Code - 识别码 - - - - - - - - - - - - - - Success - 成功 - - - - - - - - - - - - - - failed - 失败 - - - - SetNtpServer - 设置NTP服务 - - - - MasterSwitch - 设置为主设备 - - - - SlaveSwitch - 设置为从设备 - - - - IsMasterSlave - 回读主从身份 - - - - GetControllerDate - 获取日期时间 - - - - SetingSyncMethod - 设置同步方法 - - - - SyncTime - 校准时间 - - - - GetNtpServer - 获取NTP服务信息 - - - - GetingSyncMethod - 获取同步方式 - - - - - DeviceItem OnProHttpResponse 解析json文件错误! - - - - - SetTimezone - 设置时区 - - - - ControlVolumeManual - - - Form - Form - - - - Volume(0-15) - 音量(0-15) - - - - - - Readback - 回读 - - - - SetVolume - 音量调节 - - - - - - Success - 成功 - - - - - - failed - 失败 - - - - Volume(min:0-max:15) - 音量(最小値:0-最大値:15) - - - - GetVolume - 获取当前音量 - - - - + + DeviceItem OnProHttpResponse 解析json文件错误! 解析json文件错误! @@ -2090,174 +653,174 @@ ControlVolumeSchedule - + Defalut volume tip - - + + Add 添加 - - + + Delete 删除 - - + + Clear - 清除 + 清空 - + Default Volume 默认音量 - + (0-15) - - + + Import 导入 - - + + Export 导出 - - + + Apply 应用 - + Readback 回读 - + Volume value 音量值 - + Start Time 开始时间 - + End Time 结束时间 - + SUN 星期日 - + MON 星期一 - + TUE 星期二 - + WED 星期三 - + THU 星期四 - + FRI 星期五 - + SAT 星期六 - + Default volume tip 提醒:定时时间段以外的时间显示屏为默认亮度 - + Default volume 默认音量值 - - + + DeviceItem OnProHttpResponse 解析json文件错误! 解析json文件错误! - + 10 10 - - + + Volume Schedule (*.vols) - + Save File 保存文件 - - + + Tip 提示 - - + + NoSelectedController 请先选择大屏幕 - + SetAutoVolumeTask 配置定时音量表 - - + + Success 成功 - - + + failed 失败 - + GetAutoVolumeTask 获取定时音量表 @@ -2265,1187 +828,2504 @@ ControlVolumeWidget - - Form - Form + + + Tip + 提示 - - + + + NoSelectedController + 请先选择大屏幕 + + + + + SetVolume + 音量调节 + + + + + GetVolume + 获取当前音量 + + + Volume Control 音量调节 - - + Manual 手动 - - + Schedule 定时 + + + Volume + 音量 + + + + Readback + 回读 + CtrlAdvancedPanel - - Advanced parameters + + Advanced 高级参数 - + Screen Width(pixel) 屏幕宽(像素) - + Width - - + + Height - - - - - - - + + + + + + + + + + + + + + + Set 设置 - + Alias 别名 - + Web Server Address: Web服务器地址: - + www.m2mled.net - + www.ledaips.com - + https://www.taxihub.cn:2340 - + https://www.ledaips.com:2340 - + https://www.36taxi.com:2340 - + www.tlzxled.com - + + MCU Uploading + 正在上传单片机 + + + + Traffic screen settings + 交通屏设置 + + + + Setting protocol ... + 正在设置协议 ... + + + + Set protocol + 设置协议 + + + + Getting protocol ... + 正在回读协议 ... + + + + Get protocol + 回读协议 + + + + + Port + 端口 + + + Realtimer Server Address: Realtimer地址: - + + Firmware Management + 固件管理 + + + + update or uninstall + 更新或卸载 + + + Clear - 清除 + 清空 - - Apk upgrade - Apk升级 - - - + Check Apk 检查Apk - + Uninstall 卸载 - + Running check 运行状态监测 - - FPGA version check - FPGA版本查询 - - - - Sync FPGA version - 同步FPGA版本 - - - - Restart led controller system + + Restart 重启 - + Check Log 查看日志 - + Start LedSet4 使用 LedSet4.0 配置LED模组(Apk Display2.0以上版本) - + Open ADB 打开ADB调试功能 - + Post Custom JSON Post Custom JSON - - - - - - - - + + + + + + + + Clear Program 清除节目 - + www.ledokcloud.com/realtime - - M80 configuration - M80配置 + + Config + 配置 - + Refresh 刷新 - + Restore to default 恢复默认值 - + Taxi top screen configuration 车顶有无客电平配置 - + + Service:High Out of service:Low 有客:高电平 无客:低电平 - + + Service:Low Out of service:High 有客:低电平 无客:高电平 - + Start LedSet3.0 configure LED module 使用LedSet3.0配置LED模组(厂家专业人员使用) - + Binding *.ic account indentity voucher 绑定taxihub平台用户身份凭证 - + Rotate 旋转 - - 0 degrees - 0度 - - - - 90 degrees - 90度 - - - - 180 degrees - 180度 - - - - 270 degrees - 270度 - - - + Min brightness 最低亮度 - - (min:1) - (最小:1) - - - - - + + + Readback 回读 - - - + Send 发送 - + Max brightness 最高亮度 - - (max:255) - (最高:255) - - - - + + SetScreenSize 设置屏幕像素尺寸 - - - - - - - - - - - - - - - - - - - - - - - - - + + + + Success 成功 - + Compant ID: 公司ID: - - FPGA Upgrade - FPGA升级 - - - + Compant ID 公司ID - + InputWebServerAddressTip 请输入Web服务器地址 - + InputCompanyIdTip 请输入公司ID - + Do you want to modify webserveraddress and companyId? 是否确认配置服务器地址和公司ID? - - - - - - - - - - - - - - - - - - - - - - failed - 失败 - - - - + + SetOnlineAddr 设置web服务器地址 - + + ClearRealtimeServer 清除 - - InputRealTimeAddressTip - 请输入RealTimer地址 - - - + + SetRealtimeServer 设置RealTimer地址 - - - - + + + + Tip Info 提示 - - - + + + Can not find LedSet3.0.exe,down you need download and install it 找不到LedSet3.0.exe,确认下载并安装 - + + RestartAndroid 重启 - - FPGA Version - FPGA版本 - - - - + + running 正在运行 - - + + no running 没有运行 - + Check Apk Version 查询已安装apk版本 - - + + UninstallSoftware 卸载 - - - IsSoftwareRunning + + + Check apk running status 监测APK运行状态 - - apk package (*.rpd) - - - - - CheckHardwareVersions - 查询FPGA版本 - - - - - - SynchronousHardwareVersion - 同步FPGA硬件版本 - - - - Check Screen untile fpga update finished - 观察屏幕升级进度直到升级成功 - - - + + OpenAdb 打开ADB调试功能 - + indentity voucher (*.ic) 身份凭证(*.ic) - - - - - + + + + + InvokeTaxiAppFunction 绑定证书 - - Json format is error! - - - - - + + AliIotSetting - - apk package (*.apk *.zip) - - - - + Software Version Info 软件版本信息 - + Package 包名 - + Version 版本 - - - UpgradeSoftware - 升级固件 - - - - This screen is encrypted,Please decrypt and upgrade APK! - 此屏幕已加密,请解密并升级APK! - - - - + + Package name is null 包名为空 - + Clearing Program 正在清除节目 - - - - + + + + Timeout 超时 - - - - + + + + Failed 失败 - + Getting Log 正在获取日志 - - - - - - - - - + + + + + + + + + + + Error 错误 - + + Setting Timing Reboot + 正在设置定时重启 + + + + Set Timing Reboot + 设置定时重启 + + + + Getting Timing Reboot + 正在获取定时重启 + + + + Get Timing Reboot + 获取定时重启 + + + + totalResolution + 包括行场数的分辨率 + + + + strCurDisplayResolution + 当前显示屏分辨率 + + + + File not exist + 文件不存在 + + + + Uploading + 正在上传 + + + + + Set Display Mode + 设置显示模式 + + + + + Get Display Mode + 获取显示模式 + + + + + Set Screen Offset + 设置屏幕偏移 + + + + + Get Screen Offset + 获取屏幕偏移 + + + Open file Failed 文件打开失败 - + Setting Wallpaper 正在设置系统桌面背景 - - + + Set Wallpaper 设置系统桌面背景 - + System Updating 系统升级中 - - + + System Update 系统升级 - + + Getting MCU Version + 正在获取单片机版本 + + + + + MCU Version + 单片机版本 + + + Select File 选择文件 - + Setting player background 正在设置播放器背景 - - + + Set player background 设置播放器背景 - + Clearing player background 正在清除播放器背景 - - - - - - - - + + + + + + + + Clear player background 清除播放器背景 - + Setting Baud Rate 正在设置波特率 - + Set Baud Rate 设置波特率 - + Getting Baud Rate 正在获取波特率 - + Get Baud Rate 获取波特率 - + + Text is empty + 文本为空 + + + + Json Parse Error + + + + + Json isn't an Object + + + + + Setting card work mode ... + 正在设置控制卡工作模式 ... + + + + Set card work mode + 设置控制卡工作模式 + + + + Getting card work mode ... + 正在回读控制卡工作模式 ... + + + + Get card work mode + 回读控制卡工作模式 + + + + Resolution Config + 分辨率配置 + + + + Full screen + 全屏 + + + + Part + 局部 + + + + Display Mode + 显示模式 + + + + Screen Position + 屏幕位置 + + + + Offset + 偏移 + + + Hidden Settings 隐藏的设置 - + Click right button to hide 点击右键隐藏 - + + + Update MCU + 更新单片机 + + + + Get MCU Version + 获取单片机版本 + + + Baud Config 波特率配置 - + Model 设备型号 - + Uart 串口节点 - + Baud 波特率 - + + + + + + Get 获取 - - - - + + Timing Reboot + 定时重启 + + + + Protocol + 协议 + + + + Server + 服务端 + + + + Client + 客户端 + + + + SetScreenRotation 设置屏幕旋转 - + + SetMinBrightness 设置最小的亮度值 - + + SetMaxBrightness 设置亮度最大值 - + + GetMinBrightness 获取亮度最小值 - + + GetMaxBrightness 获取亮度最大值 - + + + Card work mode + 控制卡工作模式 + + + + SetSpecialResolution 设置分辨率 - + + GetSpecialResolution 读取分辨率 - + + CleanDisplayScreenSize 恢复默认分辨率 - + + SetHighForBusy 设置有无客电平 - + + GetStateForBusy 获取有无客电平 - - install start... - 开始安装... - - - + InputAliasTip 请输入别名 - - + + SetCardAlias 设置别名 - - Uploadding - 上传 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Tip 提示 - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NoSelectedController 请先选择大屏幕 - + InputWidthTip 请输入正确的宽度像素值 - + InputHeightTip 请输入正确的高度像素值 - + Password is error 密码错误 - - - - - DeviceItem OnProHttpResponse 解析json文件错误! - 解析json文件错误! - CtrlBrightPanel - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + Tip 提示 - - - - - - - - - - - + + + + + + + + + + + NoSelectedController 请先选择大屏幕 - - + + SetBrightnessSensitivity 设置亮度传感器灵敏度 - - + + GetBrightnessSensitivity 获取亮度传感器灵敏度 - - + + SetMinBrightness 设置最小的亮度值 - - + + GetMinBrightness 获取亮度最小值 - - + + NeedSelectSensorTypeTip 请先选择传感器类型 - + Open file dialog 打开文件 - + Not found current worksheet 没找到当前工作表 - - + + SensorBrightnessTable 设置亮度传感器配置表 - + GetSensorBrightnessTable 获取传感器亮度配置表 - + no sensorBrightnessTable 控制卡没有发现亮度配置表 - + Save file 保存 - - + + GetCurrentSensorBrightness 获取当前亮度 - - + + SetBrightness 设置亮度 - + GetBrightness 获取亮度值 - + Brightness 屏体亮度 - + Import File 导入文件 - - + + BrightnessSchedule (*.bjs) - + Save File 保存文件 - + BrightnessValue 亮度值 - + Start Time 开始时间 - + End Time 结束时间 - - + + SetAutoBrightnessTask 发送定时亮度表 - + GetAutoBrightnessTask 获取定时亮度表 - - - - + + Error 错误 - + Brightness Configuration 亮度配置 - + Auto 自动 - + Manual 手动 - + Schedule 定时 - + + Adapt to Old Devices + 适配旧设备 + + + BrightTip1 如果最大亮度为64,则最小亮度可以配置为1%或适当的值;如果最大亮度为255,则最小亮度必须配置为36%或更高,否则亮度将很低。 - + BrightTip2 上传文件时,请确认选择正确的传感器类型,否则无效! - + Sensitivity 灵敏度 - + Minbrightness 最小亮度值 - - - + + + Set 设置 - + Upload 上传配置文件 - - - - + + + + Readback 回读 - + ReadbackTable 回读 - + Refresh 刷新 - + Cur Brigntness 当前亮度 - + Brightness value 亮度值 - + Default brightness 默认亮度 - + Add 添加 - + Clear 清空 - + Delete 删除 - + Import 导入 - + Export 导出 - + Apply 应用 - + Default brightness tip - 提示:该设定时间内为设定亮度,设定时间外为默认亮度。例如设定默认亮度为80,设定亮度为180,时间范围是8:00-17:00,则时间范围内亮度为180,其他时间内为默认亮度80! + 提示:时间范围内为设定亮度,时间范围外为默认亮度。例如默认亮度为50%,设定亮度为80%,时间范围是8:00-17:00,则时间范围内亮度为80%,其他时间为默认亮度50% + + + + CtrlHdmiPanel + + + HDMI Configuration + 画面输入源配置 + + + + Manual + 手动 + + + + Schedule + 定时 + + + + + + + Tip + 提示 + + + + + + + NoSelectedController + 请先选择大屏幕 + + + + + SyncSwitch + 切换同步模式 + + + + + AnSyncSwitch + 切换异步模式 + + + + IsSync + 回读同异步模式 + + + + Import File + 导入文件 + + + + Save File + 保存文件 + + + + + Sync Schedule + 同步定时任务 + + + + + SetTimingHdmiInTask + 设置同步模式定时任务 + + + + GetTimingHdmiInTask + 获取同步模式定时任务 + + + + + Async + 异步 + + + + + Readback + 回读 + + + + Start Time + 开始时间 + + + + End Time + 结束时间 + + + + SUN + 星期日 + + + + MON + 星期一 + + + + TUE + 星期二 + + + + WED + 星期三 + + + + THU + 星期四 + + + + FRI + 星期五 + + + + SAT + 星期六 + + + + Add + 添加 + + + + + Apply + 应用 + + + + Clear + 清空 + + + + Delete + 删除 + + + + Import + 导入 + + + + Export + 导出 + + + + By default, the asynchronous content is played, and the synchronous signal content is played in the fixed time period + 默认播放异步内容,定时时间段内播放同步HDMI-IN端口输入内容 + + + + CtrlNetworkPanel + + + Wire Enther(RJ45) Configuration + 有线网配置 + + + + DHCP + + + + + Specify IP + 指定IP + + + + IP Address + IP地址 + + + + Gateway + 网关 + + + + DNS Address + DNS地址 + + + + + + Set + 设置 + + + + + + + Readback + 回读 + + + + WIFI Configuration + WiFi配置 + + + + WiFi Mode + 使用WiFi + + + + Cellular Config + 蜂窝数据配置 + + + + Enable Cellular Data + 启用蜂窝数据 + + + + Get cellular network status information + 获取蜂窝网络状态信息 + + + + Through the check status button + 通过“获取状态”按钮可以自动匹配国家码,然后选择“运营商”可获取到相应的APN信息。 + + + + Set APN Info + 设置APN信息 + + + + Country ID(mcc): + 国家码(mcc): + + + + + Carrier Name + 运营商 + + + + APN(Required) + APN(必填) + + + + Flight Mode + 飞行模式 + + + + WiFi name + WiFi名称 + + + + + + Password + 密码 + + + + + Input password + 输入密码 + + + + Scan + 扫描 + + + + Ap Mode + 使用热点 + + + + OFF + + + + + ON + + + + + AP name + 热点名称 + + + + Subnet mask + 子网掩码 + + + + Input ap name + 输入AP名称 + + + + + + + + + + + + + + + Tip + 提示 + + + + + + + + + + + + + + NoSelectedController + 请先选择大屏幕 + + + + + SetEthernet + 设置有线网 + + + + + + + + + + + Attention + 注意 + + + + Please input IP address! + 请输入IP地址! + + + + Your IP Address is Invalid! + IP地址无效! + + + + Please input Mask address! + 请输入子网掩码地址! + + + + Your Mask Address is Invalid! + 掩码地址无效! + + + + Please input Gateway address! + 请输入网关地址! + + + + Your Gateway Address is Invalid! + 网关地址无效! + + + + Please input DNS address! + 请输入DNS地址! + + + + Your DNS Address is Invalid! + DNS地址无效! + + + + + GetEthernet + 获取有线网配置 + + + + DHCP IP + 动态DHCP IP + + + + STATIC IP + 静态IP + + + + + ConfigurationWiFi + 配置WiFi + + + + + IsPortableHotSpot + 获取热点和WiFi模式 + + + + GetWifiList + 扫描WiFi + + + + + ConfigurationHotSpot + 配置热点 + + + + success + 成功 + + + + WifiName + Wifi名称 + + + + ApName + 热点名称 + + + + + GetCurrentAPN + 获取APN信息 + + + + GetSIMStatus + 获取SIM状态 + + + + + SetAPN + 设置APN + + + + 状态: + 状态: + + + + 未知 + 未知 + + + + 锁定状态,需要用户的PIN码解锁 + 锁定状态,需要用户的PIN码解锁 + + + + 锁定状态,需要用户的PUK码解锁 + 锁定状态,需要用户的PUK码解锁 + + + + 锁定状态,需要网络的PIN码解锁 + 锁定状态,需要网络的PIN码解锁 + + + + 就绪 + 就绪 + + + + no checked sim card + 检测不到sim卡 + + + + 国家码: + 国家码: + + + + 号码: + 号码: + + + + 用户: + 用户: + + + + 信号: + 信号: + + + + 信号正常 + 信号正常 + + + + 不在服务区 + 不在服务区 + + + + 仅限紧急呼叫 + 仅限紧急呼叫 + + + + 射频已经关闭 + 射频已经关闭 + + + + 网络: + 网络: + + + + 网络类型未知 + 未知 + + + + GPRS网络 + GPRS + + + + EDGE网络 + EDGE + + + + UMTS网络 + UMTS + + + + CDMA网络,IS95A 或 IS95B. + CDM + + + + EVDO网络, revision 0. + EVDO,revision 0. + + + + EVDO网络, revision A. + EVDO,revision A. + + + + 1xRTT网络 + 1xRTT + + + + HSDPA网络 + HSDPA + + + + HSUPA网络 + HSUPA + + + + HSPA网络 + HSPA + + + + 漫游: + 漫游: + + + + Yes + + + + + No + + + + + 数据连接状态: + 数据连接状态: + + + + 断开 + 断开 + + + + 正在连接 + 正在连接 + + + + 已连接 + 已连接 + + + + 暂停 + 暂停 + + + + 数据活动休眠状态: + 数据活动休眠状态: + + + + 活动,但无数据发送和接收 + 活动,但无数据发送和接收 + + + + 活动,正在接收数据 + 活动,正在接收数据 + + + + 活动,正在发送数据 + 活动,正在发送数据 + + + + 活动,正在接收和发送数据 + 活动,正在接收和发送数据 + + + + 休眠状态 + 休眠状态 + + + + 信号强度: + + + + + User + 用户 + + + + Type + 类型 + + + + Server + 服务端 + + + + Port + 端口 + + + + Proxy + 代理 + + + + MMS Port + 彩信端口 + + + + MMS Proxy + 彩信代理 + + + + + SetSwitchSimData + 设置4G/5G开关 + + + + + ContrFlightMode + 配置飞行模式 + + + + + GetFlightModeState + 获取飞行模式状态 + + + + CtrlPwdPanel + + + Set Password + 安全配置 + + + + Original password + 原始密码 + + + + original password + 原始密码 + + + + + New password + 新密码 + + + + Repeat new password + 重复输入 + + + + + + + Set encryption + 加密 + + + + Cancel encryption + 取消加密 + + + + Enter again + 再次输入 + + + + + + + + + + + + Tip + 提示 + + + + + NoSelectedController + 请先选择大屏幕 + + + + + InputOriginalPasswordTip + 请输入原始密码 + + + + InputNewPasswordTip + 请输入新密码 + + + + InputRepeatPasswordTip + 请重复输入新密码 + + + + InputRepeatPasswordNotSameTip + 两次输入的密码不一致 + + + + Tip Info + 提示 + + + + After setting the password, please remember the password and record it. If you forget the password, the device will be unable to operate. Are you sure you want to continue with this operation? + 设置密码后,请记住密码并记录。如果忘记密码,设备将无法运行。确实要继续此操作吗? + + + + + + + SetControllerPassword + 设置加密 + + + + + Error + 错误 + + + + + Success + 成功 + + + + + + Modify password + 修改密码 + + + + + + + OriginalPasswordErrorTip + 原始密码错误 + + + + CtrlVerifyClockPanel + + + Verify Clock Configuration + 校准时间 + + + + + Verify to Computer time + 校准到计算机时间 + + + + Cur time of controller + LED显示屏设备当前时间 + + + + + LAN + 局域网 + + + + + + + + + + + + + + Tip + 提示 + + + + + + + + + + + + + + NoSelectedController + 请先选择大屏幕 + + + + screenSwitch + 开关屏 + + + + + + YES + + + + + + + NO + + + + + volume + 音量 + + + + brightness + 亮度 + + + + + identificationCode + 识别码 + + + + + delaySync + 时间偏移 + + + + + msec + 毫秒 + + + + + + + OtherSyncItem + 其他同步项 + + + + + + + lastSynchronousTime + 上次同步时间 + + + + checkNtpTime + 同步间隔 + + + + Lora identity + Lora身份 + + + + (min/time) + (分钟/次) + + + + identification code + 同步识别码 + + + + Time offset(msec) + 时间偏移(毫秒) + + + + Brightness + 屏体亮度 + + + + Volume + 音量 + + + + Screen on/off + 屏幕开关 + + + + + Slave + + + + + NTP Server + NTP服务器 + + + + + NTP Server address + NTP服务器地址 + + + + TimeZone + 时区 + + + + + + + + Set + 设置 + + + + Language: + 语言: + + + + Enable Synchronous playing + 使能同步画面功能 + + + + + Sync time interval + 同步时间间隔 + + + + + + + + Readback + 回读 + + + + + Master + + + + + Identification Code + 识别码 + + + + + SetNtpServer + 设置NTP服务 + + + + + MasterSwitch + 设置为主设备 + + + + + SlaveSwitch + 设置为从设备 + + + + IsMasterSlave + 回读主从身份 + + + + + GetControllerDate + 获取日期时间 + + + + + SetingSyncMethod + 设置同步方法 + + + + + SyncTime + 校准时间 + + + + + GetNtpServer + 获取NTP服务信息 + + + + + GetingSyncMethod + 获取同步方式 + + + + + SetTimezone + 设置时区 Def - - - + Connection Timeout 连接超时 - - - - - - - + + + + + Device replied 设备回复 - - + + + Success 成功 - - - - Error - 错误 - - - - Tip Info - 提示 - - - - + Fail 失败 @@ -3453,666 +3333,314 @@ DeviceCtrlPanel - - - + + + + Current Screen 当前屏幕 - - + + none - - + + Clear 清空 - - - single screen operation - 单屏操作 - - - + + Multi screen operation 多屏操作 - + + selected num 选中数目 - + Brightness Adjustment 亮度调节 - + Power Control 电源控制 - + Net Config 网络配置 - - Time Synchronization + + Time Sync 对时管理 - + Video source 同异步配置 - - Encrypt - 加密配置 + + Password + 设置密码 - - Advanced parameters + + Advanced 高级设置 - - Current Screen: - 当前屏幕: - - - + Test 测试 - - Volume Adjustment + + Volume Adj. 音量调节 DeviceItem - + GetScreenDetailInfo 更多信息 - + ReadbackPic 回读画面 - + Input password 输入密码 - + GetScreenshotFull 回读画面 - + cur brightness: 当前亮度: - + android version: 安卓版本: - + IMEI: - + HardWard Version: FPGA版本: - + MAX Brightness level: 亮度等级: - + Android OS Resolution: 安卓分辨率: - + Firmware Version: 固件版本: - + Player Version: 播放器固件版本: - + Detail Info 详细信息 - - - - - - - + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + receive 接收 - - SetScreenOn - 设置电源 - - - + AliIotSetting - - + + GetScreenStatus 获取屏幕状态 - - + + Status 状态 - + Tip Info 提示 - + password is wrong 密码错误 - + GetBrightness 获取亮度值 - - - + brightness 亮度 - - MasterSlaveSwitch - 配置主从身份 - - - - SetBrightness - 设置亮度 - - - - - SetMinBrightness - 设置最小的亮度值 - - - - GetBrightnessSensitivity - 获取亮度传感器灵敏度 - - - - sensitivity - 灵敏度 - - - - GetMinBrightness - 获取亮度最小值 - - - - SetSensorBrightnessTable - 配置传感器参数表 - - - - SetSwitchWiFi - 设置WiFi开关 - - - - ConfigurationWiFi - 配置WiFi - - - - ConfigurationHotSpot - 配置热点 - - - - GetSwitchWiFi - 获取WiFi状态 - - - + SetAutoBrightnessTask 发送定时亮度表 - + SetAutoVolumeTask 配置定时音量表 - + SetVolume 音量调节 - + GetVolume 获取当前音量 - + SetTimingScreenTask 设置屏幕定时开关任务 - - GetControllerDate - 获取日期时间 - - - - SetHighForBusy - 设置有无客电平 - - - - - GetStateForBusy - 获取有无客电平 - - - - Service:Low Out of service:High - 有客:低电平 无客:高电平 - - - - Service:High Out of service:Low - 有客:高电平 无客:低电平 - - - - - - IsPortableHotSpot - 获取热点和WiFi模式 - - - - WifiName - Wifi名称 - - - - ApName - 热点名称 - - - + TestScreen 测试屏幕 - + SetOnlineAddr 设置web服务器地址 - + SetRealtimeServer 设置RealTimer地址 - - GetOnlineAddr - 获取web服务器地址 - - - - GetRealtimeServer - 获取realtime服务器地址 - - - - SetNtpServer - 设置NTP服务 - - - - GetNtpServer - 获取NTP服务信息 - - - - SyncTime - 校准时间 - - - - DelPrograms - 清除节目 - - - - SetingSyncMethod - 设置同步方法 - - - + GetCurrentSensorBrightness 获取当前亮度 - + Cur brightness 当前亮度 - - SetSpecialResolution - 设置分辨率 - - - - GetSpecialResolution - 读取分辨率 - - - - totalResolution - 包括行场数的分辨率 - - - - strCurDisplayResolution - 当前显示屏分辨率 - - - - CleanDisplayScreenSize - 恢复默认分辨率 - - - - SetMaxBrightness - 设置亮度最大值 - - - - GetMaxBrightness - 获取亮度最大值 - - - - screenSwitch - 开关屏 - - - - - - YES - - - - - - - NO - - - - - LAN - 局域网 - - - + Connect 连接 - + timeout 超时 - + Anycast 点播 - - + volume 音量 - - - - - - - GetingSyncMethod - 获取同步方式 - - - - - identificationCode - 识别码 - - - - - delaySync - 时间偏移 - - - - - msec - 毫秒 - - - - - - - OtherSyncItem - 其他同步项 - - - - - - - lastSynchronousTime - 上次同步时间 - - - - checkNtpTime - 同步间隔 - - - - Uploadding - 上传 - - - + Success 成功 - + failed 失败 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + success 成功 - - - Lora identity - Lora身份 - - - - Master - - - - - Slave - - - - - SetBrightnessSensitivity - 设置亮度传感器灵敏度 - - - - - + + + on - - - + + + off @@ -4121,116 +3649,116 @@ DevicePanel - + All 总数 总数 - + Online 在线 在线 - - + + Refresh 刷新 刷新 - + Current Screen 当前屏幕 - + none - - - + + + Specify IP 指定IP 指定IP - + Specify IP list 指定IP列表 - + Search 搜索 - - + + Attention 注意 - - + + Please input IP address! 请输入IP地址! - + Cancel 取消 - + Screen ID 屏幕ID - + Screen IP 屏幕IP - + Screen Size 屏幕像素 - + Remark Name - 別名 + 别名 - + readback pic 回读画面 - + send 发送 - + More Info 详细信息 - + Cur Brightness 屏幕当前亮度 - + Power Status 屏幕开关状态 - + Security 加密 @@ -4407,39 +3935,156 @@ - EAudio + EAClock - + Basic Properties 基本属性 - - File - 文件 + + Time Zone + 时区 - + + Custom Dial + 自定义表盘 + + + + Select + 选择 + + + + Select Dail file + 选择表盘图片 + + + + Hour Mark + 时标 + + + + + Circular + 圆形 + + + + + Rectangle + 矩形 + + + + Number + 数字 + + + + + + T + + + + + Min Mark + 分标 + + + + Color + 颜色 + + + + Length + + + + + Width + + + + + Hour Hand + 时针 + + + + Min Hand + 分针 + + + + Sec Hand + 秒针 + + + + Show + 显示 + + + + Text + 文本 + + + Play Properties 播放方式 - + Play Duration 播放时长 - + + s + + + + + EAudio + + + Basic Properties + 基本属性 + + + + File + 文件 + + + + Play Properties + 播放方式 + + + + Play Duration + 播放时长 + + + Select File 选择文件 - + s - + Audio 音频 @@ -4447,233 +4092,373 @@ EBase - + Area 区域(px) - + X - + Y - + W - + H - + Border 边框 - - + + None - + Effect 特效 - + Rotate 旋转 - + Blink 闪烁 - + Speed 速度 - + Slow - + Moderate - + Fast - EEnviron + EDClock - - - - - - - - north - + + MON + 星期一 - - - - - - - - east - + + TUE + 星期二 - - - - - - - - south - + + WED + 星期三 - - - - - - - - west - 西 + + THU + 星期四 - - - Temperature - 温度 + + FRI + 星期五 - - - Humidity - 湿度 + + SAT + 星期六 - - - Noise - 噪音 + + SUN + 星期日 - - Wind Speed - 风速 + + + AM + 上午 - - Wind Direction - 风向 + + + PM + 下午 - + Basic Properties 基本属性 - - Title - 标题 + + Time Zone + 时区 - - Compensation - 补偿 + + Year + - - Wind speed - 风速 + + Month + - - Wind direction - 风向 + + Day + - - Left - 靠左 + + Hour + - - Center - 居中 + + Min. + - - Right - 靠右 + + Sec. + - - Single scroll - 单行滚动 + + Weekly + 星期 - - Speed - 速度 + + Full Year + 四位年 - - ms/pixel - 毫秒/像素 + + 12-Hour + 12小时制 - - Back Color - 背景色 + + Date Style + 日期风格 - + + Time Style + 时间风格 + + + + Display Style + 显示风格 + + + + Multiline + 多行显示 + + + Play Properties 播放方式 - - Refresh Cycle - 刷新周期 - - - - min. - 分钟 - - - + Play Duration 播放时长 - + + s + + + + + EEnviron + + + + + + + + + north + + + + + + + + + + + east + + + + + + + + + + + south + + + + + + + + + + + west + 西 + + + + + Temperature + 温度 + + + + + Humidity + 湿度 + + + + + Noise + 噪音 + + + + Wind Speed + 风速 + + + + Wind Direction + 风向 + + + + Basic Properties + 基本属性 + + + + Title + 标题 + + + + Compensation + 补偿 + + + + Wind speed + 风速 + + + + Wind direction + 风向 + + + + Left + 靠左 + + + + Center + 居中 + + + + Right + 靠右 + + + + Single scroll + 单行滚动 + + + + Speed + 速度 + + + + ms/pixel + 毫秒/像素 + + + + Back Color + 背景色 + + + + Play Properties + 播放方式 + + + + Refresh Cycle + 刷新周期 + + + + min. + 分钟 + + + + Play Duration + 播放时长 + + + s @@ -4681,37 +4466,37 @@ EGif - + Basic Properties 基本属性 - + File 文件 - + Select File 选择文件 - + Play Properties 播放方式 - + Play Duration 播放时长 - + s - + Play Times 播放次数 @@ -4719,73 +4504,73 @@ EMultiWin - + Please add media on the right 请在右边添加媒体,可以加入多个不同媒体,LED显示屏将按列表先后顺序播放 - + Media List 媒体列表 - - - + + + Text 文本 - - - + + + Photo 图片 - - - + + + Video 视频 - - - + + + Gif 动画 - - - + + + DClock 数字时钟 - - - + + + AClock 模拟时钟 - - - + + + Select File 选择文件 - - + + Environment 环境监测 - - + + Timer 计时器 @@ -4793,118 +4578,118 @@ EPhoto - + Basic Properties 基本属性 - + File 文件 - + Select File 选择文件 - + Image Read Error 图片读取错误 - + Play Properties 播放方式 - + Play Duration 播放时长 - - + + s - + Enter Style 入场特效 - + None - + Alpha_In 淡入 - + Moving to left 连续左移 - + Moving to right 连续右移 - + Moving to top 连续上移 - + Move to bottom 连续下移 - + Zoom in 放大 - + Zoom in to left_bottom 左下角放大 - + Zoom in to left_top 左上角放大 - + Zoom in to right_top 右上角放大 - + Zoom in to right bottom 右下角放大 - + Rotate to right 向右旋转 - + Rotate to left 向左旋转 - + Enter Duration 特效时长 - + Images (*.png *.jpg *.jpeg *.bmp) 图片(*.png *.jpg *.jpeg *.bmp) @@ -4912,191 +4697,191 @@ EText - + Enter your text 请输入内容 - + Basic Properties 基本属性 - - Font Color - 字体色 - - - + Back Color 背景色 - + Kerning 字间距 - + Line Spacing 行距 - + PageCount: 总页数: - + page - + Import txt File 导入 txt 文件 - + Select File 选择文件 - + Fail 失败 - + File Open Fail 文件打开失败 - + Play Properties 播放方式 - + Flip 翻页 - + Scroll 滚动 - + Static 静态 - - - + + + Play Duration 播放时长 - + Duration/Page 每页播放时长 - + Effect time 特效时长 - - + + Tip Info 提示 - - + + Effect time cannot be longer than duration time 特效时长不能大于播放时长 - + s - + + Text Color + 文字颜色 + + + + Colorful Text + 炫彩文字 + + + Entrance Effect 入场特效 - + no - + random 随机 - + right to left 连续左移 - + bottom to top 连续上移 - + left to right 连续右移 - + top to bottom 连续下移 - - Head-Tail Connected - 首尾相接 - - - + Head-Tail Spacing 首尾间隔 - + Scroll Style 滚动方向 - + Right -> Left 向左 - + Bottom -> Top 向上 - + Left -> Right 向右 - + Top -> Bottom 向下 - + Scroll Speed 滚动速度 @@ -5104,87 +4889,87 @@ ETimer - + day - + hour - + min - + sec - + Basic Properties 基本属性 - + Count Down 倒计时 - + Count Up 正计时 - + Time 目标时间 - + Day - + Hour - + Min - + Sec - + Multiline 多行显示 - + Text 文本 - + Play Properties 播放方式 - + Play Duration 播放时长 - + s @@ -5192,64 +4977,64 @@ EVideo - + Basic Properties 基本属性 - + File 文件 - + Play Properties 播放方式 - + Play Duration 播放时长 - + Select File 选择文件 - + s - + Play Times 播放次数 - + Video Transcoding 视频转码 - - + + Video Transcoding Progress 视频转码进度 - - + + Error 错误 - + Video 视频 - + Flash 动画 @@ -5257,17 +5042,17 @@ EWeb - + Basic Properties 基本属性 - + Play Duration 播放时长 - + s @@ -5295,10 +5080,93 @@ + + GenTmpThread + + + Preparing ... + 准备中... + + + + MON + 星期一 + + + + TUE + 星期二 + + + + WED + 星期三 + + + + THU + 星期四 + + + + FRI + 星期五 + + + + SAT + 星期六 + + + + SUN + 星期日 + + + + AM + 上午 + + + + PM + 下午 + + + + day + + + + + hour + + + + + min + + + + + sec + + + + + Create json ... + 生成json... + + + + Scan program ... + 扫描节目... + + LoColorSelector - + Transparent 透明 @@ -5341,186 +5209,230 @@ MainWindow - + Language 语言 - + Help 帮助 - - + + Check for updates 检查更新 - - + + firmware manager 固件管理 - - - Software Configuration + + + Software Config 软件配置 - - + + Info 信息 - - + + About 关于 - - + + Setting 设置 - + + Software Update + 软件更新 + + + + CurVersion + 当前版本 + + + + Update + 更新 + + + + LatestVersion: + 最新版本: + + + + + Update log: + 更新日志: + + + + The current version is already the latest version + 已经是最新的版本 + + + Device 设备管理 - + Program 节目管理 - + Control 终端控制 - + GuangYinPin 光影屏 - + Check card 一键找卡 - + Tip Info 提示 - + RestoreLedCardIpByUdpTip 该操作会把局域网内的所有与计算机IP不在同一网段的控制卡修复成固定IP,请谨慎操作! + + Net + + + Connection Timeout + 连接超时 + + + + Error + 错误 + + PageEditor - + Zoom In 放大 - + Zoom Out 缩小 - + Original size 原始比例 - + Delete the secect media 删除选中的媒体 - + Clear all media 清空所有媒体 - + Move layer up 向上一层(快捷键PgUp) - + Send backward 向下一层(快捷键PgDn) - + Bring to front 图层置顶(快捷键Home) - + Move to the bottom layer 图层置底(快捷键End) - + Fill the entire screen 全屏铺满 - + Fill the screen horizontally 水平铺满 - + Fill the screen vertically 垂直铺满 - + Align top 垂直靠顶 - + Center vertically 垂直居中 - + Bottom align 垂直靠底 - + Align left 水平靠左 - + Center horizontally 水平居中 - + Align right 水平靠右 - + Tip Info 提示 - + Clear all medias? 清除所有媒体? @@ -5528,79 +5440,84 @@ PageListItem - + times - + Page name 节目名称 - + New 新建 - + Play times 播放次数 - + + Sources Repeat + 素材循环 + + + Audios 音频 - + Total Dur 总时长 - - + + s - + Select File 选择文件 - + Duration 时长 - + Vol 音量 - + Valid Date 有效日期 - - + + Warning 警告 - + Start Time can't be later than End Time 开始时间不能晚于结束时间 - + End Time can't be earlier than Start Time 结束时间不能早于开始时间 - + Plan 时间计划表 @@ -5629,17 +5546,17 @@ PlayWin - + Move to Top Left 移动到左上角 - + Set Position 设置位置 - + Close 关闭 @@ -5647,12 +5564,12 @@ PlayerBackSendThread - + Open file failed 文件读取失败 - + Read file failed 文件读取失败 @@ -5673,47 +5590,47 @@ ProgCreateDlg - + Resolution 分辨率 - + Solution Information 节目信息 - + Solution Name 节目名称 - + Width - + Height - + Remarks 备注 - - 节目超宽需要打折, 请输入打折宽度 - + + 每段打折宽度 (用空格分隔) + - + OK 确认 - + Cancel 取消 @@ -5721,221 +5638,200 @@ ProgEditorWin - + Save 保存 - - + + Save as 另存为 - + Setting 设置 - + Text 文本 - + Photo 图片 - + Video 视频 - + Gif 动画 - + Clock 数字时钟 - + Analog Clock 模拟时钟 - + Environment 环境监测 - + Web 网页 - + MuliContentWindow 多素材窗口 - + In this window, a plurality of different program materials can be added and played according to the order of joining the list; 该窗口中可以加入多个不同是节目素材,并按照加入列表的先后顺序播放 - + Timer 计时器 - + Play 播放 - + Stop 停止 - + Publish 发布 - - - - + + + + Select File 选择文件 - + program 节目列表 - + Add page 添加页面 - + Copy page 复制页面 - + Delete page 删除页面 - - + + Tip Info 提示 - + Are you sure you want to delete this program page? 确定要删除该节目页吗? - + Move up 向上移动一个页面 - + Move down 向下移动一个页面 - + widget properties 组件属性 - + Page properties 节目属性 - + Do you want to save the modifications? 是否保存修改? - - + + Saving... 正在保存... - - + + Success 成功 - - + Save failed 保存失败 - + Convertering 整理数据中 - - Converter Successed - 整理成功 - - - - Converter TimeOut - 整理超时 - - - + Generate preview data 生成预览数据 - - Ready - 准备完毕 - - - - Generate TimeOut - 超时 - - - - + + Error 错误 - + Rename fail when saving 重命名文件夹失败 - + Remove Recursively fail when saving - + Warning 警告 @@ -5943,155 +5839,177 @@ ProgItem - - + + ExportButtonTip U盘播放 - - + + SendButtonTip 发布 - - + + Convertering 整理数据中 - - - USB Export Successed - U盘导出成功 - - - - USB Export TimeOut - U盘导出失败 - - - - Converter Successed - 整理成功 - - - - Converter TimeOut - 整理超时 - ProgPanel - - + + New 新建 - - + + Edit 编辑 - - + + Delete 删除 - - + + + Import 导入 - - + + + Export 导出 - - + + Send 发送 - - + + Publish 发布 - - + + Name 名称 - - + + + Choose Directory + 选择目录 + + + + Tip + 提示 + + + + The imported directory is already in the working directory, so there is no need to import it again! + 该导入的目录已经在工作目录下,无需再次导入! + + + + :solution(s) already exist.are you sure you want to overwrite the existing solution(s)? + :节目已存在。是否确实要覆盖现有节目? + + + + Play 播放 - - + + Stop 停止 - - + + Resolution 分辨率 - - + + File Size 文件大小 - - + + Last Modify 最后修改时间 - - + + Usb playback U盘更新 - + Program name conflicted 节目名称重复 - + Warning 警告 - + You will delete the selected solution(s),are you sure? 是否确认删除选中的节目? - + + Tip Info 提示 + + ProgPortDlg + + + Solution Name + 节目名称 + + + + Progress + 进度 + + + + Done + 完成 + + QObject - + Setting up the LedOK Express... 初始化LedOK Express... @@ -6099,18 +6017,18 @@ SendProgThread - - + + Program is empty 节目为空 - + Open file failed 文件打开失败 - + Read file failed 文件读取失败 @@ -6118,73 +6036,73 @@ SendProgramDialog - - + + Publish 发布 - + success info - + Refresh 刷新 - + Cancel 取消 - + Screen ID 屏幕ID - + Remark Name - 別名 + 别名 - + Online 在线 - + Screen IP 屏幕IP - + Screen Size 屏幕像素 - + Security 加密 - + Progress 进度 - + Remarks 备注 - + This screen is encrypted 屏幕已加密 - + All 总数 @@ -6192,12 +6110,12 @@ SoftConfigDialog - - Software Configuration + + Software Config 软件配置 - + Video compress to 视频压缩成 @@ -6207,200 +6125,31 @@ 视频转码成 - + Text antialiasing 文字反锯齿 - + TextAntilaTip (提示:该选项适合小间距大尺寸的屏幕,选中此项,文字边缘会有暗影已达到字体边缘光滑的效果;小尺寸屏幕和单双色屏幕不建议使用) - + GuangYinPin 光影屏 - + + Width Split + 超长屏打折 + + + OK 确认 - - SpecialDlg - - Specify IP - 指定IP - - - Search - 搜索 - - - Cancel - 取消 - - - Attention - 注意 - - - Please input IP address! - 请输入IP地址! - - - Your IP Address is Invalid! - IP地址无效! - - - Error - 错误 - - - - ThreadUpgradeApk - - - Uploadding - 正在上传 - - - - TipDialog - - - TextLabel - - - - - - OK - 确认 - - - - - Cancel - 取消 - - - - X - - - - - - Import - 导入 - - - - - Path - 路径 - - - - - : - - - - - - browse - 选择 - - - - You will delete the selected solution(s),are you sure? - 是否确认删除选中的节目? - - - - - Export - 导出 - - - - - Done - 完成 - - - - - Solution Name - 节目名称 - - - - - Progress - 进度 - - - - Delete - 删除 - - - - Select the network to connect to the device - 选择和LED控制卡直连的网络 - - - - Network name - 网络名称 - - - - - This operation will only set cable network to static IP,are you sure? - 此操作将设置选中的网络为固定IP,并自动配置直连的LED设备为同一网段的IP地址,是否确认? - - - - Do you want set IP of cable network to DHCP - 是否设置网络为通过DHCP自动获取IP - - - - - - - - Tip - 提示 - - - - - - Please select the network to connect to the Led controller - 请选择连接到LED控制器的网络 - - - - Choose Directory - 选择目录 - - - - The imported directory is already in the working directory, so there is no need to import it again! - 该导入的目录已经在工作目录下,无需再次导入! - - - - no find program can be imported - 没有找到可以导入的节目 - - UpdateLedset3Dialog @@ -6473,262 +6222,315 @@ 祝贺你!您正在运行最新版本的%1 - - UpdaterDialog - - - Software Update - 软件更新 - - - - X - X - - - - V1.0 - - - - - Update - 升级 - - - - CurVersion - 当前版本 - - - - LatestVersion: - 最新版本: - - - - - Update log: - 更新日志: - - - - The current version is already the latest version - 已经是最新的版本 - - UpgradeApkDialog - - - Upgrade apk - 升级apk + + Update APK + 更新APK - - 口 - - - - - X - - - - - + Select apk 选择Apk包 - - - - + Upgrade 升级 - - - APK: - - - - - + Uninstall 卸载 - - + check running state 检测运行状态 - - + Select Fpga 选择FPGA文件 - - - success info - + + Installing + 正在安装 - - + Refresh 刷新 - - + Cancel 取消 - + Screen ID 屏幕ID - + Remark Name - 別名 + 别名 - + Online 在线 - + Screen IP 屏幕IP - + Security 加密 - + Progress 进度 - + xixunplayer - + cardsystem - + taxiapp - + starter - + connection - + displayer - + FPGA FPGA - + update - + State 状态 - - - + + All 总数 - + + This screen is encrypted + 屏幕已加密 + + + + + Select Online APK + 选择在线APK + + + + No Files + 没有文件 + + + + Name + 名称 + + + + Size + 大小 + + + + Create Time + 创建时间 + + + + + + Tip + 提示 + + + + Is upgrading now. Please wait + 正在更新,请稍后 + + + + NoSelectedController + 请先选择大屏幕 + + + + + Downloading Online File + 正在下载在线文件 + + + + + Error + 错误 + + + + Online file is empty + 在线文件为空 + + + + Uploading + 正在上传 + + + + Upload error + 上传错误 + + + + Install error + 安装错误 + + + + Install success + 安装成功 + + + + Reminder + 提示 + + + + Reminder: Uninstalling this program may cause the device to offline, cannot be found, lost configs and have a black screen. Please uninstall with caution! + 提示:卸载此程序会导致平台掉线,找不到设备,配置参数丢失和黑屏问题,请谨慎卸载! + + + + Do you want to continue? + 是否继续? + + + + Uninstalling + 正在卸载 + + + + Uninstall error + 卸载错误 + + + + Uninstall success + 卸载成功 + + + + Check apk running status + 监测APK运行状态 + + + + Check error + 检查错误 + + + + Running + 正在运行 + + + + Not running + 没有运行 + + + The encrypted control card can be upgraded directly 加密控制卡可以直接升级 - - - apk package (*.rpd) - - - - - apk package (*.apk *.zip) - - UsbDetectDialog - + Usb upgrade program U盘更新节目 - + Password 密码 - + OK 确认 - + Input password 输入密码 - - + + Tip 提示 - + No checked USB device 未检查USB设备 - + please select usb device in list 请在列表中选择usb设备 - + Cancel 取消 @@ -6736,7 +6538,7 @@ WaitingDlg - + Success 成功 @@ -6765,331 +6567,6 @@ 取消 - - eAClock - - - Basic Properties - 基本属性 - - - - Time Zone - 时区 - - - - Custom Dial - 自定义表盘 - - - - Select - 选择 - - - - Select Dail file - 选择表盘图片 - - - - Hour Mark - 时标 - - - - - Circular - 圆形 - - - - - Rectangle - 矩形 - - - - Number - 数字 - - - - - - T - - - - - Min Mark - 分标 - - - - Hand Color - 指针颜色 - - - - H - - - - - M - - - - - S - - - - - Text - 文本 - - - - Play Properties - 播放方式 - - - - Play Duration - 播放时长 - - - - s - - - - - eDClock - - - MON - 星期一 - - - - TUE - 星期二 - - - - WED - 星期三 - - - - THU - 星期四 - - - - FRI - 星期五 - - - - SAT - 星期六 - - - - SUN - 星期日 - - - - - AM - 上午 - - - - - PM - 下午 - - - - Basic Properties - 基本属性 - - - - Time Zone - 时区 - - - - Year - - - - - Month - - - - - Day - - - - - Hour - - - - - Min. - - - - - Sec. - - - - - Weekly - 星期 - - - - Full Year - 四位年 - - - - 12-Hour - 12小时制 - - - - Date Style - 日期风格 - - - - Time Style - 时间风格 - - - - Display Style - 显示风格 - - - - Multiline - 多行显示 - - - - Play Properties - 播放方式 - - - - Play Duration - 播放时长 - - - - s - - - - - GenTmpThread - - - Preparing ... - 准备中... - - - - MON - 星期一 - - - - TUE - 星期二 - - - - WED - 星期三 - - - - THU - 星期四 - - - - FRI - 星期五 - - - - SAT - 星期六 - - - - SUN - 星期日 - - - - AM - 上午 - - - - PM - 下午 - - - - day - - - - - hour - - - - - min - - - - - sec - - - - - Create json ... - 生成json... - - - - Scan program ... - 扫描节目... - - mGuangYingPinWidget @@ -7494,68 +6971,55 @@ 串口打开失败 - - wExportProgramItem - - - Tip Info - 提示 - - - - :solution(s) already exist.are you sure you want to overwrite the existing solution(s)? - :节目已存在。是否确实要覆盖现有节目? - - wPlanItem - + Form Form - + 1 1 - + Every week: 每周: - + M - + Tu - + W - + Th - + F - + Sa - + Su @@ -7563,30 +7027,30 @@ wProgramPublishItem - + Input password 输入密码 - - - + + + Error 错误 - - + + Tip Info 提示 - + Fail 失败 - + password is wrong 密码错误 @@ -7594,92 +7058,24 @@ wUpgradeApkItem - + Input password 输入密码 - - uninstalling - 正在卸载 + + Error + 错误 - - - IsSoftwareRunning - 监测APK运行状态 - - - - - This screen is encrypted - 屏幕已加密 - - - - - Start upgrading - 开始升级 - - - - - Timeout - 超时 - - - - install start... - 开始安装... - - - - - SynchronousHardwareVersion - 同步FPGA - - - + Tip Info 提示 - + password is wrong 密码错误 - - - - UninstallSoftware - 卸载 - - - - - Success - 成功 - - - - Running - 正在运行 - - - - NoRunning - 没有运行 - - - - install success - 安装成功 - - - - - Fail - 失败 - diff --git a/LedOK/translations/app_zh_TW.ts b/LedOK/translations/app_zh_TW.ts index cf96b0f..e99ba53 100644 --- a/LedOK/translations/app_zh_TW.ts +++ b/LedOK/translations/app_zh_TW.ts @@ -71,2018 +71,581 @@ 密碼更改成功 - - ControlEncryptWidget - - - Form - Form - - - - - Entrypt Configuration - 安全配寘 - - - - Original password - 原始密碼 - - - - - - original password - 原始密碼 - - - - - - New password - 新密碼 - - - - - Repeat new password - 重複輸入 - - - - - - - Set encryption - 加密 - - - - - Cancel encryption - 取消加密 - - - - - Enter password - 輸入密碼 - - - - Enter again - 再次輸入 - - - - - - - - - Tip - 提示 - - - - NoSelectedController - 請先選擇大螢幕 - - - - - InputOriginalPasswordTip - 請輸入原始密碼 - - - - InputNewPasswordTip - 請輸入新密碼 - - - - InputRepeatPasswordTip - 請重複輸入新密碼 - - - - InputRepeatPasswordNotSameTip - 兩次輸入的密碼不一致 - - - - Tip Info - 提示 - - - - After setting the password, please remember the password and record it. If you forget the password, the device will be unable to operate. Are you sure you want to continue with this operation? - 設置密碼後,請記住密碼並記錄。如果忘記密碼,設備將無法運行。確實要繼續此操作嗎? - - - - - SetControllerPassword - 設定加密 - - - - Readback - 回讀 - - - - - - Success - 成功 - - - - - - failed - 失敗 - - - - - Modify password - 修改密碼 - - - - OriginalPasswordErrorTip - 原始密碼錯誤 - - - - ControlHdmiSchedule - - - Form - Form - - - - - Add - 添加 - - - - - Delete - 删除 - - - - - Clear - 清除 - - - - - Import - 導入 - - - - - Export - 匯出 - - - - By default, the asynchronous content is played, and the synchronous signal content is played in the fixed time period - 默認播放非同步內容,定時時間段內播放同步HDMI-IN埠輸入內容 - - - - - Apply - 應用 - - - - Readback - 回讀 - - - - SYNC HDMI - 同步模式 - - - - Start Time - 開始時間 - - - - End Time - 結束時間 - - - - SUN - 星期日 - - - - MON - 星期一 - - - - TUE - 星期二 - - - - WED - 星期三 - - - - THU - 星期四 - - - - FRI - 星期五 - - - - SAT - 星期六 - - - - - On - - - - - SyncSchedule (*.syncs) - - - - - Save File - 保存 - - - - Sync Schedule (*.syncs) - - - - - - Tip - 提示 - - - - - NoSelectedController - 請先選擇大螢幕 - - - - SetTimingHdmiInTask - 設定同步模式定時任務 - - - - GetTimingHdmiInTask - 獲取同步模式定時任務 - - - - - Success - 成功 - - - - - DeviceItem OnProHttpResponse 解析json文件错误! - DeviceItem OnProHttpResponse 解析json檔案錯誤! - - - - - failed - 失败 - - - - ControlHdmiWidget - - - HDMI Configuration - 畫面輸入源配寘 - - - - Manual - 手動 - - - - Schedule - 定時 - - - - - Tip - 提示 - - - - - NoSelectedController - 請先選擇大螢幕 - - - - - SyncSwitch - 切換同步模式 - - - - - AnSyncSwitch - 切換异步模式 - - - - - IsSync - 回讀同非同步模式 - - - - Error - 錯誤 - - - - HDMI IN - HDMI IN - - - - Async - BOX - - - - Readback - 回讀 - - - - ControlNetConfigWidget - - - Wire Enther(RJ45) Configuration - 有線網配寘 - - - - - DHCP - - - - - - Specify IP - 指定IP - - - - - IP Address - IP地址 - - - - Mask Address - 子網路遮罩 - - - - - Gateway - 閘道 - - - - - DNS Address - DNS地址 - - - - - - - - - - Set - 設定 - - - - - - - - - Readback - 回讀 - - - - - WIFI Configuration - WiFi配寘 - - - - - WiFi On/Off - WiFi使能 - - - - Input Ap name - 輸入熱點名稱 - - - - - 4G/5G Configuration - 蜂窩數據G配寘 - - - - - Open 4G/5G - 啟用蜂窩數據 - - - - APN: - - - - - - Get cellular network status information - 獲取蜂窩網絡狀態資訊 - - - - - Check SIM can automatically match to MCC, and then select carrier get apn param,if not found carrier,you can check the CUSTOM checkbox,then enter custom param. - 通過獲取狀態按鈕可以自動匹配國家碼MCC,然後選擇“運營商”可獲取到響應的APN資訊,如果找不到運營商,可以選中“自定義”核取方塊,然後手動輸入APN資訊。 - - - - - Readback APN Info - 回讀APN資訊 - - - - - Set Apn Info,Check SIM can automatically match to MCC, and then select carrier get apn param - 設定Apn資訊 - - - - - CUSTOM - 自定義 - - - - - Check SIM - 査詢SIM資訊 - - - - - - -> - - - - - - Country ID(mcc): - 国家码(mcc):國家碼(mcc): - - - - - Carrier Name - 運營商 - - - - - APN: - 運營商APN: - - - - - APN(Required) - APN(必填) - - - - - User: - 用戶名: - - - - - - - Not required - 非必填 - - - - - Password: - 密碼: - - - - Set Apn:iot.cargo - - - - - - Flight Mode - 飛行模式 - - - - - WiFi name - WiFi名稱 - - - - - - - Password - 密碼 - - - - - - - Input password - 輸入密碼 - - - - - Scan - 掃描 - - - - - Ap Mode - AP使能 - - - - Ap name - 熱點名稱 - - - - OFF - - - - - ON - - - - - AP name - 熱點名稱 - - - - Subnet mask - 子網路遮罩 - - - - Input ap name - 輸入AP名稱 - - - - - - - - - - - - - - - Success - 成功 - - - - - - - - - - - - - - - failed - 失敗 - - - - - - - Tip - 提示 - - - - - NoSelectedController - 請先選擇大螢幕 - - - - - SetEthernet - 設定有線網 - - - - - - - - - - - Attention - 注意 - - - - Please input IP address! - 請輸入IP地址! - - - - Your IP Address is Invalid! - IP地址無效! - - - - Please input Mask address! - 請輸入子網路遮罩地址! - - - - Your Mask Address is Invalid! - 遮罩地址無效! - - - - Please input Gateway address! - 請輸入閘道地址! - - - - Your Gateway Address is Invalid! - 閘道地址無效! - - - - Please input DNS address! - 請輸入DNS地址! - - - - Your DNS Address is Invalid! - DNS地址無效! - - - - - GetEthernet - 獲取有線網配寘 - - - - DHCP IP - 動態DHCP IP - - - - STATIC IP - 靜態IP - - - - Error - 錯誤 - - - - - - - - - SignalPower - 信號強度 - - - - - ConfigurationWiFi - 配寘WiFi - - - - IsPortableHotSpot - 獲取熱點和WiFi模式 - - - - GetWifiList - 掃描WiFi - - - - ConfigurationHotSpot - 配寘熱點 - - - - GetCurrentAPN - 獲取APN資訊 - - - - - GetSIMStatus - 獲取SIM狀態 - - - - SetAPN - 設定APN - - - - - DeviceItem OnProHttpResponse 解析json文件错误! - DeviceItem OnProHttpResponse 解析json檔案錯誤! - - - - 状态: - 狀態: - - - - 未知 - 未知 - - - - 锁定状态,需要用户的PIN码解锁 - 鎖定狀態,需要用戶的PIN碼解鎖 - - - - 锁定状态,需要用户的PUK码解锁 - 鎖定狀態,需要用戶的PUK碼解鎖 - - - - 锁定状态,需要网络的PIN码解锁 - 鎖定狀態,需要網絡的PIN碼解鎖 - - - - 就绪 - 就緒 - - - - no checked sim card - 檢測不到sim卡 - - - - 国家码: - 國家碼: - - - - 号码: - 號碼: - - - - 用户: - 用戶: - - - - 信号: - 信号: - - - - 信号正常 - 訊號正常 - - - - 不在服务区 - 不在服務區 - - - - 仅限紧急呼叫 - 僅限緊急呼叫 - - - - 射频已经关闭 - 射頻已經關閉 - - - - 网络: - 網絡: - - - - 网络类型未知 - 未知 - - - - GPRS网络 - GPRS - - - - EDGE网络 - EDGE - - - - UMTS网络 - UMTS - - - - CDMA网络,IS95A 或 IS95B. - CDM - - - - EVDO网络, revision 0. - EVDO,revision 0. - - - - EVDO网络, revision A. - EVDO,revision A. - - - - 1xRTT网络 - 1xRTT - - - - HSDPA网络 - HSDPA - - - - HSUPA网络 - HSUPA - - - - HSPA网络 - HSPA - - - - 漫游: - 漫遊: - - - - Yes - - - - - No - - - - - 数据连接状态: - 數據連接狀態: - - - - 断开 - 斷開 - - - - 正在连接 - 正在連接 - - - - 已连接 - 已連接 - - - - 暂停 - 暫停 - - - - 数据活动休眠状态: - 數據活動休眠狀態: - - - - 活动,但无数据发送和接收 - 活動,但無數據發送和接收 - - - - 活动,正在接收数据 - 活動,正在接收數據 - - - - 活动,正在发送数据 - 活動,正在發送數據 - - - - 活动,正在接收和发送数据 - 活動,正在接收和發送數據 - - - - 休眠状态 - 休眠狀態 - - - - 信号强度: - 信號強度: - - - - SetSwitchSimData - 設定4G/5G開關 - - - - ContrFlightMode - 配寘飛行模式 - - - - GetFlightModeState - 獲取飛行模式狀態 - - - - ControlPowerManual - - - Form - Form - - - - - POWER - 開關 - - - - - - Readback - 回讀 - - - - OFF - - - - - ON - - - - - - Tip - 提示 - - - - - NoSelectedController - 請先選擇大螢幕 - - - - IsScreenOn - 讀取開關狀態 - - - - - - SetScreenOn - 設定電源 - - - - - DeviceItem OnProHttpResponse 解析json文件错误! - DeviceItem OnProHttpResponse 解析json檔案錯誤! - - - - - - - Success - 成功 - - - - - on - - - - - - - - failed - 失敗 - - - - - off - - - - - - SetScreenOff - 配寘荧幕開關 - - ControlPowerSchedule - + Form Form - + Edit area 編輯區 - - + + Add 添加 - - + + Delete 删除 - - + + Clear - 清除 + 清空 - - + + Import 導入 - - + + Export 匯出 - + It is power off state outside the schedule time period 定時時間段內顯示幕開啟,其他時間段為關屏狀態 - + Send command 指令區 - - + + Apply 應用 - + Clear Schedule 清除定時 - + Readback 回讀 - + Power On State - 屏开关状态 + 屏開關狀態 - + Start Time 開始時間 - + End Time 結束時間 - + SUN 星期日 - + MON 星期一 - + TUE 星期二 - + WED 星期三 - + THU 星期四 - + FRI 星期五 - + SAT 星期六 - - + + On - + - - + + PowerSchedule (*.pjs) - 开关屏定时(*.pjs) + 開關屏定時(*.pjs) - + Save File 保存 - - - + + + Tip 提示 - - - + + + NoSelectedController 請先選擇大螢幕 - - + + Tip Info 提示 - - + + Clear schedule task? 取消計畫任務? - - + + CleanTimingScreenTask 取消計畫任務 - + SetTimingScreenTask - 设置屏幕定时开关任务 + 設定螢幕定時開關任務 - - - - + + + + Success 成功 - - + + DeviceItem OnProHttpResponse 解析json文件错误! DeviceItem OnProHttpResponse 解析json檔案錯誤! - - - - + + + + failed 失败 - + GetTimingScreenTask - 获取屏幕定时开关任务 + 獲取螢幕定時開關任務 ControlPowerWidget - - Form - Form + + + Off + - - + + + On + + + + + + Tip + 提示 + + + + + NoSelectedController + 請先選擇大螢幕 + + + + + SetScreenOn + 打開螢幕電源 + + + + + SetScreenOff + 關閉螢幕電源 + + + + + IsScreenOn + 讀取開關狀態 + + + Power Configuration - 开关屏控制 + 開關屏控制 - - + Manual - 手动 + 手動 - - + Schedule - 定时 + 定時 + + + + Power + 電源 + + + + Readback + 回讀 ControlTestWidget - + Form Form - - + + Test Screen - 測試荧幕 + 測試螢幕 - - + + Line test 線條測試 - - - - - - - + + + + + + + Red - - - - - - - + + + + + + + Green - - - - - - - + + + + + + + Blue - - - - - - - + + + + + + + White - - + + Vertical 豎線 - - + + Slash 斜線 - - - + + + Horizontal 橫線 - - - - + + + + Speed 速度 - - + + ms(>10) 毫秒(>10) - - + + Line Distance 線距 - + px px - - - - - + + + + + Test 測試 - - + + Gradation test 灰度測試 - - + + Only the gray value is displayed 只顯示顏色值 - + (>10) - - + + GrayValue 灰度值 - + (0-255) - - + + Color test 顏色測試 - - + + Gradient 漸變 - + 8 8 - + 2 2 - + 3 3 - + 6 6 - + 4 4 - + 5 5 - + 1 1 - + 9 9 - + 7 7 - + 0 0 - - + + Clear - 清除 + 清空 - - + + Reset 迴圈 - - - - + + + + Anycast 點播 - - + + Stop 停止 - - - - - - - - + + + + + + + + Tip 提示 - - - - - + + + + + NoSelectedController 請先選擇大螢幕 - - - + + + StartTest 開始測試 - - - - + + + + Success 成功 - - - - + + + + failed 失敗 - + StopTest 停止測試 - + loopback mode 迴圈模式 - + Connect timeout 連接超時 - + Reset loop mode 設定迴圈 - - + + success 成功 - - - DeviceItem OnProHttpResponse 解析json文件错误! - DeviceItem OnProHttpResponse 解析json檔案錯誤! - - - - CtrlVerifyClockPanel - - - Form - Form - - - - English - - - - - 中文 - - - - - Verify Clock Configuration - 校准时间 - - - - Verify to Computer time - 校准到计算机时间 - - - - - Cur time of controller - 顯示幕設備當前時間 - - - - LAN - 局域網 - - - - (min/time) - (分鐘/次) - - - - Sync identificationCode - 同步识别码 - - - - - identification code - 同步识别码 - - - - - Time offset(msec) - 时间偏移(毫秒) - - - - - Brightness - 屏体亮度 - - - - - Volume - 音量 - - - - - Screen on/off - 荧幕開關 - - - - - Slave - - - - - Master - - - - - - NTP Server - NTP服务器 - - - - - - - NTP Server address - NTP服务器地址 - - - - - - - TimeZone - 时区 - - - - - - - - - - - - - - - Set - 设置 - - - - - Language: - 語言: - - - - - Enable Synchronous playing - 使能同步画面功能 - - - - Lora - - - - - GPS - - - - - NTP - - - - - Time zone - 时区 - - - - - - - Sync time interval - 同步时间间隔 - - - - Verify clock configuration - 校准时间 - - - - - - - - - - - - - - Readback - 回讀 - - - - Master - - - - - Sync clock to computer time - 校準時鐘到電腦時間 - - - - Identification Code - 識別碼 - - - - - - - - - - - - - - Success - 成功 - - - - - - - - - - - - - - failed - 失败 - - - - SetNtpServer - 设置NTP服务 - - - - MasterSwitch - 設定為主設備 - - - - SlaveSwitch - 設定為從設備 - - - - IsMasterSlave - 回讀主從身份 - - - - GetControllerDate - 獲取日期時間 - - - - SetingSyncMethod - 設定同步方法 - - - - SyncTime - 校准时间 - - - - GetNtpServer - 获取NTP服务信息 - - - - GetingSyncMethod - 获取同步方式 - - - - - DeviceItem OnProHttpResponse 解析json文件错误! - DeviceItem OnProHttpResponse 解析json檔案錯誤! - - - - SetTimezone - 設定時區 - - - - ControlVolumeManual - - - Form - Form - - - - Volume(0-15) - 音量(0-15) - - - - - - Readback - 回讀 - - - - SetVolume - 音量調節 - - - - - - Success - 成功 - - - - - - failed - 失败 - - - - Volume(min:0-max:15) - 音量(最小值:0-最大值:15) - - - - GetVolume - 獲取當前音量 - - - - + + DeviceItem OnProHttpResponse 解析json文件错误! DeviceItem OnProHttpResponse 解析json檔案錯誤! @@ -2090,179 +653,179 @@ ControlVolumeSchedule - + Defalut volume tip 提醒:定時時間段內亮度按定時亮度顯示,其他沒有設定時間段為默認亮度值 - - + + Add 添加 - - + + Delete 删除 - - + + Clear - 清除 + 清空 - + Default Volume 默認音量 - + (0-15) - - + + Import 導入 - - + + Export 匯出 - - + + Apply 應用 - + Readback 回讀 - + Volume value 音量值 - + 開始時間 - + Start Time 開始時間 - + End Time 結束時間 - + SUN 星期日 - + MON 星期一 - + TUE 星期二 - + WED 星期三 - + THU 星期四 - + FRI 星期五 - + SAT 星期六 - + Default volume tip 提醒:定時時間段以外的時間顯示幕為默認亮度 - + Default volume 默認音量值 - - + + DeviceItem OnProHttpResponse 解析json文件错误! DeviceItem OnProHttpResponse 解析json檔案錯誤! - + 10 10 - - + + Volume Schedule (*.vols) - + Save File 保存 - - + + Tip 提示 - - + + NoSelectedController 請先選擇大螢幕 - + SetAutoVolumeTask 配寘定時音量表 - - + + Success 成功 - - + + failed 失敗 - + GetAutoVolumeTask 獲取定時音量表 @@ -2270,849 +833,1012 @@ ControlVolumeWidget - - Form - Form + + + Tip + 提示 - - + + + NoSelectedController + 請先選擇大螢幕 + + + + + SetVolume + 音量調節 + + + + + GetVolume + 獲取當前音量 + + + Volume Control 音量調節 - - + Manual 手動 - - + Schedule 定時 + + + Volume + 音量 + + + + Readback + 回讀 + CtrlAdvancedPanel - - Advanced parameters + + Advanced 高級參數 - + Screen Width(pixel) - 荧幕寬(點數) + 螢幕寬(點數) - + Width - - + + Height - - - - - - - + + + + + + + + + + + + + + + Set 設定 - + Alias 別名 - + Web Server Address: Web伺服器地址: - + www.m2mled.net - + www.ledaips.com - + https://www.taxihub.cn:2340 - + https://www.ledaips.com:2340 - + https://www.36taxi.com:2340 - + www.tlzxled.com - + + MCU Uploading + 正在上傳單片機 + + + + Traffic screen settings + 交通屏設定 + + + + Setting protocol ... + 正在設定協定 + + + + Set protocol + 設定協定 + + + + Getting protocol ... + 正在回讀協定 ... + + + + Get protocol + 回讀協定 + + + + + Port + + + + Realtimer Server Address: Realtimer地址: - + + Firmware Management + 固件管理 + + + + update or uninstall + 更新或卸載 + + + Clear - 清除 + 清空 - - Apk upgrade - Apk陞級 - - - + Check Apk 檢查Apk - + Uninstall 卸載 - + Running check 運行狀態監測 - - FPGA version check - FPGA版本査詢 - - - - Sync FPGA version - 同步FPGA版本 - - - - Restart led controller system + + Restart 重啓 - + Check Log 查看日誌 - + Start LedSet4 - + Open ADB 打開ADB調試功能 - + Post Custom JSON Post Custom JSON - - - - - - - - + + + + + + + + Clear Program 清除節目 - + www.ledokcloud.com/realtime - - M80 configuration - M80配寘 + + Config + 配寘 - + Refresh 檢測 - + Restore to default 恢復預設值 - + Taxi top screen configuration 車頂有無客電平配寘 - + + Service:High Out of service:Low 有客:高電平無客:低電平 - + + Service:Low Out of service:High 有客:低電平 無客:高電平 - + Start LedSet3.0 configure LED module 使用LedSet3.0配寘LED模組(廠家專業人員使用) - + Binding *.ic account indentity voucher 綁定taxihub平臺用戶身份憑證 - + Rotate 旋轉 - - 0 degrees - 0度 - - - - 90 degrees - 90度 - - - - 180 degrees - 10度 - - - - 270 degrees - 270度 - - - + Min brightness 最低亮度 - - (min:1) - (最小:1) - - - - - + + + Readback 回讀 - - - + Send 發送 - + Max brightness 最高亮度 - - (max:255) - (最高:255) - - - - + + SetScreenSize - 設定荧幕點數尺寸 + 設定螢幕點數尺寸 - - - - - - - - - - - - - - - - - - - - - - - - - + + + + Success 成功 - + Compant ID: 公司ID: - - FPGA Upgrade - FPGA陞級 - - - + Compant ID 公司ID - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NoSelectedController 請先選擇大螢幕 - + InputWebServerAddressTip 請輸入Web伺服器地址 - + InputCompanyIdTip 請輸入公司ID - + Do you want to modify webserveraddress and companyId? 是否確認配寘伺服器地址和公司ID? - - - - - - - - - - - - - - - - - - - - - - failed - 失敗 - - - - + + SetOnlineAddr 設定web伺服器地址 - + + ClearRealtimeServer 清除 - - InputRealTimeAddressTip - 請輸入RealTimer地址 - - - + + SetRealtimeServer 設定RealTimer地址 - - - - + + + + Tip Info 提示 - - - + + + Can not find LedSet3.0.exe,down you need download and install it 找不到LedSet3.0.exe,確認下載並安裝 - + + RestartAndroid 重啓 - - FPGA Version - FPGA版本 - - - - + + running 正在運行 - - + + no running 沒有運行 - + Check Apk Version 査詢已安裝apk版本 - - + + UninstallSoftware 卸載 - - - IsSoftwareRunning + + + Check apk running status 監測APK運行狀態 - - apk package (*.rpd) - - - - - CheckHardwareVersions - 査詢FPGA版本 - - - - - - SynchronousHardwareVersion - 同步FPGA硬體版本 - - - - Check Screen untile fpga update finished - 觀察荧幕陞級進度直到陞級成功 - - - + + OpenAdb 打開ADB調試功能 - + indentity voucher (*.ic) 身份憑證(*.ic) - - - - - + + + + + InvokeTaxiAppFunction 綁定證書 - - Json format is error! - - - - - + + AliIotSetting - - apk package (*.apk *.zip) - - - - + Software Version Info 軟體版本資訊 - + Package 包名 - + Version 版本 - - - UpgradeSoftware - 陞級固件 - - - - This screen is encrypted,Please decrypt and upgrade APK! - 此荧幕已加密,請解密並陞級APK! - - - - + + Package name is null 包名為空 - + Clearing Program 正在清除節目 - - - - + + + + Timeout 超時 - - - - + + + + Failed 失敗 - + Getting Log 讀取日誌 - - - - - - - - - + + + + + + + + + + + Error 錯誤 - + + Setting Timing Reboot + 正在設定定時重啓 + + + + Set Timing Reboot + 設定定時重啓 + + + + Getting Timing Reboot + 正在獲取定時重啓 + + + + Get Timing Reboot + 獲取定時重啓 + + + + totalResolution + 行数を含む解像度 + + + + strCurDisplayResolution + 當前顯示分辯率 + + + + File not exist + 檔案不存在 + + + + Uploading + 正在上傳 + + + + + Set Display Mode + 設定顯示模式 + + + + + Get Display Mode + 獲取顯示模式 + + + + + Set Screen Offset + 設定螢幕偏移 + + + + + Get Screen Offset + 獲取螢幕偏移 + + + Open file Failed 檔案打開失敗 - + Setting Wallpaper 正在設定系統桌面背景 - - + + Set Wallpaper 設定系統桌面背景 - + System Updating 系統升級中 - - + + System Update 系統升級 - + + Getting MCU Version + 正在獲取單片機版本 + + + + + MCU Version + 單片機版本 + + + Select File 選擇檔案 - + Setting player background 正在設定播放機背景 - - + + Set player background 設定播放機背景 - + Clearing player background 正在清除播放機背景 - - - - - - - - + + + + + + + + Clear player background 清除播放機背景 - + Setting Baud Rate 正在設定串列傳輸速率 - + Set Baud Rate 設定串列傳輸速率 - + Getting Baud Rate 正在讀取串列傳輸速率 - + Get Baud Rate 讀取串列傳輸速率 - + + Text is empty + + + + + Json Parse Error + + + + + Json isn't an Object + + + + + Setting card work mode ... + 正在設定控制卡工作模式 ... + + + + Set card work mode + 設定控制卡工作模式 + + + + Getting card work mode ... + 正在回讀控制卡工作模式 ... + + + + Get card work mode + 回讀控制卡工作模式 + + + + Resolution Config + 分辯率配寘 + + + + Full screen + 全屏 + + + + Part + 局部 + + + + Display Mode + 顯示模式 + + + + Screen Position + 螢幕位置 + + + + Offset + 偏移 + + + Hidden Settings 隱藏的設定 - + Click right button to hide 點擊右鍵隱藏 - + + + Update MCU + 更新單片機 + + + + Get MCU Version + 獲取單片機版本 + + + Baud Config 串列傳輸速率配寘 - + Model 設備型號 - + Uart 串口節點 - + Baud 串列傳輸速率 - + + + + + + Get 讀取 - - - - DeviceItem OnProHttpResponse 解析json文件错误! - DeviceItem OnProHttpResponse 解析json檔案錯誤! + + Timing Reboot + 定時重啓 - - - - + + Protocol + 協定 + + + + Server + 服務端 + + + + Client + 用戶端 + + + + SetScreenRotation - 設定荧幕旋轉 + 設定螢幕旋轉 - + + SetMinBrightness 設定最小的亮度值 - + + SetMaxBrightness 設定亮度最大值 - + + GetMinBrightness 獲取亮度最小值 - + + GetMaxBrightness 獲取亮度最大值 - + + + Card work mode + 控制卡工作模式 + + + + SetSpecialResolution 設定分辯率 - + + GetSpecialResolution 讀取分辯率 - + + CleanDisplayScreenSize 恢復默認分辯率 - + + SetHighForBusy 設定有無客電平 - + + GetStateForBusy 獲取有無客電平 - - install start... - 開始安裝… - - - + InputAliasTip 請輸入別名 - - + + SetCardAlias 設定別名 - - Uploadding - 上傳 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Tip 提示 - + InputWidthTip 請輸入正確的寬度點數值 - + InputHeightTip 請輸入正確的高度點數值 - + Password is error 密碼錯誤 @@ -3120,342 +1846,1496 @@ CtrlBrightPanel - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + Tip 提示 - - - - - - - - - - - + + + + + + + + + + + NoSelectedController 請先選擇大螢幕 - - + + SetBrightnessSensitivity 設定亮度感測器靈敏度 - - + + GetBrightnessSensitivity 獲取亮度感測器靈敏度 - - + + SetMinBrightness 設定最小的亮度值 - - + + GetMinBrightness 獲取亮度最小值 - - + + NeedSelectSensorTypeTip 請先選擇感測器類型 - + Open file dialog 打開文件 - + Not found current worksheet 沒找到當前工作表 - - + + SensorBrightnessTable 設定亮度感測器配寘錶 - + GetSensorBrightnessTable 獲取感測器亮度配寘錶 - + no sensorBrightnessTable 控制卡沒有發現亮度配寘錶 - + Save file 保存 - - + + GetCurrentSensorBrightness 獲取當前亮度 - - + + SetBrightness 設定亮度 - + GetBrightness 獲取亮度值 - + Brightness 屏体亮度 - + Import File 導入檔案 - - + + BrightnessSchedule (*.bjs) - + Save File 保存 - + BrightnessValue 亮度值 - + 開始時間 - + Start Time 開始時間 - + End Time 結束時間 - - + + SetAutoBrightnessTask 發送定時亮度錶 - + GetAutoBrightnessTask 獲取定時亮度錶 - - - - + + Error 錯誤 - + Brightness Configuration 亮度配寘 - + Auto 自動 - + Manual 手動 - + Schedule 定時 - + + Adapt to Old Devices + 適配舊設備 + + + BrightTip1 如果最大亮度為64,則最小亮度可以配寘為1%或適當的值;如果最大亮度為255,則最小亮度必須配寘為36%或更高,否則亮度將很低。 - + BrightTip2 上傳文件時,請確認選擇正確的感測器類型,否則無效! - + Sensitivity 靈敏度 - + Minbrightness 最小亮度值 - - - + + + Set 設定 - + Upload 上傳設定檔 - - - - + + + + Readback 回讀 - + ReadbackTable 回讀 - + Refresh 檢測 - + Cur Brigntness 當前亮度 - + Brightness value 亮度值 - + Default brightness 默認亮度 - + Add 添加 - + Clear 清空 - + Delete 删除 - + Import 導入 - + Export 匯出 - + Apply 應用 - + Default brightness tip - 提示:該設定時間內為設定亮度,設定時間外為默認亮度。例如設定默認亮度為80,設定亮度為180,時間範圍是8:00-17:00,則時間範圍內亮度為180,其他時間內為默認亮度80! + 提示:時間範圍內為設定亮度,時間範圍外為默認亮度。例如默認亮度為50%,設定亮度為80%,時間範圍是8:00-17:00,則時間範圍內亮度為80%,其他時間為默認亮度50% + + + + CtrlHdmiPanel + + + HDMI Configuration + 畫面輸入源配寘 + + + + Manual + 手動 + + + + Schedule + 定時 + + + + + + + Tip + 提示 + + + + + + + NoSelectedController + 請先選擇大螢幕 + + + + + SyncSwitch + 切換同步模式 + + + + + AnSyncSwitch + 切換異步模式 + + + + IsSync + 回讀同非同步模式 + + + + Import File + 導入檔案 + + + + Save File + 保存 + + + + + Sync Schedule + 同步定時任務 + + + + + SetTimingHdmiInTask + 設定同步模式定時任務 + + + + GetTimingHdmiInTask + 獲取同步模式定時任務 + + + + + Async + BOX + + + + + Readback + 回讀 + + + + Start Time + 開始時間 + + + + End Time + 結束時間 + + + + SUN + 星期日 + + + + MON + 星期一 + + + + TUE + 星期二 + + + + WED + 星期三 + + + + THU + 星期四 + + + + FRI + 星期五 + + + + SAT + 星期六 + + + + Add + 添加 + + + + + Apply + 應用 + + + + Clear + 清空 + + + + Delete + 删除 + + + + Import + 導入 + + + + Export + 匯出 + + + + By default, the asynchronous content is played, and the synchronous signal content is played in the fixed time period + 默認播放非同步內容,定時時間段內播放同步HDMI-IN埠輸入內容 + + + + CtrlNetworkPanel + + + Wire Enther(RJ45) Configuration + 有線網配寘 + + + + DHCP + + + + + Specify IP + 指定IP + + + + IP Address + IP地址 + + + + Gateway + 閘道 + + + + DNS Address + DNS地址 + + + + + + Set + 設定 + + + + + + + Readback + 回讀 + + + + WIFI Configuration + WiFi配寘 + + + + WiFi Mode + 使用WiFi + + + + Cellular Config + 蜂窩數據配寘 + + + + Enable Cellular Data + 啟用蜂窩數據 + + + + Get cellular network status information + 獲取蜂窩網絡狀態資訊 + + + + Through the check status button + 通過“獲取狀態”按鈕可以自動匹配國家碼,然後選擇“運營商”可獲取到相應的APN資訊。 + + + + Set APN Info + 設定APN資訊 + + + + Country ID(mcc): + 国家码(mcc):國家碼(mcc): + + + + + Carrier Name + 運營商 + + + + APN(Required) + APN(必填) + + + + Flight Mode + 飛行模式 + + + + WiFi name + WiFi名稱 + + + + + + Password + 密碼 + + + + + Input password + 輸入密碼 + + + + Scan + 掃描 + + + + Ap Mode + 使用熱點 + + + + OFF + + + + + ON + + + + + AP name + 熱點名稱 + + + + Subnet mask + 子網路遮罩 + + + + Input ap name + 輸入AP名稱 + + + + + + + + + + + + + + + Tip + 提示 + + + + + + + + + + + + + + NoSelectedController + 請先選擇大螢幕 + + + + + SetEthernet + 設定有線網 + + + + + + + + + + + Attention + 注意 + + + + Please input IP address! + 請輸入IP地址! + + + + Your IP Address is Invalid! + IP地址無效! + + + + Please input Mask address! + 請輸入子網路遮罩地址! + + + + Your Mask Address is Invalid! + 遮罩地址無效! + + + + Please input Gateway address! + 請輸入閘道地址! + + + + Your Gateway Address is Invalid! + 閘道地址無效! + + + + Please input DNS address! + 請輸入DNS地址! + + + + Your DNS Address is Invalid! + DNS地址無效! + + + + + GetEthernet + 獲取有線網配寘 + + + + DHCP IP + 動態DHCP IP + + + + STATIC IP + 靜態IP + + + + + ConfigurationWiFi + 配寘WiFi + + + + + IsPortableHotSpot + 獲取熱點和WiFi模式 + + + + GetWifiList + 掃描WiFi + + + + + ConfigurationHotSpot + 配寘熱點 + + + + success + 成功 + + + + WifiName + Wifi名稱 + + + + ApName + 熱點名稱 + + + + + GetCurrentAPN + 獲取APN資訊 + + + + GetSIMStatus + 獲取SIM狀態 + + + + + SetAPN + 設定APN + + + + 状态: + 狀態: + + + + 未知 + 未知 + + + + 锁定状态,需要用户的PIN码解锁 + 鎖定狀態,需要用戶的PIN碼解鎖 + + + + 锁定状态,需要用户的PUK码解锁 + 鎖定狀態,需要用戶的PUK碼解鎖 + + + + 锁定状态,需要网络的PIN码解锁 + 鎖定狀態,需要網絡的PIN碼解鎖 + + + + 就绪 + 就緒 + + + + no checked sim card + 檢測不到sim卡 + + + + 国家码: + 國家碼: + + + + 号码: + 號碼: + + + + 用户: + 用戶: + + + + 信号: + 信号: + + + + 信号正常 + 訊號正常 + + + + 不在服务区 + 不在服務區 + + + + 仅限紧急呼叫 + 僅限緊急呼叫 + + + + 射频已经关闭 + 射頻已經關閉 + + + + 网络: + 網絡: + + + + 网络类型未知 + 未知 + + + + GPRS网络 + GPRS + + + + EDGE网络 + EDGE + + + + UMTS网络 + UMTS + + + + CDMA网络,IS95A 或 IS95B. + CDM + + + + EVDO网络, revision 0. + EVDO,revision 0. + + + + EVDO网络, revision A. + EVDO,revision A. + + + + 1xRTT网络 + 1xRTT + + + + HSDPA网络 + HSDPA + + + + HSUPA网络 + HSUPA + + + + HSPA网络 + HSPA + + + + 漫游: + 漫遊: + + + + Yes + + + + + No + + + + + 数据连接状态: + 數據連接狀態: + + + + 断开 + 斷開 + + + + 正在连接 + 正在連接 + + + + 已连接 + 已連接 + + + + 暂停 + 暫停 + + + + 数据活动休眠状态: + 數據活動休眠狀態: + + + + 活动,但无数据发送和接收 + 活動,但無數據發送和接收 + + + + 活动,正在接收数据 + 活動,正在接收數據 + + + + 活动,正在发送数据 + 活動,正在發送數據 + + + + 活动,正在接收和发送数据 + 活動,正在接收和發送數據 + + + + 休眠状态 + 休眠狀態 + + + + 信号强度: + 信號強度: + + + + User + 用戶 + + + + Type + 型態 + + + + Server + 服務端 + + + + Port + + + + + Proxy + 代理 + + + + MMS Port + 彩信埠 + + + + MMS Proxy + 彩信代理 + + + + + SetSwitchSimData + 設定4G/5G開關 + + + + + ContrFlightMode + 配寘飛行模式 + + + + + GetFlightModeState + 獲取飛行模式狀態 + + + + CtrlPwdPanel + + + Set Password + 安全配寘 + + + + Original password + 原始密碼 + + + + original password + 原始密碼 + + + + + New password + 新密碼 + + + + Repeat new password + 重複輸入 + + + + + + + Set encryption + 加密 + + + + Cancel encryption + 取消加密 + + + + Enter again + 再次輸入 + + + + + + + + + + + + Tip + 提示 + + + + + NoSelectedController + 請先選擇大螢幕 + + + + + InputOriginalPasswordTip + 請輸入原始密碼 + + + + InputNewPasswordTip + 請輸入新密碼 + + + + InputRepeatPasswordTip + 請重複輸入新密碼 + + + + InputRepeatPasswordNotSameTip + 兩次輸入的密碼不一致 + + + + Tip Info + 提示 + + + + After setting the password, please remember the password and record it. If you forget the password, the device will be unable to operate. Are you sure you want to continue with this operation? + 設定密碼後,請記住密碼並記錄。如果忘記密碼,設備將無法運行。確實要繼續此操作嗎? + + + + + + + SetControllerPassword + 設定加密 + + + + + Error + 錯誤 + + + + + Success + 成功 + + + + + + Modify password + 修改密碼 + + + + + + + OriginalPasswordErrorTip + 原始密碼錯誤 + + + + CtrlVerifyClockPanel + + + Verify Clock Configuration + 校準時間 + + + + + Verify to Computer time + 校準到電腦時間 + + + + Cur time of controller + 顯示幕設備當前時間 + + + + + LAN + 局域網 + + + + + + + + + + + + + + Tip + 提示 + + + + + + + + + + + + + + NoSelectedController + 請先選擇大螢幕 + + + + screenSwitch + 開關屏 + + + + + + YES + + + + + + + NO + + + + + volume + 音量 + + + + brightness + 亮度 + + + + + identificationCode + 識別碼 + + + + + delaySync + 時間偏移 + + + + + msec + 毫秒 + + + + + + + OtherSyncItem + 其他同步項 + + + + + + + lastSynchronousTime + 上次同步時間 + + + + checkNtpTime + 同步間隔 + + + + Lora identity + Lora身份 + + + + (min/time) + (分鐘/次) + + + + identification code + 同步识别码 + + + + Time offset(msec) + 時間偏移(毫秒) + + + + Brightness + 屏体亮度 + + + + Volume + 音量 + + + + Screen on/off + 螢幕開關 + + + + + Slave + + + + + NTP Server + NTP服務器 + + + + + NTP Server address + NTP服務器地址 + + + + TimeZone + 時區 + + + + + + + + Set + 設定 + + + + Language: + 語言: + + + + Enable Synchronous playing + 使能同步画面功能 + + + + + Sync time interval + 同步時間間隔 + + + + + + + + Readback + 回讀 + + + + + Master + + + + + Identification Code + 識別碼 + + + + + SetNtpServer + 設定NTP服務 + + + + + MasterSwitch + 設定為主設備 + + + + + SlaveSwitch + 設定為從設備 + + + + IsMasterSlave + 回讀主從身份 + + + + + GetControllerDate + 獲取日期時間 + + + + + SetingSyncMethod + 設定同步方法 + + + + + SyncTime + 校準時間 + + + + + GetNtpServer + 獲取NTP服務資訊 + + + + + GetingSyncMethod + 獲取同步方式 + + + + + SetTimezone + 設定時區 Def - - - + Connection Timeout 連接超時 - - - - - - - + + + + + Device replied 設備回復 - - + + + Success 成功 - - - - Error - 錯誤 - - - - Tip Info - 提示 - - - - + Fail 失敗 @@ -3463,666 +3343,314 @@ DeviceCtrlPanel - - - + + + + Current Screen 当前屏幕 - - + + none - + - - + + Clear 清空 - - - single screen operation - 單屏操作 - - - + + Multi screen operation 多屏操作 - + + selected num 選中數目 - + Brightness Adjustment 亮度調節 - + Power Control 電源控制 - + Net Config 網絡配寘 - - Time Synchronization + + Time Sync 對時管理 - + Video source - 同异步配置 + 同異步配寘 - - Encrypt - 加密配寘 + + Password + 設寘密碼 - - Advanced parameters + + Advanced 高級設定 - - Current Screen: - 当前屏幕: - - - + Test 測試 - - Volume Adjustment + + Volume Adj. 音量調節 DeviceItem - + GetScreenDetailInfo 更多資訊 - + ReadbackPic 回讀畫面 - + Input password 輸入密碼 - + GetScreenshotFull 回讀畫面 - + cur brightness: 當前亮度: - + android version: 安卓版本: - + IMEI: - + HardWard Version: FPGA版本: - + MAX Brightness level: 亮度等級: - + Android OS Resolution: 安卓分辯率: - + Firmware Version: 固件版本: - + Player Version: 播放機固件版本: - + Detail Info 詳細資訊 - - - - - - - + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + receive 接收 - - SetScreenOn - 設定電源 - - - + AliIotSetting - - + + GetScreenStatus - 獲取荧幕狀態 + 獲取螢幕狀態 - - + + Status 狀態 - + Tip Info 提示 - + password is wrong 密碼錯誤 - + GetBrightness 獲取亮度值 - - - + brightness 亮度 - - MasterSlaveSwitch - 配寘主從身份 - - - - SetBrightness - 設定亮度 - - - - - SetMinBrightness - 設定最小的亮度值 - - - - GetBrightnessSensitivity - 獲取亮度感測器靈敏度 - - - - sensitivity - 靈敏度 - - - - GetMinBrightness - 獲取亮度最小值 - - - - SetSensorBrightnessTable - 配寘感測器參數表 - - - - SetSwitchWiFi - 設定WiFi開關 - - - - ConfigurationWiFi - 配寘WiFi - - - - ConfigurationHotSpot - 配寘熱點 - - - - GetSwitchWiFi - 獲取WiFi狀態 - - - + SetAutoBrightnessTask 發送定時亮度錶 - + SetAutoVolumeTask 配寘定時音量表 - + SetVolume 音量調節 - + GetVolume 獲取當前音量 - + SetTimingScreenTask - 設定荧幕定時開關任務 + 設定螢幕定時開關任務 - - GetControllerDate - 獲取日期時間 - - - - SetHighForBusy - 設定有無客電平 - - - - - GetStateForBusy - 獲取有無客電平 - - - - Service:Low Out of service:High - 有客:低電平 無客:高電平 - - - - Service:High Out of service:Low - 有客:高電平無客:低電平 - - - - - - IsPortableHotSpot - 獲取熱點和WiFi模式 - - - - WifiName - Wifi名稱 - - - - ApName - 熱點名稱 - - - + TestScreen - 測試荧幕 + 測試螢幕 - + SetOnlineAddr 設定web伺服器地址 - + SetRealtimeServer 設定RealTimer地址 - - GetOnlineAddr - 取得web伺服器地址 - - - - GetRealtimeServer - 獲取realtime伺服器地址 - - - - SetNtpServer - 設定NTP服務 - - - - GetNtpServer - 獲取NTP服務資訊 - - - - SyncTime - 校準時間 - - - - DelPrograms - 清除節目 - - - - SetingSyncMethod - 設定同步方法 - - - + GetCurrentSensorBrightness 獲取當前亮度 - + Cur brightness 當前亮度 - - SetSpecialResolution - 設定分辯率 - - - - GetSpecialResolution - 讀取分辯率 - - - - totalResolution - 行数を含む解像度 - - - - strCurDisplayResolution - 當前顯示分辯率 - - - - CleanDisplayScreenSize - 恢復默認分辯率 - - - - SetMaxBrightness - 設定亮度最大值 - - - - GetMaxBrightness - 獲取亮度最大值 - - - - screenSwitch - 開關屏 - - - - - - YES - - - - - - - NO - - - - - LAN - 局域網 - - - + Connect 連接 - + timeout 超時 - + Anycast 點播 - - + volume 音量 - - - - - - - GetingSyncMethod - 獲取同步管道 - - - - - identificationCode - 識別碼 - - - - - delaySync - 時間偏移 - - - - - msec - 毫秒 - - - - - - - OtherSyncItem - 其他同步項 - - - - - - - lastSynchronousTime - 上次同步時間 - - - - checkNtpTime - 同步間隔 - - - - Uploadding - 上傳 - - - + Success 成功 - + failed 失敗 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + success 成功 - - - Lora identity - Lora身份 - - - - Master - - - - - Slave - - - - - SetBrightnessSensitivity - 設定亮度感測器靈敏度 - - - - - + + + on - - - + + + off @@ -4131,114 +3659,114 @@ DevicePanel - + All 總數 - + Online 在线 線上 - - + + Refresh 檢測 - - - + + + Specify IP 指定IP 指定IP - + Current Screen 当前屏幕 - + none - + - + Specify IP list 指定IP清單 - + Search 蒐索 - - + + Attention 注意 - - + + Please input IP address! 請輸入IP地址! - + Cancel 取消 - - - Screen ID - 荧幕ID - - - - Screen IP - 荧幕IP - - - - Screen Size - 荧幕點數 - + Screen ID + 螢幕ID + + + + Screen IP + 螢幕IP + + + + Screen Size + 螢幕點數 + + + Remark Name 別名 - + readback pic 回讀畫面 - + send 發送 - + More Info 詳細資訊 - + Cur Brightness - 荧幕當前亮度 + 螢幕當前亮度 - + Power Status - 荧幕開關狀態 + 螢幕開關狀態 - + Security 加密 @@ -4271,7 +3799,7 @@ Open - 打开 + 打開 @@ -4283,7 +3811,7 @@ Time remaining - 剩余时间 + 剩餘時間 @@ -4313,7 +3841,7 @@ The installer will open separately - 安装程序将单独打开 + 安裝程式將單獨打開 @@ -4323,7 +3851,7 @@ In order to install the update, you may need to quit the application. This is a mandatory update, exiting now will close the application - 要安装更新,可能需要退出应用程序。这是强制更新,现在退出将关闭应用程序 + 要安裝更新,可能需要退出應用程序。 這是強制更新,現在退出將關閉應用程序 @@ -4333,17 +3861,17 @@ Click the "Open" button to apply the update - 单击“打开”按钮应用更新 + 按一下“打開”按鈕應用更新 Are you sure you want to cancel the download? - 您想现在下载更新吗? + 您想現在下載更新嗎? Are you sure you want to cancel the download? This is a mandatory update, exiting now will close the application - 确实要取消下载吗?这是强制更新,现在退出将关闭应用程序 + 確實要取消下載嗎? 這是強制更新,現在退出將關閉應用程序 @@ -4376,7 +3904,7 @@ Time Remaining - 剩余时间 + 剩餘時間 @@ -4386,22 +3914,22 @@ about %1 hours - 约%1小时 + 約%1小時 about one hour - 约1小时 + 約1小時 %1 minutes - %1 分钟 + %1 分鐘 1 minute - 1 分钟 + 1 分鐘 @@ -4415,39 +3943,156 @@ - EAudio + EAClock - + Basic Properties 基本屬性 - - File - 檔案 + + Time Zone + 時區 - + + Custom Dial + 自定義錶盤 + + + + Select + 選擇 + + + + Select Dail file + 選擇錶盤圖片 + + + + Hour Mark + 時標 + + + + + Circular + 圓形 + + + + + Rectangle + 矩形 + + + + Number + 數位 + + + + + + T + + + + + Min Mark + 分標 + + + + Color + 顏色 + + + + Length + + + + + Width + + + + + Hour Hand + 時針 + + + + Min Hand + 分針 + + + + Sec Hand + 分針 + + + + Show + 顯示 + + + + Text + 文字 + + + Play Properties 播放管道 - + Play Duration 播放時長 - + + s + + + + + EAudio + + + Basic Properties + 基本屬性 + + + + File + 檔案 + + + + Play Properties + 播放管道 + + + + Play Duration + 播放時長 + + + Select File 選擇檔案 - + s - + Audio 音訊 @@ -4455,233 +4100,373 @@ EBase - + Area 區域(px) - + X - + Y - + W - + H - + Border 邊框 - - + + None - + Effect 特效 - + Rotate 旋轉 - + Blink 閃爍 - + Speed 速度 - + Slow - + Moderate - + Fast - EEnviron + EDClock - - - - - - - - north - + + MON + 星期一 - - - - - - - - east - + + TUE + 星期二 - - - - - - - - south - + + WED + 星期三 - - - - - - - - west - 西 + + THU + 星期四 - - - Temperature - 溫度 + + FRI + 星期五 - - - Humidity - 濕度 + + SAT + 星期六 - - - Noise - 譟音 + + SUN + 星期日 - - Wind Speed - 風速 + + + AM + 上午 - - Wind Direction - 風向 + + + PM + 下午 - + Basic Properties 基本屬性 - - Title - 標題 + + Time Zone + 時區 - - Compensation - 補償 + + Year + - - Wind speed - 風速 + + Month + - - Wind direction - 風向 + + Day + - - Left - 靠左 + + Hour + - - Center - 居中 + + Min. + - - Right - 靠右 + + Sec. + - - Single scroll - 單行滾動 + + Weekly + 星期 - - Speed - 速度 + + Full Year + 四位年 - - ms/pixel - 毫秒/點數 + + 12-Hour + 12小時制 - - Back Color - 背景色 + + Date Style + 日期風格 - + + Time Style + 時間風格 + + + + Display Style + 顯示風格 + + + + Multiline + 多行顯示 + + + Play Properties 播放管道 - - Refresh Cycle - 重繪週期 - - - - min. - 分鐘 - - - + Play Duration 播放時長 - + + s + + + + + EEnviron + + + + + + + + + north + + + + + + + + + + + east + + + + + + + + + + + south + + + + + + + + + + + west + 西 + + + + + Temperature + 溫度 + + + + + Humidity + 濕度 + + + + + Noise + 譟音 + + + + Wind Speed + 風速 + + + + Wind Direction + 風向 + + + + Basic Properties + 基本屬性 + + + + Title + 標題 + + + + Compensation + 補償 + + + + Wind speed + 風速 + + + + Wind direction + 風向 + + + + Left + 靠左 + + + + Center + 居中 + + + + Right + 靠右 + + + + Single scroll + 單行滾動 + + + + Speed + 速度 + + + + ms/pixel + 毫秒/點數 + + + + Back Color + 背景色 + + + + Play Properties + 播放管道 + + + + Refresh Cycle + 重繪週期 + + + + min. + 分鐘 + + + + Play Duration + 播放時長 + + + s @@ -4689,37 +4474,37 @@ EGif - + Basic Properties 基本屬性 - + File 檔案 - + Select File 選擇檔案 - + Play Properties 播放管道 - + Play Duration 播放時長 - + s - + Play Times 播放次數 @@ -4727,73 +4512,73 @@ EMultiWin - + Please add media on the right 請在右邊添加媒體,可以加入多個不同媒體,LED顯示幕將按清單先後順序播放 - + Media List 媒體清單 - - - + + + Text 文字 - - - + + + Photo 圖片 - - - + + + Video 視頻 - - - + + + Gif 動畫 - - - + + + DClock 數位時鐘 - - - + + + AClock 圓形時鐘 - - - + + + Select File 選擇檔案 - - + + Environment 環境監測 - - + + Timer 計時器 @@ -4801,118 +4586,118 @@ EPhoto - + Basic Properties 基本屬性 - + File 檔案 - + Select File 選擇檔案 - + Image Read Error 圖片讀取錯誤 - + Play Properties 播放管道 - + Play Duration 播放時長 - - + + s - + Enter Style 入場特效 - + None - + Alpha_In 淡入 - + Moving to left 連續左移 - + Moving to right 連續右移 - + Moving to top 連續上移 - + Move to bottom 連續下移 - + Zoom in 放大 - + Zoom in to left_bottom 左下角放大 - + Zoom in to left_top 左上角放大 - + Zoom in to right_top 右上角放大 - + Zoom in to right bottom 右下角放大 - + Rotate to right 向右旋轉 - + Rotate to left 向左旋轉 - + Enter Duration 特效時長 - + Images (*.png *.jpg *.jpeg *.bmp) 圖片(*.png *.jpg *.jpeg *.bmp) @@ -4920,191 +4705,191 @@ EText - + Enter your text 請輸入內容 - + Basic Properties 基本屬性 - - Font Color - 字體色 - - - + Back Color 背景色 - + Kerning 字間距 - + Line Spacing 行距 - + PageCount: 總頁數: - + page - + Import txt File 導入 txt 檔案 - + Select File 選擇檔案 - + Fail 失敗 - + File Open Fail 檔案打開失敗 - + Play Properties 播放管道 - + Flip 翻頁 - + Scroll 滾動 - + Static 靜態 - - - + + + Play Duration 播放時長 - + Duration/Page 每頁播放時長 - + Effect time 特效時長 - - + + Tip Info 提示 - - + + Effect time cannot be longer than duration time 特效時長不能大於播放時長 - + s - + + Text Color + 文字顏色 + + + + Colorful Text + 炫彩文字 + + + Entrance Effect 入場特效 - + no - + random 隨機 - + right to left 連續左移 - + bottom to top 連續上移 - + left to right 連續右移 - + top to bottom 連續下移 - - Head-Tail Connected - 首尾相接 - - - + Head-Tail Spacing 首尾間隔 - + Scroll Style 滾動方向 - + Right -> Left 向左 - + Bottom -> Top 向上 - + Left -> Right 向右 - + Top -> Bottom 向下 - + Scroll Speed 滾動速度 @@ -5112,87 +4897,87 @@ ETimer - + day - + hour - + min - + sec - + Basic Properties 基本屬性 - + Count Down 倒數計時 - + Count Up 正計時 - + Time 目標時間 - + Day - + Hour - + Min - + Sec - + Multiline 多行顯示 - + Text 文字 - + Play Properties 播放管道 - + Play Duration 播放時長 - + s @@ -5200,64 +4985,64 @@ EVideo - + Basic Properties 基本屬性 - + File 檔案 - + Play Properties 播放管道 - + Play Duration 播放時長 - + Select File 選擇檔案 - + s - + Play Times 播放次數 - + Video Transcoding - - + + Video Transcoding Progress 視頻轉碼進度 - - + + Error 錯誤 - + Video 視頻 - + Flash 動畫 @@ -5265,17 +5050,17 @@ EWeb - + Basic Properties 基本屬性 - + Play Duration 播放時長 - + s @@ -5303,10 +5088,93 @@ + + GenTmpThread + + + Preparing ... + 準備中… + + + + MON + 星期一 + + + + TUE + 星期二 + + + + WED + 星期三 + + + + THU + 星期四 + + + + FRI + 星期五 + + + + SAT + 星期六 + + + + SUN + 星期日 + + + + AM + 上午 + + + + PM + 下午 + + + + day + + + + + hour + + + + + min + + + + + sec + + + + + Create json ... + 生成json… + + + + Scan program ... + 掃描節目… + + LoColorSelector - + Transparent 透明 @@ -5349,186 +5217,230 @@ MainWindow - + Language 語言 - + Help 幫助 - - + + Check for updates 檢查更新 - - + + firmware manager 固件管理 - - - Software Configuration + + + Software Config 軟件配寘 - - + + Info 資訊 - - + + About 關於 - - + + Setting 設定 - + + Software Update + 軟體更新 + + + + CurVersion + 當前版本 + + + + Update + 更新 + + + + LatestVersion: + 最新版本: + + + + + Update log: + 更新日誌: + + + + The current version is already the latest version + 已經是最新的版本 + + + Device 設備管理 - + Program 節目管理 - + Control 終端控制 - + GuangYinPin 光影屏 - + Check card - 一键找卡 + 一鍵找卡 - + Tip Info 提示 - + RestoreLedCardIpByUdpTip 該操作會把局域網內的所有與電腦IP不在同一網段的控制卡修復成固定IP,請謹慎操作! + + Net + + + Connection Timeout + 連接超時 + + + + Error + 錯誤 + + PageEditor - + Zoom In 放大 - + Zoom Out 縮小 - + Original size 原始比例 - + Delete the secect media 删除選中的媒體 - + Clear all media 清空所有媒體 - + Move layer up 向上一層(快速鍵PgUp) - + Send backward 向下一層(快速鍵PgDn) - + Bring to front 圖層置頂(快速鍵Home) - + Move to the bottom layer 圖層置底(快速鍵End) - + Fill the entire screen 全屏鋪滿 - + Fill the screen horizontally 水准鋪滿 - + Fill the screen vertically 垂直鋪滿 - + Align top 垂直靠頂 - + Center vertically 垂直居中 - + Bottom align 垂直靠底 - + Align left 水准靠左 - + Center horizontally 水准居中 - + Align right 水准靠右 - + Tip Info 提示 - + Clear all medias? 清除所有媒體? @@ -5536,79 +5448,84 @@ PageListItem - + times - + Page name 節目名稱 - + New 新建 - + Play times 播放次數 - + + Sources Repeat + 素材迴圈 + + + Audios 音訊 - + Total Dur 總時長 - - + + s - + Select File 選擇檔案 - + Duration 時長 - + Vol 音量 - + Valid Date 有效日期 - - + + Warning 警告 - + Start Time can't be later than End Time 開始時間不能晚於結束時間 - + End Time can't be earlier than Start Time 結束時間不能早於開始時間 - + Plan 時間計畫表 @@ -5637,17 +5554,17 @@ PlayWin - + Move to Top Left 移動到左上角 - + Set Position 設定位置 - + Close 關閉 @@ -5655,12 +5572,12 @@ PlayerBackSendThread - + Open file failed 檔案打開失敗 - + Read file failed 檔案讀取失敗 @@ -5681,47 +5598,47 @@ ProgCreateDlg - + Resolution 分辯率 - + Solution Information 節目資訊 - + Solution Name 節目名稱 - + Width - + Height - + Remarks 備註 - - 节目超宽需要打折, 请输入打折宽度 - + + 每段打折宽度 (用空格分隔) + 每段讓利寬度(用空格分隔) - + OK 確認 - + Cancel 取消 @@ -5729,221 +5646,200 @@ ProgEditorWin - + Save 保存 - - + + Save as 另存為 - + Setting 設定 - + Text 文字 - + Photo 圖片 - + Video 視頻 - + Gif 動畫 - + Clock 數位時鐘 - + Analog Clock 圓形時鐘 - + Environment 環境監測 - + Web 網頁 - + MuliContentWindow 多素材視窗 - + In this window, a plurality of different program materials can be added and played according to the order of joining the list; 該視窗中可以加入多個不同是節目素材,並按照加入列表的先後順序播放 - + Timer 計時器 - + Play 播放 - + Stop 停止 - + Publish 發佈 - - - - + + + + Select File 選擇檔案 - + program 節目清單 - + Add page 添加頁面 - + Copy page 複製頁面 - + Delete page 删除頁面 - - + + Tip Info 提示 - + Are you sure you want to delete this program page? 確定要删除該節目頁嗎? - + Move up 向上移動一個頁面 - + Move down 向下移動一個頁面 - + widget properties 組件内容 - + Page properties 節目内容 - + Do you want to save the modifications? 是否保存修改? - - + + Saving... 正在保存… - - + + Success 成功 - - + Save failed 保存失敗 - + Convertering 整理數據中 - - Converter Successed - 整理成功 - - - - Converter TimeOut - 整理超時 - - - + Generate preview data 生成預覽數據 - - Ready - 準備完畢 - - - - Generate TimeOut - 超時 - - - - + + Error 錯誤 - + Rename fail when saving - + Remove Recursively fail when saving - + Warning 警告 @@ -5951,155 +5847,177 @@ ProgItem - - + + ExportButtonTip U盤播放 - - + + SendButtonTip 發佈 - - + + Convertering 整理數據中 - - - USB Export Successed - U盤匯出成功 - - - - USB Export TimeOut - U盤匯出失敗 - - - - Converter Successed - 整理成功 - - - - Converter TimeOut - 整理超時 - ProgPanel - - + + New 新建 - - + + Edit 編輯 - - + + Delete 删除 - - + + + Import 導入 - - + + + Export 匯出 - - + + Send 發送 - - + + Publish 發佈 - - + + Name 名稱 - - + + + Choose Directory + 選擇目錄 + + + + Tip + 提示 + + + + The imported directory is already in the working directory, so there is no need to import it again! + 該導入的目錄已經在工作目錄下,無需再次導入! + + + + :solution(s) already exist.are you sure you want to overwrite the existing solution(s)? + :節目已存在。是否確實要覆蓋現有節目? + + + + Play 播放 - - + + Stop 停止 - - + + Resolution 分辯率 - - + + File Size 文件大小 - - + + Last Modify 最後修改時間 - - + + Usb playback U盤更新 - + Program name conflicted 節目名稱重複 - + Warning 警告 - + You will delete the selected solution(s),are you sure? 是否確認删除選中的節目? - + + Tip Info 提示 + + ProgPortDlg + + + Solution Name + 節目名稱 + + + + Progress + 進度 + + + + Done + 完成 + + QObject - + Setting up the LedOK Express... 初始化LedOK Express… @@ -6107,18 +6025,18 @@ SendProgThread - - + + Program is empty 節目為空 - + Open file failed 檔案打開失敗 - + Read file failed 檔案讀取失敗 @@ -6126,73 +6044,73 @@ SendProgramDialog - - + + Publish 發佈 - + success info - + Refresh 檢測 - + Cancel 取消 - + Screen ID - 荧幕ID + 螢幕ID - + Remark Name 別名 - + Online 線上 - + Screen IP - 荧幕IP + 螢幕IP - + Screen Size - 荧幕點數 + 螢幕點數 - + Security 加密 - + Progress 進度 - + Remarks 備註 - + This screen is encrypted - 荧幕已加密 + 螢幕已加密 - + All 總數 @@ -6200,12 +6118,12 @@ SoftConfigDialog - - Software Configuration + + Software Config 軟件配寘 - + Video compress to 視頻壓縮成 @@ -6215,200 +6133,31 @@ 視頻轉碼成 - + Text antialiasing 文字反鋸齒 - + TextAntilaTip - (提示:該選項適合小間距大尺寸的荧幕,選中此項,文字邊緣會有暗影已達到字體邊緣光滑的效果;小尺寸荧幕和單雙色荧幕不建議使用) + (提示:該選項適合小間距大尺寸的螢幕,選中此項,文字邊緣會有暗影已達到字體邊緣光滑的效果;小尺寸螢幕和單雙色螢幕不建議使用) - + GuangYinPin 光影屏 - + + Width Split + 超長屏打折 + + + OK 確認 - - SpecialDlg - - Specify IP - 指定IP - - - Search - 蒐索 - - - Cancel - 取消 - - - Attention - 注意 - - - Please input IP address! - 請輸入IP地址! - - - Your IP Address is Invalid! - IP地址無效! - - - Error - 錯誤 - - - - ThreadUpgradeApk - - - Uploadding - 正在上傳 - - - - TipDialog - - - TextLabel - - - - - - OK - 確認 - - - - - Cancel - 取消 - - - - X - X - - - - - Import - 導入 - - - - - Path - 路徑 - - - - - : - - - - - - browse - 選擇 - - - - You will delete the selected solution(s),are you sure? - 是否確認删除選中的節目? - - - - - Export - 匯出 - - - - - Done - 完成 - - - - - Solution Name - 節目名稱 - - - - - Progress - 進度 - - - - Delete - 删除 - - - - Select the network to connect to the device - 選擇和LED控制卡直連的網絡 - - - - Network name - 網絡名稱 - - - - - This operation will only set cable network to static IP,are you sure? - 此操作將設定選中的網絡為固定IP,並自動配寘直連的LED設備為同一網段的IP地址,是否確認? - - - - Do you want set IP of cable network to DHCP - 是否設定網絡為通過DHCP自動獲取IP - - - - - - - - Tip - 提示 - - - - - - Please select the network to connect to the Led controller - 請選擇連接到LED控制器的網絡 - - - - Choose Directory - 選擇目錄 - - - - The imported directory is already in the working directory, so there is no need to import it again! - 該導入的目錄已經在工作目錄下,無需再次導入! - - - - no find program can be imported - 沒有找到可以導入的節目 - - UpdateLedset3Dialog @@ -6440,7 +6189,7 @@ Apk is download finished from internet,you can select LED Screen SYNC firmware now! - 固件APK成功下載,您可以選擇需要的LED荧幕同步固件! + 固件APK成功下載,您可以選擇需要的LED螢幕同步固件! @@ -6455,7 +6204,7 @@ The current version is already the latest version,,you can select LED Screen SYNC firmware now! - 當前固件APK版本已經是最新版本,您可以選擇需要的LED荧幕同步固件! + 當前固件APK版本已經是最新版本,您可以選擇需要的LED螢幕同步固件! @@ -6481,262 +6230,315 @@ 祝賀你!您正在運行最新版本的%1 - - UpdaterDialog - - - Software Update - 软件更新 - - - - X - X - - - - V1.0 - - - - - Update - 陞級 - - - - CurVersion - 當前版本 - - - - LatestVersion: - 最新版本: - - - - - Update log: - 更新日誌: - - - - The current version is already the latest version - 已經是最新的版本 - - UpgradeApkDialog - - - Upgrade apk - 陞級apk + + Update APK + 更新APK - - 口 - - - - - X - - - - - + Select apk 選擇Apk包 - - - - + Upgrade 陞級 - - - APK: - - - - - + Uninstall 卸載 - - + check running state 檢測運行狀態 - - + Select Fpga 選擇FPGA檔案 - - - success info - + + Installing + 正在安裝 - - + Refresh 檢測 - - + Cancel 取消 - + Screen ID - 荧幕ID + 螢幕ID - + Remark Name 別名 - + Online 線上 - + Screen IP - 荧幕IP + 螢幕IP - + Security 加密 - + Progress 進度 - + xixunplayer - + cardsystem - + taxiapp - + starter - + connection - + displayer - + FPGA FPGA - + update - + State 陳述 - - - + + All 總數 - + + This screen is encrypted + 螢幕已加密 + + + + + Select Online APK + 選擇線上APK + + + + No Files + 沒有檔案 + + + + Name + 名稱 + + + + Size + 大小 + + + + Create Time + 創建時間 + + + + + + Tip + 提示 + + + + Is upgrading now. Please wait + 正在更新,請稍後 + + + + NoSelectedController + 請先選擇大螢幕 + + + + + Downloading Online File + 正在下載線上檔案 + + + + + Error + 錯誤 + + + + Online file is empty + 線上檔案為空 + + + + Uploading + + + + + Upload error + 上傳錯誤 + + + + Install error + 安裝錯誤 + + + + Install success + 安裝成功 + + + + Reminder + 提示 + + + + Reminder: Uninstalling this program may cause the device to offline, cannot be found, lost configs and have a black screen. Please uninstall with caution! + 提示:卸載此程式會導致平臺掉線,找不到設備,配寘參數遺失和黑屏問題,請謹慎卸載! + + + + Do you want to continue? + 是否繼續? + + + + Uninstalling + 正在卸載 + + + + Uninstall error + 卸載錯誤 + + + + Uninstall success + 卸載成功 + + + + Check apk running status + 監測APK運行狀態 + + + + Check error + 檢查錯誤 + + + + Running + 正在運行 + + + + Not running + 沒有運行 + + + The encrypted control card can be upgraded directly 加密控制卡可以直接陞級 - - - apk package (*.rpd) - - - - - apk package (*.apk *.zip) - - UsbDetectDialog - + Usb upgrade program U盘更新节目 - + Password - + OK 確認 - + Input password 輸入密碼 - - + + Tip 提示 - + No checked USB device 未檢查USB設備 - + please select usb device in list 請在清單中選擇usb設備 - + Cancel 取消 @@ -6744,7 +6546,7 @@ WaitingDlg - + Success 成功 @@ -6773,331 +6575,6 @@ 取消 - - eAClock - - - Basic Properties - 基本屬性 - - - - Time Zone - 時區 - - - - Custom Dial - 自定義錶盤 - - - - Select - 選擇 - - - - Select Dail file - 選擇錶盤圖片 - - - - Hour Mark - 時標 - - - - - Circular - 圓形 - - - - - Rectangle - 矩形 - - - - Number - 數位 - - - - - - T - - - - - Min Mark - 分標 - - - - Hand Color - 指針顏色 - - - - H - - - - - M - - - - - S - - - - - Text - 文字 - - - - Play Properties - 播放管道 - - - - Play Duration - 播放時長 - - - - s - - - - - eDClock - - - MON - 星期一 - - - - TUE - 星期二 - - - - WED - 星期三 - - - - THU - 星期四 - - - - FRI - 星期五 - - - - SAT - 星期六 - - - - SUN - 星期日 - - - - - AM - 上午 - - - - - PM - 下午 - - - - Basic Properties - 基本屬性 - - - - Time Zone - 時區 - - - - Year - - - - - Month - - - - - Day - - - - - Hour - - - - - Min. - - - - - Sec. - - - - - Weekly - 星期 - - - - Full Year - 四位年 - - - - 12-Hour - 12小時制 - - - - Date Style - 日期風格 - - - - Time Style - 時間風格 - - - - Display Style - 顯示風格 - - - - Multiline - 多行顯示 - - - - Play Properties - 播放管道 - - - - Play Duration - 播放時長 - - - - s - - - - - GenTmpThread - - - Preparing ... - 準備中… - - - - MON - 星期一 - - - - TUE - 星期二 - - - - WED - 星期三 - - - - THU - 星期四 - - - - FRI - 星期五 - - - - SAT - 星期六 - - - - SUN - 星期日 - - - - AM - 上午 - - - - PM - 下午 - - - - day - - - - - hour - - - - - min - - - - - sec - - - - - Create json ... - 生成json… - - - - Scan program ... - 掃描節目… - - mGuangYingPinWidget @@ -7295,7 +6772,7 @@ Open - 打开 + 打開 @@ -7502,68 +6979,55 @@ 串口打開失敗 - - wExportProgramItem - - - Tip Info - 提示 - - - - :solution(s) already exist.are you sure you want to overwrite the existing solution(s)? - :節目已存在。是否確實要覆蓋現有節目? - - wPlanItem - + Form Form - + 1 1 - + Every week: 每週: - + M - + Tu - + W - + Th - + F - + Sa - + Su @@ -7571,30 +7035,30 @@ wProgramPublishItem - + Input password 輸入密碼 - - - + + + Error 錯誤 - - + + Tip Info 提示 - + Fail 失敗 - + password is wrong 密碼錯誤 @@ -7602,92 +7066,24 @@ wUpgradeApkItem - + Input password 輸入密碼 - - uninstalling - 正在卸載 + + Error + 錯誤 - - - IsSoftwareRunning - 監測APK運行狀態 - - - - - This screen is encrypted - 荧幕已加密 - - - - - Start upgrading - 開始陞級 - - - - - Timeout - 超時 - - - - install start... - 開始安裝… - - - - - SynchronousHardwareVersion - 同步FPGA - - - + Tip Info 提示 - + password is wrong 密碼錯誤 - - - - UninstallSoftware - 卸載 - - - - - Success - 成功 - - - - Running - 正在運行 - - - - NoRunning - 沒有運行 - - - - install success - 安裝成功 - - - - - Fail - 失敗 - diff --git a/LedOK/wDevicesManager/controlencryptwidget.cpp b/LedOK/wDevicesManager/controlencryptwidget.cpp deleted file mode 100644 index 69cf55a..0000000 --- a/LedOK/wDevicesManager/controlencryptwidget.cpp +++ /dev/null @@ -1,290 +0,0 @@ -#include "controlencryptwidget.h" -#include "ui_controlencryptwidget.h" -#include "base/x_uimsgboxok.h" -#include "QFileDialog" -#include -#include -#include -#include -#include "tools.h" - -extern QWidget *gMainWin; - -ControlEncryptWidget::ControlEncryptWidget(QWidget *parent,QList *list) : - QWidget(parent), - ui(new Ui::ControlEncryptWidget) -{ - m_pLedlist=list; - ui->setupUi(this); - refreshLable(); -setStyleSheet(Tools::styleSheet()); - ui->pushButtonSetPassword->setProperty("ssType", "progManageTool"); - ui->pushButtonCancelPassword->setProperty("ssType", "progManageTool"); - //按钮事件绑定 - connect(ui->pushButtonSetPassword,SIGNAL(clicked()),this,SLOT(OnSetPassword())); - connect(ui->pushButtonCancelPassword,SIGNAL(clicked()),this,SLOT(OnCancelPassword())); - MARCO_DEFINE_CONTROL_FUNC2(parent->parent(),parent) - } - -ControlEncryptWidget::~ControlEncryptWidget() -{ - delete ui; - if(pHpptClient != nullptr) - { - qDebug() <<"delete pHpptClient in ~NetComm"; - delete pHpptClient; - pHpptClient=nullptr; - } - if(pHpptClientAll != nullptr) - { - qDebug() <<"delete pHpptClientAll in ~NetComm"; - delete pHpptClientAll; - pHpptClientAll=nullptr; - } -} - -void ControlEncryptWidget::refreshLable() -{ - ui->labelNewPassword->setText(tr("New password")); - ui->labelRepeatPassword->setText(tr("Enter password")); - ui->labelOriginalPassword->setText(tr("original password")); - ui->labelEntryptConfiguration->setText(tr("Entrypt Configuration")); - ui->lineEditNewPassword->setPlaceholderText(tr("New password")); - ui->lineEditRepeatPassword->setPlaceholderText(tr("Repeat new password")); - ui->lineEditOriginalPassword->setPlaceholderText(tr("original password")); - ui->pushButtonSetPassword->setText(tr("Set encryption")); - ui->pushButtonCancelPassword->setText(tr("Cancel encryption")); -} - -void ControlEncryptWidget::OnSetPassword() -{ - if(m_pLedlist==nullptr) - return; - if(m_pLedlist->count()<=1) - { - if(m_pLedCard==nullptr||m_pLedlist->count()==0) - { - X_UIMsgBoxOk *pDlg=new X_UIMsgBoxOk(tr("Tip"),tr("NoSelectedController"),this,1); - pDlg->exec(); - return; - } - } - - if(ui->lineEditOriginalPassword->isVisible()) - { - if(ui->lineEditOriginalPassword->text().isEmpty()) - { - X_UIMsgBoxOk *pDlg=new X_UIMsgBoxOk(tr("Tip"),tr("InputOriginalPasswordTip"),this,1); - pDlg->exec(); - return; - } - } - - if(ui->lineEditNewPassword->text().isEmpty()) - { - X_UIMsgBoxOk *pDlg=new X_UIMsgBoxOk(tr("Tip"),tr("InputNewPasswordTip"),this,1); - pDlg->exec(); - return; - } - if(ui->lineEditRepeatPassword->text().isEmpty()) - { - X_UIMsgBoxOk *pDlg=new X_UIMsgBoxOk(tr("Tip"),tr("InputRepeatPasswordTip"),this,1); - pDlg->exec(); - return; - } - if(ui->lineEditNewPassword->text()!=ui->lineEditRepeatPassword->text()) - { - X_UIMsgBoxOk *pDlg=new X_UIMsgBoxOk(tr("Tip"),tr("InputRepeatPasswordNotSameTip"),this,1); - pDlg->exec(); - return; - } - auto res = QMessageBox::information(gMainWin, tr("Tip Info"), tr("After setting the password, please remember the password and record it. If you forget the password, the device will be unable to operate. Are you sure you want to continue with this operation?"), QMessageBox::Ok, QMessageBox::Cancel); - if(res == QMessageBox::Ok) { - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "SetControllerPassword"); - json.insert("pwd", ui->lineEditOriginalPassword->text()); - json.insert("newPwd", ui->lineEditNewPassword->text()); - MACRO_DEFINE_TIPDLG_FUCN(tr("SetControllerPassword"),tr("Success"),tr("failed")) - } -} -void ControlEncryptWidget::OnCancelPassword() -{ - if(ui->lineEditOriginalPassword->isVisible()) - { - if(ui->lineEditOriginalPassword->text().isEmpty()) - { - X_UIMsgBoxOk *pDlg=new X_UIMsgBoxOk(tr("Tip"),tr("InputOriginalPasswordTip"),this,1); - pDlg->exec(); - return; - } - } - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "SetControllerPassword"); - json.insert("pwd", ui->lineEditOriginalPassword->text()); - json.insert("newPwd",""); - MACRO_DEFINE_TIPDLG_FUCN(tr("SetControllerPassword"),tr("Success"),tr("failed")) -} -void ControlEncryptWidget::onSelectedDeviceList(QList *list) -{ - m_pLedlist=list; - if(m_pLedlist==nullptr) - return; - MACRO_DEFINE_CONTROL_FUNC3 -} -void ControlEncryptWidget::OnControlTypeSwitchIndexChanged(int index) -{ - if(index==Setting_Encrypt) - { - m_bSelected=true; - if(m_pLedCard!=nullptr) - onReadbackAllThisPage(); - } - else { - m_bSelected=false; - } -} -void ControlEncryptWidget::onReadbackAllThisPage() -{ - if(m_pLedlist==nullptr) - return; - if(m_pLedlist->count()!=1) - return; - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "HasControllerPassword"); - HttpPostByTypeJsonObject(pHpptClientAll,m_strUrl,json); - MACRO_DEFINE_TIPDLG_ALL_FUCN(tr("Readback"),tr("Success"),tr("failed")) -} -//获取到httpPost的应答,如果参数变化需要出发修改控件item的内容 -void ControlEncryptWidget::OnProHttpResponse(QString url, QString postMD5, QByteArray data) -{ - Q_UNUSED(postMD5) - //qDebug()<< url + "\r\n"+m_strUrl; - if(url == m_strUrl) - { - QJsonParseError parseJsonErr; - QJsonDocument document = QJsonDocument::fromJson(data,&parseJsonErr); - if(!(parseJsonErr.error == QJsonParseError::NoError)) - { - if(data.size()==0) - qDebug()<<"json is empty"; - else - qDebug()<<"DeviceItem OnProHttpResponse 解析json文件错误!"; - return; - } - QJsonObject jsonObject = document.object(); - QString strType=jsonObject["_type"].toString(); - if(jsonObject["success"].toBool()==true) - { - qDebug()<m_strCardId +"---------"+ strType; - if(strType == "HasControllerPassword") - { - if(jsonObject["result"].toBool()) - {//已经加密 - ui->labelOriginalPassword->show(); - ui->lineEditOriginalPassword->show(); - ui->pushButtonCancelPassword->show(); - ui->pushButtonSetPassword->setText(tr("Modify password")); - m_pLedCard->bPassword=true; - - } - else {//没有加密 - ui->labelOriginalPassword->hide(); - ui->lineEditOriginalPassword->hide(); - ui->pushButtonCancelPassword->hide(); - ui->pushButtonSetPassword->setText(tr("Set encryption")); - m_pLedCard->bPassword=false; - } - } - else if(strType == "SetControllerPassword") - { - if(jsonObject["result"].toInt()==0) - {//原始密码正确 - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "HasControllerPassword"); - HttpPostByTypeJsonObject(pHpptClientAll,m_strUrl,json); - ui->lineEditNewPassword->clear(); - ui->lineEditRepeatPassword->clear(); - ui->lineEditOriginalPassword->clear(); - } - else {//原始密码错误 - MACRO_ASKTIME_STOP - if(m_PostingDlg!=nullptr) - { - m_PostingDlg->SetFailedTipString(tr("OriginalPasswordErrorTip")); - m_PostingDlg->TimerOutUnlock(); - } - ui->lineEditNewPassword->clear(); - ui->lineEditRepeatPassword->clear(); - ui->lineEditOriginalPassword->clear(); - return; - - } - } - MACRO_ASKTIME_STOP - MACRO_POSTING_DLG_UNLOCK - - } - } -} - -//获取到httpPost的应答,如果参数变化需要出发修改控件item的内容 -void ControlEncryptWidget::OnProHttpResponseAll(QString url, QString postMD5, QByteArray data) -{ - Q_UNUSED(postMD5) - //qDebug()<< url + "\r\n"+m_strUrl; - if(url == m_strUrl) - { - QJsonParseError parseJsonErr; - QJsonDocument document = QJsonDocument::fromJson(data,&parseJsonErr); - if(!(parseJsonErr.error == QJsonParseError::NoError)) - { - if(data.size()==0) - qDebug()<<"json is empty"; - else - qDebug()<<"DeviceItem OnProHttpResponse 解析json文件错误!"; - return; - } - QJsonObject jsonObject = document.object(); - QString strType=jsonObject["_type"].toString(); - if(jsonObject["success"].toBool()==true) - { - qDebug()<m_strCardId +"---------"+ strType; - if(strType == "HasControllerPassword") - { - if(jsonObject["result"].toBool()) - {//已经加密 - ui->labelOriginalPassword->show(); - ui->lineEditOriginalPassword->show(); - ui->pushButtonCancelPassword->show(); - ui->pushButtonSetPassword->setText(tr("Modify password")); - m_pLedCard->bPassword=true; - - } - else {//没有加密 - ui->labelOriginalPassword->hide(); - ui->lineEditOriginalPassword->hide(); - ui->pushButtonCancelPassword->hide(); - ui->pushButtonSetPassword->setText(tr("Set encryption")); - m_pLedCard->bPassword=false; - - } - - } - MACRO_ASKTIME_STOP - MACRO_POSTING_DLG_UNLOCK - - } - } -} -void ControlEncryptWidget::DeletePostingDlg() -{ - if(m_PostingDlg!=nullptr) - { - delete m_PostingDlg; - m_PostingDlg=nullptr; - } -} diff --git a/LedOK/wDevicesManager/controlencryptwidget.h b/LedOK/wDevicesManager/controlencryptwidget.h deleted file mode 100644 index cb30b49..0000000 --- a/LedOK/wDevicesManager/controlencryptwidget.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef CONTROLENCRYPTWIDGET_H -#define CONTROLENCRYPTWIDGET_H - -#include -#include -#include -#include -namespace Ui { -class ControlEncryptWidget; -} - -class ControlEncryptWidget : public QWidget -{ - Q_OBJECT - -public: - explicit ControlEncryptWidget(QWidget *parent = nullptr,QList *m_pLedlist=nullptr); - ~ControlEncryptWidget(); -private: - Ui::ControlEncryptWidget *ui; -protected slots: - void DeletePostingDlg(); - void OnSetPassword(); - void OnCancelPassword(); - void refreshLable(); - //类似的控制操作信号和槽函数和变量定义 - signals: - void sigSend(QJsonObject &,QString); - protected slots: - void OnProHttpResponse(QString url, QString postMD5, QByteArray data); - void OnProHttpResponseAll(QString url, QString postMD5, QByteArray data); - void onSelectedDeviceList(QList *); - void onReadbackAllThisPage(); - void OnControlTypeSwitchIndexChanged(int index); - private: - QList *m_pLedlist=nullptr; - LedCard *m_pLedCard = nullptr; - LedCard *m_oldLedlist = nullptr; - HpptClient *pHpptClient = nullptr; - HpptClient *pHpptClientAll = nullptr; - QString m_strUrl=""; - LoEmptyDialog * m_PostingDlg=nullptr; - QTimer *m_pGetAskTimer=nullptr; - bool m_bSelected=false; -}; - -#endif // CONTROLENCRYPTWIDGET_H diff --git a/LedOK/wDevicesManager/controlencryptwidget.ui b/LedOK/wDevicesManager/controlencryptwidget.ui deleted file mode 100644 index af45b1a..0000000 --- a/LedOK/wDevicesManager/controlencryptwidget.ui +++ /dev/null @@ -1,336 +0,0 @@ - - - ControlEncryptWidget - - - - 0 - 0 - 572 - 412 - - - - - 0 - 0 - - - - Form - - - background-color: #F5F5F5; - - - - - - - 0 - 0 - - - - - Arial - 12 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - Entrypt Configuration - - - Qt::AlignCenter - - - - - - - Qt::Horizontal - - - - - - - Qt::Vertical - - - QSizePolicy::Minimum - - - - 20 - 20 - - - - - - - - - 330 - 16777215 - - - - - - - false - - - false - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Original password - - - - - - - Enter password - - - - - - - Enter again - - - - - - - - - - - - 0 - 30 - - - - background-color: #FFFFFF; - - - QLineEdit::PasswordEchoOnEdit - - - original password - - - - - - - - 160 - 30 - - - - - 160 - 16777215 - - - - background-color: #FFFFFF; - - - - - - QLineEdit::PasswordEchoOnEdit - - - New password - - - - - - - - 160 - 30 - - - - - 160 - 16777215 - - - - background-color: #FFFFFF; - - - - - - QLineEdit::PasswordEchoOnEdit - - - Repeat new password - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - - - - - Qt::Vertical - - - QSizePolicy::Minimum - - - - 20 - 20 - - - - - - - - - 60 - 30 - - - - Set encryption - - - - - - - Qt::Vertical - - - QSizePolicy::Minimum - - - - 20 - 20 - - - - - - - - - 60 - 30 - - - - Cancel encryption - - - - - - - Qt::Vertical - - - QSizePolicy::Minimum - - - - 20 - 20 - - - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - diff --git a/LedOK/wDevicesManager/controlhdmischedule.cpp b/LedOK/wDevicesManager/controlhdmischedule.cpp deleted file mode 100644 index a5b60ff..0000000 --- a/LedOK/wDevicesManager/controlhdmischedule.cpp +++ /dev/null @@ -1,523 +0,0 @@ -#include "controlhdmischedule.h" -#include "ui_controlhdmischedule.h" -#include "base/x_uimsgboxok.h" -#include "QFileDialog" -#include "QDir" -#include -#include -#include -#include -#include -#include -#include "cfg.h" -#include "QSettings" -#include "base/x_spinboxdelegate.h" -#include "base/x_timeeditdelegate.h" -#include "base/x_checkboxdelegate.h" -#include "tools.h" -ControlHdmiSchedule::ControlHdmiSchedule(QWidget *parent,QList *list) : - QWidget(parent), - ui(new Ui::ControlHdmiSchedule) -{ - m_pLedlist=list; - ui->setupUi(this); - refreshLable(); -setStyleSheet(Tools::styleSheet()); - ui->labelSyncScheduleTip->setVisible(false); - - ui->pushButtonAdd->setProperty("ssType", "progManageTool"); - ui->pushButtonAdd->setFlat(true); - ui->pushButtonDelete->setProperty("ssType", "progManageTool"); - ui->pushButtonDelete->setFlat(true); - ui->pushButtonClear->setProperty("ssType", "progManageTool"); - ui->pushButtonClear->setFlat(true); - ui->pushButtonApply->setProperty("ssType", "progManageTool"); - ui->pushButtonApply->setFlat(true); - ui->pushButtonImport->setProperty("ssType", "progManageTool"); - ui->pushButtonExport->setProperty("ssType", "progManageTool"); - ui->pushButtonReadback->setProperty("ssType", "progManageTool"); - - m_pModel = new QStandardItemModel(this); - m_pModel->setColumnCount(10); - m_pModel->setHeaderData(0,Qt::Horizontal, tr("SYNC HDMI")); - m_pModel->setHeaderData(1,Qt::Horizontal, tr("Start Time")); - m_pModel->setHeaderData(2,Qt::Horizontal, tr("End Time")); - m_pModel->setHeaderData(3,Qt::Horizontal, tr("SUN")); - m_pModel->setHeaderData(4,Qt::Horizontal, tr("MON")); - m_pModel->setHeaderData(5,Qt::Horizontal, tr("TUE")); - m_pModel->setHeaderData(6,Qt::Horizontal, tr("WED")); - m_pModel->setHeaderData(7,Qt::Horizontal, tr("THU")); - m_pModel->setHeaderData(8,Qt::Horizontal, tr("FRI")); - m_pModel->setHeaderData(9,Qt::Horizontal, tr("SAT")); - ui->tableView->setModel(m_pModel); - - X_timeEditDelegate *pStartTimeDelegate=new X_timeEditDelegate(this); - ui->tableView->setItemDelegateForColumn(1,pStartTimeDelegate); - ui->tableView->setItemDelegateForColumn(2,pStartTimeDelegate); - X_CheckBoxDelegate *WeekDelegate=new X_CheckBoxDelegate(this); - ui->tableView->setItemDelegateForColumn(3,WeekDelegate); - ui->tableView->setItemDelegateForColumn(4,WeekDelegate); - ui->tableView->setItemDelegateForColumn(5,WeekDelegate); - ui->tableView->setItemDelegateForColumn(6,WeekDelegate); - ui->tableView->setItemDelegateForColumn(7,WeekDelegate); - ui->tableView->setItemDelegateForColumn(8,WeekDelegate); - ui->tableView->setItemDelegateForColumn(9,WeekDelegate); - - - ReadOnlyDelegate1* readOnlyDelegate = new ReadOnlyDelegate1(); - ui->tableView->setItemDelegateForColumn(0, readOnlyDelegate); //设置某列只读 - - ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); - // ui->tableView->verticalHeader()->hide(); - ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows); - ui->tableView->setFocusPolicy(Qt::NoFocus); - - - MARCO_DEFINE_CONTROL_FUNC2(parent->parent()->parent(),parent->parent()) - - connect(ui->pushButtonAdd,SIGNAL(clicked()),this,SLOT(OnClickAdd())); - connect(ui->pushButtonImport,SIGNAL(clicked()),this,SLOT(OnClickImport())); - connect(ui->pushButtonExport,SIGNAL(clicked()),this,SLOT(OnClickExport())); - connect(ui->pushButtonDelete,SIGNAL(clicked()),this,SLOT(OnClickDelete())); - connect(ui->pushButtonClear,SIGNAL(clicked()),this,SLOT(OnClickClear())); - connect(ui->pushButtonApply,SIGNAL(clicked()),this,SLOT(OnClickApply())); - connect(ui->pushButtonReadback,SIGNAL(clicked()),this,SLOT(OnClickReadback())); -} - -ControlHdmiSchedule::~ControlHdmiSchedule() -{ - delete ui; - if(pHpptClient != nullptr) - { - qDebug() <<"delete pHpptClient in ~NetComm"; - delete pHpptClient; - pHpptClient=nullptr; - } - if(pHpptClientAll != nullptr) - { - qDebug() <<"delete pHpptClientAll in ~NetComm"; - delete pHpptClientAll; - pHpptClientAll=nullptr; - } -} - -void ControlHdmiSchedule::refreshLable() -{ - ui->pushButtonAdd->setText(tr("Add")); - ui->pushButtonApply->setText(tr("Apply")); - ui->pushButtonClear->setText(tr("Clear")); - ui->pushButtonDelete->setText(tr("Delete")); - ui->pushButtonImport->setText(tr("Import")); - ui->pushButtonExport->setText(tr("Export")); - -} - -void ControlHdmiSchedule::onSelectedDeviceList(QList *list) -{ - m_pLedlist=list; - if(m_pLedlist==nullptr) - return; - if(m_pLedlist->count()==1) - { - ui->pushButtonReadback->setEnabled(true); - } - else { - ui->pushButtonReadback->setEnabled(false); - } - MACRO_DEFINE_CONTROL_FUNC3 - -} -//获取到httpPost的应答,如果参数变化需要出发修改控件item的内容 -void ControlHdmiSchedule::OnProHttpResponse(QString url, QString postMD5, QByteArray data) -{ - Q_UNUSED(postMD5) - //qDebug()<< url + "\r\n"+m_strUrl; - if(url == m_strUrl) - { - QJsonParseError parseJsonErr; - QJsonDocument document = QJsonDocument::fromJson(data,&parseJsonErr); - if(!(parseJsonErr.error == QJsonParseError::NoError)) - { - if(data.size()==0) - qDebug()<<"json is empty"; - else - qDebug()<m_strCardId +"---------"+ strType; - if(strType == "GetHdminScheduleTask") - { - - } - else if(strType == "etHdminScheduleTask") - { - } - - MACRO_ASKTIME_STOP - MACRO_POSTING_DLG_UNLOCK - - } - } -} -//获取到httpPost的应答,如果参数变化需要出发修改控件item的内容 -void ControlHdmiSchedule::OnProHttpResponseAll(QString url, QString postMD5, QByteArray data) -{ - Q_UNUSED(postMD5) - //qDebug()<< url + "\r\n"+m_strUrl; - if(url == m_strUrl) - { - QJsonParseError parseJsonErr; - QJsonDocument document = QJsonDocument::fromJson(data,&parseJsonErr); - if(!(parseJsonErr.error == QJsonParseError::NoError)) - { - if(data.size()==0) - qDebug()<<"json is empty"; - else - qDebug()<m_strCardId +"---------"+ strType; - if(strType == "GetHdminScheduleTask") - { - - } - } - } -} - -void ControlHdmiSchedule::OnControlTypeSwitchIndexChanged(int index) -{ - if(index==Setting_HDMI) - { - m_bSelected=true; - if(m_pLedCard!=nullptr) - onReadbackAllThisPage(); - } - else { - m_bSelected=false; - } -} -void ControlHdmiSchedule::onReadbackAllThisPage() -{ - if(m_pLedlist==nullptr) - return; - if(m_pLedlist->count()!=1) - return; - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "GetBrightness"); - HttpPostByTypeJsonObject(pHpptClientAll,m_strUrl,json); - -} -void ControlHdmiSchedule::OnClickAdd() -{ - QList Item; - Item.append(new QStandardItem(tr("On"))); - Item.append(new QStandardItem("00:00")); - Item.append(new QStandardItem("01:00")); -// Item.append(new QStandardItem(true)); -// Item.append(new QStandardItem(true)); -// Item.append(new QStandardItem(true)); -// Item.append(new QStandardItem(true)); -// Item.append(new QStandardItem(true)); -// Item.append(new QStandardItem(true)); -// Item.append(new QStandardItem(true)); - - Item.at(0)->setTextAlignment(Qt::AlignCenter); - Item.at(1)->setTextAlignment(Qt::AlignCenter); - Item.at(2)->setTextAlignment(Qt::AlignCenter); - m_pModel->appendRow(Item); - //m_lineEidt[i]->installEventFilter(this); - //Item.at(0)->setdsetValidator(new QRegExpValidator(rx, this)); - int i=m_pModel->rowCount()-1; - m_pModel->setData(m_pModel->index(i, 3),true,Qt::UserRole); - m_pModel->setData(m_pModel->index(i, 4),true,Qt::UserRole); - m_pModel->setData(m_pModel->index(i, 5),true,Qt::UserRole); - m_pModel->setData(m_pModel->index(i, 6),true,Qt::UserRole); - m_pModel->setData(m_pModel->index(i, 7),true,Qt::UserRole); - m_pModel->setData(m_pModel->index(i, 8),true,Qt::UserRole); - m_pModel->setData(m_pModel->index(i, 9),true,Qt::UserRole); - - if(m_pModel->rowCount()>0) - { - ui->labelSyncScheduleTip->setVisible(true); - } - else { - ui->labelSyncScheduleTip->setVisible(false); - } -} -void ControlHdmiSchedule::OnClickImport(){ - QSettings settings; - QString strDir="/"; - if(settings.value("lasOpendFileDlgtDir").isValid()) - { - strDir=settings.value("lasOpendFileDlgtDir").toString(); - } - QFileDialog dlg; - QString strBrightScheduleFile = QFileDialog::getOpenFileName(this, "open file dialog", - strDir, - tr("SyncSchedule (*.syncs)")); - if(strBrightScheduleFile.isEmpty()) return; - QFile fJson(strBrightScheduleFile); - if(fJson.open(QIODevice::ReadOnly)){ - QJsonDocument jBrightSchedule = QJsonDocument::fromJson(fJson.readAll()); - QJsonObject oTaskSync=jBrightSchedule.object(); - JieXiJsonTaskSync(oTaskSync); - fJson.close(); - } -} -bool ControlHdmiSchedule::JieXiJsonTaskSync(QJsonObject oTaskSync) -{ - OnClickClear(); - QJsonArray oSchedules; - oSchedules=oTaskSync["schedules"].toArray(); - if(oSchedules.count()>0) - { - ui->labelSyncScheduleTip->setVisible(true); - } - else - { - ui->labelSyncScheduleTip->setVisible(false); - } - for(int i=0;i Item; - Item.append(new QStandardItem(tr("On"))); - Item.append(new QStandardItem(oSchedule["startTime"].toString())); - Item.append(new QStandardItem(oSchedule["endTime"].toString())); - Item.at(0)->setTextAlignment(Qt::AlignCenter); - Item.at(1)->setTextAlignment(Qt::AlignCenter); - Item.at(2)->setTextAlignment(Qt::AlignCenter); - m_pModel->appendRow(Item); - if(oSchedule["filterType"].toString()=="None") - { - m_pModel->setData(m_pModel->index(i, 3),true,Qt::UserRole); - m_pModel->setData(m_pModel->index(i, 4),true,Qt::UserRole); - m_pModel->setData(m_pModel->index(i, 5),true,Qt::UserRole); - m_pModel->setData(m_pModel->index(i, 6),true,Qt::UserRole); - m_pModel->setData(m_pModel->index(i, 7),true,Qt::UserRole); - m_pModel->setData(m_pModel->index(i, 8),true,Qt::UserRole); - m_pModel->setData(m_pModel->index(i, 9),true,Qt::UserRole); - } - else if(oSchedule["filterType"].toString()=="Week") - { - QJsonArray oWeeks; - oWeeks=oSchedule["weekFilter"].toArray(); - for(int m=0;m<7;m++) - { - bool bHave=false; - for (int j=0;jsetData(m_pModel->index(i, m+3),bHave,Qt::UserRole); - } - - - } - - - - - } - if(oSchedules.count()>0) - return true; - else { - return false; - } -} -void ControlHdmiSchedule::OnClickExport() { - QSettings settings; - QString strDir="/"; - if(settings.value("lasOpendFileDlgtDir").isValid()) strDir=settings.value("lasOpendFileDlgtDir").toString(); - QFileDialog dlg; - QString saveFileName = dlg.getSaveFileName(this, tr("Save File"), strDir, tr("Sync Schedule (*.syncs)")); - if( saveFileName.isEmpty() ) return; - settings.setValue("lasOpendFileDlgtDir",saveFileName); - QJsonObject oTaskSync=GetJsonObjectSyncSchedule(); - QJsonDocument tSyncScheduleJsonDoc; - tSyncScheduleJsonDoc.setObject(oTaskSync); - - QFile f(saveFileName); - if(f.open(QIODevice::WriteOnly)) { - f.write(tSyncScheduleJsonDoc.toJson()); - f.close(); - } -} -void ControlHdmiSchedule::OnClickDelete() -{ - if(m_pModel->rowCount()>0) - { - QModelIndexList selected = ui->tableView->selectionModel()->selectedRows(0); - if(selected.count()>0) - m_pModel->removeRows(selected.begin()->row(),selected.count()); - - } - if(m_pModel->rowCount()>0) - { - ui->labelSyncScheduleTip->setVisible(true); - } - else { - ui->labelSyncScheduleTip->setVisible(false); - } -} -void ControlHdmiSchedule:: OnClickClear() -{ - //QModelIndexList selected = ui->tableView->selectionModel()->selectedRows(0); - - if(m_pModel->rowCount()>0) - m_pModel->removeRows(0,m_pModel->rowCount()); - if(m_pModel->rowCount()>0) - { - ui->labelSyncScheduleTip->setVisible(true); - } - else { - ui->labelSyncScheduleTip->setVisible(false); - } - } -void ControlHdmiSchedule::OnClickApply() -{ - - if(m_pLedlist==nullptr) - return; - if(m_pLedlist->count()<=1) - { - if(m_pLedCard==nullptr||m_pLedlist->count()==0) - { - X_UIMsgBoxOk *pDlg=new X_UIMsgBoxOk(tr("Tip"),tr("NoSelectedController"),this,1); - pDlg->exec(); - return; - } - } - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "SetTimingHdmiInTask"); - QJsonObject oTaskSync=GetJsonObjectSyncSchedule(); - json.insert("HdmiInTask", oTaskSync); - MACRO_DEFINE_TIPDLG_FUCN(tr("SetTimingHdmiInTask"),tr("Success"),tr("failed")) - -} -void ControlHdmiSchedule::OnClickReadback() -{ - if(m_pLedlist==nullptr) - return; - if(m_pLedlist->count()<=1) - { - if(m_pLedCard==nullptr||m_pLedlist->count()==0) - { - X_UIMsgBoxOk *pDlg=new X_UIMsgBoxOk(tr("Tip"),tr("NoSelectedController"),this,1); - pDlg->exec(); - return; - } - } - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "GetTimingHdmiInTask"); - MACRO_DEFINE_TIPDLG_FUCN(tr("GetTimingHdmiInTask"),tr("Success"),tr("failed")) - -} -QJsonObject ControlHdmiSchedule::GetJsonObjectSyncSchedule() -{ - QJsonObject oTaskSync; - QJsonArray oItems; - - oTaskSync["createDate"] = QJsonValue::Null; - oTaskSync["createBy"] = "alahover"; - oTaskSync["name"] = "TimingScreen"; - - QJsonArray oSchedules; - for(int i=0; irowCount(); i++) - { - - QJsonObject oSchedule; - oSchedule["timeType"] = "Range"; - oSchedule["startTime"] = m_pModel->data(m_pModel->index(i, 1)).toString();; - oSchedule["endTime"] = m_pModel->data(m_pModel->index(i, 2)).toString();; - oSchedule["dateType"] = "All"; - oSchedule["startDate"] = QJsonValue::Null; - oSchedule["endDate"] = QJsonValue::Null; - oSchedule["monthFilter"] = QJsonArray(); - - bool bSun=m_pModel->data(m_pModel->index(i, 3),Qt::UserRole).toBool(); - bool bMon=m_pModel->data(m_pModel->index(i, 4),Qt::UserRole).toBool(); - bool bTur=m_pModel->data(m_pModel->index(i, 5),Qt::UserRole).toBool(); - bool bWed=m_pModel->data(m_pModel->index(i, 6),Qt::UserRole).toBool(); - bool bThu=m_pModel->data(m_pModel->index(i, 7),Qt::UserRole).toBool(); - bool bFri=m_pModel->data(m_pModel->index(i, 8),Qt::UserRole).toBool(); - bool bSat=m_pModel->data(m_pModel->index(i, 9),Qt::UserRole).toBool(); - - - if(bMon && bTur && bWed && bThu && bFri && bSat && bSun) - { - oSchedule["filterType"] = "None"; - oSchedule["weekFilter"] = QJsonArray(); - - } - else { - oSchedule["filterType"] = "Week"; - QJsonArray tempArray; - if( bSun) - { - tempArray.append(0); - } - if(bMon) - { - tempArray.append(1); - } - if(bTur) - { - tempArray.append(2); - } - if( bWed) - { - tempArray.append(3); - } - if( bThu) - { - tempArray.append(4); - } - if( bFri) - { - tempArray.append(5); - } - if( bSat) - { - tempArray.append(6); - } - - - oSchedule["weekFilter"] = tempArray; - - } - - - oSchedules.append(oSchedule); - } - - oTaskSync["schedules"] = oSchedules; - return oTaskSync; - -} -void ControlHdmiSchedule::DeletePostingDlg() -{ - if(m_PostingDlg!=nullptr) - { - delete m_PostingDlg; - m_PostingDlg=nullptr; - } -} diff --git a/LedOK/wDevicesManager/controlhdmischedule.h b/LedOK/wDevicesManager/controlhdmischedule.h deleted file mode 100644 index df91ccd..0000000 --- a/LedOK/wDevicesManager/controlhdmischedule.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef CONTROLHDMISCHEDULE_H -#define CONTROLHDMISCHEDULE_H - -#include -#include -#include -#include -#include -#include -namespace Ui { -class ControlHdmiSchedule; -} - -class ControlHdmiSchedule : public QWidget -{ - Q_OBJECT - -public: - explicit ControlHdmiSchedule(QWidget *parent = nullptr,QList *m_pLedlist=nullptr); - ~ControlHdmiSchedule(); -protected slots: - void refreshLable(); - void OnClickAdd(); - void OnClickImport(); - void OnClickExport(); - void OnClickDelete(); - void OnClickClear(); - void OnClickApply(); - void OnClickReadback(); -private: - Ui::ControlHdmiSchedule *ui; - //类似的控制操作信号和槽函数和变量定义 - signals: - void sigSend(QJsonObject &,QString); - void sigHaveSchedule(bool); - protected slots: - void DeletePostingDlg(); - void OnProHttpResponse(QString url, QString postMD5, QByteArray data); - void OnProHttpResponseAll(QString url, QString postMD5, QByteArray data); - void onSelectedDeviceList(QList *); - void onReadbackAllThisPage(); - void OnControlTypeSwitchIndexChanged(int index); - private: - QList *m_pLedlist=nullptr; - LedCard *m_pLedCard = nullptr; - LedCard *m_oldLedlist = nullptr; - HpptClient *pHpptClient = nullptr; - HpptClient *pHpptClientAll = nullptr; - QString m_strUrl=""; - LoEmptyDialog * m_PostingDlg=nullptr; - QTimer *m_pGetAskTimer=nullptr; - bool m_bSelected=false; - QStandardItemModel * m_pModel; - bool JieXiJsonTaskSync(QJsonObject oTaskSync); - QJsonObject GetJsonObjectSyncSchedule(); - - - -}; -class ReadOnlyDelegate1: public QStyledItemDelegate -{ - Q_OBJECT -public: - ReadOnlyDelegate1(QWidget *parent = nullptr):QStyledItemDelegate(parent) - {} - - QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, -const QModelIndex &index) const override //final - { - Q_UNUSED(parent) - Q_UNUSED(option) - Q_UNUSED(index) - return nullptr; - } -}; -#endif // CONTROLHDMISCHEDULE_H diff --git a/LedOK/wDevicesManager/controlhdmischedule.ui b/LedOK/wDevicesManager/controlhdmischedule.ui deleted file mode 100644 index 9134dea..0000000 --- a/LedOK/wDevicesManager/controlhdmischedule.ui +++ /dev/null @@ -1,214 +0,0 @@ - - - ControlHdmiSchedule - - - - 0 - 0 - 777 - 480 - - - - Form - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - 10 - - - 0 - - - - - - 60 - 30 - - - - Add - - - - - - - - 60 - 30 - - - - Delete - - - - - - - - 60 - 30 - - - - Clear - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 30 - - - - Import - - - - - - - - 0 - 30 - - - - Export - - - - - - - - - By default, the asynchronous content is played, and the synchronous signal content is played in the fixed time period - - - true - - - - - - - background-color: #FFFFFF; - - - - - - - 0 - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 60 - 30 - - - - Apply - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 30 - - - - Readback - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - - - - diff --git a/LedOK/wDevicesManager/controlhdmiwidget.cpp b/LedOK/wDevicesManager/controlhdmiwidget.cpp deleted file mode 100644 index 3c24656..0000000 --- a/LedOK/wDevicesManager/controlhdmiwidget.cpp +++ /dev/null @@ -1,172 +0,0 @@ -#include "controlhdmiwidget.h" -#include "gqt.h" -#include "tools.h" -#include "globaldefine.h" -#include "base/waitingdlg.h" -#include -#include - -ControlHdmiWidget::ControlHdmiWidget(QWidget *parent,QList *list) : QWidget(parent) { - auto vBox = new QVBoxLayout(this); - labelHdmiConfiguration = new QLabel; - labelHdmiConfiguration->setAlignment(Qt::AlignCenter); - vBox->addWidget(labelHdmiConfiguration); - - auto line = new QFrame; - line->setFrameShape(QFrame::HLine); - line->setFrameShadow(QFrame::Sunken); - vBox->addWidget(line); - - auto hBox = new QHBoxLayout(); - hBox->addStretch(); - - radioButtonManual = new QRadioButton; - hBox->addWidget(radioButtonManual); - hBox->addStretch(); - - radioButtonSchedule = new QRadioButton; - hBox->addWidget(radioButtonSchedule); - hBox->addStretch(); - - vBox->addLayout(hBox); - - m_pStackedW = new QStackedWidget; - m_pManual = new QWidget; - { - auto vBox = new VBox(m_pManual); - auto hBox = new HBox(vBox); - hBox->addStretch(); - - lbAsync = new QLabel; - hBox->addWidget(lbAsync); - - swich = new SwitchControl; - swich->setMinimumSize(QSize(66, 33)); - swich->setBgColor(QColor(200,200,200), QColor(200,200,200)); - swich->setSliderColor(QColor(0, 160, 230), QColor(0, 160, 230)); - connect(swich, &SwitchControl::checkedChanged, this, [this](bool checked) { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - QJsonObject json; - json.insert("_id", "SyncSwitch"); - json.insert("_type", "SyncSwitch"); - json.insert("switchOn", checked); - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, checked ? tr("SyncSwitch") : tr("AnSyncSwitch")); - Def_CtrlReqPre - connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { - Def_CtrlSetReqAfter - }); - } else { - foreach(auto card, *gSelCards) { - if(checked){ - Def_CtrlSetMulti(tr("SyncSwitch")) - } else { - Def_CtrlSetMulti(tr("AnSyncSwitch")) - } - } - } - }); - hBox->addWidget(swich); - - lbSync = new QLabel; - hBox->addWidget(lbSync); - hBox->addStretch(); - - vBox->addSpacing(20); - - hBox = new HBox(vBox); - hBox->addStretch(); - btnGetSync = new QPushButton; - btnGetSync->setMinimumSize(60, 30); - btnGetSync->setProperty("ssType", "progManageTool"); - connect(btnGetSync, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - QJsonObject json; - json.insert("_id", "IsSync"); - json.insert("_type", "IsSync"); - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, tr("IsSync")); - Def_CtrlReqPre - connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg] { - Def_CtrlSingleGetReply - waitingDlg->success(); - qDebug()<<"IsSync res"<setCheckedStatus(json["result"].toBool()); - }); - } else { - foreach(auto card, *gSelCards) { - auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); - connect(reply, &QNetworkReply::finished, this, [reply, card] { - QJsonDocument json; - QString err = checkReplyForJson(reply, &json); - if(err.isEmpty()) err = json["result"].toBool() ? "true" : "false"; - gFdResInfo->append(card->m_strCardId+" "+tr("IsSync")+" "+err); - }); - } - } - }); - hBox->addWidget(btnGetSync); - hBox->addStretch(); - - vBox->addStretch(); - } - m_pSchedule = new ControlHdmiSchedule(this, list); - m_pStackedW->addWidget(m_pManual); - m_pStackedW->addWidget(m_pSchedule); - vBox->addWidget(m_pStackedW); - - auto m_buttonGroup = new QButtonGroup; - m_buttonGroup->addButton(radioButtonManual, 0); - m_buttonGroup->addButton(radioButtonSchedule, 1); - connect(m_buttonGroup,SIGNAL(buttonClicked(int)),m_pStackedW,SLOT(setCurrentIndex(int))); - radioButtonManual->setChecked(true); - m_pStackedW->setCurrentIndex(0); - - connect(gDevicePanel, &DevicePanel::sigSelectedDeviceList, this, [this] { - if(isVisible()) init(); - }); - transUi(); -} - -void ControlHdmiWidget::showEvent(QShowEvent *event) { - QWidget::showEvent(event); - init(); -} - -void ControlHdmiWidget::init() { - bool isSingle = gSelCards->count()==1; - if(! isSingle) return; - QJsonObject json; - json.insert("_id", "IsSync"); - json.insert("_type", "IsSync"); - auto card = gSelCards->at(0); - auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); - connect(reply, &QNetworkReply::finished, this, [this, reply] { - QJsonDocument json; - QString err = checkReplyForJson(reply, &json); - if(! err.isEmpty()) { - QMessageBox::critical(gMainWin, tr("Error"), err); - return; - } - swich->setCheckedStatus(json["result"].toBool()); - }); -} -void ControlHdmiWidget::changeEvent(QEvent *event) { - QWidget::changeEvent(event); - if(event->type() == QEvent::LanguageChange) transUi(); -} -void ControlHdmiWidget::transUi() { - labelHdmiConfiguration->setText(tr("HDMI Configuration")); - radioButtonManual->setText(tr("Manual")); - radioButtonSchedule->setText(tr("Schedule")); - - lbSync->setText(tr("HDMI IN")); - lbAsync->setText(tr("Async")); - btnGetSync->setText(tr("Readback")); -} diff --git a/LedOK/wDevicesManager/controlhdmiwidget.h b/LedOK/wDevicesManager/controlhdmiwidget.h deleted file mode 100644 index f1dbaee..0000000 --- a/LedOK/wDevicesManager/controlhdmiwidget.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef CONTROLHDMIWIDGET_H -#define CONTROLHDMIWIDGET_H - -#include "base/switchcontrol.h" -#include -#include -#include - -class ControlHdmiWidget : public QWidget { - Q_OBJECT -public: - explicit ControlHdmiWidget(QWidget *parent = nullptr,QList *m_pLedlist=nullptr); -protected: - void showEvent(QShowEvent *event) override; - void init(); - void changeEvent(QEvent *) override; - void transUi(); - -private: - QLabel *labelHdmiConfiguration; - QRadioButton *radioButtonManual; - QRadioButton *radioButtonSchedule; - - QWidget *m_pManual=nullptr; - ControlHdmiSchedule *m_pSchedule=nullptr; - QStackedWidget *m_pStackedW; - - QLabel *lbAsync; - SwitchControl *swich; - QLabel *lbSync; - QPushButton *btnGetSync; - - LedCard *m_pLedCard = nullptr; - LedCard *m_oldLedlist = nullptr; - HpptClient *pHpptClient = nullptr; - HpptClient *pHpptClientAll = nullptr; - QString m_strUrl=""; - LoEmptyDialog * m_PostingDlg=nullptr; - QTimer *m_pGetAskTimer=nullptr; - bool m_bSelected=false; -}; - -#endif // CONTROLHDMIWIDGET_H diff --git a/LedOK/wDevicesManager/controlnetconfigwidget.cpp b/LedOK/wDevicesManager/controlnetconfigwidget.cpp deleted file mode 100644 index 7630987..0000000 --- a/LedOK/wDevicesManager/controlnetconfigwidget.cpp +++ /dev/null @@ -1,1571 +0,0 @@ -#include "controlnetconfigwidget.h" -#include "base/waitingdlg.h" -#include "globaldefine.h" -#include "tools.h" -#include -#include -#include - -ControlNetConfigWidget::ControlNetConfigWidget(QWidget *parent,QList *list) : QWidget(parent) { - auto vBox = new QVBoxLayout(this); - - lbLanCfg = new QLabel; - QFont font = lbLanCfg->font(); - font.setPointSize(12); - lbLanCfg->setFont(font); - lbLanCfg->setAlignment(Qt::AlignCenter); - vBox->addWidget(lbLanCfg); - - auto hBox = new QHBoxLayout(); - hBox->addStretch(); - - fdDhcp = new QRadioButton; - hBox->addWidget(fdDhcp, 0, Qt::AlignTop); - - hBox->addSpacing(40); - - vBoxSpecifyIp = new QVBoxLayout(); - vBoxSpecifyIp->setContentsMargins(0, 0, 0, 0); - - fdSpecifyIp = new QRadioButton; - vBoxSpecifyIp->addWidget(fdSpecifyIp, 0, Qt::AlignCenter); - - gBoxSpecifyIp = new QGroupBox; - gBoxSpecifyIp->setMaximumWidth(340); - { - auto vvv = new QVBoxLayout(gBoxSpecifyIp); - auto hhh = new QHBoxLayout(); - - labelIpAddress = new QLabel; - hhh->addWidget(labelIpAddress); - - fdIP = new QIPLineEdit; - fdIP->setFixedWidth(160); - fdIP->setStyleSheet("background-color: #fff;"); - hhh->addWidget(fdIP); - - vvv->addLayout(hhh); - hhh = new QHBoxLayout(); - - labelMaskAddress = new QLabel; - hhh->addWidget(labelMaskAddress); - - fdMask = new QIPLineEdit; - fdMask->setFixedWidth(160); - fdMask->setStyleSheet("background-color: #FFF;"); - hhh->addWidget(fdMask); - - vvv->addLayout(hhh); - hhh = new QHBoxLayout(); - - labelGateway = new QLabel; - hhh->addWidget(labelGateway); - - fdGateWay = new QIPLineEdit; - fdGateWay->setFixedWidth(160); - fdGateWay->setStyleSheet("background-color: #fff;"); - hhh->addWidget(fdGateWay); - - vvv->addLayout(hhh); - hhh = new QHBoxLayout(); - - labelDnsAddress = new QLabel; - hhh->addWidget(labelDnsAddress); - - fdDns = new QIPLineEdit; - fdDns->setFixedWidth(160); - fdDns->setStyleSheet("background-color: #FFF;"); - hhh->addWidget(fdDns); - - vvv->addLayout(hhh); - } - vBoxSpecifyIp->addWidget(gBoxSpecifyIp); - - hBox->addLayout(vBoxSpecifyIp); - - hBox->addStretch(); - vBox->addLayout(hBox); - - hBox = new QHBoxLayout(); - hBox->addStretch(); - - btnLanSet = new QPushButton; - btnLanSet->setMinimumSize(QSize(60, 30)); - connect(btnLanSet, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - QString ip = fdIP->text(); - QString mask = fdMask->text(); - QString gateWay = fdGateWay->text(); - QString dns = fdDns->text(); - if(fdDhcp->isChecked()) { - if(ip=="...") ip="0.255.255.255"; - if(mask=="...") mask="0.255.255.255"; - if(gateWay=="...") gateWay="0.255.255.255"; - if(dns=="...") dns="0.255.255.255"; - } else { - if(ip=="...") { - QMessageBox::warning(gMainWin, tr("Attention"), tr("Please input IP address!")); - fdIP->setFocus(); - return; - } - if(!isTextValid(ip)) { - QMessageBox::warning(gMainWin, tr("Attention"), tr("Your IP Address is Invalid!")+"["+ip+"]"); - fdIP->setFocus(); - return; - } - if(mask=="...") { - QMessageBox::warning(gMainWin, tr("Attention"), tr("Please input Mask address!")); - fdMask->setFocus(); - return; - } - if(!isTextValid(mask)) { - QMessageBox::warning(gMainWin, tr("Attention"), tr("Your Mask Address is Invalid!")); - fdMask->setFocus(); - return; - } - if(gateWay=="...") { - QMessageBox::warning(gMainWin, tr("Attention"), tr("Please input Gateway address!")); - fdGateWay->setFocus(); - return; - } - if(!isTextValid(gateWay)) { - QMessageBox::warning(gMainWin, tr("Attention"), tr("Your Gateway Address is Invalid!")); - fdGateWay->setFocus(); - return; - } - if(dns=="...") { - QMessageBox::warning(gMainWin, tr("Attention"), tr("Please input DNS address!")); - fdDns->setFocus(); - return; - } - if (!isTextValid(dns)) { - QMessageBox::warning(gMainWin, tr("Attention"), tr("Your DNS Address is Invalid!")); - fdDns->setFocus(); - return; - } - } - QJsonObject json; - json.insert("_id", "SetEthernet"); - json.insert("_type", "SetEthernet"); - json.insert("dhcp", fdDhcp->isChecked()); - json.insert("ip", ip); - json.insert("netMask", mask); - json.insert("gateWay", gateWay); - json.insert("dns", dns); - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, tr("SetEthernet")); - Def_CtrlReqPre - connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { - Def_CtrlSetReqAfter - }); - } else { - foreach(auto card, *gSelCards) { - Def_CtrlSetMulti(tr("SetEthernet")) - } - } - }); - hBox->addWidget(btnLanSet); - - hBox->addSpacing(100); - - btnLanGet = new QPushButton; - btnLanGet->setMinimumSize(QSize(60, 30)); - connect(btnLanGet, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - QJsonObject json; - json.insert("_id", "GetEthernet"); - json.insert("_type", "GetEthernet"); - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, tr("GetEthernet")); - Def_CtrlReqPre - connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg] { - Def_CtrlSingleGetReply - waitingDlg->success(); - if(json["dhcp"].toBool()) { - fdDhcp->setChecked(true); - emit sigGetDhcpOrSpecifyIp(0); - } else { - fdSpecifyIp->setChecked(true); - emit sigGetDhcpOrSpecifyIp(1); - } - fdIP->setText(json["ipAddr"].toString()); - fdMask->setText(json["netMask"].toString()); - fdGateWay->setText(json["gateWay"].toString()); - fdDns->setText(json["dnsAddr"].toString()); - }); - } else { - foreach(auto card, *gSelCards) { - auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); - connect(reply, &QNetworkReply::finished, this, [reply, card] { - QJsonDocument json; - QString err = checkReplyForJson(reply, &json); - if(err.isEmpty()) err = json["dhcp"].toBool() ? tr("DHCP IP") : tr("STATIC IP"); - gFdResInfo->append(card->m_strCardId+" "+tr("GetEthernet")+" "+err); - gFdResInfo->append(" IP: "+json["ipAddr"].toString()); - gFdResInfo->append(" Mask: "+json["netMask"].toString()); - gFdResInfo->append(" GateWay: "+json["gateWay"].toString()); - gFdResInfo->append(" Dns: "+json["dnsAddr"].toString()); - }); - } - } - }); - hBox->addWidget(btnLanGet); - - hBox->addStretch(); - vBox->addLayout(hBox); - - auto line = new QFrame; - line->setFrameShape(QFrame::HLine); - line->setFrameShadow(QFrame::Sunken); - vBox->addWidget(line); - - label_5 = new QLabel; - label_5->setFont(font); - label_5->setAlignment(Qt::AlignCenter); - - vBox->addWidget(label_5); - - horizontalLayout_2 = new QHBoxLayout(); - horizontalLayout_2->setContentsMargins(-1, -1, 10, -1); - verticalLayout_6 = new QVBoxLayout(); - verticalLayout_6->setContentsMargins(-1, -1, -1, 0); - groupBox_3 = new QGroupBox; - groupBox_3->setMinimumSize(QSize(0, 144)); - groupBox_3->setMaximumSize(QSize(460, 16777215)); - groupBox_3->setCheckable(true); - verticalLayout_7 = new QVBoxLayout(groupBox_3); - horizontalLayout_9 = new QHBoxLayout(); - horizontalLayout_9->setSpacing(6); - horizontalLayout_9->setContentsMargins(0, 0, -1, -1); - verticalLayout_11 = new QVBoxLayout(); - verticalLayout_11->setContentsMargins(-1, -1, 0, -1); - labelWifiName = new QLabel(groupBox_3); - labelWifiName->setMinimumSize(QSize(0, 30)); - - verticalLayout_11->addWidget(labelWifiName); - - labelWifiPassword = new QLabel(groupBox_3); - labelWifiPassword->setMinimumSize(QSize(0, 30)); - - verticalLayout_11->addWidget(labelWifiPassword); - - - horizontalLayout_9->addLayout(verticalLayout_11); - - verticalLayout_12 = new QVBoxLayout(); - verticalLayout_12->setContentsMargins(-1, -1, 0, -1); - comboBox = new QComboBox(groupBox_3); - comboBox->setMinimumSize(QSize(260, 30)); - comboBox->setMaximumSize(QSize(260, 16777215)); - comboBox->setStyleSheet(QString::fromUtf8("background-color: #FFFFFF;")); - comboBox->setEditable(true); - - verticalLayout_12->addWidget(comboBox); - - lineEditWifiPassword = new QLineEdit(groupBox_3); - lineEditWifiPassword->setMinimumSize(QSize(140, 30)); - lineEditWifiPassword->setMaximumSize(QSize(160, 16777215)); - lineEditWifiPassword->setStyleSheet(QString::fromUtf8("background-color: #FFFFFF;")); - lineEditWifiPassword->setEchoMode(QLineEdit::PasswordEchoOnEdit); - - verticalLayout_12->addWidget(lineEditWifiPassword); - - - horizontalLayout_9->addLayout(verticalLayout_12); - - verticalLayout_13 = new QVBoxLayout(); - verticalLayout_13->setContentsMargins(-1, -1, 0, -1); - pushButtonScan = new QPushButton(groupBox_3); - pushButtonScan->setMinimumSize(QSize(60, 30)); - pushButtonScan->setMaximumSize(QSize(100, 16777215)); - - verticalLayout_13->addWidget(pushButtonScan); - - horizontalSpacer_10 = new QSpacerItem(40, 30, QSizePolicy::Expanding, QSizePolicy::Minimum); - - verticalLayout_13->addItem(horizontalSpacer_10); - - - horizontalLayout_9->addLayout(verticalLayout_13); - - - verticalLayout_7->addLayout(horizontalLayout_9); - - pushButtonWiFiModel = new QPushButton(groupBox_3); - pushButtonWiFiModel->setMinimumSize(QSize(60, 30)); - - verticalLayout_7->addWidget(pushButtonWiFiModel, 0, Qt::AlignHCenter); - - - verticalLayout_6->addWidget(groupBox_3); - - - horizontalLayout_2->addLayout(verticalLayout_6); - - pushButtonReadbackWiFiModel = new QPushButton; - QSizePolicy sizePolicy3(QSizePolicy::Expanding, QSizePolicy::Fixed); - sizePolicy3.setHorizontalStretch(0); - sizePolicy3.setVerticalStretch(0); - sizePolicy3.setHeightForWidth(pushButtonReadbackWiFiModel->sizePolicy().hasHeightForWidth()); - pushButtonReadbackWiFiModel->setSizePolicy(sizePolicy3); - pushButtonReadbackWiFiModel->setMinimumSize(QSize(0, 30)); - pushButtonReadbackWiFiModel->setMaximumSize(QSize(100, 16777215)); - - horizontalLayout_2->addWidget(pushButtonReadbackWiFiModel, 0, Qt::AlignBottom); - - verticalLayout_4 = new QVBoxLayout(); - verticalLayout_4->setContentsMargins(-1, 0, -1, -1); - groupBox_4 = new QGroupBox; - groupBox_4->setMinimumSize(QSize(0, 144)); - groupBox_4->setMaximumSize(QSize(300, 16777215)); - groupBox_4->setCheckable(true); - verticalLayout_8 = new QVBoxLayout(groupBox_4); - horizontalLayout_12 = new QHBoxLayout(); - horizontalLayout_12->setContentsMargins(0, -1, -1, -1); - verticalLayout_14 = new QVBoxLayout(); - verticalLayout_14->setContentsMargins(0, -1, -1, -1); - labelApName = new QLabel(groupBox_4); - - verticalLayout_14->addWidget(labelApName); - - labelApPassword = new QLabel(groupBox_4); - - verticalLayout_14->addWidget(labelApPassword); - - - horizontalLayout_12->addLayout(verticalLayout_14); - - verticalLayout_15 = new QVBoxLayout(); - verticalLayout_15->setContentsMargins(0, -1, -1, -1); - lineEditHotspotName = new QLineEdit(groupBox_4); - lineEditHotspotName->setMinimumSize(QSize(120, 30)); - lineEditHotspotName->setMaximumSize(QSize(120, 16777215)); - lineEditHotspotName->setStyleSheet(QString::fromUtf8("background-color: #FFFFFF;")); - - verticalLayout_15->addWidget(lineEditHotspotName); - - lineEditApPassword = new QLineEdit(groupBox_4); - lineEditApPassword->setMinimumSize(QSize(120, 30)); - lineEditApPassword->setMaximumSize(QSize(120, 16777215)); - lineEditApPassword->setStyleSheet(QString::fromUtf8("background-color: #FFFFFF;")); - lineEditApPassword->setEchoMode(QLineEdit::PasswordEchoOnEdit); - - verticalLayout_15->addWidget(lineEditApPassword); - - - horizontalLayout_12->addLayout(verticalLayout_15); - - - verticalLayout_8->addLayout(horizontalLayout_12); - - pushButtonApSet = new QPushButton(groupBox_4); - pushButtonApSet->setMinimumSize(QSize(60, 30)); - - verticalLayout_8->addWidget(pushButtonApSet, 0, Qt::AlignHCenter); - - - verticalLayout_4->addWidget(groupBox_4); - - - horizontalLayout_2->addLayout(verticalLayout_4); - - horizontalSpacer_2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); - - horizontalLayout_2->addItem(horizontalSpacer_2); - - - vBox->addLayout(horizontalLayout_2); - - line_3 = new QFrame; - line_3->setFrameShape(QFrame::HLine); - line_3->setFrameShadow(QFrame::Sunken); - - vBox->addWidget(line_3); - - label = new QLabel; - label->setFont(font); - - vBox->addWidget(label, 0, Qt::AlignHCenter); - - checkBox4g = new QCheckBox; - - vBox->addWidget(checkBox4g); - - horizontalLayout_13 = new QHBoxLayout(); - horizontalLayout_13->setContentsMargins(-1, 0, -1, -1); - pushButtonReadback4G = new QPushButton; - pushButtonReadback4G->setMinimumSize(QSize(60, 30)); - pushButtonReadback4G->setMaximumSize(QSize(200, 16777215)); - - horizontalLayout_13->addWidget(pushButtonReadback4G); - - label_ApnInfo = new QLabel; - label_ApnInfo->setMinimumSize(QSize(0, 0)); - - horizontalLayout_13->addWidget(label_ApnInfo); - - lineEditApnInfo = new QLineEdit; - - horizontalLayout_13->addWidget(lineEditApnInfo); - - pushButtonRead4GStatus = new QPushButton; - pushButtonRead4GStatus->setMinimumSize(QSize(0, 30)); - - horizontalLayout_13->addWidget(pushButtonRead4GStatus); - - horizontalSpacer_6 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); - - horizontalLayout_13->addItem(horizontalSpacer_6); - - - vBox->addLayout(horizontalLayout_13); - - verticalSpacer_2 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); - - vBox->addItem(verticalSpacer_2); - - groupBox_5 = new QGroupBox; - groupBox_5->setMinimumSize(QSize(0, 80)); - groupBox_5->setAlignment(Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter); - groupBox_5->setFlat(false); - groupBox_5->setCheckable(true); - groupBox_5->setChecked(false); - verticalLayout_16 = new QVBoxLayout(groupBox_5); - label_8 = new QLabel(groupBox_5); - label_8->setWordWrap(true); - - verticalLayout_16->addWidget(label_8); - - checkBoxCustom = new QCheckBox(groupBox_5); - checkBoxCustom->setChecked(false); - - verticalLayout_16->addWidget(checkBoxCustom); - - horizontalLayout_10 = new QHBoxLayout(); - horizontalLayout_10->setContentsMargins(-1, 0, -1, -1); - pushButtonGetMcc = new QPushButton(groupBox_5); - pushButtonGetMcc->setMinimumSize(QSize(0, 30)); - - horizontalLayout_10->addWidget(pushButtonGetMcc); - - label_9 = new QLabel(groupBox_5); - - horizontalLayout_10->addWidget(label_9); - - label_2 = new QLabel(groupBox_5); - - horizontalLayout_10->addWidget(label_2); - - comboBoxCountryID = new QComboBox(groupBox_5); - comboBoxCountryID->setMinimumSize(QSize(80, 0)); - comboBoxCountryID->setStyleSheet(QString::fromUtf8("background-color: #FFFFFF")); - comboBoxCountryID->setEditable(false); - - horizontalLayout_10->addWidget(comboBoxCountryID); - - label_11 = new QLabel(groupBox_5); - - horizontalLayout_10->addWidget(label_11); - - label_3 = new QLabel(groupBox_5); - - horizontalLayout_10->addWidget(label_3); - - comboBoxCarrierName = new QComboBox(groupBox_5); - comboBoxCarrierName->setMinimumSize(QSize(200, 0)); - comboBoxCarrierName->setContextMenuPolicy(Qt::DefaultContextMenu); - comboBoxCarrierName->setStyleSheet(QString::fromUtf8("background-color: #FFFFFF")); - comboBoxCarrierName->setEditable(false); - comboBoxCarrierName->setDuplicatesEnabled(false); - - horizontalLayout_10->addWidget(comboBoxCarrierName); - - label_12 = new QLabel(groupBox_5); - - horizontalLayout_10->addWidget(label_12); - - label_4 = new QLabel(groupBox_5); - - horizontalLayout_10->addWidget(label_4); - - lineEditAPN = new QLineEdit(groupBox_5); - lineEditAPN->setMinimumSize(QSize(200, 0)); - lineEditAPN->setMaximumSize(QSize(200, 16777215)); - lineEditAPN->setStyleSheet(QString::fromUtf8("background-color: #FFFFFF")); - lineEditAPN->setReadOnly(true); - - horizontalLayout_10->addWidget(lineEditAPN); - - horizontalSpacer_3 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); - - horizontalLayout_10->addItem(horizontalSpacer_3); - - - verticalLayout_16->addLayout(horizontalLayout_10); - - horizontalLayout_11 = new QHBoxLayout(); - horizontalLayout_11->setContentsMargins(-1, 10, -1, -1); - label_6 = new QLabel(groupBox_5); - - horizontalLayout_11->addWidget(label_6); - - lineEditUser = new QLineEdit(groupBox_5); - lineEditUser->setMaximumSize(QSize(120, 16777215)); - lineEditUser->setStyleSheet(QString::fromUtf8("background-color: #FFFFFF")); - lineEditUser->setReadOnly(true); - - horizontalLayout_11->addWidget(lineEditUser); - - label_7 = new QLabel(groupBox_5); - - horizontalLayout_11->addWidget(label_7); - - lineEditPassword = new QLineEdit(groupBox_5); - lineEditPassword->setMaximumSize(QSize(120, 16777215)); - lineEditPassword->setStyleSheet(QString::fromUtf8("background-color: #FFFFFF")); - lineEditPassword->setReadOnly(true); - - horizontalLayout_11->addWidget(lineEditPassword); - - horizontalSpacer_7 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); - - horizontalLayout_11->addItem(horizontalSpacer_7); - - - verticalLayout_16->addLayout(horizontalLayout_11); - - horizontalLayout_8 = new QHBoxLayout(); - horizontalLayout_8->setContentsMargins(-1, 0, -1, -1); - horizontalSpacer_5 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); - - horizontalLayout_8->addItem(horizontalSpacer_5); - - pushButtonSet4GInfo = new QPushButton(groupBox_5); - pushButtonSet4GInfo->setMinimumSize(QSize(60, 30)); - - horizontalLayout_8->addWidget(pushButtonSet4GInfo); - - pushButtonSetYuanHengApn = new QPushButton(groupBox_5); - pushButtonSetYuanHengApn->setMinimumSize(QSize(0, 30)); - - horizontalLayout_8->addWidget(pushButtonSetYuanHengApn); - - horizontalSpacer_4 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); - - horizontalLayout_8->addItem(horizontalSpacer_4); - - - verticalLayout_16->addLayout(horizontalLayout_8); - - - vBox->addWidget(groupBox_5); - - verticalSpacer_4 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); - - vBox->addItem(verticalSpacer_4); - - horizontalLayout_15 = new QHBoxLayout(); - horizontalLayout_15->setContentsMargins(-1, 0, 10, -1); - label_10 = new QLabel; - - horizontalLayout_15->addWidget(label_10); - - widgetFightModel = new SwitchControl; - widgetFightModel->setMinimumSize(QSize(80, 35)); - - horizontalLayout_15->addWidget(widgetFightModel); - - pushButtonReadbackFlightModel = new QPushButton; - pushButtonReadbackFlightModel->setMinimumSize(QSize(0, 30)); - - horizontalLayout_15->addWidget(pushButtonReadbackFlightModel); - - horizontalSpacer_8 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); - - horizontalLayout_15->addItem(horizontalSpacer_8); - - - vBox->addLayout(horizontalLayout_15); - - verticalSpacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); - - vBox->addItem(verticalSpacer); - - - fdDhcp->setText(QCoreApplication::translate("ControlNetConfigWidget", "DHCP", nullptr)); - fdSpecifyIp->setText(QCoreApplication::translate("ControlNetConfigWidget", "Specify IP", nullptr)); - labelIpAddress->setText(QCoreApplication::translate("ControlNetConfigWidget", "IP Address", nullptr)); - labelMaskAddress->setText(QCoreApplication::translate("ControlNetConfigWidget", "Mask Address", nullptr)); - labelGateway->setText(QCoreApplication::translate("ControlNetConfigWidget", "Gateway", nullptr)); - labelDnsAddress->setText(QCoreApplication::translate("ControlNetConfigWidget", "DNS Address", nullptr)); - label_5->setText(QCoreApplication::translate("ControlNetConfigWidget", "WIFI Configuration", nullptr)); - groupBox_3->setTitle(QCoreApplication::translate("ControlNetConfigWidget", "WiFi On/Off", nullptr)); - labelWifiName->setText(QCoreApplication::translate("ControlNetConfigWidget", "WiFi name", nullptr)); - labelWifiPassword->setText(QCoreApplication::translate("ControlNetConfigWidget", "Password", nullptr)); - lineEditWifiPassword->setPlaceholderText(QCoreApplication::translate("ControlNetConfigWidget", "Input password", nullptr)); - pushButtonScan->setText(QCoreApplication::translate("ControlNetConfigWidget", "Scan", nullptr)); - pushButtonWiFiModel->setText(QCoreApplication::translate("ControlNetConfigWidget", "Set", nullptr)); - pushButtonReadbackWiFiModel->setText(QCoreApplication::translate("ControlNetConfigWidget", "Readback", nullptr)); - groupBox_4->setTitle(QCoreApplication::translate("ControlNetConfigWidget", "Ap Mode", nullptr)); - labelApName->setText(QCoreApplication::translate("ControlNetConfigWidget", "Ap name", nullptr)); - labelApPassword->setText(QCoreApplication::translate("ControlNetConfigWidget", "Password", nullptr)); - lineEditHotspotName->setPlaceholderText(QCoreApplication::translate("ControlNetConfigWidget", "Input Ap name", nullptr)); - lineEditApPassword->setPlaceholderText(QCoreApplication::translate("ControlNetConfigWidget", "Input password", nullptr)); - pushButtonApSet->setText(QCoreApplication::translate("ControlNetConfigWidget", "Set", nullptr)); - label->setText(QCoreApplication::translate("ControlNetConfigWidget", "4G/5G Configuration", nullptr)); - checkBox4g->setText(QCoreApplication::translate("ControlNetConfigWidget", "Open 4G/5G", nullptr)); - pushButtonReadback4G->setText(QCoreApplication::translate("ControlNetConfigWidget", "Readback APN Info", nullptr)); - label_ApnInfo->setText(QCoreApplication::translate("ControlNetConfigWidget", " APN:", nullptr)); - pushButtonRead4GStatus->setText(QCoreApplication::translate("ControlNetConfigWidget", "Get cellular network status information", nullptr)); - groupBox_5->setTitle(QCoreApplication::translate("ControlNetConfigWidget", "Set Apn Info,Check SIM can automatically match to MCC, and then select carrier get apn param", nullptr)); - label_8->setText(QCoreApplication::translate("ControlNetConfigWidget", "Check SIM can automatically match to MCC, and then select carrier get apn param,if not found carrier,you can check the CUSTOM checkbox,then enter custom param.", nullptr)); - checkBoxCustom->setText(QCoreApplication::translate("ControlNetConfigWidget", "CUSTOM", nullptr)); - pushButtonGetMcc->setText(QCoreApplication::translate("ControlNetConfigWidget", "Check SIM", nullptr)); - label_9->setText(QCoreApplication::translate("ControlNetConfigWidget", "->", nullptr)); - label_2->setText(QCoreApplication::translate("ControlNetConfigWidget", "Country ID(mcc):", nullptr)); - label_11->setText(QCoreApplication::translate("ControlNetConfigWidget", "->", nullptr)); - label_3->setText(QCoreApplication::translate("ControlNetConfigWidget", "Carrier Name", nullptr)); - label_12->setText(QCoreApplication::translate("ControlNetConfigWidget", "->", nullptr)); - label_4->setText(QCoreApplication::translate("ControlNetConfigWidget", "APN:", nullptr)); - lineEditAPN->setPlaceholderText(QCoreApplication::translate("ControlNetConfigWidget", "APN(Required)", nullptr)); - label_6->setText(QCoreApplication::translate("ControlNetConfigWidget", "User:", nullptr)); - lineEditUser->setPlaceholderText(QCoreApplication::translate("ControlNetConfigWidget", "Not required", nullptr)); - label_7->setText(QCoreApplication::translate("ControlNetConfigWidget", "Password:", nullptr)); - lineEditPassword->setPlaceholderText(QCoreApplication::translate("ControlNetConfigWidget", "Not required", nullptr)); - pushButtonSet4GInfo->setText(QCoreApplication::translate("ControlNetConfigWidget", "Set", nullptr)); - pushButtonSetYuanHengApn->setText(QCoreApplication::translate("ControlNetConfigWidget", "Set Apn:iot.cargo", nullptr)); - label_10->setText(QCoreApplication::translate("ControlNetConfigWidget", "Flight Mode", nullptr)); - pushButtonReadbackFlightModel->setText(QCoreApplication::translate("ControlNetConfigWidget", "Readback", nullptr)); - - - btnLanGet->setProperty("ssType", "progManageTool"); - pushButtonReadbackWiFiModel->setProperty("ssType", "progManageTool"); - btnLanSet->setProperty("ssType", "progManageTool"); - pushButtonApSet->setProperty("ssType", "progManageTool"); - pushButtonWiFiModel->setProperty("ssType", "progManageTool"); - pushButtonScan->setProperty("ssType", "progManageTool"); - pushButtonReadback4G->setProperty("ssType", "progManageTool"); - pushButtonSet4GInfo->setProperty("ssType", "progManageTool"); - pushButtonGetMcc->setProperty("ssType", "progManageTool"); - pushButtonSetYuanHengApn->setProperty("ssType", "progManageTool"); - pushButtonReadbackFlightModel->setProperty("ssType", "progManageTool"); - pushButtonRead4GStatus->setProperty("ssType", "progManageTool"); - widgetFightModel->setSliderColor(QColor(0, 0, 0),QColor(0, 160, 230)); - widgetFightModel->setBgColor(QColor(200,200,200),QColor(0,200,0)); - widgetFightModel->setTextColor(QColor(100,100,100),QColor(0, 160, 230)); - widgetFightModel->setText(tr("OFF"),tr("ON")); - - m_buttonGroup = new QButtonGroup; - m_buttonGroup->addButton(fdDhcp,0); - m_buttonGroup->addButton(fdSpecifyIp,1); - - checkBox4g->setStyleSheet("QCheckBox::indicator {width: 16px; height: 16px;}"); - checkBoxCustom->setStyleSheet("QCheckBox::indicator {width: 16px; height: 16px;}"); - comboBoxCountryID->setStyleSheet("background:rgba(216,216,216,1);"); - comboBoxCarrierName->setStyleSheet("background:rgba(216,216,216,1);"); - lineEditAPN->setStyleSheet("background:rgba(216,216,216,1);"); - lineEditUser->setStyleSheet("background:rgba(216,216,216,1);"); - lineEditPassword->setStyleSheet("background:rgba(216,216,216,1);"); - checkBox4g->setChecked(true); - fdDhcp->setChecked(true); - - connect(this,SIGNAL(sigGetDhcpOrSpecifyIp(int)),this,SLOT(OnDhcpOrSpecifyIp(int))); - connect(m_buttonGroup,SIGNAL(buttonClicked(int)),this,SLOT(OnDhcpOrSpecifyIp(int))); - - connect(pushButtonWiFiModel, SIGNAL(clicked()), this, SLOT(onSetWiFiModel())); - connect(pushButtonReadbackWiFiModel, SIGNAL(clicked()), this, SLOT(onReadbackWiFiModel())); - connect(pushButtonApSet, SIGNAL(clicked()), this, SLOT(onSetAp())); - connect(pushButtonScan,SIGNAL(clicked()),this,SLOT(OnScanWifi())); - - connect(pushButtonSet4GInfo, SIGNAL(clicked()), this, SLOT(onSet4GInfo())); - connect(pushButtonReadback4G, SIGNAL(clicked()), this, SLOT(onReadback4G())); - connect(pushButtonGetMcc, SIGNAL(clicked()), this, SLOT(onGetMcc())); - connect(pushButtonRead4GStatus, SIGNAL(clicked()), this, SLOT(onGet4GStatus())); - - connect(comboBoxCountryID, SIGNAL(currentIndexChanged(int)), this, SLOT(OnComboMccChanged(int))); - connect(comboBoxCarrierName, SIGNAL(currentIndexChanged(int)), this, SLOT(OnComboCarrierChanged(int))); - connect(checkBoxCustom, SIGNAL(clicked(bool)), this, SLOT(OnCustom4G(bool))); - connect(checkBox4g, SIGNAL(clicked(bool)), this, SLOT(OnOpne4G(bool))); - connect(widgetFightModel, SIGNAL(checkedChanged(bool)), this, SLOT(onFightModelChecked(bool))); - connect(pushButtonReadbackFlightModel, SIGNAL(clicked()), this, SLOT(onReadbackFlightModel())); - - MARCO_DEFINE_CONTROL_FUNC2(parent->parent(),parent) - emit sigGetDhcpOrSpecifyIp(0); - - pushButtonSetYuanHengApn->setVisible(false); - checkBoxCustom->setVisible(false); - OnCustom4G(true); - - transUi(); -} - -ControlNetConfigWidget::~ControlNetConfigWidget() -{ - if(pHpptClient != nullptr) - { - qDebug() <<"delete pHpptClient in ~NetComm"; - delete pHpptClient; - pHpptClient=nullptr; - } - if(pHpptClientAll != nullptr) - { - qDebug() <<"delete pHpptClientAll in ~NetComm"; - delete pHpptClientAll; - pHpptClientAll=nullptr; - } -} -void ControlNetConfigWidget::changeEvent(QEvent *event) { - QWidget::changeEvent(event); - if(event->type() == QEvent::LanguageChange) transUi(); -} -void ControlNetConfigWidget::transUi() { - lbLanCfg->setText(tr("Wire Enther(RJ45) Configuration")); - fdDhcp->setText(tr("DHCP")); - fdSpecifyIp->setText(tr("Specify IP")); - labelApName->setText(tr("AP name")); - labelGateway->setText(tr("Gateway")); - labelWifiName->setText(tr("WiFi name")); - labelIpAddress->setText(tr("IP Address")); - labelApPassword->setText(tr("Password")); - labelDnsAddress->setText(tr("DNS Address")); - labelMaskAddress->setText(tr("Subnet mask")); - labelWifiPassword->setText(tr("Password")); - pushButtonScan->setText(tr("Scan")); - pushButtonApSet->setText(tr("Set")); - pushButtonWiFiModel->setText(tr("Set")); - btnLanSet->setText(tr("Set")); - pushButtonReadbackWiFiModel->setText(tr("Readback")); - btnLanGet->setText(tr("Readback")); - groupBox_3->setTitle(tr("WiFi On/Off")); - groupBox_4->setTitle(tr("Ap Mode")); - label_5->setText(tr("WIFI Configuration")); - lineEditApPassword->setPlaceholderText(tr("Input password")); - lineEditWifiPassword->setPlaceholderText(tr("Input password")); - lineEditHotspotName->setPlaceholderText(tr("Input ap name")); - label->setText(tr("4G/5G Configuration")); - label_8->setText(tr("Check SIM can automatically match to MCC, and then select carrier get apn param,if not found carrier,you can check the CUSTOM checkbox,then enter custom param.")); - checkBox4g->setText(tr("Open 4G/5G")); - - - groupBox_5->setTitle(tr("Set Apn Info,Check SIM can automatically match to MCC, and then select carrier get apn param")); - checkBoxCustom->setText(tr("CUSTOM")); - pushButtonGetMcc->setText(tr("Check SIM")); - label_2->setText(tr("Country ID(mcc):")); - label_3->setText(tr("Carrier Name")); - label_4->setText(tr("APN:")); - label_6->setText(tr("User:")); - label_7->setText(tr("Password:")); - pushButtonSet4GInfo->setText(tr("Set")); - lineEditAPN->setPlaceholderText(tr("APN(Required)")); - lineEditUser->setPlaceholderText(tr("Not required")); - lineEditPassword->setPlaceholderText(tr("Not required")); - pushButtonReadback4G->setText(tr("Readback APN Info")); - pushButtonReadbackFlightModel->setText(tr("Readback")); - pushButtonRead4GStatus->setText(tr("Get cellular network status information")); - label_10->setText(tr("Flight Mode")); -} - -void ControlNetConfigWidget::OnDhcpOrSpecifyIp(int iIndex) -{ - if(iIndex==0) - { - gBoxSpecifyIp->setEnabled(false); - fdDns->setStyleSheet("QLineEdit{background:rgba(216,216,216,1);}"); - fdIP->setStyleSheet("QLineEdit{background:rgba(216,216,216,1);}"); - fdMask->setStyleSheet("QLineEdit{background:rgba(216,216,216,1);}"); - fdGateWay->setStyleSheet("QLineEdit{background:rgba(216,216,216,1);}"); - fdDns->MySetColor(QColor::fromRgb(216,216,216)); - fdIP->MySetColor(QColor::fromRgb(216,216,216)); - fdMask->MySetColor(QColor::fromRgb(216,216,216)); - fdGateWay->MySetColor(QColor::fromRgb(216,216,216)); - } - else { - gBoxSpecifyIp->setEnabled(true); - fdDns->setStyleSheet("QLineEdit{background:rgba(255,255,255,1);}"); - fdIP->setStyleSheet("QLineEdit{background:rgba(255,255,255,1);}" ); - fdMask->setStyleSheet("QLineEdit{background:rgba(255,255,255,1);}" ); - fdGateWay->setStyleSheet("QLineEdit{background:rgba(255,255,255,1);}"); - fdDns->MySetColor(QColor::fromRgb(255,255,255)); - fdIP->MySetColor(QColor::fromRgb(255,255,255)); - fdMask->MySetColor(QColor::fromRgb(255,255,255)); - fdGateWay->MySetColor(QColor::fromRgb(255,255,255)); - } - -} -void ControlNetConfigWidget::onSelectedDeviceList(QList *list) -{ - m_pLedlist=list; - if(m_pLedlist==nullptr) - return; - if(m_pLedlist->count()==1) - { - if(groupBox_3->isChecked()) - pushButtonScan->setEnabled(true); - } - else { - if(groupBox_3->isChecked()) - pushButtonScan->setEnabled(false); - } - //MACRO_DEFINE_CONTROL_FUNC3 - if(m_pLedlist->count()==1) - { - m_pLedCard=list->at(0); - m_strUrl="http://"+m_pLedCard->m_strCardIp+":2016/settings"; - if(m_oldLedlist!=m_pLedCard&&m_bSelected==true) - { - m_oldLedlist=m_pLedCard; - onReadbackAllThisPage(); - } - } -} -void ControlNetConfigWidget::onReadbackAllThisPage() -{ - if(m_pLedlist==nullptr) - return; - if(m_pLedlist->count()!=1) - return; - - QJsonObject json; - json.insert("_id", "GetEthernet"); - json.insert("_type", "GetEthernet"); - if(gSelCards->count() == 1) { - auto card = gSelCards->at(0); - auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); - connect(reply, &QNetworkReply::finished, this, [this, reply] { - QJsonDocument json; - QString err = checkReplyForJson(reply, &json); - if(! err.isEmpty()) { - QMessageBox::critical(gMainWin, tr("Error"), err); - return; - } - if(json["dhcp"].toBool()) { - fdDhcp->setChecked(true); - emit sigGetDhcpOrSpecifyIp(0); - } else { - fdSpecifyIp->setChecked(true); - emit sigGetDhcpOrSpecifyIp(1); - } - fdIP->setText(json["ipAddr"].toString()); - fdGateWay->setText(json["gateWay"].toString()); - fdMask->setText(json["netMask"].toString()); - fdDns->setText(json["dnsAddr"].toString()); - }); - } - - QJsonObject json1; - json1.insert("_id", getRandomString(10)); - json1.insert("_type", "GetWifiList"); - HttpPostByTypeJsonObject(pHpptClientAll,m_strUrl,json1); - comboBox->clear(); - QJsonObject json55; - json55.insert("_id", getRandomString(10)); - json55.insert("_type", "GetSwitchSimData"); - HttpPostByTypeJsonObject(pHpptClientAll,m_strUrl,json55); - QJsonObject json2; - json2.insert("_id", getRandomString(10)); - json2.insert("_type", "IsPortableHotSpot"); - HttpPostByTypeJsonObject(pHpptClientAll,m_strUrl,json2); - QJsonObject json66; - json66.insert("_id", getRandomString(10)); - json66.insert("_type", "GetSwitchWiFi"); - HttpPostByTypeJsonObject(pHpptClientAll,m_strUrl,json66); - QJsonObject json3; - json3.insert("_id", getRandomString(10)); - json3.insert("_type", "GetAPNList"); - HttpPostByTypeJsonObject(pHpptClientAll,m_strUrl,json3); - - QJsonObject json4; - json4.insert("_id", getRandomString(10)); - json4.insert("_type", "GetCurrentAPN"); - HttpPostByTypeJsonObject(pHpptClientAll,m_strUrl,json4); - - QJsonObject json5; - json5.insert("_id", getRandomString(10)); - json5.insert("_type", "GetTimezone"); - HttpPostByTypeJsonObject(pHpptClientAll,m_strUrl,json5); - - QJsonObject json6; - json6.insert("_id", getRandomString(10)); - json6.insert("_type", "GetFlightModeState"); - HttpPostByTypeJsonObject(pHpptClientAll,m_strUrl,json6); - MACRO_DEFINE_TIPDLG_ALL_FUCN(tr("Readback"),tr("Success"),tr("failed")) -} -void ControlNetConfigWidget::onSetWiFiModel() -{ - CHECK_CARD_SELECTED - - if(groupBox_3->isChecked()) - { - comboBox->setStyleSheet("background:rgba(216,216,216,1);"); - lineEditWifiPassword->setStyleSheet("background:rgba(216,216,216,1);"); - - } - else { - comboBox->setStyleSheet("background:rgba(216,216,216,1);"); - lineEditWifiPassword->setStyleSheet("background:rgba(216,216,216,1);"); - - } - - if(m_pLedlist->count()==1) - { - if(groupBox_3->isChecked()) - { - comboBox->setStyleSheet("background:rgba(255,255,255,1);"); - lineEditWifiPassword->setStyleSheet("background:rgba(255,255,255,1);"); - QJsonObject json1; - json1.insert("_id", getRandomString(10)); - json1.insert("_type", "SetSwitchWiFi"); - json1.insert("enable", true); - HttpPostByTypeJsonObject(pHpptClient,m_strUrl,json1); - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "ConfigurationWiFi"); - QString strSsid=comboBox->currentText(); - if(strSsid.contains(tr("SignalPower"))) - { - int itempOffset=strSsid.indexOf(tr("SignalPower")); - strSsid=strSsid.left(itempOffset-4); - } - qDebug()<<"strSsid="<text()); - HttpPostByTypeJsonObject(pHpptClient,m_strUrl,json); - MACRO_DEFINE_TIPDLG_FUCN(tr("ConfigurationWiFi"),tr("Success"),tr("failed")) - } - - } - else { - if(groupBox_3->isChecked()) - { - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "ConfigurationWiFi"); - QString strSsid=comboBox->currentText(); - if(strSsid.contains(tr("SignalPower"))) - { - int itempOffset=strSsid.indexOf(tr("SignalPower")); - strSsid=strSsid.left(itempOffset-4); - } - qDebug()<<"strSsid="<text()); - emit sigSend(json,tr("ConfigurationWiFi")); - } - } -} - -void ControlNetConfigWidget:: onReadbackWiFiModel() -{ - - CHECK_CARD_SELECTED - QJsonObject json66; - json66.insert("_id", getRandomString(10)); - json66.insert("_type", "GetSwitchWiFi"); - HttpPostByTypeJsonObject(pHpptClientAll,m_strUrl,json66); - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "IsPortableHotSpot"); - - MACRO_DEFINE_TIPDLG_FUCN(tr("IsPortableHotSpot"),tr("Success"),tr("failed")) -} -void ControlNetConfigWidget:: OnScanWifi() -{ - CHECK_CARD_SELECTED - - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "GetWifiList"); - comboBox->clear(); - MACRO_DEFINE_TIPDLG_FUCN(tr("GetWifiList"),tr("Success"),tr("failed")) -} -void ControlNetConfigWidget:: onSetAp() -{ - CHECK_CARD_SELECTED - if(groupBox_4->isChecked()) - { - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "ConfigurationHotSpot"); - json.insert("apName", lineEditHotspotName->text()); - json.insert("password", lineEditApPassword->text()); - MACRO_DEFINE_TIPDLG_FUCN(tr("ConfigurationHotSpot"),tr("Success"),tr("failed")) - } -} - -void ControlNetConfigWidget::onReadback4G() -{ - CHECK_CARD_SELECTED - lineEditApnInfo->setText(""); - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "GetCurrentAPN"); - MACRO_DEFINE_TIPDLG_FUCN(tr("GetCurrentAPN"),tr("Success"),tr("failed")) -} -void ControlNetConfigWidget::onGetMcc() -{ - m_buttonFlagClick=1; - CHECK_CARD_SELECTED - - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "GetSIMStatus"); - MACRO_DEFINE_TIPDLG_FUCN(tr("GetSIMStatus"),tr("Success"),tr("failed")) -} -void ControlNetConfigWidget::onGet4GStatus() -{ - m_buttonFlagClick=0; - CHECK_CARD_SELECTED - - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "GetSIMStatus"); - MACRO_DEFINE_TIPDLG_FUCN(tr("GetSIMStatus"),tr("Success"),tr("failed")) -} -void ControlNetConfigWidget::onSet4GInfo() -{ - CHECK_CARD_SELECTED - - QJsonObject json; - if(checkBoxCustom->isChecked()) - { - json.insert("_id", getRandomString(10)); - json.insert("_type", "SetAPN"); - json.insert("carrier", comboBoxCarrierName->currentText()); - json.insert("apn",lineEditAPN->text()); - json.insert("user", lineEditUser->text()); - json.insert("password", lineEditPassword->text()); - json.insert("type",""); - json.insert("server", ""); - json.insert("proxy", ""); - json.insert("port",""); - json.insert("mmsc",""); - json.insert("mmsproxy",""); - json.insert("mmsport",""); - } - else { - json.insert("_id", getRandomString(10)); - json.insert("_type", "SetAPN"); - json.insert("carrier", m_4gObj["carrier"].toString()); - json.insert("apn",lineEditAPN->text()); - json.insert("user", lineEditUser->text()); - json.insert("password", lineEditPassword->text()); - json.insert("type", m_4gObj["type"].toString()); - json.insert("server", m_4gObj["server"].toString()); - json.insert("proxy", m_4gObj["proxy"].toString()); - json.insert("port", m_4gObj["port"].toString()); - json.insert("mmsc", m_4gObj["mmsc"].toString()); - json.insert("mmsproxy", m_4gObj["mmsproxy"].toString()); - json.insert("mmsport", m_4gObj["mmsport"].toString()); - } - MACRO_DEFINE_TIPDLG_FUCN(tr("SetAPN"),tr("Success"),tr("failed")) -} -//获取到httpPost的应答,如果参数变化需要出发修改控件item的内容 -void ControlNetConfigWidget::OnProHttpResponse(QString url, QString postMD5, QByteArray data) { - Q_UNUSED(postMD5) - //qDebug()<< url + "\r\n"+m_strUrl; - if(url == m_strUrl) - { - QJsonParseError parseJsonErr; - QJsonDocument document = QJsonDocument::fromJson(data,&parseJsonErr); - if(!(parseJsonErr.error == QJsonParseError::NoError)) - { - if(data.size()==0) - qDebug()<<"json is empty"; - else - qDebug()<setChecked(jsonObject["enable"].toBool()); - } - else if(strType == "GetWifiList") - { - //QVariant iTemp=jsonObject["wifiList"].toVariant(); - QJsonValue value = jsonObject.take("wifiList"); - QJsonArray array= value.toArray(); - int iSize=array.size(); - QList wifInfoiList; - for(int i=0;i infoB.signal;}); - for(int j=0;jaddItem(wifInfoiList.at(j).ssid+"...["+tr("SignalPower")+":"+strSignalPower+"]"); - - } - } - else if(strType == "IsPortableHotSpot") - { - QString iTemp=jsonObject["wifi"].toString(); -// if(iTemp.isEmpty()) -// groupBox_3->setChecked(false); -// else -// { -// groupBox_3->setChecked(true); -// } - QString strKong=""; - comboBox->setCurrentText(iTemp+strKong); - QString iTempHotSpot=jsonObject["hotSpots"].toString(); - if(iTempHotSpot.isEmpty()) - groupBox_4->setChecked(false); - else - groupBox_4->setChecked(true); - lineEditHotspotName->setText(iTempHotSpot); - } - else if(strType == "SetAPN") - { - onReadback4G(); - } - else if(strType == "GetSIMStatus") { - QString str4GStatus=""; - if(m_buttonFlagClick==0) { - str4GStatus = tr("状态:"); - switch(jsonObject["state"].toInt()) { - case 0: - case 1: - str4GStatus+=tr("未知"); - break; - case 2: - str4GStatus+=tr("锁定状态,需要用户的PIN码解锁"); - break; - case 3: - str4GStatus+=tr("锁定状态,需要用户的PUK码解锁"); - break; - case 4: - str4GStatus+=tr("锁定状态,需要网络的PIN码解锁"); - break; - case 5: - str4GStatus+=tr("就绪"); - break; - } - } - QString strImsi=jsonObject["imsi"].toString(); - if(strImsi.isEmpty()) { - str4GStatus+="\r\n"+tr("no checked sim card"); - QMessageBox::information(gMainWin, tr("Tip"),str4GStatus); - } else { - str4GStatus+="\r\nAPN: "+apn+"\r\nIMSI: "+strImsi+"\r\n"; - mcc = strImsi.left(3); - //comboBoxCountryID->setCurrentText(m_mcc); - comboBoxCountryID->setCurrentText(""); - comboBoxCarrierName->setCurrentText(""); - lineEditAPN->setText(""); - lineEditUser->setText(""); - lineEditPassword->setText(""); - - //SetMcc(m_mcc); - str4GStatus+=tr("国家码:"); - str4GStatus+=jsonObject["countryCode"].toString()+"("+mcc+")\r\n"; - str4GStatus+=tr("号码:"); - str4GStatus+=jsonObject["phoneNumber"].toString()+"\r\n"; - if(m_buttonFlagClick==0) - { - str4GStatus+=tr("用户:"); - str4GStatus+=jsonObject["user"].toString()+"\r\n"; - str4GStatus+=tr("信号:"); - switch(jsonObject["serviceState"].toInt()) - { - case 0: str4GStatus+=tr("信号正常")+"\r\n"; break; - case 1: str4GStatus+=tr("不在服务区")+"\r\n"; break; - case 2: str4GStatus+=tr("仅限紧急呼叫")+"\r\n"; break; - case 3: str4GStatus+=tr("射频已经关闭")+"\r\n"; break; - } - str4GStatus+=tr("网络:"); - switch(jsonObject["networkType"].toInt()) - { - case 0: str4GStatus+=tr("网络类型未知")+"\r\n"; break; - case 1: str4GStatus+=tr("GPRS网络")+"\r\n"; break; - case 2: str4GStatus+=tr("EDGE网络")+"\r\n"; break; - case 3: str4GStatus+=tr("UMTS网络")+"\r\n"; break; - case 4: str4GStatus+=tr("CDMA网络,IS95A 或 IS95B.")+"\r\n"; break; - case 5: str4GStatus+=tr("EVDO网络, revision 0.")+"\r\n"; break; - case 6: str4GStatus+=tr("EVDO网络, revision A.")+"\r\n"; break; - case 7: str4GStatus+=tr("1xRTT网络")+"\r\n"; break; - case 8: str4GStatus+=tr("HSDPA网络")+"\r\n"; break; - case 9: str4GStatus+=tr("HSUPA网络")+"\r\n"; break; - case 10: str4GStatus+=tr("HSPA网络")+"\r\n"; break; - } - str4GStatus+=tr("漫游:"); - - // 是否为漫游 - if(jsonObject["roaming"].toBool()) - { - str4GStatus+=tr("Yes")+"\r\n"; - } - else - { - str4GStatus+=tr("No")+"\r\n"; - } - str4GStatus+=tr("数据连接状态:"); - switch(jsonObject["dataState"].toInt()) - { - case 0: str4GStatus+=tr("断开")+"\r\n"; break; - case 1: str4GStatus+=tr("正在连接")+"\r\n"; break; - case 2: str4GStatus+=tr("已连接")+"\r\n"; break; - case 3: str4GStatus+=tr("暂停")+"\r\n"; break; - } - str4GStatus+=tr("数据活动休眠状态:"); - switch(jsonObject["dataActivity"].toInt()) - { - case 0: str4GStatus+=tr("活动,但无数据发送和接收")+"\r\n"; break; - case 1: str4GStatus+=tr("活动,正在接收数据")+"\r\n"; break; - case 2: str4GStatus+=tr("活动,正在发送数据")+"\r\n"; break; - case 3: str4GStatus+=tr("活动,正在接收和发送数据")+"\r\n"; break; - case 4: str4GStatus+=tr("休眠状态")+"\r\n"; break; - } - str4GStatus+=tr("信号强度:"); - QString strSignalStrength=QString::number(jsonObject["signalStrength"].toInt()); - str4GStatus+=strSignalStrength+"\r\n"; - } - QMessageBox::information(gMainWin, tr("Tip"),str4GStatus); - } - } - else if(strType == "GetCurrentAPN"){ -// lineEditAPN->setText(jsonObject["apn"].toString()); -// lineEditUser->setText(jsonObject["user"].toString()); -// lineEditPassword->setText(jsonObject["password"].toString()); - apn = jsonObject["apn"].toString(); - if(jsonObject["user"].toString().isEmpty()) lineEditApnInfo->setText(apn); - else lineEditApnInfo->setText(apn+",USER:"+jsonObject["user"].toString()+",PASSWORD:"+jsonObject["password"].toString()); - } - else if(strType == "SetSwitchSimData"){ - } - else if(strType=="ContrFlightMode"){ - } - else if(strType=="GetFlightModeState"){ - //widgetFightModel->setChecked(jsonObject["result"].toBool()); - widgetFightModel->setCheckedStatus(jsonObject["result"].toBool()); - widgetFightModel->update(); - } - else if(strType == "GetTimezone"){ - QString strtemp=jsonObject["timezone"].toString(); - // strtemp=strtemp.right(strtemp.length()-strtemp.indexOf("/")-1); - //comboBox_Timezone->setCurrentText(strtemp); - } - else if(strType == "SetTimezone"){ - - } - - - if(strType!="SetSwitchWiFi") - { - if(iEnableFlag==true) - { - iEnableFlag=false; - MACRO_ASKTIME_STOP - MACRO_POSTING_DLG_UNLOCK - - } - - } - - } - } -} - -void ControlNetConfigWidget::OnProHttpResponseAll(QString url, QString postMD5, QByteArray data) -{ - Q_UNUSED(postMD5) - //qDebug()<< url + "\r\n"+m_strUrl; - if(url == m_strUrl) - { - QJsonParseError parseJsonErr; - QJsonDocument document = QJsonDocument::fromJson(data,&parseJsonErr); - if(!(parseJsonErr.error == QJsonParseError::NoError)) - { - if(data.size()==0) - qDebug()<<"json is empty"; - else - qDebug()<setChecked(jsonObject["enable"].toBool()); - else if(strType == "GetWifiList") { - QJsonValue value = jsonObject.take("wifiList"); - QJsonArray array= value.toArray(); - int iSize=array.size(); - QList wifInfoiList; - for(int i=0;iaddItem(wifInfoiList.at(j).ssid+"...["+tr("SignalPower")+":"+strSignalPower+"]"); - } - - } - else if(strType == "IsPortableHotSpot") - { - QString iTemp=jsonObject["wifi"].toString(); - QString strKong=""; - comboBox->setCurrentText(iTemp+strKong); - QString iTempHotSpot=jsonObject["hotSpots"].toString(); - if(iTempHotSpot.isEmpty()) - groupBox_4->setChecked(false); - else - groupBox_4->setChecked(true); - lineEditHotspotName->setText(iTempHotSpot); - if(iEnableFlag==true) - { - iEnableFlag=false; - MACRO_ASKTIME_STOP - MACRO_POSTING_DLG_UNLOCK - } - } - else if(strType == "GetAPNList") - { - qDebug()<<"GetAPNList"; - if(m_ApnInfoiList.count()<=0) - { -// if(m_ApnInfoiList.count()>0) -// m_ApnInfoiList.clear(); -// if(comboBoxCountryID->count()>0) -// comboBoxCountryID->clear(); -// if(comboBoxCarrierName->count()>0) -// comboBoxCarrierName->clear(); - foreach(QJsonValue value, jsonObject["apns"].toArray()) { - QJsonObject oApn = value.toObject(); - QString strtempmcc=oApn["mcc"].toString(); - bool itempHave=false; - for (int i=0;icount();i++) { - if(strtempmcc==comboBoxCountryID->itemText(i)) - { - itempHave=true; - break; - } - - } - qDebug()<addItem(strtempmcc); - m_ApnInfoiList.append(oApn); - } - } - comboBoxCountryID->setCurrentText(""); - - - } - else if(strType=="GetFlightModeState") - { - //widgetFightModel->setChecked(jsonObject["result"].toBool()); - widgetFightModel->setCheckedStatus(jsonObject["result"].toBool()); - widgetFightModel->update(); - } - else if(strType == "GetCurrentAPN") { - apn = jsonObject["apn"].toString(); -// lineEditAPN->setText(strApn); -// lineEditUser->setText(jsonObject["user"].toString()); -// lineEditPassword->setText(jsonObject["password"].toString()); - if(jsonObject["user"].toString().isEmpty()) lineEditApnInfo->setText(apn); - else lineEditApnInfo->setText(apn+",USER:"+jsonObject["user"].toString()+",PASSWORD:"+jsonObject["password"].toString()); - } - else if(strType == "GetTimezone"){ - QString strtemp=jsonObject["timezone"].toString(); - //comboBox_Timezone->setCurrentText(strtemp); - } - else if(strType == "SetTimezone"){ - - } - else if(strType == "GetSwitchSimData"){ - bool b=jsonObject["enable"].toBool(); - checkBox4g->setChecked(b); - pushButtonSet4GInfo->setVisible(b); - pushButtonReadback4G->setVisible(b); - pushButtonGetMcc->setVisible(b); -#ifndef MACRO_YUANHENG_VERSION - comboBoxCountryID->setVisible(b); - comboBoxCarrierName->setVisible(b); - //checkBoxCustom->setVisible(b); - lineEditAPN->setVisible(b); - lineEditUser->setVisible(b); - lineEditPassword->setVisible(b); - label_2->setVisible(b); - label_3->setVisible(b); - label_4->setVisible(b); - label_6->setVisible(b); - label_7->setVisible(b); - label_8->setVisible(b); -#else - lineEditAPN->setVisible(b); - -#endif - } - } - } -} -void ControlNetConfigWidget::OnControlTypeSwitchIndexChanged(int index) -{ - if(index==Setting_NetCfg) - { - m_bSelected=true; - if(m_pLedCard!=nullptr) - onReadbackAllThisPage(); - } - else { - m_bSelected=false; - } -} -void ControlNetConfigWidget::OnComboMccChanged(int index) -{ - Q_UNUSED(index); - SetMcc(comboBoxCountryID->currentText()); -} - -void ControlNetConfigWidget::SetMcc(QString strMcc) -{ - qDebug()<<"SetMcc:"<clear(); - foreach(QJsonObject obj, m_ApnInfoiList) - { - if(obj["mcc"].toString()==strMcc) - { - m_MccCarrierInfoiList.append(obj); - comboBoxCarrierName->addItem(obj["carrier"].toString()); - // comboBoxCarrierName->insertItem(0,obj["carrier"].toString()); - } - } - comboBoxCarrierName->clearEditText(); -// if(comboBoxCarrierName->isEditable()==false) -// { -// comboBoxCarrierName->setEditable(true); -// comboBoxCarrierName->setCurrentText(""); -// comboBoxCarrierName->setEditable(false); -// } - - -} -void ControlNetConfigWidget::OnComboCarrierChanged(int index) -{ - if(m_MccCarrierInfoiList.count()>0 && indexsetText(m_4gObj["apn"].toString()); - lineEditUser->setText(m_4gObj["user"].toString()); - lineEditPassword->setText(m_4gObj["password"].toString()); - } -} -void ControlNetConfigWidget::OnCustom4G(bool b) -{ - //pushButtonGetMcc->setEnabled(b); - comboBoxCountryID->setEditable(b); - comboBoxCarrierName->setEditable(b); - - lineEditUser->setReadOnly(!b); - lineEditPassword->setReadOnly(!b); - if(b) - { - comboBoxCountryID->setStyleSheet("background:rgba(255,255,255,1);"); - comboBoxCarrierName->setStyleSheet("background:rgba(255,255,255,1);"); - lineEditAPN->setStyleSheet("background:rgba(255,255,255,1);"); - lineEditUser->setStyleSheet("background:rgba(255,255,255,1);"); - lineEditPassword->setStyleSheet("background:rgba(255,255,255,1);"); - - } - else { - comboBoxCountryID->setStyleSheet("background:rgba(216,216,216,1);"); - comboBoxCarrierName->setStyleSheet("background:rgba(216,216,216,1);"); - lineEditAPN->setStyleSheet("background:rgba(216,216,216,1);"); - lineEditUser->setStyleSheet("background:rgba(216,216,216,1);"); - lineEditPassword->setStyleSheet("background:rgba(216,216,216,1);"); - - } -#ifndef MACRO_YUANHENG_VERSION - lineEditAPN->setReadOnly(false); -#else - lineEditAPN->setReadOnly(!b); - lineEditAPN->setStyleSheet("background:rgba(255,255,255,1);"); - -#endif -} -void ControlNetConfigWidget::OnOpne4G(bool b) -{ - CHECK_CARD_SELECTED - pushButtonSet4GInfo->setVisible(b); - pushButtonReadback4G->setVisible(b); - pushButtonGetMcc->setVisible(b); - groupBox_5->setVisible(b); - comboBoxCountryID->setVisible(b); - comboBoxCarrierName->setVisible(b); - lineEditAPN->setVisible(b); - lineEditUser->setVisible(b); - lineEditPassword->setVisible(b); - label_2->setVisible(b); - label_3->setVisible(b); - label_4->setVisible(b); - label_6->setVisible(b); - label_7->setVisible(b); - label_8->setVisible(b); - - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "SetSwitchSimData"); - json.insert("enable", b); - MACRO_DEFINE_TIPDLG_FUCN(tr("SetSwitchSimData"),tr("Success"),tr("failed")) -} - -void ControlNetConfigWidget::DeletePostingDlg() -{ - qDebug()<<"ControlNetConfigWidget::DeletePostingDlg"; - if(m_PostingDlg!=nullptr) - { - delete m_PostingDlg; - m_PostingDlg=nullptr; - iEnableFlag=true; - } -} -void ControlNetConfigWidget::onFightModelChecked(bool b) -{ - CHECK_CARD_SELECTED - - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "ContrFlightMode"); - json.insert("state", b); - MACRO_DEFINE_TIPDLG_FUCN(tr("ContrFlightMode"),tr("Success"),tr("failed")) -} -void ControlNetConfigWidget::onReadbackFlightModel() -{ - CHECK_CARD_SELECTED - - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "GetFlightModeState"); - MACRO_DEFINE_TIPDLG_FUCN(tr("GetFlightModeState"),tr("Success"),tr("failed")) -} diff --git a/LedOK/wDevicesManager/controlnetconfigwidget.h b/LedOK/wDevicesManager/controlnetconfigwidget.h deleted file mode 100644 index 201af2d..0000000 --- a/LedOK/wDevicesManager/controlnetconfigwidget.h +++ /dev/null @@ -1,182 +0,0 @@ -#ifndef CONTROLNETCONFIGWIDGET_H -#define CONTROLNETCONFIGWIDGET_H - -#include -#include -#include -#include "base/qiplineedit.h" -#include "base/switchcontrol.h" -#include -#include -#include -#include -#include - -typedef struct wifiInfo{ - QString ssid; - int signal; - QString encryptionMethod; - -}ST_WIFiINFO; -typedef struct ApnInfo{ - QString apn; - QString carrier; - QString mcc; - QString mmsc; - QString mmsport; - QString mmsproxy; - QString mnc; - QString password; - QString port; - QString proxy; - QString server; - QString type; - QString user; -}ST_APNINFO; -class ControlNetConfigWidget : public QWidget { - Q_OBJECT -public: - explicit ControlNetConfigWidget(QWidget *parent = nullptr,QList *m_pLedlist=nullptr); - ~ControlNetConfigWidget(); -protected slots: - void changeEvent(QEvent *) override; - void transUi(); - - void onSetWiFiModel(); - void onReadbackWiFiModel(); - void onSetAp(); - void OnDhcpOrSpecifyIp(int iIndex); - void OnScanWifi(); - void onSet4GInfo(); - void onReadback4G(); - void onReadbackFlightModel(); - void onGetMcc(); - void onGet4GStatus(); - void SetMcc(QString strMcc); - void onFightModelChecked(bool b); -signals: - void sigSend(QJsonObject &,QString); - void sigGetDhcpOrSpecifyIp(int); -protected slots: - void DeletePostingDlg(); - void OnProHttpResponse(QString url, QString postMD5, QByteArray data); - void OnProHttpResponseAll(QString url, QString postMD5, QByteArray data); - void onSelectedDeviceList(QList *); - void onReadbackAllThisPage(); - void OnControlTypeSwitchIndexChanged(int index); - void OnComboMccChanged(int); - void OnComboCarrierChanged(int index); - void OnCustom4G(bool b); - void OnOpne4G(bool b); - -private: - QList *m_pLedlist=nullptr; - LedCard *m_pLedCard = nullptr; - LedCard *m_oldLedlist = nullptr; - HpptClient *pHpptClient = nullptr; - HpptClient *pHpptClientAll = nullptr; - QString m_strUrl=""; - LoEmptyDialog * m_PostingDlg=nullptr; - QTimer *m_pGetAskTimer=nullptr; - bool m_bSelected=false; - QList m_ApnInfoiList; - QList m_MccCarrierInfoiList; - QJsonObject m_4gObj; - QString mcc; - QString apn; - bool iEnableFlag=true; - int m_buttonFlagClick=0; - - - QButtonGroup *m_buttonGroup; - QLabel *lbLanCfg; - QRadioButton *fdDhcp; - QRadioButton *fdSpecifyIp; - QVBoxLayout *vBoxSpecifyIp; - QGroupBox *gBoxSpecifyIp; - QLabel *labelIpAddress; - QIPLineEdit *fdIP; - QLabel *labelMaskAddress; - QIPLineEdit *fdGateWay; - QLabel *labelGateway; - QIPLineEdit *fdMask; - QLabel *labelDnsAddress; - QIPLineEdit *fdDns; - QPushButton *btnLanSet; - QPushButton *btnLanGet; - QLabel *label_5; - QHBoxLayout *horizontalLayout_2; - QVBoxLayout *verticalLayout_6; - QGroupBox *groupBox_3; - QVBoxLayout *verticalLayout_7; - QHBoxLayout *horizontalLayout_9; - QVBoxLayout *verticalLayout_11; - QLabel *labelWifiName; - QLabel *labelWifiPassword; - QVBoxLayout *verticalLayout_12; - QComboBox *comboBox; - QLineEdit *lineEditWifiPassword; - QVBoxLayout *verticalLayout_13; - QPushButton *pushButtonScan; - QSpacerItem *horizontalSpacer_10; - QPushButton *pushButtonWiFiModel; - QPushButton *pushButtonReadbackWiFiModel; - QVBoxLayout *verticalLayout_4; - QGroupBox *groupBox_4; - QVBoxLayout *verticalLayout_8; - QHBoxLayout *horizontalLayout_12; - QVBoxLayout *verticalLayout_14; - QLabel *labelApName; - QLabel *labelApPassword; - QVBoxLayout *verticalLayout_15; - QLineEdit *lineEditHotspotName; - QLineEdit *lineEditApPassword; - QPushButton *pushButtonApSet; - QSpacerItem *horizontalSpacer_2; - QFrame *line_3; - QLabel *label; - QCheckBox *checkBox4g; - QHBoxLayout *horizontalLayout_13; - QPushButton *pushButtonReadback4G; - QLabel *label_ApnInfo; - QLineEdit *lineEditApnInfo; - QPushButton *pushButtonRead4GStatus; - QSpacerItem *horizontalSpacer_6; - QSpacerItem *verticalSpacer_2; - QGroupBox *groupBox_5; - QVBoxLayout *verticalLayout_16; - QLabel *label_8; - QCheckBox *checkBoxCustom; - QHBoxLayout *horizontalLayout_10; - QPushButton *pushButtonGetMcc; - QLabel *label_9; - QLabel *label_2; - QComboBox *comboBoxCountryID; - QLabel *label_11; - QLabel *label_3; - QComboBox *comboBoxCarrierName; - QLabel *label_12; - QLabel *label_4; - QLineEdit *lineEditAPN; - QSpacerItem *horizontalSpacer_3; - QHBoxLayout *horizontalLayout_11; - QLabel *label_6; - QLineEdit *lineEditUser; - QLabel *label_7; - QLineEdit *lineEditPassword; - QSpacerItem *horizontalSpacer_7; - QHBoxLayout *horizontalLayout_8; - QSpacerItem *horizontalSpacer_5; - QPushButton *pushButtonSet4GInfo; - QPushButton *pushButtonSetYuanHengApn; - QSpacerItem *horizontalSpacer_4; - QSpacerItem *verticalSpacer_4; - QHBoxLayout *horizontalLayout_15; - QLabel *label_10; - SwitchControl *widgetFightModel; - QPushButton *pushButtonReadbackFlightModel; - QSpacerItem *horizontalSpacer_8; - QSpacerItem *verticalSpacer; -}; - -#endif // CONTROLNETCONFIGWIDGET_H diff --git a/LedOK/wDevicesManager/controlpowermanual.cpp b/LedOK/wDevicesManager/controlpowermanual.cpp deleted file mode 100644 index 58a56c3..0000000 --- a/LedOK/wDevicesManager/controlpowermanual.cpp +++ /dev/null @@ -1,222 +0,0 @@ -#include "controlpowermanual.h" -#include "ui_controlpowermanual.h" -#include "base/x_uimsgboxok.h" -#include -#include -#include -#include -#include "tools.h" -ControlPowerManual::ControlPowerManual(QWidget *parent,QList *list) : - QWidget(parent), - ui(new Ui::ControlPowerManual) -{ - ui->setupUi(this); - refreshLable(); -setStyleSheet(Tools::styleSheet()); - ui->pushButtonReadback->setProperty("ssType", "progManageTool"); - ui->widget->setSliderColor(QColor(0, 0, 0),QColor(0, 160, 230)); - ui->widget->setBgColor(QColor(200,200,200),QColor(0,200,0)); - ui->widget->setTextColor(QColor(100,100,100),QColor(0, 160, 230)); - ui->widget->setText(tr("OFF"),tr("ON")); - //按钮槽函数绑定 - connect(ui->widget, SIGNAL(checkedChanged(bool)), this, SLOT(onPowerChecked(bool))); - connect(ui->pushButtonReadback,SIGNAL(clicked()),this,SLOT(OnReadback())); - MARCO_DEFINE_CONTROL_FUNC2(parent->parent()->parent(),parent->parent()) - -} - -ControlPowerManual::~ControlPowerManual() -{ - delete ui; - if(pHpptClient != nullptr) - { - qDebug() <<"delete pHpptClient in ~NetComm"; - delete pHpptClient; - pHpptClient=nullptr; - } - if(pHpptClientAll != nullptr) - { - qDebug() <<"delete pHpptClientAll in ~NetComm"; - delete pHpptClientAll; - pHpptClientAll=nullptr; - } -} -void ControlPowerManual::refreshLable() -{ - ui->labelPower->setText(tr("POWER")); - ui->pushButtonReadback->setText(tr("Readback")); -} - -void ControlPowerManual::OnReadback() -{ - if(m_pLedlist==nullptr) - return; - if(m_pLedlist->count()<=1) - { - if(m_pLedCard==nullptr||m_pLedlist->count()==0) - { - X_UIMsgBoxOk *pDlg=new X_UIMsgBoxOk(tr("Tip"),tr("NoSelectedController"),this,1); - pDlg->exec(); - return; - } - } - - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "IsScreenOn"); - MACRO_DEFINE_TIPDLG_FUCN(tr("IsScreenOn"),tr("Success"),tr("failed")) - -} -void ControlPowerManual::onPowerChecked(bool b) -{ - if(m_pLedlist==nullptr) - return; - if(m_pLedlist->count()<=1) - { - if(m_pLedCard==nullptr||m_pLedlist->count()==0) - { - X_UIMsgBoxOk *pDlg=new X_UIMsgBoxOk(tr("Tip"),tr("NoSelectedController"),this,1); - pDlg->exec(); - return; - } - } - - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "SetScreenOn"); - json.insert("on", b); - if(m_pLedlist->count()==1) - { - HttpPostByTypeJsonObject(pHpptClient,m_strUrl,json); - if(m_PostingDlg==nullptr) - { - m_PostingDlg = new LoEmptyDialog(this); - connect(m_PostingDlg,SIGNAL(sigClose()),this,SLOT(DeletePostingDlg())); - connect(m_pGetAskTimer,SIGNAL(timeout()),m_PostingDlg,SLOT(TimerOutUnlock())); - if(b) - m_PostingDlg->lock(tr("SetScreenOn"),tr("Success"),tr("SetScreenOn")+tr("on")+tr("failed")); - else - m_PostingDlg->lock(tr("SetScreenOn"),tr("Success"),tr("SetScreenOff")+tr("off")+tr("failed")); - m_pGetAskTimer->start(3000); - m_PostingDlg->exec(); - - } - } - else { - if(b) - emit sigSend(json,tr("SetScreenOn")+":"+tr("on")); - else - emit sigSend(json,tr("SetScreenOff")+":"+tr("off")); - } -} -void ControlPowerManual::onSelectedDeviceList(QList *list) -{ - m_pLedlist=list; - if(m_pLedlist==nullptr) - return; - MACRO_DEFINE_CONTROL_FUNC3 -} -//获取到httpPost的应答,如果参数变化需要出发修改控件item的内容 -void ControlPowerManual::OnProHttpResponse(QString url, QString postMD5, QByteArray data) -{ - Q_UNUSED(postMD5) - //qDebug()<< url + "\r\n"+m_strUrl; - if(url == m_strUrl) - { - QJsonParseError parseJsonErr; - QJsonDocument document = QJsonDocument::fromJson(data,&parseJsonErr); - if(!(parseJsonErr.error == QJsonParseError::NoError)) - { - if(data.size()==0) - qDebug()<<"json is empty"; - else - qDebug()<m_strCardId +"---------"+ strType; - if(strType == "SetScreenOn") - { - //emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("SetBrightness")+":"+tr("success")); - } - else if(strType == "IsScreenOn"){ - - ui->widget->setCheckedStatus(jsonObject["on"].toBool()); - - } - - MACRO_ASKTIME_STOP - MACRO_POSTING_DLG_UNLOCK - - } - } -} -//获取到httpPost的应答,如果参数变化需要出发修改控件item的内容 -void ControlPowerManual::OnProHttpResponseAll(QString url, QString postMD5, QByteArray data) -{ - Q_UNUSED(postMD5) - //qDebug()<< url + "\r\n"+m_strUrl; - if(url == m_strUrl) - { - QJsonParseError parseJsonErr; - QJsonDocument document = QJsonDocument::fromJson(data,&parseJsonErr); - if(!(parseJsonErr.error == QJsonParseError::NoError)) - { - if(data.size()==0) - qDebug()<<"json is empty"; - else - qDebug()<m_strCardId +"---------"+ strType; - if(strType == "IsScreenOn"){ - - ui->widget->setCheckedStatus(jsonObject["on"].toBool()); - - } - - MACRO_ASKTIME_STOP - MACRO_POSTING_DLG_UNLOCK - - } - } -} -void ControlPowerManual::OnControlTypeSwitchIndexChanged(int index) -{ - if(index==Setting_PowerControl) - { - m_bSelected=true; - if(m_pLedCard!=nullptr) - onReadbackAllThisPage(); - } - else { - m_bSelected=false; - } -} -void ControlPowerManual::onReadbackAllThisPage() -{ - if(m_pLedlist==nullptr) - return; - if(m_pLedlist->count()!=1) - return; - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "IsScreenOn"); - HttpPostByTypeJsonObject(pHpptClientAll,m_strUrl,json); - MACRO_DEFINE_TIPDLG_ALL_FUCN(tr("Readback"),tr("Success"),tr("failed")) -} -void ControlPowerManual::DeletePostingDlg() -{ - if(m_PostingDlg!=nullptr) - { - delete m_PostingDlg; - m_PostingDlg=nullptr; - } -} diff --git a/LedOK/wDevicesManager/controlpowermanual.h b/LedOK/wDevicesManager/controlpowermanual.h deleted file mode 100644 index 430a44c..0000000 --- a/LedOK/wDevicesManager/controlpowermanual.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef CONTROLPOWERMANUAL_H -#define CONTROLPOWERMANUAL_H - -#include -#include -#include -#include -namespace Ui { -class ControlPowerManual; -} - -class ControlPowerManual : public QWidget -{ - Q_OBJECT - -public: - explicit ControlPowerManual(QWidget *parent = nullptr,QList *m_pLedlist=nullptr); - ~ControlPowerManual(); -protected slots: - void onPowerChecked(bool b); - void OnReadback(); - void refreshLable(); -private: - Ui::ControlPowerManual *ui; - - //类似的控制操作信号和槽函数和变量定义 - signals: - void sigSend(QJsonObject &,QString); - protected slots: - void DeletePostingDlg(); - void OnProHttpResponse(QString url, QString postMD5, QByteArray data); - void OnProHttpResponseAll(QString url, QString postMD5, QByteArray data); - void onSelectedDeviceList(QList *); - void onReadbackAllThisPage(); - void OnControlTypeSwitchIndexChanged(int index); - private: - QList *m_pLedlist=nullptr; - LedCard *m_pLedCard = nullptr; - LedCard *m_oldLedlist = nullptr; - HpptClient *pHpptClient = nullptr; - HpptClient *pHpptClientAll = nullptr; - QString m_strUrl=""; - LoEmptyDialog * m_PostingDlg=nullptr; - QTimer *m_pGetAskTimer=nullptr; - bool m_bSelected=false; -}; - -#endif // CONTROLPOWERMANUAL_H diff --git a/LedOK/wDevicesManager/controlpowermanual.ui b/LedOK/wDevicesManager/controlpowermanual.ui deleted file mode 100644 index 9f778fc..0000000 --- a/LedOK/wDevicesManager/controlpowermanual.ui +++ /dev/null @@ -1,162 +0,0 @@ - - - ControlPowerManual - - - - 0 - 0 - 576 - 401 - - - - Form - - - - - - Qt::Vertical - - - QSizePolicy::Minimum - - - - 20 - 40 - - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - POWER - - - - - - - - 0 - 0 - - - - - 80 - 33 - - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 60 - 30 - - - - Readback - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - SwitchControl - QWidget -

base/switchcontrol.h
- 1 - - - - - diff --git a/LedOK/wDevicesManager/controlpowerwidget.cpp b/LedOK/wDevicesManager/controlpowerwidget.cpp deleted file mode 100644 index cb0a2dc..0000000 --- a/LedOK/wDevicesManager/controlpowerwidget.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include "controlpowerwidget.h" -#include "ui_controlpowerwidget.h" -#include "tools.h" - -ControlPowerWidget::ControlPowerWidget(QWidget *parent,QList *list) : - QWidget(parent), - ui(new Ui::ControlPowerWidget) -{ - m_pLedlist=list; - ui->setupUi(this); -setStyleSheet(Tools::styleSheet()); - m_pStackedW = new QStackedWidget; - m_pManual = new ControlPowerManual(this,m_pLedlist); - m_pSchedule = new ControlPowerSchedule(this,m_pLedlist); - m_pStackedW->addWidget(m_pManual); - m_pStackedW->addWidget(m_pSchedule); - ui->horizontalLayout_2->addWidget(m_pStackedW); - init(); - connect(m_pSchedule,SIGNAL(sigHaveSchedule(bool)),this,SLOT(OnGetPowerModeType(bool))); - - } - -ControlPowerWidget::~ControlPowerWidget() -{ - m_pStackedW->deleteLater() ; - m_pManual->deleteLater() ; - m_pSchedule->deleteLater() ; - delete ui; -} -void ControlPowerWidget::refreshLable() -{ - ui->labelPowerConfiguration->setText(tr("Power Configuration")); - ui->radioButtonManual->setText(tr("Manual")); - ui->radioButtonSchedule->setText(tr("Schedule")); -} - -void ControlPowerWidget::init() -{ - m_buttonGroup = new QButtonGroup; - //第二个参数id可以自行定义 - m_buttonGroup->addButton(ui->radioButtonManual,0); - m_buttonGroup->addButton(ui->radioButtonSchedule,1); - connect(m_buttonGroup,SIGNAL(buttonClicked(int)),m_pStackedW,SLOT(setCurrentIndex(int))); - ui->radioButtonManual->setChecked(true); - m_pStackedW->setCurrentIndex(0); - -} - -void ControlPowerWidget::OnGetPowerModeType(bool b) -{ - if(b) - { - m_pStackedW->setCurrentIndex(1); - ui->radioButtonSchedule->setChecked(true); - } - else { - m_pStackedW->setCurrentIndex(0); - ui->radioButtonManual->setChecked(true); - - } -} diff --git a/LedOK/wDevicesManager/controlpowerwidget.h b/LedOK/wDevicesManager/controlpowerwidget.h deleted file mode 100644 index 0534282..0000000 --- a/LedOK/wDevicesManager/controlpowerwidget.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef CONTROLPOWERWIDGET_H -#define CONTROLPOWERWIDGET_H - -#include -#include -#include -#include "QStackedWidget" -#include -namespace Ui { -class ControlPowerWidget; -} - -class ControlPowerWidget : public QWidget -{ - Q_OBJECT - -public: - explicit ControlPowerWidget(QWidget *parent = nullptr,QList *m_pLedlist=nullptr); - ~ControlPowerWidget(); -protected slots: - void refreshLable(); - void OnGetPowerModeType(bool b); - -private: - void init(); -private: - Ui::ControlPowerWidget *ui; - ControlPowerManual *m_pManual=nullptr; - ControlPowerSchedule *m_pSchedule=nullptr; - QStackedWidget *m_pStackedW; - QButtonGroup *m_buttonGroup; - QList *m_pLedlist=nullptr; - -}; - -#endif // CONTROLPOWERWIDGET_H diff --git a/LedOK/wDevicesManager/controlpowerwidget.ui b/LedOK/wDevicesManager/controlpowerwidget.ui deleted file mode 100644 index 48321ac..0000000 --- a/LedOK/wDevicesManager/controlpowerwidget.ui +++ /dev/null @@ -1,145 +0,0 @@ - - - ControlPowerWidget - - - - 0 - 0 - 234 - 423 - - - - Form - - - background-color: #F5F5F5; - - - - - - - Arial - 12 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - Power Configuration - - - Qt::AlignCenter - - - - - - - Qt::Horizontal - - - - - - - 9 - - - 9 - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - background-color:transparent - - - Manual - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - background-color:transparent - - - Schedule - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - - diff --git a/LedOK/wDevicesManager/controlvolumemanual.cpp b/LedOK/wDevicesManager/controlvolumemanual.cpp deleted file mode 100644 index d4e39ea..0000000 --- a/LedOK/wDevicesManager/controlvolumemanual.cpp +++ /dev/null @@ -1,184 +0,0 @@ -#include "controlvolumemanual.h" -#include "ui_controlvolumemanual.h" -#include -#include -#include -#include -#include "tools.h" -extern QWidget *gMainWin; - -ControlVolumeManual::ControlVolumeManual(QWidget *parent,QList *list) : - QWidget(parent), - ui(new Ui::ControlVolumeManual) -{ - ui->setupUi(this); - refreshLable(); -setStyleSheet(Tools::styleSheet()); - onSelectedDeviceList(list); - ui->horizontalSlider->setRange(0,15); - ui->horizontalSlider->setTickPosition(QSlider::TicksAbove); - ui->pushButtonReadback->setProperty("ssType", "progManageTool"); - connect(ui->pushButtonReadback,SIGNAL(clicked()),this,SLOT(OnReadback())); - connect(ui->horizontalSlider, SIGNAL(valueChanged(int)), ui->labelCurValue, SLOT(setNum(int))); - connect(ui->horizontalSlider, SIGNAL(sliderReleased()), this, SLOT(setVolumeValue())); - - MARCO_DEFINE_CONTROL_FUNC2(parent->parent()->parent(),parent->parent()) -} - -ControlVolumeManual::~ControlVolumeManual() -{ - delete ui; - if(pHpptClient != nullptr) - { - qDebug() <<"delete pHpptClient in ~NetComm"; - delete pHpptClient; - pHpptClient=nullptr; - } - if(pHpptClientAll != nullptr) - { - qDebug() <<"delete pHpptClientAll in ~NetComm"; - delete pHpptClientAll; - pHpptClientAll=nullptr; - } -} -void ControlVolumeManual::setVolumeValue() -{ - CHECK_CARD_SELECTED - - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "SetVolume"); - json.insert("volume", ui->labelCurValue->text().toInt()); - MACRO_DEFINE_TIPDLG_FUCN(tr("SetVolume"),tr("Success"),tr("failed")) - -} -void ControlVolumeManual::refreshLable() -{ - ui->labelVolume->setText(tr("Volume(min:0-max:15)")); - ui->pushButtonReadback->setText(tr("Readback")); -} - - -void ControlVolumeManual::OnReadback() -{ - CHECK_CARD_SELECTED - - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "GetVolume"); - MACRO_DEFINE_TIPDLG_FUCN(tr("GetVolume"),tr("Success"),tr("failed")) - -} -void ControlVolumeManual::onSelectedDeviceList(QList *list) -{ - m_pLedlist=list; - MACRO_DEFINE_CONTROL_FUNC3 - -} -//获取到httpPost的应答,如果参数变化需要出发修改控件item的内容 -void ControlVolumeManual::OnProHttpResponse(QString url, QString postMD5, QByteArray data) -{ - Q_UNUSED(postMD5) - //qDebug()<< url + "\r\n"+m_strUrl; - if(url == m_strUrl) - { - QJsonParseError parseJsonErr; - QJsonDocument document = QJsonDocument::fromJson(data,&parseJsonErr); - if(!(parseJsonErr.error == QJsonParseError::NoError)) - { - if(data.size()==0) - qDebug()<<"json is empty"; - else - qDebug()<m_strCardId +"---------"+ strType; - if(strType == "SetVolume") - { - //emit sigOutputInfo(m_pLedCard->m_strCardId+":"+tr("receive")+"<-"+tr("SetBrightness")+":"+tr("success")); - } - else if(strType == "GetVolume"){ - - int itempVolume=jsonObject["volume"].toInt(); - ui->horizontalSlider->setValue(itempVolume); - ui->labelCurValue->setNum(itempVolume); - } - - MACRO_ASKTIME_STOP - MACRO_POSTING_DLG_UNLOCK - - } - } -} -//获取到httpPost的应答,如果参数变化需要出发修改控件item的内容 -void ControlVolumeManual::OnProHttpResponseAll(QString url, QString postMD5, QByteArray data) -{ - Q_UNUSED(postMD5) - //qDebug()<< url + "\r\n"+m_strUrl; - if(url == m_strUrl) - { - QJsonParseError parseJsonErr; - QJsonDocument document = QJsonDocument::fromJson(data,&parseJsonErr); - if(!(parseJsonErr.error == QJsonParseError::NoError)) - { - if(data.size()==0) - qDebug()<<"json is empty"; - else - qDebug()<m_strCardId +"---------"+ strType; - if(strType == "GetVolume"){ - int itempVolume=jsonObject["volume"].toInt(); - ui->horizontalSlider->setValue(itempVolume); - ui->labelCurValue->setNum(itempVolume); - - } - - MACRO_ASKTIME_STOP - MACRO_POSTING_DLG_UNLOCK - - } - } -} -void ControlVolumeManual::OnControlTypeSwitchIndexChanged(int index) -{ - if(index==Setting_Volume) - { - m_bSelected=true; - if(m_pLedCard!=nullptr) - onReadbackAllThisPage(); - } - else { - m_bSelected=false; - } -} -void ControlVolumeManual::onReadbackAllThisPage() -{ - if(m_pLedlist==nullptr) - return; - if(m_pLedlist->count()!=1) - return; - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "GetVolume"); - HttpPostByTypeJsonObject(pHpptClientAll,m_strUrl,json); - MACRO_DEFINE_TIPDLG_ALL_FUCN(tr("Readback"),tr("Success"),tr("failed")) - -} -void ControlVolumeManual::DeletePostingDlg() -{ - if(m_PostingDlg!=nullptr) - { - delete m_PostingDlg; - m_PostingDlg=nullptr; - } -} diff --git a/LedOK/wDevicesManager/controlvolumemanual.h b/LedOK/wDevicesManager/controlvolumemanual.h deleted file mode 100644 index 2cb4302..0000000 --- a/LedOK/wDevicesManager/controlvolumemanual.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef CONTROLVOLUMEMANUAL_H -#define CONTROLVOLUMEMANUAL_H - -#include -#include -#include -#include -namespace Ui { -class ControlVolumeManual; -} - -class ControlVolumeManual : public QWidget -{ - Q_OBJECT - -public: - explicit ControlVolumeManual(QWidget *parent = nullptr,QList *m_pLedlist=nullptr); - ~ControlVolumeManual(); -protected slots: - void OnReadback(); - void refreshLable(); - -private: - Ui::ControlVolumeManual *ui; - //类似的控制操作信号和槽函数和变量定义 - signals: - void sigSend(QJsonObject &,QString); - protected slots: - void DeletePostingDlg(); - void OnProHttpResponse(QString url, QString postMD5, QByteArray data); - void OnProHttpResponseAll(QString url, QString postMD5, QByteArray data); - void onSelectedDeviceList(QList *); - void onReadbackAllThisPage(); - void OnControlTypeSwitchIndexChanged(int index); - void setVolumeValue(); - private: - QList *m_pLedlist=nullptr; - LedCard *m_pLedCard = nullptr; - LedCard *m_oldLedlist = nullptr; - HpptClient *pHpptClient = nullptr; - HpptClient *pHpptClientAll = nullptr; - QString m_strUrl=""; - LoEmptyDialog * m_PostingDlg=nullptr; - QTimer *m_pGetAskTimer=nullptr; - bool m_bSelected=false; -}; - -#endif // CONTROLVOLUMEMANUAL_H diff --git a/LedOK/wDevicesManager/controlvolumemanual.ui b/LedOK/wDevicesManager/controlvolumemanual.ui deleted file mode 100644 index 78ea608..0000000 --- a/LedOK/wDevicesManager/controlvolumemanual.ui +++ /dev/null @@ -1,123 +0,0 @@ - - - ControlVolumeManual - - - - 0 - 0 - 555 - 416 - - - - Form - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - Volume(0-15) - - - - - - - Qt::Horizontal - - - - - - - - - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - 60 - 30 - - - - Readback - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - diff --git a/LedOK/wDevicesManager/controlvolumewidget.cpp b/LedOK/wDevicesManager/controlvolumewidget.cpp deleted file mode 100644 index 736fa7e..0000000 --- a/LedOK/wDevicesManager/controlvolumewidget.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#include "controlvolumewidget.h" -#include "ui_controlvolumewidget.h" -#include "tools.h" - -ControlVolumeWidget::ControlVolumeWidget(QWidget *parent,QList *list) : - QWidget(parent), - ui(new Ui::ControlVolumeWidget) -{ - m_pLedlist=list; - ui->setupUi(this); - refreshLable(); -setStyleSheet(Tools::styleSheet()); - m_pStackedW = new QStackedWidget; - m_pManual = new ControlVolumeManual(this,m_pLedlist); - m_pSchedule = new ControlVolumeSchedule(this,m_pLedlist); - m_pStackedW->addWidget(m_pManual); - m_pStackedW->addWidget(m_pSchedule); - ui->horizontalLayout_2->addWidget(m_pStackedW); - init(); - connect(parent->parent(),SIGNAL(sigSelectedDeviceList(QList *)),this,SLOT(onSelectedDeviceList(QList *))); - connect(m_pSchedule,SIGNAL(sigHaveSchedule(bool)),this,SLOT(OnGetVolumeModeType(bool))); - -} - -ControlVolumeWidget::~ControlVolumeWidget() -{ - m_pStackedW->deleteLater() ; - m_pManual->deleteLater() ; - m_pSchedule->deleteLater() ; - delete ui; -} -void ControlVolumeWidget::refreshLable() -{ - ui->labelVolumeControl->setText(tr("Volume Control")); - ui->radioButtonManual->setText(tr("Manual")); - ui->radioButtonSchedule->setText(tr("Schedule")); -} - -void ControlVolumeWidget::init() -{ - m_buttonGroup = new QButtonGroup; - //第二个参数id可以自行定义 - m_buttonGroup->addButton(ui->radioButtonManual,0); - m_buttonGroup->addButton(ui->radioButtonSchedule,1); - connect(m_buttonGroup,SIGNAL(buttonClicked(int)),m_pStackedW,SLOT(setCurrentIndex(int))); - ui->radioButtonManual->setChecked(true); - m_pStackedW->setCurrentIndex(0); - -} -void ControlVolumeWidget::OnGetVolumeModeType(bool b) -{ - if(b) - { - m_pStackedW->setCurrentIndex(1); - ui->radioButtonSchedule->setChecked(true); - } - else - { - m_pStackedW->setCurrentIndex(0); - ui->radioButtonManual->setChecked(true); - } -} diff --git a/LedOK/wDevicesManager/controlvolumewidget.h b/LedOK/wDevicesManager/controlvolumewidget.h deleted file mode 100644 index 1b65eff..0000000 --- a/LedOK/wDevicesManager/controlvolumewidget.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef CONTROLVOLUMEWIDGET_H -#define CONTROLVOLUMEWIDGET_H - -#include -#include -#include -#include "QStackedWidget" -#include -namespace Ui { -class ControlVolumeWidget; -} - -class ControlVolumeWidget : public QWidget -{ - Q_OBJECT - -public: - explicit ControlVolumeWidget(QWidget *parent = nullptr,QList *m_pLedlist=nullptr); - ~ControlVolumeWidget(); -private: - void init(); -protected slots: - void refreshLable(); - void OnGetVolumeModeType(bool b); -private: - Ui::ControlVolumeWidget *ui; - ControlVolumeManual *m_pManual=nullptr; - ControlVolumeSchedule *m_pSchedule=nullptr; - QStackedWidget *m_pStackedW; - QButtonGroup *m_buttonGroup; - QList *m_pLedlist=nullptr; -}; - -#endif // CONTROLVOLUMEWIDGET_H diff --git a/LedOK/wDevicesManager/controlvolumewidget.ui b/LedOK/wDevicesManager/controlvolumewidget.ui deleted file mode 100644 index 4e3cd05..0000000 --- a/LedOK/wDevicesManager/controlvolumewidget.ui +++ /dev/null @@ -1,154 +0,0 @@ - - - ControlVolumeWidget - - - - 0 - 0 - 407 - 512 - - - - Form - - - - - - - Arial - 12 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - Volume Control - - - Qt::AlignCenter - - - - - - - Qt::Horizontal - - - - - - - 9 - - - 9 - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - Arial - 12 - - - - background-color:transparent - - - Manual - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - Arial - 12 - - - - background-color:transparent - - - Schedule - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - - diff --git a/LedOK/wDevicesManager/ctrladvancedpanel.cpp b/LedOK/wDevicesManager/ctrladvancedpanel.cpp deleted file mode 100644 index ba011b5..0000000 --- a/LedOK/wDevicesManager/ctrladvancedpanel.cpp +++ /dev/null @@ -1,2044 +0,0 @@ -#include "ctrladvancedpanel.h" -#include "deviceitem.h" -#include "globaldefine.h" -#include "base/waitingdlg.h" -#include "base/changepasswordform.h" -#include "base/updateledset3dialog.h" -#include "passwordindlg.h" -#include "tools.h" -#include "wProgramManager/ephoto.h" -#include "upgradeapkdialog.h" -#include "base/table.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "tcpsocket.h" - -CtrlAdvancedPanel::CtrlAdvancedPanel(QWidget *parent,QList *list) : QWidget(parent), m_pLedlist(list) { - m_pLedlist = gSelCards; - setFocusPolicy(Qt::StrongFocus); - auto vBox = new QVBoxLayout(this); - - lbTitle = new QLabel; - lbTitle->setAlignment(Qt::AlignCenter); - vBox->addWidget(lbTitle); - - auto hBox = new QHBoxLayout; - - lbScreenWidth = new QLabel; - hBox->addWidget(lbScreenWidth); - - fdScreenWidth = new QLineEdit; - fdScreenWidth->setMaximumWidth(60); - hBox->addWidget(fdScreenWidth); - - lbScreenHeight = new QLabel; - hBox->addWidget(lbScreenHeight); - - fdScreenHeight = new QLineEdit; - fdScreenHeight->setMaximumWidth(60); - hBox->addWidget(fdScreenHeight); - - btnScreenSet = new QPushButton; - btnScreenSet->setProperty("ssType", "progManageTool"); - connect(btnScreenSet, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - auto width = fdScreenWidth->text(); - if(width.isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"),tr("InputWidthTip")); - fdScreenWidth->setFocus(); - return; - } - auto height = fdScreenHeight->text(); - if(height.isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"),tr("InputHeightTip")); - fdScreenHeight->setFocus(); - return; - } - QJsonObject json; - json.insert("_id", "SetScreenSize"); - json.insert("_type", "SetScreenSize"); - json.insert("width", width.toInt()); - json.insert("height", height.toInt()); - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, tr("SetScreenSize")); - Def_CtrlReqPre - connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { - Def_CtrlSetReqAfter - }); - } else { - foreach(auto card, *gSelCards) { - Def_CtrlSetMulti(tr("SetScreenSize")) - } - } - }); - hBox->addWidget(btnScreenSet); - - hBox->addSpacing(20); - - lbAlias = new QLabel; - hBox->addWidget(lbAlias); - - fdAlias = new QLineEdit; - fdAlias->setMaximumWidth(200); - hBox->addWidget(fdAlias); - - btnAliasSet = new QPushButton; - btnAliasSet->setProperty("ssType", "progManageTool"); - connect(btnAliasSet, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - auto alias = fdAlias->text(); - if(alias.isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"),tr("InputAliasTip")); - fdAlias->setFocus(); - return; - } - QJsonObject json; - json.insert("_id", "SetCardAlias"); - json.insert("_type", "SetCardAlias"); - json.insert("alias", QString::fromLatin1(alias.toUtf8().toBase64())); - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, tr("SetCardAlias")); - Def_CtrlReqPre - connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { - Def_CtrlSetReqAfter - }); - } else { - foreach(auto card, *gSelCards) { - Def_CtrlSetMulti(tr("SetCardAlias")) - } - } - }); - hBox->addWidget(btnAliasSet); - - hBox->addStretch(); - vBox->addLayout(hBox); - - hBox = new QHBoxLayout(); - - labelWebServer = new QLabel; - hBox->addWidget(labelWebServer); - - fdWebServerAddr = new QComboBox; - fdWebServerAddr->addItem(tr("www.m2mled.net")); - fdWebServerAddr->addItem(tr("www.ledaips.com")); - fdWebServerAddr->addItem(tr("https://www.taxihub.cn:2340")); - fdWebServerAddr->addItem(tr("https://www.ledaips.com:2340")); - fdWebServerAddr->addItem(tr("https://www.36taxi.com:2340")); - fdWebServerAddr->addItem(tr("www.tlzxled.com")); - fdWebServerAddr->setMinimumWidth(260); - fdWebServerAddr->setEditable(true); - hBox->addWidget(fdWebServerAddr); - - lbCompanyId = new QLabel; - hBox->addWidget(lbCompanyId); - - fdCompanyId = new QLineEdit; - fdCompanyId->setFixedWidth(100); - hBox->addWidget(fdCompanyId); - - btnWebServerSet = new QPushButton; - btnWebServerSet->setProperty("ssType", "progManageTool"); - connect(btnWebServerSet, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - - QString serverAddr = fdWebServerAddr->currentText(); - if(serverAddr.isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"),tr("InputWebServerAddressTip")); - fdWebServerAddr->setFocus(); - return; - } - auto companyId = fdCompanyId->text(); - if(companyId.isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"),tr("InputCompanyIdTip")); - fdCompanyId->setFocus(); - return; - } - auto res = QMessageBox::question(gMainWin, tr("Tip Info"), tr("Do you want to modify webserveraddress and companyId?")); - if(res != QMessageBox::Yes) return; - QJsonObject json; - json.insert("_id", "SetOnlineAddr"); - json.insert("_type", "SetOnlineAddr"); - json.insert("server", serverAddr); - json.insert("companyID", companyId); - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, tr("SetOnlineAddr")); - Def_CtrlReqPre - connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { - Def_CtrlSetReqAfter - }); - } else { - foreach(auto card, *gSelCards) { - Def_CtrlSetMulti(tr("SetOnlineAddr")) - } - } - }); - hBox->addWidget(btnWebServerSet); - - hBox->addStretch(); - vBox->addLayout(hBox); - - hBox = new QHBoxLayout(); - - label = new QLabel; - hBox->addWidget(label); - - comboBox_realtimeServer = new QComboBox; - comboBox_realtimeServer->addItem(tr("www.ledokcloud.com/realtime")); - comboBox_realtimeServer->setMinimumWidth(260); - comboBox_realtimeServer->setEditable(true); - hBox->addWidget(comboBox_realtimeServer); - - pushButtonSetREaltimeServer = new QPushButton; - hBox->addWidget(pushButtonSetREaltimeServer); - - pushButtonClearRealtimerAddress = new QPushButton; - hBox->addWidget(pushButtonClearRealtimerAddress); - - hBox->addStretch(); - - vBox->addLayout(hBox); - - hBox = new QHBoxLayout(); - - btnApkCheck = new QPushButton; - btnApkCheck->setProperty("ssType", "progManageTool"); - connect(btnApkCheck, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - QJsonObject json; - json.insert("_id", "CheckSoftVersions"); - json.insert("_type", "CheckSoftVersions"); - if(gSelCards->count() != 1) return; - auto waitingDlg = new WaitingDlg(this, tr("Check Apk Version")); - Def_CtrlReqPre - connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg] { - Def_CtrlSingleGetReply - waitingDlg->close(); - fdPkg->clear(); - auto apps = json["apps"].toArray(); - auto infoDlg = new QDialog(this); - infoDlg->setWindowFlag(Qt::WindowContextHelpButtonHint, false); - infoDlg->resize(500, 500); - infoDlg->setWindowTitle(tr("Software Version Info")); - auto vBox = new QVBoxLayout(infoDlg); - vBox->setContentsMargins(0, 0, 0, 0); - auto table = new Table{ - {"apk", "Apk"}, - {"ver", tr("Version")}, - {"pkg", tr("Package")} - }; - table->setDefs(); - table->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); - table->setRowCount(apps.size()); - vBox->addWidget(table); - for(int i=0; isetItem(i, "apk", new QTableWidgetItem{app["appName"].toString()}); - table->setItem(i, "ver", new QTableWidgetItem{app["versionName"].toString()}); - table->setItem(i, "pkg", new QTableWidgetItem{packageName}); - if(! (packageName.endsWith(".cardsystem") || packageName.endsWith(".systemcore") || packageName.endsWith(".update"))) fdPkg->addItem(packageName); - } - infoDlg->show(); - }); - }); - hBox->addWidget(btnApkCheck); - - btnApkUpgrade = new QPushButton; - btnApkUpgrade->setProperty("ssType", "progManageTool"); - connect(btnApkUpgrade, &QPushButton::clicked, this, [this] { - if(m_pLedlist==0) return; - if(m_pLedlist->count()==0 || (m_pLedlist->count()==1 && m_pLedCard==nullptr)) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - if(m_pLedlist->count() != 1) return; - if(m_pLedCard->bPassword && m_pLedCard->m_bLockStatus && m_lockFlag) { - QMessageBox::information(gMainWin, tr("Tip"),tr("This screen is encrypted,Please decrypt and upgrade APK!")); - return; - } - QString url = "http://"+m_pLedCard->m_strCardIp+":2016/upload?type=software"; - m_strUpgradeApkFile = QFileDialog::getOpenFileName(this, "open file dialog", "", tr("apk package (*.apk *.zip)")); - QFileInfo file1(m_strUpgradeApkFile); - QFile file(m_strUpgradeApkFile); - QMap params_send; //上传的普通参数 在本程序中 需要上传一个普通参数为"username" - params_send.insert("username","10005"); - UpLoadForm(url, params_send, file1.fileName(), &file, 0); - }); - hBox->addWidget(btnApkUpgrade); - - fdPkg = new QComboBox; - fdPkg->setEditable(true); - fdPkg->setMinimumWidth(200); - hBox->addWidget(fdPkg); - - fdUnload = new QPushButton; - connect(fdUnload, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - auto pkg = fdPkg->currentText(); - if(pkg.isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("Package name is null")); - return; - } - QJsonObject json; - json.insert("_id", "UninstallSoftware"); - json.insert("_type", "UninstallSoftware"); - json.insert("packageName", pkg); - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, tr("UninstallSoftware")); - Def_CtrlReqPre - connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { - Def_CtrlSetReqAfter - }); - } else { - foreach(auto card, *gSelCards) { - Def_CtrlSetMulti(tr("UninstallSoftware")) - } - } - }); - hBox->addWidget(fdUnload); - - btnRunningCheck = new QPushButton; - connect(btnRunningCheck, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - auto pkg = fdPkg->currentText(); - if(pkg.isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("Package name is null")); - return; - } - QJsonObject json; - json.insert("_id", "IsSoftwareRunning"); - json.insert("_type", "IsSoftwareRunning"); - json.insert("packageName", pkg); - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, tr("IsSoftwareRunning")); - Def_CtrlReqPre - connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { - Def_CtrlSingleGetReply - waitingDlg->close(); - QMessageBox::information(gMainWin, tr("Tip"), json["running"].toBool() ? tr("running") : tr("no running")); - }); - } else { - foreach(auto card, *gSelCards) { - auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); - connect(reply, &QNetworkReply::finished, this, [reply, card] { - QJsonDocument json; - QString err = checkReplyForJson(reply, &json); - gFdResInfo->append(card->m_strCardId+" "+tr("IsSoftwareRunning")+" "+(err.isEmpty() ? (json["running"].toBool() ? tr("running") : tr("no running")) : err)); - }); - } - } - }); - hBox->addWidget(btnRunningCheck); - - hBox->addStretch(); - - vBox->addLayout(hBox); - - hBox = new QHBoxLayout(); - - pushButtonFpgaUpgrade = new QPushButton; - hBox->addWidget(pushButtonFpgaUpgrade); - - pushButtonFpgaVerCheck = new QPushButton; - hBox->addWidget(pushButtonFpgaVerCheck); - - pushButtonSyncFpgaVer = new QPushButton; - hBox->addWidget(pushButtonSyncFpgaVer); - - pushButtonRestart = new QPushButton; - hBox->addWidget(pushButtonRestart); - - hBox->addStretch(); - vBox->addLayout(hBox); - - hBox = new QHBoxLayout(); - - btnClearProg = new QPushButton; - btnClearProg->setProperty("ssType", "progManageTool"); - connect(btnClearProg, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, tr("Clearing Program")+" ..."); - waitingDlg->show(); - auto card = gSelCards->at(0); - auto tcp = new QTcpSocket(); - auto timer = new QTimer(tcp); - timer->setSingleShot(true); - connect(timer, &QTimer::timeout, tcp, [tcp] { - tcp->close(); - QMessageBox::critical(gMainWin, tr("Tip"), tr("Clear Program")+" "+tr("Timeout")); - }); - connect(tcp, &QTcpSocket::disconnected, tcp, &QTcpSocket::deleteLater); - connect(tcp, &QTcpSocket::connected, tcp, [tcp, timer] { - timer->stop(); - tcp->write("{\"_type\":\"DelPrograms\",\"_id\":\"DelPrograms\",\"zVer\":\"xixun1\"}"); - timer->start(10000); - }); - connect(tcp, &QTcpSocket::readyRead, tcp, [tcp, timer, waitingDlg] { - timer->stop(); - QByteArray resp = tcp->readAll(); - tcp->close(); - QJsonParseError parseErr; - QJsonDocument json = QJsonDocument::fromJson(resp, &parseErr); - if(parseErr.error != QJsonParseError::NoError) { - waitingDlg->close(); - QMessageBox::critical(gMainWin, tr("Tip"), parseErr.errorString()); - } - else if(! json["success"].toBool()) { - waitingDlg->close(); - QMessageBox::critical(gMainWin, tr("Tip"), tr("Clear Program")+" "+tr("Failed")); - } else waitingDlg->success(); - }); - connect(tcp, &QTcpSocket::errorOccurred, tcp, [tcp, timer, waitingDlg](QAbstractSocket::SocketError err) { - timer->stop(); - tcp->close(); - waitingDlg->close(); - QMessageBox::critical(gMainWin, tr("Tip"), QString(socketErrKey(err))+" ("+QString::number(err)+") "+tcp->errorString()); - }); - tcp->connectToHost(card->m_strCardIp, 3333); - timer->start(10000); - } else { - foreach(auto card, *gSelCards) { - auto tcp = new QTcpSocket(); - auto timer = new QTimer(tcp); - timer->setSingleShot(true); - connect(timer, &QTimer::timeout, tcp, [tcp, card] { - tcp->close(); - gFdResInfo->append(card->m_strCardId+" "+tr("Clear Program")+" "+tr("Timeout")); - }); - connect(tcp, &QTcpSocket::disconnected, tcp, &QTcpSocket::deleteLater); - connect(tcp, &QTcpSocket::connected, tcp, [tcp, timer] { - timer->stop(); - tcp->write("{\"_type\":\"DelPrograms\",\"_id\":\"DelPrograms\",\"zVer\":\"xixun1\"}"); - timer->start(10000); - }); - connect(tcp, &QTcpSocket::readyRead, tcp, [tcp, timer, card] { - timer->stop(); - QByteArray resp = tcp->readAll(); - tcp->close(); - QJsonParseError parseErr; - QJsonDocument json = QJsonDocument::fromJson(resp, &parseErr); - if(parseErr.error != QJsonParseError::NoError) gFdResInfo->append(card->m_strCardId+" "+tr("Clear Program")+" "+parseErr.errorString()); - else if(! json["success"].toBool()) gFdResInfo->append(card->m_strCardId+" "+tr("Clear Program")+" "+tr("Failed")); - else gFdResInfo->append(card->m_strCardId+" "+tr("Clear Program")+" "+tr("Success")); - }); - connect(tcp, &QTcpSocket::errorOccurred, tcp, [tcp, timer, card](QAbstractSocket::SocketError err) { - timer->stop(); - tcp->close(); - gFdResInfo->append(card->m_strCardId+" "+tr("Clear Program")+" "+QMetaEnum::fromType().valueToKey(err)+" ("+QString::number(err)+") "+tcp->errorString()); - }); - tcp->connectToHost(card->m_strCardIp, 3333); - timer->start(10000); - } - } - }); - - hBox->addWidget(btnClearProg); - - btnGetLog = new QPushButton; - btnGetLog->setProperty("ssType", "progManageTool"); - connect(btnGetLog, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, tr("Getting Log")+" ..."); - waitingDlg->show(); - auto card = gSelCards->at(0); - auto reply = Tools::netManager().get(netReq("http://"+card->m_strCardIp+":2016/download?file=logs")); - connect(reply, &QNetworkReply::finished, this, [this, reply, waitingDlg] { - waitingDlg->close(); - QString err = parseReplyJson(reply); - if(! err.isEmpty()) { - QMessageBox::critical(gMainWin, tr("Error"), err); - return; - } - QString logFile = QApplication::applicationDirPath()+"/log_"+m_pLedCard->m_strCardId+".txt"; - QFile file(logFile); - if(! file.open(QIODevice::WriteOnly)) { - QMessageBox::critical(gMainWin, tr("Error"), "Open for Write Fail"); - return; - } - file.write(reply->readAll()); - file.close(); - QProcess::execute("notepad", {logFile}); - }); - } - }); - hBox->addWidget(btnGetLog); - - hBox->addStretch(); - vBox->addLayout(hBox); - - groupM80 = new QGroupBox; - hBox = new QHBoxLayout(groupM80); - - fdM80 = new QComboBox(); - fdM80->setMinimumWidth(160); - fdM80->setEditable(true); - mM80Map.insert("576×3840","625×3960"); - mM80Map.insert("640×3840","660×3960"); - mM80Map.insert("720×3200","750×3300"); - mM80Map.insert("864×2672","900×2750"); - mM80Map.insert("1080×1920","1125×2200"); - mM80Map.insert("1280×1760","1320×1850"); - mM80Map.insert("1472×1536","1500×1650"); - mM80Map.insert("1536×1472","1650×1500"); - mM80Map.insert("1760×1280","1850×1320"); - mM80Map.insert("1920×1080","2200×1125"); - mM80Map.insert("2672×864","2750×900"); - mM80Map.insert("3200×760","3300×825"); - mM80Map.insert("3200×720","3300×750"); - mM80Map.insert("3840×640","3960×660"); - mM80Map.insert("3840×576","3960×625"); - mM80Map.insert("4096×480","4500×550"); - fdM80->addItems(mM80Map.keys()); - hBox->addWidget(fdM80); - - btnM80Set = new QPushButton(); - hBox->addWidget(btnM80Set); - - btnM80Refresh = new QPushButton(); - hBox->addWidget(btnM80Refresh); - - btnM80Restore = new QPushButton(); - hBox->addWidget(btnM80Restore); - - hBox->addStretch(); - - vBox->addWidget(groupM80); - - hBox = new QHBoxLayout(); - - btnLedSet3 = new QPushButton; - btnLedSet3->setMinimumHeight(34); - btnLedSet3->setProperty("ssType", "progManageTool"); - connect(btnLedSet3, SIGNAL(clicked()),this,SLOT(OnStartConfigLedScreenSoft())); - hBox->addWidget(btnLedSet3); - - btnLedSet4 = new QPushButton; - btnLedSet4->setMinimumHeight(34); - btnLedSet4->setProperty("ssType", "progManageTool"); - connect(btnLedSet4, &QPushButton::clicked, btnLedSet4, [] { - QFileInfo file("LedSet4.0/LedSet4.0.exe"); - if(file.exists()) QProcess::startDetached(file.absoluteFilePath(), QStringList()); - }); - hBox->addWidget(btnLedSet4); - - vBox->addLayout(hBox); - - auto line = new QFrame; - line->setFrameShape(QFrame::HLine); - line->setFrameShadow(QFrame::Sunken); - vBox->addWidget(line); - - hBox = new QHBoxLayout(); - btnBindTaxiIc = new QPushButton; - btnBindTaxiIc->setProperty("ssType", "progManageTool"); - connect(btnBindTaxiIc, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - QString icFile = QFileDialog::getOpenFileName(this, "open file dialog", "", tr("indentity voucher (*.ic)")); - if(icFile.isEmpty()) return; - QFile file(icFile); - if(! file.open(QIODevice::ReadOnly)) { - QMessageBox::information(gMainWin, tr("Tip"), tr("Open file Failed")); - return; - } - auto data = file.readAll(); - file.close(); - QJsonParseError jsonErr; - QJsonDocument icJson = QJsonDocument::fromJson(data, &jsonErr); - if(jsonErr.error != QJsonParseError::NoError) { - QMessageBox::information(gMainWin, tr("Tip"), "JsonError "+jsonErr.errorString()+"\n"+data); - return; - } - QJsonObject jsonCommand; - jsonCommand.insert("action", "BindAccount"); - jsonCommand.insert("accountIdToken", icJson["account_id_token"]); - jsonCommand.insert("server", icJson["taxiServerURL"]); - jsonCommand.insert("tlsServer", icJson["taxiServerTLSURL"]); - QJsonObject json; - json.insert("action", "InvokeTaxiAppFunction"); - json.insert("jsonCommand", jsonCommand); - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, tr("InvokeTaxiAppFunction")); - waitingDlg->show(); - auto reply = Tools::netManager().post(reqForJson("http://"+gSelCards->at(0)->m_strCardIp+":3000"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); - connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { - QString err = parseReplyJson(reply); - if(! err.isEmpty()) { - waitingDlg->close(); - QMessageBox::critical(gMainWin, tr("Error"), err); - return; - } - auto data = reply->readAll(); - QJsonParseError jsonErr; - QJsonDocument json = QJsonDocument::fromJson(data, &jsonErr); - if(jsonErr.error != QJsonParseError::NoError) { - waitingDlg->close(); - QMessageBox::critical(gMainWin, tr("Error"), "JsonError "+jsonErr.errorString()+"\n"+data); - return; - } - if(json["result"].toString() != "true") { - waitingDlg->close(); - QMessageBox::critical(gMainWin, tr("Error"), data); - return; - } - waitingDlg->success(); - }); - } else { - foreach(auto card, *gSelCards) { - auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":3000"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); - connect(reply, &QNetworkReply::finished, this, [reply, card] { - QString err = parseReplyJson(reply); - if(! err.isEmpty()) { - gFdResInfo->append(card->m_strCardId+" "+tr("InvokeTaxiAppFunction")+" "+tr("Error")+" "+err); - return; - } - auto data = reply->readAll(); - QJsonParseError jsonErr; - QJsonDocument json = QJsonDocument::fromJson(data, &jsonErr); - if(jsonErr.error != QJsonParseError::NoError) { - gFdResInfo->append(card->m_strCardId+" "+tr("InvokeTaxiAppFunction")+" "+tr("Error")+" JsonError "+jsonErr.errorString()+"\n"+data); - return; - } - if(json["result"].toString() != "true") { - gFdResInfo->append(card->m_strCardId+" "+tr("InvokeTaxiAppFunction")+" "+tr("Error")+" "+data); - return; - } - gFdResInfo->append(card->m_strCardId+" "+tr("InvokeTaxiAppFunction")+" "+QCoreApplication::translate("Def","Success")); - }); - } - } - }); - hBox->addWidget(btnBindTaxiIc); - hBox->addStretch(); - - vBox->addLayout(hBox); - - groupTopLevel = new QGroupBox(); - hBox = new QHBoxLayout(groupTopLevel); - - fdTopLevelHL = new QRadioButton(groupTopLevel); - fdTopLevelHL->setChecked(true); - hBox->addWidget(fdTopLevelHL); - - fdTopLevelLH = new QRadioButton(groupTopLevel); - hBox->addWidget(fdTopLevelLH); - - btnSetTopLevel = new QPushButton(groupTopLevel); - hBox->addWidget(btnSetTopLevel); - - btnGetTopLevel = new QPushButton(groupTopLevel); - hBox->addWidget(btnGetTopLevel); - - hBox->addStretch(); - - vBox->addWidget(groupTopLevel); - - groupBoxRotate = new QGroupBox(); - hBox = new QHBoxLayout(groupBoxRotate); - - radioButton0degrees = new QRadioButton(groupBoxRotate); - hBox->addWidget(radioButton0degrees); - - radioButton90degrees = new QRadioButton(groupBoxRotate); - hBox->addWidget(radioButton90degrees); - - radioButton180degrees = new QRadioButton(groupBoxRotate); - hBox->addWidget(radioButton180degrees); - - radioButton270degrees = new QRadioButton(groupBoxRotate); - hBox->addWidget(radioButton270degrees); - - hBox->addStretch(); - - vBox->addWidget(groupBoxRotate); - - groupBoxMinMaxBrightness = new QGroupBox(); - hBox = new QHBoxLayout(groupBoxMinMaxBrightness); - - lbMinBright = new QLabel(); - hBox->addWidget(lbMinBright); - - fdMinBright = new QLineEdit("1"); - fdMinBright->setMaximumWidth(50); - hBox->addWidget(fdMinBright); - - lbMinBrightTip = new QLabel(); - hBox->addWidget(lbMinBrightTip); - - btnMinBrightGet = new QPushButton(); - hBox->addWidget(btnMinBrightGet); - - btnMinBrightSet = new QPushButton(); - hBox->addWidget(btnMinBrightSet); - - label_3 = new QLabel(); - hBox->addWidget(label_3); - - lineEdit_4 = new QLineEdit("255"); - lineEdit_4->setMaximumWidth(50); - hBox->addWidget(lineEdit_4); - - label_5 = new QLabel(); - hBox->addWidget(label_5); - - pushButtonReadbackMaxBrightess = new QPushButton(); - hBox->addWidget(pushButtonReadbackMaxBrightess); - - pushButtonSendMaxBrightness = new QPushButton(); - hBox->addWidget(pushButtonSendMaxBrightness); - - hBox->addStretch(); - vBox->addWidget(groupBoxMinMaxBrightness); - - vBox->addSpacing(20); - - grpBoxHiddenSettings = new QGroupBox; - grpBoxHiddenSettings->setVisible(false); - { - auto vBox = new QVBoxLayout(grpBoxHiddenSettings); - vBox->setContentsMargins(6,6,6,6); - - hBox = new QHBoxLayout; - - btnSetBack = new QPushButton; - btnSetBack->setProperty("ssType", "progManageTool"); - connect(btnSetBack, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - QColorDialog colorDlg(this); - colorDlg.setOption(QColorDialog::DontUseNativeDialog); - - if(colorDlg.exec() != QColorDialog::Accepted) return; - QColor color = colorDlg.selectedColor(); - if(! color.isValid()) return; - QJsonObject json; - json.insert("_id", "SetWallpaper"); - json.insert("_type", "SetWallpaper"); - json.insert("rgb", color.name()); - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, tr("Setting Wallpaper")+" ..."); - Def_CtrlReqPre - connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { - Def_CtrlSetReqAfter - }); - } else { - foreach(auto card, *gSelCards) { - Def_CtrlSetMulti(tr("Set Wallpaper")) - } - } - }); - hBox->addWidget(btnSetBack); - - btnSysUpd = new QPushButton; - btnSysUpd->setProperty("ssType", "progManageTool"); - connect(btnSysUpd, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - QJsonObject json; - json.insert("_id", "SystemUpdate"); - json.insert("_type", "SystemUpdate"); - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, tr("System Updating")+" ..."); - Def_CtrlReqPre - connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { - Def_CtrlSetReqAfter - }); - } else { - foreach(auto card, *gSelCards) { - Def_CtrlSetMulti(tr("System Update")) - } - } - }); - hBox->addWidget(btnSysUpd); - - hBox->addSpacing(20); - - btnPlayerBackSet = new QPushButton; - btnPlayerBackSet->setProperty("ssType", "progManageTool"); - connect(btnPlayerBackSet, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - QString file = QFileDialog::getOpenFileName(gMainWin, tr("Select File"), gFileHome, EPhoto::filters()); - if(file.isEmpty()) return; - QFileInfo info(file); - if(! info.isFile()) return; - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, tr("Setting player background")+" ..."); - waitingDlg->show(); - auto thread = new PlayerBackSendThread(file, gSelCards->at(0)->m_strCardIp); - connect(thread, &PlayerBackSendThread::emErr, this, [waitingDlg](QString err) { - if(err.isEmpty()) waitingDlg->success(); - else { - waitingDlg->close(); - QMessageBox::critical(gMainWin, tr("Error"), err); - } - }); - thread->start(); - } else { - foreach(auto card, *gSelCards) { - auto thread = new PlayerBackSendThread(file, card->m_strCardIp); - connect(thread, &PlayerBackSendThread::emErr, this, [card](QString err) { - gFdResInfo->append(card->m_strCardId+" "+tr("Set player background")+" "+(err.isEmpty() ? tr("Success") : err)); - }); - thread->start(); - } - } - }); - hBox->addWidget(btnPlayerBackSet); - - btnPlayerBackClear = new QPushButton; - btnPlayerBackClear->setProperty("ssType", "progManageTool"); - connect(btnPlayerBackClear, &QPushButton::clicked, this, [this] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, tr("Clearing player background")+" ..."); - waitingDlg->show(); - auto card = gSelCards->at(0); - auto tcp = new QTcpSocket(); - auto timer = new QTimer(tcp); - timer->setSingleShot(true); - connect(timer, &QTimer::timeout, tcp, [tcp, waitingDlg] { - tcp->close(); - waitingDlg->close(); - QMessageBox::critical(gMainWin, tr("Tip"), tr("Clear player background")+" "+tr("Timeout")); - }); - connect(tcp, &QTcpSocket::disconnected, tcp, &QTcpSocket::deleteLater); - connect(tcp, &QTcpSocket::connected, tcp, [tcp, timer] { - timer->stop(); - tcp->write("{\"_type\":\"DelBackImg\",\"_id\":\"DelBackImg\",\"zVer\":\"xixun1\"}"); - timer->start(10000); - }); - connect(tcp, &QTcpSocket::readyRead, tcp, [tcp, timer, waitingDlg] { - timer->stop(); - QByteArray resp = tcp->readAll(); - tcp->close(); - QJsonParseError parseErr; - QJsonDocument json = QJsonDocument::fromJson(resp, &parseErr); - if(parseErr.error != QJsonParseError::NoError) { - waitingDlg->close(); - QMessageBox::critical(gMainWin, tr("Tip"), parseErr.errorString()); - } else if(! json["success"].toBool()) { - waitingDlg->close(); - QMessageBox::critical(gMainWin, tr("Tip"), tr("Clear player background")+" "+tr("Failed")); - } else waitingDlg->success(); - }); - connect(tcp, &QTcpSocket::errorOccurred, tcp, [tcp, timer, waitingDlg](QAbstractSocket::SocketError err) { - timer->stop(); - tcp->close(); - waitingDlg->close(); - QMessageBox::critical(gMainWin, tr("Tip"), QString(socketErrKey(err))+" ("+QString::number(err)+") "+tcp->errorString()); - }); - tcp->connectToHost(card->m_strCardIp, 3333); - timer->start(10000); - } else { - foreach(auto card, *gSelCards) { - auto tcp = new QTcpSocket(); - auto timer = new QTimer(tcp); - timer->setSingleShot(true); - connect(timer, &QTimer::timeout, tcp, [tcp, card] { - tcp->close(); - gFdResInfo->append(card->m_strCardId+" "+tr("Clear player background")+" "+tr("Timeout")); - }); - connect(tcp, &QTcpSocket::disconnected, tcp, &QTcpSocket::deleteLater); - connect(tcp, &QTcpSocket::connected, tcp, [tcp, timer] { - timer->stop(); - tcp->write("{\"_type\":\"DelBackImg\",\"_id\":\"DelBackImg\",\"zVer\":\"xixun1\"}"); - timer->start(10000); - }); - connect(tcp, &QTcpSocket::readyRead, tcp, [tcp, timer, card] { - timer->stop(); - QByteArray resp = tcp->readAll(); - tcp->close(); - QJsonParseError parseErr; - QJsonDocument json = QJsonDocument::fromJson(resp, &parseErr); - if(parseErr.error != QJsonParseError::NoError) gFdResInfo->append(card->m_strCardId+" "+tr("Clear player background")+" "+parseErr.errorString()); - else if(! json["success"].toBool()) gFdResInfo->append(card->m_strCardId+" "+tr("Clear player background")+" "+tr("Failed")); - else gFdResInfo->append(card->m_strCardId+" "+tr("Clear player background")+" "+tr("Success")); - }); - connect(tcp, &QTcpSocket::errorOccurred, tcp, [tcp, timer, card](QAbstractSocket::SocketError err) { - timer->stop(); - tcp->close(); - gFdResInfo->append(card->m_strCardId+" "+tr("Clear player background")+" "+QMetaEnum::fromType().valueToKey(err)+" ("+QString::number(err)+") "+tcp->errorString()); - }); - tcp->connectToHost(card->m_strCardIp, 3333); - timer->start(10000); - } - } - }); - hBox->addWidget(btnPlayerBackClear); - - hBox->addStretch(); - vBox->addLayout(hBox); - - lbBaudCfg = new QLabel; - vBox->addWidget(lbBaudCfg); - - hBox = new QHBoxLayout; - - lbBaudModel = new QLabel; - hBox->addWidget(lbBaudModel); - - auto fdBaudDevMod = new QComboBox; - fdBaudDevMod->addItems({ - "M5x/M6x", - "M7x/Y7x", - "E2x/Y6x", - "L20" - }); - hBox->addWidget(fdBaudDevMod); - - lbUart = new QLabel; - hBox->addWidget(lbUart); - - auto fdUart = new QComboBox; - fdUart->setEditable(true); - fdUart->setMinimumWidth(140); - fdUart->setSizeAdjustPolicy(QComboBox::AdjustToContents); - fdUart->addItems({ - "/dev/ttyS3", - "/dev/ttyS4", - "/dev/ttyS5" - }); - hBox->addWidget(fdUart); - - connect(fdBaudDevMod, &QComboBox::currentTextChanged, fdUart, [fdUart](const QString &text) { - fdUart->clear(); - if(text.startsWith("M5x")) fdUart->addItems({ - "/dev/ttyS3", - "/dev/ttyS4", - "/dev/ttyS5" - }); - else if(text.startsWith("M7x")) fdUart->addItem("/dev/ttyS4"); - else if(text.startsWith("E2x")) fdUart->addItems({ - "/dev/ttysWK0", - "/dev/ttysWK1", - "/dev/ttysWK2", - "/dev/ttysWK3", - "/dev/tty232", - "/dev/tty485", - "/dev/ttyTTL" - }); - else if(text.startsWith("L20")) fdUart->addItems({ - "/dev/ttyS0", - "/dev/ttyS1", - "/dev/ttyS4" - }); - }); - - lbBaud = new QLabel; - hBox->addWidget(lbBaud); - - auto fdBaud = new QLineEdit; - fdBaud->setMaximumWidth(70); - hBox->addWidget(fdBaud); - - btnBaudSet = new QPushButton; - btnBaudSet->setProperty("ssType", "progManageTool"); - connect(btnBaudSet, &QPushButton::clicked, this, [this, fdUart, fdBaud] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - QJsonObject json; - json.insert("_id", "SetBaudRateByCardType"); - json.insert("_type", "SetBaudRateByCardType"); - json.insert("uartName", fdUart->currentText()); - json.insert("baud", fdBaud->text().toInt()); - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, tr("Setting Baud Rate")+" ..."); - Def_CtrlReqPre - connect(reply, &QNetworkReply::finished, this, [reply, waitingDlg] { - Def_CtrlSetReqAfter - }); - } else { - foreach(auto card, *gSelCards) { - Def_CtrlSetMulti(tr("Set Baud Rate")) - } - } - }); - hBox->addWidget(btnBaudSet); - - btnBaudGet = new QPushButton; - btnBaudGet->setProperty("ssType", "progManageTool"); - connect(btnBaudGet, &QPushButton::clicked, this, [this, fdUart, fdBaud] { - if(gSelCards->isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"), tr("NoSelectedController")); - return; - } - QJsonObject json; - json.insert("_id", "GetBaudRateByCardType"); - json.insert("_type", "GetBaudRateByCardType"); - json.insert("uartName", fdUart->currentText()); - if(gSelCards->count() == 1) { - auto waitingDlg = new WaitingDlg(this, tr("Getting Baud Rate")+" ..."); - Def_CtrlReqPre - connect(reply, &QNetworkReply::finished, this, [reply, fdBaud, waitingDlg] { - Def_CtrlSingleGetReply - waitingDlg->success(); - fdBaud->setText(QString::number(json["baud"].toInt())); - }); - } else { - foreach(auto card, *gSelCards) { - auto reply = Tools::netManager().post(reqForJson("http://"+card->m_strCardIp+":2016/settings"), QJsonDocument{json}.toJson(QJsonDocument::Compact)); - connect(reply, &QNetworkReply::finished, this, [reply, card] { - QJsonDocument json; - QString err = checkReplyForJson(reply, &json); - gFdResInfo->append(card->m_strCardId+" "+tr("Get Baud Rate")+" "+(err.isEmpty()?QString::number(json["baud"].toInt()):err)); - }); - } - } - }); - hBox->addWidget(btnBaudGet); - - hBox->addStretch(); - vBox->addLayout(hBox); - - - fdIsOpenADB = new QCheckBox; - vBox->addWidget(fdIsOpenADB); - - hBox = new QHBoxLayout(); - - lbCustomJson = new QLabel; - hBox->addWidget(lbCustomJson); - - hBox->addSpacing(40); - - btnSendCustomJson = new QPushButton; - hBox->addWidget(btnSendCustomJson); - - hBox->addStretch(); - vBox->addLayout(hBox); - - fdCustomJson = new QTextEdit; - fdCustomJson->setMinimumHeight(120); - vBox->addWidget(fdCustomJson); - } - vBox->addWidget(grpBoxHiddenSettings); - vBox->addStretch(); - - pushButtonSetREaltimeServer->setProperty("ssType", "progManageTool"); - pushButtonClearRealtimerAddress->setProperty("ssType", "progManageTool"); - pushButtonRestart->setProperty("ssType", "progManageTool"); - fdUnload->setProperty("ssType", "progManageTool"); - btnRunningCheck->setProperty("ssType", "progManageTool"); - pushButtonFpgaUpgrade->setProperty("ssType", "progManageTool"); - pushButtonFpgaVerCheck->setProperty("ssType", "progManageTool"); - pushButtonSyncFpgaVer->setProperty("ssType", "progManageTool"); - btnMinBrightGet->setProperty("ssType", "progManageTool"); - pushButtonReadbackMaxBrightess->setProperty("ssType", "progManageTool"); - btnMinBrightSet->setProperty("ssType", "progManageTool"); - pushButtonSendMaxBrightness->setProperty("ssType", "progManageTool"); - btnM80Set->setProperty("ssType", "progManageTool"); - btnM80Refresh->setProperty("ssType", "progManageTool"); - btnM80Restore->setProperty("ssType", "progManageTool"); - btnGetTopLevel->setProperty("ssType", "progManageTool"); - btnSetTopLevel->setProperty("ssType", "progManageTool"); - btnSendCustomJson->setProperty("ssType", "progManageTool"); - - groupBoxRotate->setVisible(false); - groupBoxMinMaxBrightness->setVisible(false); - groupTopLevel->setVisible(false); - - - connect(pushButtonSetREaltimeServer,SIGNAL(clicked()),this,SLOT(OnSetRealtimeServer())); - connect(pushButtonClearRealtimerAddress,SIGNAL(clicked()),this,SLOT(OnClearRealtimeServer())); - - connect(pushButtonRestart, SIGNAL(clicked()),this,SLOT(OnRestart())); - - connect(pushButtonFpgaUpgrade,SIGNAL(clicked()),this,SLOT(OnFpgaUpgrade())); - connect(pushButtonFpgaVerCheck,SIGNAL(clicked()),this,SLOT(OnFpgaVerCheck())); - connect(pushButtonSyncFpgaVer,SIGNAL(clicked()),this,SLOT(OnSyncFpgaVer())); - - connect(radioButton0degrees,SIGNAL(clicked()),this,SLOT(On0degrees())); - connect(radioButton90degrees,SIGNAL(clicked()),this,SLOT(On90degrees())); - connect(radioButton180degrees,SIGNAL(clicked()),this,SLOT(On180degrees())); - connect(radioButton270degrees,SIGNAL(clicked()),this,SLOT(On270degrees())); - - connect(btnMinBrightSet,SIGNAL(clicked()),this,SLOT(OnSendMinBrightness())); - connect(pushButtonSendMaxBrightness,SIGNAL(clicked()),this,SLOT(OnSendMaxBrightness())); - connect(btnMinBrightGet,SIGNAL(clicked()),this,SLOT(OnGetMinBrightness())); - - connect(pushButtonReadbackMaxBrightess,SIGNAL(clicked()),this,SLOT(OnGetMaxBrightness())); - connect(btnSendCustomJson,SIGNAL(clicked()),this,SLOT(OnSendCustomJson())); - - pHpptClient = new HpptClient(this); - connect(pHpptClient, &HpptClient::httpPostRspReady, this, &CtrlAdvancedPanel::OnProHttpResponse); - pHpptClientAll = new HpptClient(this); - connect(pHpptClientAll,SIGNAL(httpPostRspReady(QString , QString , QByteArray )),this, SLOT(OnProHttpResponseAll(QString , QString , QByteArray))); - m_pGetAskTimer = new QTimer(this); - connect(this, SIGNAL(sigSend(QJsonObject &,QString)), parent->parent(), SLOT(OnControlSendJson(QJsonObject &,QString))); - - connect(pHpptClient,SIGNAL(httpGetRspReady(QString , QByteArray )),this,SLOT(OnProHttpGetResponse(QString , QByteArray))); - - connect(btnM80Set,SIGNAL(clicked()),this,SLOT(OnM80Set())); - connect(btnM80Refresh,SIGNAL(clicked()),this,SLOT(OnM80Refresh())); - connect(btnM80Restore,SIGNAL(clicked()),this,SLOT(OnM80Restore())); - connect(btnSetTopLevel,SIGNAL(clicked()),this,SLOT(OnSetTaxiTopScreen())); - connect(btnGetTopLevel,SIGNAL(clicked()),this,SLOT(OnReadbackTaxiTopScreen())); - connect(fdIsOpenADB,SIGNAL(clicked()),this,SLOT(OnOpenAdb())); - - connect(gDevicePanel, &DevicePanel::sigSelectedDeviceList, this, [this] { - if(isVisible()) init(); - }); - transUi(); -} - -CtrlAdvancedPanel::~CtrlAdvancedPanel(){ - if(pHpptClient != nullptr){ - delete pHpptClient; - pHpptClient=nullptr; - } - if(pHpptClientAll != nullptr){ - delete pHpptClientAll; - pHpptClientAll=nullptr; - } -} -void CtrlAdvancedPanel::showEvent(QShowEvent *event) { - QWidget::showEvent(event); - init(); -} -void CtrlAdvancedPanel::init() { - m_pLedCard = gSelCards->at(0); - if(! m_passwordOk) { - hide(); - PasswordInChDlg dlg(gMainWin); - connect(dlg.btnBox, &QDialogButtonBox::accepted, &dlg, [&dlg]() { - QString passRaw = QSettings().value("advUiPs").toString(); - QString password = passRaw.isEmpty() ? "888" : QTextCodec::codecForName("GBK")->toUnicode(QByteArray::fromBase64(passRaw.toLocal8Bit())); - if(dlg.fdPassword->text() == password) dlg.accept(); - else QMessageBox::critical(&dlg, tr("Tip"),tr("Password is error")); - }); - if(dlg.exec()==QDialog::Accepted) { - if(m_pLedlist->count()==1) btnScreenSet->setEnabled(true); - m_passwordOk = true; - show(); - } else return; - } - - bool isSingle = gSelCards->count()==1; - btnApkUpgrade->setEnabled(isSingle); - btnApkCheck->setEnabled(isSingle); - pushButtonFpgaUpgrade->setEnabled(isSingle); - pushButtonFpgaVerCheck->setEnabled(isSingle); - pushButtonSyncFpgaVer->setEnabled(isSingle); - pushButtonRestart->setEnabled(isSingle); - btnGetLog->setEnabled(isSingle); - if(isSingle) groupM80->setVisible(m_pLedCard->m_strCardId.startsWith("M8", Qt::CaseInsensitive)); - else groupM80->setVisible(true); - - if(! isSingle) return; - m_strUrl = "http://"+m_pLedCard->m_strCardIp+":2016/settings"; - - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "GetScreenSize"); - HttpPostByTypeJsonObject(pHpptClientAll,m_strUrl,json); - - QJsonObject json1; - json1.insert("_id", getRandomString(10)); - json1.insert("_type", "GetOnlineAddr"); - HttpPostByTypeJsonObject(pHpptClientAll,m_strUrl,json1); - - QJsonObject json2; - json2.insert("_id", getRandomString(10)); - json2.insert("_type", "GetRealtimeServer"); - HttpPostByTypeJsonObject(pHpptClientAll,m_strUrl,json2); - - QJsonObject json3; - json3.insert("_id", getRandomString(10)); - json3.insert("_type", "GetCardAlias"); - HttpPostByTypeJsonObject(pHpptClientAll,m_strUrl,json3); - - if(m_pLedCard->m_strCardId.startsWith("M8", Qt::CaseInsensitive)) { - QJsonObject json3; - json3.insert("_id", getRandomString(10)); - json3.insert("_type", "GetAllScreenSizeM80"); - qDebug()<<"GetAllScreenSizeM80 send"; - HttpPostByTypeJsonObject(pHpptClientAll,m_strUrl,json3); - } -} -void CtrlAdvancedPanel::changeEvent(QEvent *event) { - QWidget::changeEvent(event); - if(event->type() == QEvent::LanguageChange) transUi(); -} -void CtrlAdvancedPanel::transUi() { - btnBindTaxiIc->setText(tr("Binding *.ic account indentity voucher")); - btnGetTopLevel->setText(tr("Readback")); - btnLedSet3->setText(tr("Start LedSet3.0 configure LED module")); - btnLedSet4->setText(tr("Start LedSet4")); - btnM80Refresh->setText(tr("Refresh")); - btnM80Restore->setText(tr("Restore to default")); - btnM80Set->setText(tr("Set")); - btnAliasSet->setText(tr("Set")); - btnScreenSet->setText(tr("Set")); - btnSetTopLevel->setText(tr("Set")); - fdScreenHeight->setPlaceholderText(tr("Height")); - fdScreenWidth->setPlaceholderText(tr("Width")); - fdTopLevelHL->setText(tr("Service:High Out of service:Low")); - fdTopLevelLH->setText(tr("Service:Low Out of service:High")); - groupBoxRotate->setTitle(tr("Rotate")); - - grpBoxHiddenSettings->setTitle(tr("Hidden Settings")+" ("+tr("Click right button to hide")+")"); - btnSysUpd->setText(tr("System Update")); - lbBaudCfg->setText(tr("Baud Config")); - lbBaudModel->setText(tr("Model")); - lbUart->setText(tr("Uart")); - lbBaud->setText(tr("Baud")); - btnBaudSet->setText(tr("Set")); - btnBaudGet->setText(tr("Get")); - fdIsOpenADB->setText(tr("Open ADB")); - lbCustomJson->setText(tr("Post Custom JSON")); - btnSendCustomJson->setText(tr("Send")); - - groupM80->setTitle(tr("M80 configuration")); - groupTopLevel->setTitle(tr("Taxi top screen configuration")); - label->setText(tr("Realtimer Server Address:")); - lbTitle->setText(tr("Advanced parameters")); - lbCompanyId->setText(tr("Compant ID:")); - labelWebServer->setText(tr("Web Server Address:")); - lbMinBright->setText(tr("Min brightness")); - label_3->setText(tr("Max brightness ")); - lbMinBrightTip->setText(tr("(min:1)")); - label_5->setText(tr("(max:255)")); - lbAlias->setText(tr("Alias")); - lbScreenHeight->setText(tr("Height")); - lbScreenWidth->setText(tr("Screen Width(pixel)")); - fdCompanyId->setPlaceholderText(tr("Compant ID")); - btnApkCheck->setText(tr("Check Apk")); - btnApkUpgrade->setText(tr("Apk upgrade")); - btnGetLog->setText(tr("Check Log")); - btnSetBack->setText(tr("Set Wallpaper")); - btnClearProg->setText(tr("Clear Program")); - btnPlayerBackSet->setText(tr("Set player background")); - btnPlayerBackClear->setText(tr("Clear player background")); - - pushButtonClearRealtimerAddress->setText(tr("Clear")); - pushButtonFpgaUpgrade->setText(tr("FPGA Upgrade")); - pushButtonFpgaVerCheck->setText(tr("FPGA version check")); - btnMinBrightGet->setText(tr("Readback")); - pushButtonReadbackMaxBrightess->setText(tr("Readback")); - pushButtonRestart->setText(tr("Restart led controller system")); - btnRunningCheck->setText(tr("Running check")); - pushButtonSendMaxBrightness->setText(tr("Send")); - btnMinBrightSet->setText(tr("Send")); - pushButtonSetREaltimeServer->setText(tr("Set")); - btnWebServerSet->setText(tr("Set")); - pushButtonSyncFpgaVer->setText(tr("Sync FPGA version")); - fdUnload->setText(tr("Uninstall")); - radioButton0degrees->setText(tr("0 degrees")); - radioButton180degrees->setText(tr("180 degrees")); - radioButton270degrees->setText(tr("270 degrees")); - radioButton90degrees->setText(tr("90 degrees")); -} - -void CtrlAdvancedPanel::OnClearRealtimeServer(){ - CHECK_CARD_SELECTED - comboBox_realtimeServer->clearEditText(); - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "SetRealtimeServer"); - json.insert("server", ""); - MACRO_DEFINE_TIPDLG_FUCN(tr("ClearRealtimeServer"),tr("Success"),tr("failed")) -} -void CtrlAdvancedPanel::OnSetRealtimeServer(){ - CHECK_CARD_SELECTED - if(comboBox_realtimeServer->currentText().isEmpty()) { - QMessageBox::information(gMainWin, tr("Tip"),tr("InputRealTimeAddressTip")); - comboBox_realtimeServer->setFocus(); - return; - } - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "SetRealtimeServer"); - json.insert("server", comboBox_realtimeServer->currentText()); - MACRO_DEFINE_TIPDLG_FUCN(tr("SetRealtimeServer"),tr("Success"),tr("failed")) -} -void CtrlAdvancedPanel::OnStartConfigLedScreenSoft() { - QString strLedSetFile = QApplication::applicationDirPath()+"/LedSet/LedSet3.0.exe"; - QFileInfo cc22(strLedSetFile); - if(cc22.exists()) { - QProcess::startDetached(strLedSetFile,QStringList()); - return; - } - QSettings reg("HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\sysolution\\LedSet3.0", QSettings::NativeFormat); - QString strLedsetPath = reg.value("Program_path").toString(); - if(!strLedsetPath.isEmpty()) { - QFileInfo cc(strLedsetPath); - if(cc.exists()) QProcess::startDetached(strLedsetPath,QStringList()); - else { - auto res = QMessageBox::question(gMainWin, tr("Tip Info"), tr("Can not find LedSet3.0.exe,down you need download and install it")+strLedsetPath); - if(res == QMessageBox::Yes) { - UpdateLedset3Dialog *pDlg=new UpdateLedset3Dialog(this); - pDlg->exec(); - } - } - return; - } - QSettings reg1("HKEY_LOCAL_MACHINE\\SOFTWARE\\sysolution\\LedSet3.0", QSettings::NativeFormat); - strLedsetPath = reg1.value("Program_path").toString(); - QFileInfo cc(strLedsetPath); - if(!strLedsetPath.isEmpty()) { - if(cc.exists()) QProcess::startDetached(strLedsetPath,QStringList()); - else { - QString str1="C:/Program Files/sysolution/LedSet3.0/LedSet3.0.exe"; - QFileInfo cc1(str1); - if(cc1.exists()) QProcess::startDetached(str1,QStringList()); - else { - QString str2="C:/Program Files (x86)/sysolution/LedSet3.0/LedSet3.0.exe"; - QFileInfo cc2(str1); - if(cc2.exists()) QProcess::startDetached(str2,QStringList()); - else { - auto res = QMessageBox::question(gMainWin, tr("Tip Info"), tr("Can not find LedSet3.0.exe,down you need download and install it")+strLedsetPath); - if(res == QMessageBox::Yes) { - UpdateLedset3Dialog *pDlg=new UpdateLedset3Dialog(this); - pDlg->exec(); - } - } - } - } - } else { - QString str1="C:/Program Files/sysolution/LedSet3.0/LedSet3.0.exe"; - QFileInfo cc1(str1); - if(cc1.exists()) QProcess::startDetached(str1,QStringList()); - else { - QString str2="C:/Program Files (x86)/sysolution/LedSet3.0/LedSet3.0.exe"; - QFileInfo cc2(str1); - if(cc2.exists())QProcess::startDetached(str2,QStringList()); - else { - auto res = QMessageBox::question(gMainWin, tr("Tip Info"), tr("Can not find LedSet3.0.exe,down you need download and install it")+strLedsetPath); - if(res == QMessageBox::Yes) { - UpdateLedset3Dialog *pDlg=new UpdateLedset3Dialog(this); - pDlg->exec(); - } - } - } - } -} -void CtrlAdvancedPanel::OnRestart(){ - CHECK_CARD_SELECTED - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "RestartAndroid"); - MACRO_DEFINE_TIPDLG_FUCN(tr("RestartAndroid"),tr("Success"),tr("failed")) -} - -//获取到httpPost的应答,如果参数变化需要出发修改控件item的内容 -void CtrlAdvancedPanel::OnProHttpResponse(QString url, QString, QByteArray data){ - if(url == m_strUrl) { - QJsonParseError parseJsonErr; - QJsonDocument document = QJsonDocument::fromJson(data,&parseJsonErr); - if(parseJsonErr.error != QJsonParseError::NoError){ - if(data.size()!=0) qDebug()<setCurrentText(jsonObject["server"].toString()); - fdCompanyId->setText(jsonObject["companuID"].toString()); - MACRO_ASKTIME_STOP - MACRO_POSTING_DLG_UNLOCK - } - else if(strType == "GetRealtimeServer"){ - comboBox_realtimeServer->setCurrentText(jsonObject["server"].toString()); - MACRO_ASKTIME_STOP - MACRO_POSTING_DLG_UNLOCK - } - else if(strType == "GetCardAlias") - { - fdAlias->setText(QString::fromUtf8(QByteArray::fromBase64(jsonObject["alias"].toString().toLatin1()))); - MACRO_ASKTIME_STOP - MACRO_POSTING_DLG_UNLOCK - } - else if(strType =="UpgradeSoftware") - { - MACRO_ASKTIME_STOP - MACRO_POSTING_DLG_UNLOCK - QMessageBox::information(gMainWin, tr("Tip"),tr("UpgradeSoftware")+tr("Success")); - } - else if(strType == "SynchronousHardwareVersion"){ - - MACRO_ASKTIME_STOP - MACRO_POSTING_DLG_UNLOCK - QMessageBox::information(gMainWin, tr("Tip"),tr("SynchronousHardwareVersion")+" "+tr("Success")); - } - else if(strType == "DelPrograms") - { - MACRO_ASKTIME_STOP - MACRO_POSTING_DLG_UNLOCK - - } - else if(strType == "SetScreenRotation") - { - MACRO_ASKTIME_STOP - MACRO_POSTING_DLG_UNLOCK - - } - else if(strType == "SetMinBrightness") - { - MACRO_ASKTIME_STOP - MACRO_POSTING_DLG_UNLOCK - } - else if(strType == "SetMaxBrightness") - { - MACRO_ASKTIME_STOP - MACRO_POSTING_DLG_UNLOCK - } - else if(strType == "GetMinBrightness") - { - - fdMinBright->setText(QString::number(jsonObject["brightness"].toInt())); - MACRO_ASKTIME_STOP - MACRO_POSTING_DLG_UNLOCK - } - else if(strType == "GetMaxBrightness") - { - lineEdit_4->setText(QString::number(jsonObject["brightness"].toInt())); - MACRO_ASKTIME_STOP - MACRO_POSTING_DLG_UNLOCK - } - else if(strType == "GetSpecialResolution") - { - - QString strCurDisplayResolution = jsonObject["displayResolution"].toString(); - fdM80->setCurrentText(strCurDisplayResolution); - MACRO_ASKTIME_STOP - MACRO_POSTING_DLG_UNLOCK - } - - else if(strType == "CheckHardwareVersions"){ - MACRO_ASKTIME_STOP - MACRO_POSTING_DLG_UNLOCK - QString strtempVer=""; - int itempVerCount=0; - foreach(QJsonValue value, jsonObject["versions"].toArray()) { - QString strtempIcount=QString::number(itempVerCount); - strtempVer += "[card"+strtempIcount+"]:"+value.toString()+"\r\n"; - itempVerCount++; - - } - QMessageBox::information(gMainWin, tr("FPGA Version"),strtempVer); - } - else if (strType == "SetHighForBusy") { - MACRO_ASKTIME_STOP - MACRO_POSTING_DLG_UNLOCK - - } - else if(strType == "OpenAdb") - { - MACRO_ASKTIME_STOP - MACRO_POSTING_DLG_UNLOCK - } - else if (strType == "GetStateForBusy") { - MACRO_ASKTIME_STOP - MACRO_POSTING_DLG_UNLOCK - if(jsonObject["result"].toInt()==0) - { - fdTopLevelLH->setChecked(true); - fdTopLevelHL->setChecked(false); - } - else { - fdTopLevelLH->setChecked(false); - fdTopLevelHL->setChecked(true); - - } - } - }else { - if(strType =="UpgradeSoftware"){ - qDebug()<<"slotUploadFinished failed ack"; - MACRO_ASKTIME_STOP - MACRO_POSTING_DLG_UNLOCK - } - } - } - if(url == m_strStartUrl) - { - QJsonParseError parseJsonErr; - QJsonDocument document = QJsonDocument::fromJson(data,&parseJsonErr); - if(!(parseJsonErr.error == QJsonParseError::NoError)) - { - if(data.size()==0) - qDebug()<<"json is empty"; - else - qDebug()<m_strCardId +"---------"+ strType; - if(strType == "GetScreenSize") - { - fdScreenWidth->setText(QString::number(jsonObject["width"].toInt())); - fdScreenHeight->setText(QString::number(jsonObject["height"].toInt())); - } - - else if(strType == "GetCardAlias") - { - fdAlias->setText(QString::fromUtf8(QByteArray::fromBase64(jsonObject["alias"].toString().toLatin1()))); - - } - else if(strType == "GetOnlineAddr") - { - fdWebServerAddr->setCurrentText(jsonObject["server"].toString()); - fdCompanyId->setText(jsonObject["companuID"].toString()); - } - else if(strType == "GetRealtimeServer") - { - qDebug()<<"GetRealtimeServer ack"<setCurrentText(jsonObject["server"].toString()); - } - else if(strType == "GetAllScreenSizeM80") - { - mM80Map=jsonObject["result"].toObject(); - QStringList strlist=mM80Map.keys(); - fdM80->clear(); - fdM80->addItems(strlist); - comboBox_realtimeServer->setCurrentText(jsonObject["server"].toString()); - } - - } - - } -} -void CtrlAdvancedPanel::OnFpgaUpgrade() -{ - QString url="http://"+m_pLedCard->m_strCardIp+":2016/upload?type=hardware"; - QFileDialog dlg; - m_strUpgradeFpgaFile = QFileDialog::getOpenFileName(this, "open file dialog", "", tr("apk package (*.rpd)")); - QFileInfo file1(m_strUpgradeFpgaFile); - QFile file(m_strUpgradeFpgaFile); - QMap params_send; //上传的普通参数 在本程序中 需要上传一个普通参数为"username" - params_send.insert("username","10005"); - UpLoadForm(url, params_send, file1.fileName(), &file, 1); -} -void CtrlAdvancedPanel::OnFpgaVerCheck() -{ - CHECK_CARD_SELECTED - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "CheckHardwareVersions"); - MACRO_DEFINE_TIPDLG_FUCN(tr("CheckHardwareVersions"),tr("Success"),tr("failed")) -} -void CtrlAdvancedPanel::OnSyncFpgaVer() -{ - CHECK_CARD_SELECTED - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "SynchronousHardwareVersion"); - MACRO_DEFINE_TIPDLG_FUCN(tr("SynchronousHardwareVersion"),tr("Check Screen untile fpga update finished"),tr("failed")) -} -void CtrlAdvancedPanel::slotUploadFpgaFinished() -{ - QFileInfo file(m_strUpgradeApkFile); - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "SynchronousHardwareVersion"); - HttpPostByTypeJsonObject(pHpptClient,m_strUrl,json); - emit sigSetTipTextContent(tr("SynchronousHardwareVersion")); - qDebug()<<"slotUploadFinished"; - -} -void CtrlAdvancedPanel::slotUploadFinished() -{ - QFileInfo file(m_strUpgradeApkFile); - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "UpgradeSoftware"); - json.insert("fileName", file.fileName()); - json.insert("isCustom", true); - HttpPostByTypeJsonObject(pHpptClient,m_strUrl,json); - emit sigSetTipTextContent(tr("install start...")); - MACRO_ASKTIME_STOP - m_pGetAskTimer->start(50000); - - qDebug()<<"slotUploadFinished"; - -} -void CtrlAdvancedPanel::slotUploadProgress(qint64 A,qint64 B) -{ - if(B!=0) - { - QString strbaifenbi=tr("Uploadding")+":"+QString("%1%").arg(A*100/B); - emit sigSetTipTextContent(strbaifenbi); - m_pGetAskTimer->stop(); - m_pGetAskTimer->start(30000); - } -} - -void CtrlAdvancedPanel::UpLoadForm(QString Path, QMap params, QString fileName, QFile *uploadFile, int iType) { - auto boundary = QUuid::createUuid().toByteArray(); - QByteArray data; - for(QMap::iterator t=params.begin(); t!=params.end(); t++) { - data.append("--").append(boundary).append("\r\n"); - data.append("Content-Disposition: form-data;name=\"").append(t.key().toUtf8()).append("\"\r\n"); - data.append("\r\n"); - data.append(t.value().toUtf8()).append("\r\n"); - } - //上传文件的头部 - data.append("--").append(boundary).append("\r\n"); - data.append("Content-Disposition: form-data;name=\"").append(fileName.toUtf8()).append("\";filename=\"").append(fileName.toUtf8()).append("\"\r\n"); - data.append("\r\n"); - //上传文件内容 - if(!uploadFile->open(QIODevice::ReadOnly)) return; - data.append(uploadFile->readAll()); - uploadFile->close(); - data.append("\r\n"); - data.append("--").append(boundary).append("\r\n"); - - //编辑HTTP头部 - QNetworkRequest request = netReq(Path, 15000, "multipart/form-data;boundary="+boundary); - request.setHeader(QNetworkRequest::ContentLengthHeader, data.length()); - //执行post请求 - if(m_PostingDlg==nullptr) - { - m_PostingDlg = new LoEmptyDialog(); - connect(m_PostingDlg,SIGNAL(sigClose()),this,SLOT(DeletePostingDlg())); - connect(m_pGetAskTimer,SIGNAL(timeout()),m_PostingDlg,SLOT(TimerOutUnlock())); - m_PostingDlg->lock(tr("UpgradeSoftware"),tr("Success"),tr("UpgradeSoftware")+tr("failed")); - m_pGetAskTimer->start(60000); - QNetworkReply * m_netReply = Tools::netManager().post(request, data); - connect(m_netReply, SIGNAL(uploadProgress(qint64,qint64)), this, SLOT(slotUploadProgress(qint64,qint64))); - connect(this, SIGNAL(sigSetTipTextContent ( QString )), m_PostingDlg, SLOT( SetTipTextContent(QString))); - if(iType==0)//apk - { - connect(m_netReply, SIGNAL(finished()), this, SLOT(slotUploadFinished())); - - } - else if(iType==1)//fpga.rpd - { - connect(m_netReply, SIGNAL(finished()), this, SLOT(slotUploadFpgaFinished())); - - } - m_PostingDlg->exec(); - } -} -void messageHandler(QtMsgType type, const QMessageLogContext &, const QString &msg) { - auto cur = QDateTime::currentDateTime(); - QFile file("D:/LedOK-advanced-"+cur.toString("yy-MM-dd")+".log"); - file.open(QIODevice::WriteOnly | QIODevice::Append); - file.write(cur.toString("yy-MM-dd hh:mm:ss ").toUtf8()); - if(type==QtDebugMsg) file.write(" Debug: "); - else if(type==QtWarningMsg) file.write(" Warning: "); - else if(type==QtCriticalMsg)file.write("Critical: "); - else if(type==QtFatalMsg) file.write(" Fatal: "); - else if(type==QtInfoMsg) file.write(" Info: "); - else if(type==QtSystemMsg) file.write(" System: "); - file.write(msg.toUtf8()); - file.close(); -} -void CtrlAdvancedPanel::keyReleaseEvent(QKeyEvent *event) { - auto key = event->key(); - if(key == Qt::Key_F3) m_lockFlag = false; - else if(key == Qt::Key_F5) groupBoxRotate->setVisible(! groupBoxRotate->isVisible()); - else if(key == Qt::Key_F6) groupBoxMinMaxBrightness->setVisible(! groupBoxMinMaxBrightness->isVisible()); - else if(key == Qt::Key_F8) groupTopLevel->setVisible(! groupTopLevel->isVisible()); - else if(key == Qt::Key_F12) qInstallMessageHandler(messageHandler); - QWidget::keyPressEvent(event); -} -void CtrlAdvancedPanel::mouseReleaseEvent(QMouseEvent *event){ - if(event->button()==Qt::RightButton) grpBoxHiddenSettings->setVisible(! grpBoxHiddenSettings->isVisible()); -} -void CtrlAdvancedPanel::On0degrees() -{ - CHECK_CARD_SELECTED - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "SetScreenRotation"); - json.insert("rotation", 0); - MACRO_DEFINE_TIPDLG_FUCN(tr("SetScreenRotation"),tr("Success"),tr("failed")) -} - -void CtrlAdvancedPanel::On90degrees() -{ - CHECK_CARD_SELECTED - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "SetScreenRotation"); - json.insert("rotation", 1); - MACRO_DEFINE_TIPDLG_FUCN(tr("SetScreenRotation"),tr("Success"),tr("failed")) -} -void CtrlAdvancedPanel::On180degrees() -{ - CHECK_CARD_SELECTED - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "SetScreenRotation"); - json.insert("rotation", 2); - MACRO_DEFINE_TIPDLG_FUCN(tr("SetScreenRotation"),tr("Success"),tr("failed")) -} -void CtrlAdvancedPanel::On270degrees() -{ - CHECK_CARD_SELECTED - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "SetScreenRotation"); - json.insert("rotation", 3); - MACRO_DEFINE_TIPDLG_FUCN(tr("SetScreenRotation"),tr("Success"),tr("failed")) -} -void CtrlAdvancedPanel::OnSendMinBrightness() -{ - CHECK_CARD_SELECTED - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "SetMinBrightness"); - json.insert("brightness", fdMinBright->text().toInt()); - MACRO_DEFINE_TIPDLG_FUCN(tr("SetMinBrightness"),tr("Success"),tr("failed")) - - -} -void CtrlAdvancedPanel::OnSendMaxBrightness() -{ - CHECK_CARD_SELECTED - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "SetMaxBrightness"); - json.insert("brightness", lineEdit_4->text().toInt()); - MACRO_DEFINE_TIPDLG_FUCN(tr("SetMaxBrightness"),tr("Success"),tr("failed")) -} -void CtrlAdvancedPanel::OnGetMinBrightness() -{ - CHECK_CARD_SELECTED - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "GetMinBrightness"); - MACRO_DEFINE_TIPDLG_FUCN(tr("GetMinBrightness"),tr("Success"),tr("failed")) -} -void CtrlAdvancedPanel::OnGetMaxBrightness() -{ - CHECK_CARD_SELECTED - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "GetMaxBrightness"); - MACRO_DEFINE_TIPDLG_FUCN(tr("GetMaxBrightness"),tr("Success"),tr("failed")) -} - -void CtrlAdvancedPanel::OnM80Set() -{ - CHECK_CARD_SELECTED - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "SetSpecialResolution"); - json.insert("displayResolution",fdM80->currentText()), //显示分辨率 - json.insert("totalResolution",mM80Map[fdM80->currentText()].toString() ); //显示分辨率 - MACRO_DEFINE_TIPDLG_FUCN(tr("SetSpecialResolution"),tr("Success"),tr("failed")) -} - -void CtrlAdvancedPanel::OnM80Refresh() -{ - CHECK_CARD_SELECTED - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "GetSpecialResolution"); - MACRO_DEFINE_TIPDLG_FUCN(tr("GetSpecialResolution"),tr("Success"),tr("failed")) -} - -void CtrlAdvancedPanel::OnM80Restore() -{ - CHECK_CARD_SELECTED - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "CleanDisplayScreenSize"); - MACRO_DEFINE_TIPDLG_FUCN(tr("CleanDisplayScreenSize"),tr("Success"),tr("failed")) -} -void CtrlAdvancedPanel::OnSetTaxiTopScreen() -{ - CHECK_CARD_SELECTED - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "SetHighForBusy"); - if(fdTopLevelLH->isChecked()) - json.insert("busyState", 0); - else if(fdTopLevelHL->isChecked()) - json.insert("busyState", 1); - else { - json.insert("busyState", 1); - } - - MACRO_DEFINE_TIPDLG_FUCN(tr("SetHighForBusy"),tr("Success"),tr("failed")) -} -void CtrlAdvancedPanel::OnReadbackTaxiTopScreen() -{ - CHECK_CARD_SELECTED - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "GetStateForBusy"); - MACRO_DEFINE_TIPDLG_FUCN(tr("GetStateForBusy"),tr("Success"),tr("failed")) -} - -void CtrlAdvancedPanel::OnOpenAdb() -{ - - CHECK_CARD_SELECTED - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "OpenAdb"); - if(fdIsOpenADB->isChecked()) - { - json.insert("open", true); - } - else { - json.insert("open", false); - } - MACRO_DEFINE_TIPDLG_FUCN(tr("OpenAdb"),tr("Success"),tr("failed")) -} -void CtrlAdvancedPanel::DeletePostingDlg() -{ - if(m_PostingDlg!=nullptr) - { - delete m_PostingDlg; - m_PostingDlg=nullptr; - } -} -void CtrlAdvancedPanel::OnSendCustomJson(){//ok - - CHECK_CARD_SELECTED - m_strStartUrl="http://"+m_pLedCard->m_strCardIp+":3000"; - - QJsonObject json; - - QJsonParseError l_err; - QJsonDocument l_doc = QJsonDocument::fromJson(fdCustomJson->toPlainText().toUtf8(), &l_err); - if (l_err.error == QJsonParseError::NoError) - { - if (l_doc.isObject()) - { - json = l_doc.object(); - } - } - - if(json.count()<=0) - { - QMessageBox::information(gMainWin, tr("Tip"),tr("Json format is error!")); - return; - } - if(m_pLedlist==nullptr) - return; - if(m_pLedlist->count()<=1) - { - if(m_pLedCard!=nullptr) - { - HttpPostByTypeJsonObject(pHpptClient,m_strStartUrl,json); - if(m_PostingDlg==nullptr) - { - m_PostingDlg = new LoEmptyDialog(this); - connect(m_PostingDlg,SIGNAL(sigClose()),this,SLOT(DeletePostingDlg())); - connect(m_pGetAskTimer,SIGNAL(timeout()),m_PostingDlg,SLOT(TimerOutUnlock())); - m_PostingDlg->lock(tr("AliIotSetting"),tr("Success"),tr("failed")); - m_pGetAskTimer->start(5000); - m_PostingDlg->exec(); - - } - } - } - else { - emit sigSend(json,tr("AliIotSetting")); - } -} - -PlayerBackSendThread::PlayerBackSendThread(const QString &file, const QString &ip) : file(file), ip(ip) { - connect(this, &QThread::finished, this, &QThread::deleteLater); -} -void PlayerBackSendThread::run() { - TcpSocket tcp; - tcp.connectToHost(ip, 3333); - if(! tcp.waitForConnected()) { - emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when waitForConnected"); - tcp.close(); - return; - } - QFileInfo info(file); - auto baseName = info.baseName(); - auto remain = info.size(); - - auto req = QJsonObject(); - req.insert("_type", "proStart"); - req.insert("proName", "program"); - req.insert("proSize", remain); - req.insert("zVer","xixun1"); - auto resNum = tcp.write(QJsonDocument(req).toJson(QJsonDocument::Compact)); - if(resNum == -1 || ! tcp.waitForBytesWritten()) { - emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when write 'proStart'"); - tcp.close(); - return; - } - req = QJsonObject(); - req.insert("_type", "imgFileStart"); - req.insert("id", baseName); - req.insert("size", remain); - req.insert("zVer","xixun1"); - resNum = tcp.write(QJsonDocument(req).toJson(QJsonDocument::Compact)); - if(resNum == -1 || ! tcp.waitForBytesWritten()) { - emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when write 'imgFileStart'"); - tcp.close(); - return; - } - auto file = new QFile(info.filePath()); - if(! file->open(QFile::ReadOnly)) { - emit emErr(tr("Open file failed")+" "+file->errorString()); - tcp.close(); - return; - } - while(remain > 0) { - auto readed = file->read(qMin(4096LL, remain)); - if(readed.isEmpty()) { - emit emErr(tr("Read file failed")+" "+file->errorString()); - tcp.close(); - file->close(); - return; - } - resNum = tcp.write(readed); - if(resNum == -1) { - emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when write file: "+file->fileName()); - tcp.close(); - file->close(); - return; - } - if(! tcp.waitForBytesWritten()) { - emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when waitForWritten file: "+file->fileName()); - tcp.close(); - file->close(); - return; - } - remain -= resNum; - } - file->close(); - req = QJsonObject(); - req.insert("_type", "imgFileEnd"); - req.insert("id", baseName); - req.insert("zVer","xixun1"); - resNum = tcp.write(QJsonDocument(req).toJson(QJsonDocument::Compact)); - if(resNum == -1 || ! tcp.waitForBytesWritten()) { - emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when write 'fileEnd'"); - tcp.close(); - return; - } - req = QJsonObject(); - req.insert("_type", "proEnd"); - req.insert("proName", "program"); - req.insert("zVer","xixun1"); - resNum = tcp.write(QJsonDocument(req).toJson(QJsonDocument::Compact)); - if(resNum == -1 || ! tcp.waitForBytesWritten()) { - emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when write 'proEnd'"); - tcp.close(); - return; - }; - if(! tcp.waitForReadyRead()) { - emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when waitForRead 'proEnd'"); - tcp.close(); - return; - } - auto resp = tcp.readAll(); - if(resp.isEmpty()) { - emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") when read 'proEnd'"); - tcp.close(); - return; - } - tcp.close(); - emit emErr(""); -} diff --git a/LedOK/wDevicesManager/ctrladvancedpanel.h b/LedOK/wDevicesManager/ctrladvancedpanel.h deleted file mode 100644 index 8f921f7..0000000 --- a/LedOK/wDevicesManager/ctrladvancedpanel.h +++ /dev/null @@ -1,163 +0,0 @@ -#ifndef CTRLADVANCEDPANEL_H -#define CTRLADVANCEDPANEL_H - -#include "wDevicesManager/ledcard.h" -#include "communication/hpptclient.h" -#include "base/loemptydialog.h" -#include -#include -#include -#include -#include -#include -#include -#include - -class CtrlAdvancedPanel : public QWidget { - Q_OBJECT -public: - explicit CtrlAdvancedPanel(QWidget *parent = nullptr,QList *m_pLedlist=nullptr); - ~CtrlAdvancedPanel(); -protected: - void showEvent(QShowEvent *event) override; - void init(); - void changeEvent(QEvent *) override; - void transUi(); - - void keyReleaseEvent(QKeyEvent *) override; - void mouseReleaseEvent(QMouseEvent *) override; - -protected slots: - void On0degrees(); - void On90degrees(); - void On180degrees(); - void On270degrees(); - void OnSendMinBrightness(); - void OnSendMaxBrightness(); - void OnGetMinBrightness(); - void OnGetMaxBrightness(); - void OnSendCustomJson(); -signals: - void sigSend(QJsonObject &,QString); - void sigSetTipTextContent(QString); -protected slots: - void DeletePostingDlg(); - void OnProHttpResponse(QString url, QString postMD5, QByteArray data); - void OnProHttpResponseAll(QString url, QString postMD5, QByteArray data); - void OnSetRealtimeServer(); - void OnClearRealtimeServer(); - void OnStartConfigLedScreenSoft(); - void OnRestart(); - void OnFpgaUpgrade(); - void OnFpgaVerCheck(); - void OnSyncFpgaVer(); - void slotUploadFinished(); - void slotUploadFpgaFinished(); - void slotUploadProgress(qint64 A,qint64 B); - void OnM80Set(); - void OnM80Refresh(); - void OnM80Restore(); - void OnSetTaxiTopScreen(); - void OnReadbackTaxiTopScreen(); - void OnOpenAdb(); -private: - QList *m_pLedlist=nullptr; - LedCard *m_pLedCard = nullptr; - HpptClient *pHpptClient = nullptr; - HpptClient *pHpptClientAll = nullptr; - QString m_strUrl=""; - QString m_strStartUrl=""; - LoEmptyDialog * m_PostingDlg=nullptr; - QTimer *m_pGetAskTimer=nullptr; - bool m_passwordOk=false; - QString m_strUpgradeApkFile=""; - QString m_strUpgradeFpgaFile=""; - QJsonObject mM80Map; - bool m_lockFlag=true; - void UpLoadForm(QString Path, QMap params, QString fileFormName, QFile *uploadFile, int iType); - - QLabel *lbTitle; - QLabel *lbScreenWidth; - QLineEdit *fdScreenWidth; - QLabel *lbScreenHeight; - QLineEdit *fdScreenHeight; - QPushButton *btnScreenSet; - QLabel *lbAlias; - QLineEdit *fdAlias; - QPushButton *btnAliasSet; - QLabel *labelWebServer; - QComboBox *fdWebServerAddr; - QLabel *lbCompanyId; - QLineEdit *fdCompanyId; - QPushButton *btnWebServerSet; - QLabel *label; - QComboBox *comboBox_realtimeServer; - QPushButton *pushButtonSetREaltimeServer; - QPushButton *pushButtonClearRealtimerAddress; - QPushButton *btnApkCheck; - QPushButton *btnApkUpgrade; - QComboBox *fdPkg; - QPushButton *fdUnload; - QPushButton *btnRunningCheck; - QPushButton *pushButtonFpgaUpgrade; - QPushButton *pushButtonFpgaVerCheck; - QPushButton *pushButtonSyncFpgaVer; - QPushButton *pushButtonRestart; - QPushButton *btnClearProg; - QPushButton *btnGetLog; - QPushButton *btnSetBack, *btnPlayerBackSet, *btnPlayerBackClear; - - QGroupBox *groupM80; - QComboBox *fdM80; - QPushButton *btnM80Set; - QPushButton *btnM80Refresh; - QPushButton *btnM80Restore; - QGroupBox *groupTopLevel; - QRadioButton *fdTopLevelHL; - QRadioButton *fdTopLevelLH; - QPushButton *btnSetTopLevel; - QPushButton *btnGetTopLevel; - QPushButton *btnLedSet3; - QPushButton *btnLedSet4; - QPushButton *btnBindTaxiIc; - - QGroupBox *groupBoxRotate; - QRadioButton *radioButton0degrees; - QRadioButton *radioButton90degrees; - QRadioButton *radioButton180degrees; - QRadioButton *radioButton270degrees; - QGroupBox *groupBoxMinMaxBrightness; - QLabel *lbMinBright; - QLineEdit *fdMinBright; - QLabel *lbMinBrightTip; - QPushButton *btnMinBrightGet; - QPushButton *btnMinBrightSet; - QLabel *label_3; - QLineEdit *lineEdit_4; - QLabel *label_5; - QPushButton *pushButtonReadbackMaxBrightess; - QPushButton *pushButtonSendMaxBrightness; - - QGroupBox *grpBoxHiddenSettings; - QPushButton *btnSysUpd; - QLabel *lbBaudCfg, *lbBaudModel, *lbUart, *lbBaud; - QPushButton *btnBaudSet, *btnBaudGet; - QCheckBox *fdIsOpenADB; - QLabel *lbCustomJson; - QTextEdit *fdCustomJson; - QPushButton *btnSendCustomJson; -}; - -class PlayerBackSendThread : public QThread { - Q_OBJECT -public: - PlayerBackSendThread(const QString &file, const QString &ip); - QString file, ip; - QString err; -protected: - void run(); -signals: - void emErr(QString); -}; - -#endif // CTRLADVANCEDPANEL_H diff --git a/LedOK/wDevicesManager/threadupgradeapk.cpp b/LedOK/wDevicesManager/threadupgradeapk.cpp deleted file mode 100644 index 494b641..0000000 --- a/LedOK/wDevicesManager/threadupgradeapk.cpp +++ /dev/null @@ -1,182 +0,0 @@ -#include "threadupgradeapk.h" -#include "QFileInfo" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -ThreadUpgradeApk::ThreadUpgradeApk(QString strApkPathAndName,QString url,int iType) -{ - m_strApkName=strApkPathAndName; - m_strUrl=url; - m_iType=iType; -} -ThreadUpgradeApk::~ThreadUpgradeApk() -{ - -} -void ThreadUpgradeApk::run() -{ - // QCoreApplication::processEvents(); - if(bSendCloseFlag==true) - bSendCloseFlag=false; - else { - return; - } - QFileInfo file1(m_strApkName); - QFile file(m_strApkName); - QMap params_send; //上传的普通参数 在本程序中 需要上传一个普通参数为"username" - params_send.insert("username","10005"); - //emit sigSetLableText(tr("UpLoadForm")); - UpLoadForm(m_strUrl,params_send,file1.fileName(),&file,file1.fileName(),m_iType); - -} - - -//void ThreadUpgradeApk::UpLoadForm(QString strUrl,QString strFilePathName) -//{ -//QString xlname = "text.xlsx"; -// QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); -// QHttpPart imagePart; -// imagePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/xlsx")); -// imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"file\"; filename=\""+ xlname + "\"")); // file为后端定义的key,filename即为excel文件名 - -// QFile *file = new QFile(strFilePathName);//pathbuf1 为文件路径 -// file->open(QIODevice::ReadOnly); -// imagePart.setBodyDevice(file); -// file->setParent(multiPart); -// multiPart->append(imagePart); - -// QUrl url(strUrl); -// QNetworkRequest netReq; -// netReq.setUrl(url); -// QNetworkAccessManager *_uploadManager=new QNetworkAccessManager(); - -// connect(_uploadManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(send_xlsdata(QNetworkReply*))); -// _uploadManager->post(netReq,multiPart); -//} -void ThreadUpgradeApk::UpLoadForm(QString Path,QMap params,QString fileFormName,QFile *uploadFile,QString newFileName,int iType) -{ - QString BOUNDARY=QUuid::createUuid().toString(); - QByteArray sb=QByteArray(); - //先上传普通的表单数据 -// for(QMap::iterator t=params.begin();t!=params.end();t++) - { - sb.append("--"+BOUNDARY+"\r\n"); - sb.append(QString("Content-Disposition: form-data;name=\"")+t.key()+QString("\"")+QString("\r\n")); - sb.append("\r\n"); - sb.append(t.value()+"\r\n"); - } - //上传文件的头部 - sb.append("--"+BOUNDARY+"\r\n"); - sb.append(QString("Content-Disposition: form-data;name=\"")+fileFormName+QString("\";filename=\"")+newFileName+QString("\"")+QString("\r\n")); - sb.append("\r\n"); - //上传文件内容 - if(!uploadFile->open(QIODevice::ReadOnly)){ - return; - } - sb.append(uploadFile->readAll()); - sb.append("\r\n"); - sb.append("--"+BOUNDARY+"\r\n"); - - //编辑HTTP头部 - QNetworkAccessManager *_uploadManager=new QNetworkAccessManager(); - QNetworkRequest request=QNetworkRequest(QUrl(Path)); - request.setRawHeader(QString("Content-Type").toLatin1(),QString("multipart/form-data;boundary="+BOUNDARY).toLatin1()); - request.setRawHeader(QString("Content-Length").toLatin1(),QString::number(sb.length()).toLatin1()); - //执行post请求 - // if(m_PostingDlg==nullptr) - { - //m_PostingDlg = new LoEmptyDialog(); - //connect(m_PostingDlg,SIGNAL(sigClose()),this,SLOT(DeletePostingDlg())); - //connect(m_pGetAskTimer,SIGNAL(timeout()),m_PostingDlg,SLOT(TimerOutUnlock())); - //m_PostingDlg->lock(tr("UpgradeSoftware"),tr("Success"),tr("UpgradeSoftware")+tr("failed")); - //m_pGetAskTimer->start(60000); - QNetworkReply * m_netReply =_uploadManager->post(request,sb); - connect(m_netReply, SIGNAL(uploadProgress(qint64,qint64)), this, SLOT(slotUploadProgress(qint64,qint64))); - // connect(this, SIGNAL(sigSetTipTextContent ( QString )), m_PostingDlg, SLOT( SetTipTextContent(QString))); - if(iType==0)//apk - { - connect(m_netReply, SIGNAL(finished()), this, SLOT(slotUploadFinished())); - - } - else if(iType==1)//fpga.rpd - { - connect(m_netReply, SIGNAL(finished()), this, SLOT(slotUploadFpgaFinished())); - - } - QEventLoop eventLoop; - QTimer timer; - - connect(m_netReply, SIGNAL(finished()), &eventLoop, SLOT(quit())); - connect(&timer, SIGNAL(timeout()), &eventLoop, SLOT(quit())); - timer.start(600 * 1000); - eventLoop.exec(); // block until finish - - if (timer.isActive()) { - timer.stop(); - } else { - disconnect(m_netReply, SIGNAL(finished()), &eventLoop, SLOT(quit())); - m_netReply->abort(); - m_netReply->deleteLater(); - return ; - } - //m_PostingDlg->exec(); - } - - -} -void ThreadUpgradeApk::slotTimerOutUnlock() -{ - emit sigTimerOut(); - bSendCloseFlag=true; -} -void ThreadUpgradeApk::slotUploadProgress(qint64 A,qint64 B) -{ - if(B!=0) - { - QString strbaifenbi=tr("Uploadding")+":"+QString("%1%").arg(A*100/B); - emit sigSetProgressValue(A*100/B); - emit sigSetLableText(strbaifenbi); -// m_pGetAskTimer->stop(); -// m_pGetAskTimer->start(30000); - } -} -void ThreadUpgradeApk::slotUploadFinished() -{ - emit sigFinished(); -// MACRO_ASKTIME_STOP -// m_pGetAskTimer->start(40000); - - qDebug()<<"slotUploadFinished"; - -} -void ThreadUpgradeApk::slotUploadFpgaFinished() -{ - emit sigFpgaFinished(); -// MACRO_ASKTIME_STOP -// m_pGetAskTimer->start(40000); - - qDebug()<<"slotUploadFinished"; - -} - -void ThreadUpgradeApk::OnUpgradeSuccess() -{ -// MACRO_ASKTIME_STOP - bSendCloseFlag=true; - -} -void ThreadUpgradeApk::OnUpgradeFail() -{ -// MACRO_ASKTIME_STOP - bSendCloseFlag=true; - -} diff --git a/LedOK/wDevicesManager/threadupgradeapk.h b/LedOK/wDevicesManager/threadupgradeapk.h deleted file mode 100644 index ab29a4e..0000000 --- a/LedOK/wDevicesManager/threadupgradeapk.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef THREADUPGRADEAPK_H -#define THREADUPGRADEAPK_H -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -const quint16 PORT = 3333; -const qint64 LOADBYTES = 4 * 1024; // 4 kilo-byte -const int DATA_STREAM_VERSION = QDataStream::Qt_4_8; -class ThreadUpgradeApk:public QThread -{ - Q_OBJECT -public: - ThreadUpgradeApk(QString strApkPathAndName,QString url="",int iPort=3333); - ~ThreadUpgradeApk(); - void run(); -protected slots: - void slotUploadProgress(qint64 A,qint64 B); - void slotUploadFinished(); - void slotUploadFpgaFinished(); - void slotTimerOutUnlock(); - void OnUpgradeSuccess(); - void OnUpgradeFail(); -signals: - void sigSetLableText(QString); - - void sigSetProgressValue(int); - void sigSetProgressMax(int); - void sigFinished(); - void sigFpgaFinished(); - void sigTimerOut(); -private: - bool bSendCloseFlag=true; - QString m_strApkName; - QString m_strUrl; - int m_reSendCount=0; - QTimer *m_pGetAskTimer=nullptr; - int m_iType=0; - void UpLoadForm(QString Path,QMap params,QString fileFormName,QFile *uploadFile,QString newFileName,int iType); -// void UpLoadForm(QString strUrl,QString strFilePathName); - -}; - -#endif // THREADSENDPRO_H diff --git a/LedOK/wDevicesManager/upgradeapkdialog.cpp b/LedOK/wDevicesManager/upgradeapkdialog.cpp deleted file mode 100644 index b3f1139..0000000 --- a/LedOK/wDevicesManager/upgradeapkdialog.cpp +++ /dev/null @@ -1,493 +0,0 @@ -#include "upgradeapkdialog.h" -#include "tools.h" -#include "ui_upgradeapkdialog.h" -#include -#include -#include -#include -UpgradeApkDialog::UpgradeApkDialog(QWidget *parent) : QDialog(parent) { - resize(1280, 720); - setWindowState(Qt::WindowMaximized); - setSizeGripEnabled(false); - - setWindowTitle(tr("Upgrade apk")); - - auto vBox = new QVBoxLayout(this); - auto hBox = new QHBoxLayout(); - auto pushButtonSelectApk = new QPushButton(tr("Select apk")); - pushButtonSelectApk->setMinimumSize(QSize(100, 30)); - hBox->addWidget(pushButtonSelectApk); - - auto label_ApkPath = new QLabel(); - label_ApkPath->setMinimumSize(QSize(200, 30)); - label_ApkPath->setStyleSheet("background-color: #ffffff;"); - label_ApkPath->setFrameShape(QFrame::NoFrame); - label_ApkPath->setFrameShadow(QFrame::Plain); - label_ApkPath->setScaledContents(false); - - hBox->addWidget(label_ApkPath); - - auto pushButtonPublish = new QPushButton(tr("Upgrade")); - pushButtonPublish->setMinimumSize(QSize(80, 30)); - hBox->addWidget(pushButtonPublish); - hBox->addStretch(); - - auto label_4 = new QLabel(tr("APK:")); - hBox->addWidget(label_4); - - auto comboBoxApk = new QComboBox(); - comboBoxApk->setEnabled(true); - comboBoxApk->setMinimumSize(QSize(200, 30)); - comboBoxApk->setStyleSheet(QString::fromUtf8("background-color: #FFFFFF;")); - comboBoxApk->setEditable(false); - comboBoxApk->setFrame(false); - - hBox->addWidget(comboBoxApk); - - auto lineEditPackageName = new QLineEdit(); - lineEditPackageName->setMinimumSize(QSize(120, 30)); - lineEditPackageName->setStyleSheet(QString::fromUtf8("background-color: #FFFFFF;")); - - hBox->addWidget(lineEditPackageName); - - auto pushButtonUninstall = new QPushButton(tr("Uninstall")); - pushButtonUninstall->setMinimumSize(QSize(80, 30)); - hBox->addWidget(pushButtonUninstall); - - auto pushButtonCheckRuningState = new QPushButton(tr("check running state")); - pushButtonCheckRuningState->setMinimumSize(QSize(140, 30)); - hBox->addWidget(pushButtonCheckRuningState); - - - vBox->addLayout(hBox); - - hBox = new QHBoxLayout(); - auto pushButtonSelectFpga = new QPushButton(tr("Select Fpga")); - pushButtonSelectFpga->setMinimumSize(QSize(100, 30)); - hBox->addWidget(pushButtonSelectFpga); - - auto label_FpgaPath = new QLabel(); - label_FpgaPath->setMinimumSize(QSize(200, 30)); - label_FpgaPath->setStyleSheet("QLabel{background: #fff;}"); - hBox->addWidget(label_FpgaPath); - - auto pushButtonUpgradeFpga = new QPushButton(tr("Upgrade")); - pushButtonUpgradeFpga->setMinimumSize(QSize(0, 30)); - hBox->addWidget(pushButtonUpgradeFpga); - - hBox->addStretch(); - - vBox->addLayout(hBox); - - hBox = new QHBoxLayout(); - auto label = new QLabel(tr("success info")); - hBox->addWidget(label); - - hBox->addStretch(); - - auto pushButtonRefresh = new QPushButton(tr("Refresh")); - pushButtonRefresh->setMinimumSize(QSize(0, 30)); - hBox->addWidget(pushButtonRefresh); - - auto txtSearch = new QLineEdit(); - txtSearch->setStyleSheet(QString::fromUtf8("background-color: #FFFFFF;")); - txtSearch->setClearButtonEnabled(false); - hBox->addWidget(txtSearch, 0, Qt::AlignRight); - - vBox->addLayout(hBox); - - wDevicePublishList = new LoQTreeWidget(); - vBox->addWidget(wDevicePublishList); - - hBox = new QHBoxLayout(); - hBox->addStretch(); - - auto pushButtonCancel = new QPushButton(tr("Cancel")); - pushButtonCancel->setMinimumSize(QSize(0, 30)); - connect(pushButtonCancel, &QPushButton::clicked, this, &UpgradeApkDialog::reject); - hBox->addWidget(pushButtonCancel, 0, Qt::AlignRight); - - vBox->addLayout(hBox); - - QAction *search = new QAction(txtSearch); - search->setIcon(QIcon(":/res/ProgramManager/bnSearch.png")); - txtSearch->addAction(search, QLineEdit::LeadingPosition); - txtSearch->setClearButtonEnabled(true); - txtSearch->setStyleSheet("border: 2px solid #aaaaaa;"); - wDevicePublishList->setProperty("ssType", "topList"); - pushButtonRefresh->setProperty("ssType", "progManageTool"); - pushButtonPublish->setProperty("ssType", "progManageTool"); - pushButtonSelectApk->setProperty("ssType", "progManageTool"); - pushButtonSelectFpga->setProperty("ssType", "progManageTool"); - pushButtonUpgradeFpga->setProperty("ssType", "progManageTool"); - pushButtonUninstall->setProperty("ssType", "progManageTool"); - pushButtonCheckRuningState->setProperty("ssType", "progManageTool"); - pushButtonCancel->setProperty("ssType", "progManageTool"); - - m_headerItem = new QTreeWidgetItem(); - m_headerItem->setTextAlignment(1, Qt::AlignHCenter | Qt::AlignVCenter); - - for(int i=1; isetTextAlignment(i, Qt::AlignCenter); - - m_headerItem->setData(ENUM_DEVICE_PUBLISH_HEADE_CHECK, 0, ""); - m_headerItem->setData(ENUM_DEVICE_PUBLISH_HEADE_SCREEN_ID, 0, tr("Screen ID")); - m_headerItem->setData(ENUM_DEVICE_PUBLISH_HEADE_REMARK_NAME, 0, tr("Remark Name")); - m_headerItem->setData(ENUM_DEVICE_PUBLISH_HEADE_ONLINE, 0, tr("Online")); - m_headerItem->setData(ENUM_DEVICE_PUBLISH_HEADE_SCREEN_IP, 0, tr("Screen IP")); - m_headerItem->setData(ENUM_DEVICE_PUBLISH_HEADE_ENCRYPT,0,tr("Security")); - m_headerItem->setData(ENUM_DEVICE_PUBLISH_HEADE_PROGRESS, 0, tr("Progress")); - m_headerItem->setData(ENUM_DEVICE_PUBLISH_HEADE_XIXUNPLAYER_VERSION, 0, tr("xixunplayer")); - m_headerItem->setData(ENUM_DEVICE_PUBLISH_HEADE_CARDSYSTEM_VERSION,0,tr("cardsystem")); - m_headerItem->setData(ENUM_DEVICE_PUBLISH_HEADE_TAXIAPP_VERSION,0,tr("taxiapp")); - m_headerItem->setData(ENUM_DEVICE_PUBLISH_HEADE_STARTER_VERSION,0,tr("starter")); - m_headerItem->setData(ENUM_DEVICE_PUBLISH_HEADE_CONNECTION_VERSION,0,tr("connection")); - m_headerItem->setData(ENUM_DEVICE_PUBLISH_HEADE_DISPLAYER_VERSION,0,tr("displayer")); - m_headerItem->setData(ENUM_DEVICE_PUBLISH_HEADE_FPAG_VERSION,0,tr("FPGA")); - - m_headerItem->setData(ENUM_DEVICE_PUBLISH_HEADE_UPDATE_VERSION,0,tr("update")); - m_headerItem->setData(ENUM_DEVICE_PUBLISH_HEADE_REMARKS,0,tr("State")); - - wDevicePublishList->setHeaderItem(m_headerItem); - wDevicePublishList->header()->setSectionResizeMode(ENUM_DEVICE_PUBLISH_HEADE_CHECK, QHeaderView::Fixed); - wDevicePublishList->header()->setSectionResizeMode(ENUM_DEVICE_PUBLISH_HEADE_ONLINE, QHeaderView::Fixed); - wDevicePublishList->header()->setSectionResizeMode(ENUM_DEVICE_PUBLISH_HEADE_SCREEN_ID, QHeaderView::Fixed); - wDevicePublishList->header()->setSectionResizeMode(ENUM_DEVICE_PUBLISH_HEADE_REMARK_NAME, QHeaderView::ResizeToContents); - wDevicePublishList->header()->setSectionResizeMode(ENUM_DEVICE_PUBLISH_HEADE_SCREEN_IP, QHeaderView::ResizeToContents); - wDevicePublishList->header()->setSectionResizeMode(ENUM_DEVICE_PUBLISH_HEADE_ENCRYPT, QHeaderView::Fixed); - wDevicePublishList->header()->setSectionResizeMode(ENUM_DEVICE_PUBLISH_HEADE_PROGRESS, QHeaderView::Fixed); - wDevicePublishList->header()->setSectionResizeMode(ENUM_DEVICE_PUBLISH_HEADE_XIXUNPLAYER_VERSION, QHeaderView::Stretch); - wDevicePublishList->header()->setSectionResizeMode(ENUM_DEVICE_PUBLISH_HEADE_CARDSYSTEM_VERSION, QHeaderView::Stretch); - wDevicePublishList->header()->setSectionResizeMode(ENUM_DEVICE_PUBLISH_HEADE_TAXIAPP_VERSION, QHeaderView::ResizeToContents); - wDevicePublishList->header()->setSectionResizeMode(ENUM_DEVICE_PUBLISH_HEADE_STARTER_VERSION, QHeaderView::ResizeToContents); - wDevicePublishList->header()->setSectionResizeMode(ENUM_DEVICE_PUBLISH_HEADE_CONNECTION_VERSION, QHeaderView::ResizeToContents); - wDevicePublishList->header()->setSectionResizeMode(ENUM_DEVICE_PUBLISH_HEADE_DISPLAYER_VERSION, QHeaderView::ResizeToContents); - wDevicePublishList->header()->setSectionResizeMode(ENUM_DEVICE_PUBLISH_HEADE_FPAG_VERSION, QHeaderView::ResizeToContents); - - wDevicePublishList->header()->setSectionResizeMode(ENUM_DEVICE_PUBLISH_HEADE_UPDATE_VERSION, QHeaderView::ResizeToContents); - wDevicePublishList->header()->setSectionResizeMode(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, QHeaderView::Stretch); - - wDevicePublishList->header()->setStretchLastSection(false); - wDevicePublishList->setColumnWidth(ENUM_DEVICE_PUBLISH_HEADE_CHECK, 50); - wDevicePublishList->setColumnWidth(ENUM_DEVICE_PUBLISH_HEADE_SCREEN_ID, 120); - wDevicePublishList->setColumnWidth(ENUM_DEVICE_PUBLISH_HEADE_ONLINE, 50); - wDevicePublishList->setColumnWidth(ENUM_DEVICE_PUBLISH_HEADE_ENCRYPT, 50); - wDevicePublishList->setColumnWidth(ENUM_DEVICE_PUBLISH_HEADE_PROGRESS, 100); - lineEditPackageName->setVisible(false); - comboBoxApk->addItem("com.xixun.xixunplayer"); - comboBoxApk->addItem("com.xixun.joey.cardsystem"); - comboBoxApk->addItem("com.xixun.joey.systemcore"); - comboBoxApk->addItem("net.sysolution.taxiapp"); - comboBoxApk->addItem("net.sysolution.starter"); - comboBoxApk->addItem("com.xixun.display"); - comboBoxApk->addItem("com.xixun.xy.conn"); - comboBoxApk->addItem("com.xixun.xy.update"); - comboBoxApk->addItem("net.sysolution.basicapp"); - comboBoxApk->addItem("PackageName"); - - comboBoxApk->setCurrentIndex(0); - comboBoxApk->setFocus(); - pushButtonPublish->setEnabled(false); - pushButtonUpgradeFpga->setEnabled(false); - connect(pushButtonRefresh, &QPushButton::clicked, this, [this, label] { - wDevicePublishList->clear(); - wDevicePublishList->onCheckAll(false); - int iCount = gDevicePanel->LedCardList.count(); - for(int i=0;iLedCardList.at(i)); - label->setText(tr("All")+":"+QString::number(iCount)); - }); - connect(pushButtonPublish, &QPushButton::clicked, this, [this, label_ApkPath] { - QString strApkName = label_ApkPath->text(); - if(strApkName.length()<3) return; - int cnt = wDevicePublishList->topLevelItemCount(); - for(int i=0; itopLevelItem(i)->checkState(0) == Qt::Checked) static_cast(wDevicePublishList->topLevelItem(i))->onUpgradeApk(strApkName); - }); - connect(pushButtonUpgradeFpga, &QPushButton::clicked, this, [this, label_FpgaPath] { - QString strFpgaName = label_FpgaPath->text(); - if(strFpgaName.length()<3) return; - int cnt = wDevicePublishList->topLevelItemCount(); - for(int i=0; itopLevelItem(i)->checkState(0) == Qt::Checked) static_cast(wDevicePublishList->topLevelItem(i))->onUpgradeFpga(strFpgaName); - }); - - connect(pushButtonSelectApk,&QPushButton::clicked, this, [this, label_ApkPath, pushButtonPublish] { - QString strUpgradeApkFile = QFileDialog::getOpenFileName(this, "Open file", QString(), tr("apk package (*.apk *.zip)")); - label_ApkPath->setText(strUpgradeApkFile); - pushButtonPublish->setEnabled(QFileInfo::exists(strUpgradeApkFile)); - }); - connect(pushButtonSelectFpga, &QPushButton::clicked, this, [this, label_FpgaPath, pushButtonUpgradeFpga] { - QString m_strUpgradeFpgaFile = QFileDialog::getOpenFileName(this, "Open File", QString(), tr("apk package (*.rpd)")); - label_FpgaPath->setText(m_strUpgradeFpgaFile); - pushButtonUpgradeFpga->setEnabled(QFileInfo::exists(m_strUpgradeFpgaFile)); - }); - connect(pushButtonUninstall, &QPushButton::clicked, this, [this, comboBoxApk, lineEditPackageName] { - QString strApkName = comboBoxApk->currentText(); - if(strApkName=="PackageName") strApkName = lineEditPackageName->text(); - int cnt = wDevicePublishList->topLevelItemCount(); - for(int i=0; itopLevelItem(i)->checkState(0) == Qt::Checked) static_cast(wDevicePublishList->topLevelItem(i))->onUninstallApk(strApkName); - }); - connect(pushButtonCheckRuningState, &QPushButton::clicked, this, [this, comboBoxApk, lineEditPackageName] { - QString strApkName = comboBoxApk->currentText(); - if(strApkName=="PackageName") strApkName= lineEditPackageName->text(); - int cnt = wDevicePublishList->topLevelItemCount(); - for(int i=0; itopLevelItem(i)->checkState(0) == Qt::Checked) static_cast(wDevicePublishList->topLevelItem(i))->onCheckRuningState(strApkName); - }); - - connect(txtSearch,SIGNAL(textChanged(const QString &)),this,SLOT(FilterProgram(const QString &))); - connect(comboBoxApk, (void(QComboBox::*)(int))&QComboBox::currentIndexChanged, this, [comboBoxApk, lineEditPackageName](int) { - if(comboBoxApk->currentText()=="PackageName") { - lineEditPackageName->setVisible(true); - lineEditPackageName->setFocus(); - } else lineEditPackageName->setVisible(false); - }); - - int iCount = gDevicePanel->LedCardList.count(); - for(int i=0; iLedCardList.at(i)); - label->setText(tr("All")+":"+QString::number(iCount)); - - auto timer = new QTimer(this); - connect(timer, &QTimer::timeout, this, [this, label] { - int iCount = gDevicePanel->LedCardList.count(); - for(int i=0;iLedCardList.at(i)); - label->setText(tr("All")+":"+QString::number(iCount)); - }); - timer->start(500000); -} - -void UpgradeApkDialog::onAddLedCard(LedCard *card) { - int iExistFlg=0; - int cnt = wDevicePublishList->topLevelItemCount(); - for(int i=0; i(wDevicePublishList->topLevelItem(i))->m_pLedCard->m_strCardId; - if(strTempCardId == card->m_strCardId) { - iExistFlg=1; - static_cast(wDevicePublishList->topLevelItem(i))->SetItemParam(card); - break; - } - } - if(iExistFlg==0) new wUpgradeApkItem(card, wDevicePublishList, this); -} - -void UpgradeApkDialog::keyPressEvent(QKeyEvent *ev) { - if(ev->key() == Qt::Key_F3) { - QMessageBox::warning(this, "Tip", tr("The encrypted control card can be upgraded directly")); - int cnt = wDevicePublishList->topLevelItemCount(); - for(int i=0; i(wDevicePublishList->topLevelItem(i))->SetLockFlagFalse(); - } -} -void UpgradeApkDialog::FilterProgram(const QString &strtemp) -{ - if (strtemp.isEmpty()) //显示全部 - { - for (int i = 0; i< wDevicePublishList->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = wDevicePublishList->topLevelItem(i); - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),false); - } - } - else - { - QList resultList = wDevicePublishList->findItems(strtemp, Qt::MatchContains,ENUM_DEVICE_PUBLISH_HEADE_SCREEN_ID); //搜索结果 - if (resultList.size() > 0) - { - //QMessageBox::warning(this, "Export", QString(resultList.size())); - for (int i = 0; i< wDevicePublishList->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = wDevicePublishList->topLevelItem(i); - if (resultList.contains(topItem)) - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),false); //显示匹配的结果 - else - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - else { - - QList resultList6 = wDevicePublishList->findItems(strtemp, Qt::MatchContains,ENUM_DEVICE_PUBLISH_HEADE_REMARK_NAME); //搜索结果 - if (resultList6.size() > 0) - { - //QMessageBox::warning(this, "Export", QString(resultList.size())); - for (int i = 0; i< wDevicePublishList->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = wDevicePublishList->topLevelItem(i); - if (resultList6.contains(topItem)) - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),false); //显示匹配的结果 - else - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - else { - - - //QMessageBox::warning(this, "Export", "FilterProgram"); - QList resultList1 = wDevicePublishList->findItems(strtemp, Qt::MatchContains,ENUM_DEVICE_PUBLISH_HEADE_XIXUNPLAYER_VERSION); //搜索结果 - if (resultList1.size() > 0) - { - //QMessageBox::warning(this, "Export", QString(resultList.size())); - for (int i = 0; i< wDevicePublishList->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = wDevicePublishList->topLevelItem(i); - if (resultList1.contains(topItem)) - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),false); //显示匹配的结果 - else - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - else { - QList resultList2 = wDevicePublishList->findItems(strtemp, Qt::MatchContains,ENUM_DEVICE_PUBLISH_HEADE_SCREEN_IP); //搜索结果 - if (resultList2.size() > 0) - { - //QMessageBox::warning(this, "Export", QString(resultList.size())); - for (int i = 0; i< wDevicePublishList->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = wDevicePublishList->topLevelItem(i); - if (resultList2.contains(topItem)) - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),false); //显示匹配的结果 - else - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - else { - QList resultList2 = wDevicePublishList->findItems(strtemp, Qt::MatchContains,ENUM_DEVICE_PUBLISH_HEADE_XIXUNPLAYER_VERSION); //搜索结果 - if (resultList2.size() > 0) - { - //QMessageBox::warning(this, "Export", QString(resultList.size())); - for (int i = 0; i< wDevicePublishList->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = wDevicePublishList->topLevelItem(i); - if (resultList2.contains(topItem)) - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),false); //显示匹配的结果 - else - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - else { - QList resultList2 = wDevicePublishList->findItems(strtemp, Qt::MatchContains,ENUM_DEVICE_PUBLISH_HEADE_CARDSYSTEM_VERSION); //搜索结果 - if (resultList2.size() > 0) - { - //QMessageBox::warning(this, "Export", QString(resultList.size())); - for (int i = 0; i< wDevicePublishList->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = wDevicePublishList->topLevelItem(i); - if (resultList2.contains(topItem)) - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),false); //显示匹配的结果 - else - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - else { - QList resultList2 = wDevicePublishList->findItems(strtemp, Qt::MatchContains,ENUM_DEVICE_PUBLISH_HEADE_TAXIAPP_VERSION); //搜索结果 - if (resultList2.size() > 0) - { - //QMessageBox::warning(this, "Export", QString(resultList.size())); - for (int i = 0; i< wDevicePublishList->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = wDevicePublishList->topLevelItem(i); - if (resultList2.contains(topItem)) - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),false); //显示匹配的结果 - else - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - else { - QList resultList2 = wDevicePublishList->findItems(strtemp, Qt::MatchContains,ENUM_DEVICE_PUBLISH_HEADE_DISPLAYER_VERSION); //搜索结果 - if (resultList2.size() > 0) - { - //QMessageBox::warning(this, "Export", QString(resultList.size())); - for (int i = 0; i< wDevicePublishList->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = wDevicePublishList->topLevelItem(i); - if (resultList2.contains(topItem)) - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),false); //显示匹配的结果 - else - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - else { - QList resultList2 = wDevicePublishList->findItems(strtemp, Qt::MatchContains,ENUM_DEVICE_PUBLISH_HEADE_STARTER_VERSION); //搜索结果 - if (resultList2.size() > 0) - { - //QMessageBox::warning(this, "Export", QString(resultList.size())); - for (int i = 0; i< wDevicePublishList->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = wDevicePublishList->topLevelItem(i); - if (resultList2.contains(topItem)) - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),false); //显示匹配的结果 - else - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - else { - QList resultList2 = wDevicePublishList->findItems(strtemp, Qt::MatchContains,ENUM_DEVICE_PUBLISH_HEADE_CONNECTION_VERSION); //搜索结果 - if (resultList2.size() > 0) - { - //QMessageBox::warning(this, "Export", QString(resultList.size())); - for (int i = 0; i< wDevicePublishList->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = wDevicePublishList->topLevelItem(i); - if (resultList2.contains(topItem)) - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),false); //显示匹配的结果 - else - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - else { - QList resultList2 = wDevicePublishList->findItems(strtemp, Qt::MatchContains,ENUM_DEVICE_PUBLISH_HEADE_UPDATE_VERSION); //搜索结果 - if (resultList2.size() > 0) - { - //QMessageBox::warning(this, "Export", QString(resultList.size())); - for (int i = 0; i< wDevicePublishList->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = wDevicePublishList->topLevelItem(i); - if (resultList2.contains(topItem)) - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),false); //显示匹配的结果 - else - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - else { - QList resultList2 = wDevicePublishList->findItems(strtemp, Qt::MatchContains,ENUM_DEVICE_PUBLISH_HEADE_FPAG_VERSION); //搜索结果 - if (resultList2.size() > 0) - { - //QMessageBox::warning(this, "Export", QString(resultList.size())); - for (int i = 0; i< wDevicePublishList->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = wDevicePublishList->topLevelItem(i); - if (resultList2.contains(topItem)) - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),false); //显示匹配的结果 - else - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - else { - QList resultList2 = wDevicePublishList->findItems(strtemp, Qt::MatchContains,ENUM_DEVICE_PUBLISH_HEADE_REMARKS); //搜索结果 - if (resultList2.size() > 0) - { - //QMessageBox::warning(this, "Export", QString(resultList.size())); - for (int i = 0; i< wDevicePublishList->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = wDevicePublishList->topLevelItem(i); - if (resultList2.contains(topItem)) - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),false); //显示匹配的结果 - else - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - else { - for (int i = 0; i< wDevicePublishList->topLevelItemCount(); ++i) - { - QTreeWidgetItem* topItem = wDevicePublishList->topLevelItem(i); - wDevicePublishList->setRowHidden(i,wDevicePublishList->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果 - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } -} diff --git a/LedOK/wDevicesManager/upgradeapkdialog.ui b/LedOK/wDevicesManager/upgradeapkdialog.ui deleted file mode 100644 index 4433f28..0000000 --- a/LedOK/wDevicesManager/upgradeapkdialog.ui +++ /dev/null @@ -1,468 +0,0 @@ - - - UpgradeApkDialog - - - Qt::NonModal - - - - 0 - 0 - 1024 - 640 - - - - false - - - false - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - 19 - - - - - 0 - - - - - Upgrade apk - - - - - - - - 32 - 16777215 - - - - - - - - - - - - 32 - 16777215 - - - - X - - - - - - - - - border-top: 1px solid gray; - - - Qt::Horizontal - - - - - - - 10 - - - - - - 0 - 0 - - - - - 100 - 30 - - - - Select apk - - - - - - - - 200 - 30 - - - - background-color: #ffffff; - - - QFrame::NoFrame - - - QFrame::Plain - - - - - - false - - - - - - - - 80 - 30 - - - - Upgrade - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - APK: - - - - - - - true - - - - 200 - 30 - - - - background-color: #FFFFFF; - - - false - - - false - - - - - - - - 120 - 30 - - - - background-color: #FFFFFF; - - - - - - - - 80 - 30 - - - - Uninstall - - - - - - - - 140 - 30 - - - - check running state - - - - - - - - - 10 - - - - - - 0 - 0 - - - - - 100 - 30 - - - - Select Fpga - - - - - - - - 200 - 30 - - - - background-color: #ffffff; - - - - - - - - - - - 0 - 30 - - - - Upgrade - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - success info - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 30 - - - - Refresh - - - - - - - background-color: #FFFFFF; - - - false - - - - - - - - - - 1 - - - - - - - - - 0 - 0 - - - - border-top: 2px solid gray; - - - Qt::Horizontal - - - - - - - 0 - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 30 - - - - Cancel - - - - - - - - - - - - - LoQTreeWidget - QTreeWidget -
base/loqtreewidget.h
-
-
- - - - pushButtonClose - clicked() - UpgradeApkDialog - close() - - - 987 - 31 - - - 511 - 383 - - - - - pushButtonCancel - clicked() - UpgradeApkDialog - reject() - - - 966 - 736 - - - 511 - 383 - - - - -
diff --git a/LedOK/wDevicesManager/wupgradeapkitem.cpp b/LedOK/wDevicesManager/wupgradeapkitem.cpp deleted file mode 100644 index 9901626..0000000 --- a/LedOK/wDevicesManager/wupgradeapkitem.cpp +++ /dev/null @@ -1,525 +0,0 @@ -#include "wupgradeapkitem.h" -#include "tools.h" -#include "base/x_uimsgboxok.h" -#include "passwordindlg.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -wUpgradeApkItem::wUpgradeApkItem(LedCard *pLedCard, LoQTreeWidget *parent, QWidget *pWnd) : - QObject(parent), - QTreeWidgetItem(UserType), - m_parent(parent) -{ - m_pWnd=pWnd; - m_pLedCard=pLedCard; - pHpptClient = new HpptClient(this); - connect(pHpptClient,SIGNAL(httpPostRspReady(QString , QString , QByteArray )),this,SLOT(OnProHttpResponse(QString , QString , QByteArray))); - init(); - -} -wUpgradeApkItem::~wUpgradeApkItem() -{ - if(pHpptClient!=nullptr) - { - qDebug() <<"delete pHpptClient in ~wUpgradeApkItem"; - delete pHpptClient; - pHpptClient=nullptr; - } -} - -void wUpgradeApkItem::init() -{ - setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); - setCheckState(0, Qt::Unchecked); - m_parent->addTopLevelItem(this); - m_ImageOnline = new QLabel(); - m_ImageOnline->setStyleSheet("margin-top:12px; margin-bottom:12px"); - m_parent->setItemWidget(this, ENUM_DEVICE_PUBLISH_HEADE_ONLINE, m_ImageOnline); - m_ImageOnline->setAlignment(Qt::AlignCenter); - for(int i=1; isetMaximumHeight(16); - m_pProgress->setStyleSheet("margin-top:12px; margin-bottom:12px"); - //setData(ENUM_DEVICE_PUBLISH_HEADE_PROGRESS,) - m_parent->setItemWidget(this, ENUM_DEVICE_PUBLISH_HEADE_PROGRESS, m_pProgress); - m_pProgress->setAlignment(Qt::AlignCenter); - QSizePolicy policy = m_pProgress->sizePolicy(); - policy.setHorizontalStretch(1); - policy.setVerticalStretch(1); - policy.setHorizontalPolicy(QSizePolicy::Expanding); - m_pProgress->setSizePolicy(policy); - m_pProgress->setValue(0); - m_pProgress->setFixedWidth(100); - //启动心跳,监测设备在线和下线,3次超时表示下线 - OnCheckSoftVersions(); - OnCheckFpgaVersions(); - -} -void wUpgradeApkItem::SetLockFlagFalse() -{ - m_lockFlag=false; - -} - -void wUpgradeApkItem::refreshLable() -{ - -} -void wUpgradeApkItem::OnCheckFpgaVersions() -{ - m_strUrl="http://"+m_pLedCard->m_strCardIp+":2016/settings"; - QJsonObject json1; - json1.insert("_id", getRandomString(10)); - json1.insert("_type", "CheckHardwareVersions"); - HttpPostByTypeJsonObject(pHpptClient,m_strUrl,json1); -} -void wUpgradeApkItem::OnCheckSoftVersions() -{ - m_strUrl="http://"+m_pLedCard->m_strCardIp+":2016/settings"; - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "CheckSoftVersions"); - HttpPostByTypeJsonObject(pHpptClient,m_strUrl,json); - -} -extern QWidget *gMainWin; -void wUpgradeApkItem::onVerifyLockPassword() { - bool ok; - auto pwd = QInputDialog::getText(gMainWin, tr("Input password"), tr("Input password"), QLineEdit::Password, QString(), &ok); - if(! ok) return; - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "VerifyPassword"); - json.insert("pwd", pwd); - m_strUrl = "http://"+m_pLedCard->m_strCardIp+":2016/settings"; - HttpPostByTypeJsonObject(pHpptClient, m_strUrl, json); -} -void wUpgradeApkItem::SetPasswordItem(LedCard *p){ - if(p->bPassword) {//加过密 - if(m_bnLock==nullptr){ - m_bnLock = new QPushButton(m_pWnd); - m_bnLock->setStyleSheet("background-color:transparent;"); - m_bnLock->setStyleSheet("margin-left:12px; margin-right:12px;margin-top:12px; margin-bottom:12px;"); - m_parent->setItemWidget(this, ENUM_DEVICE_PUBLISH_HEADE_ENCRYPT, m_bnLock); - connect(m_bnLock, SIGNAL(clicked()), this, SLOT(onVerifyLockPassword())); - } - if(p->m_bLockStatus) m_bnLock->setIcon(QIcon(":/res/DeviceManager/Lock.png")); //如果已经验证通过密码显示绿色图标 - else m_bnLock->setIcon(QIcon(":/res/DeviceManager/UnLock.png")); //如果没有验证显示蓝色锁图标 - m_parent->setItemWidget(this, ENUM_DEVICE_PUBLISH_HEADE_ENCRYPT, m_bnLock); - } -} -void wUpgradeApkItem::onUninstallApk(QString strApkName){ - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "UninstallSoftware"); - json.insert("packageName", strApkName); - m_strUrl="http://"+m_pLedCard->m_strCardIp+":2016/settings"; - HttpPostByTypeJsonObject(pHpptClient,m_strUrl,json); - if(strApkName=="com.xixun.xixunplayer"){ - QString strtemp=this->text(ENUM_DEVICE_PUBLISH_HEADE_XIXUNPLAYER_VERSION); - if(strtemp.isEmpty()) return; - }else if(strApkName=="com.xixun.joey.cardsystem"){ - QString strtemp=this->text(ENUM_DEVICE_PUBLISH_HEADE_CARDSYSTEM_VERSION); - if(strtemp.isEmpty()) return; - }else if(strApkName=="net.sysolution.taxiapp"){ - QString strtemp=this->text(ENUM_DEVICE_PUBLISH_HEADE_TAXIAPP_VERSION); - if(strtemp.isEmpty()) return; - } - else if(strApkName=="net.sysolution.starter") - { - QString strtemp=this->text(ENUM_DEVICE_PUBLISH_HEADE_STARTER_VERSION); - if(strtemp.isEmpty()) - return; - - } - else if(strApkName=="com.xixun.display") - { - QString strtemp=this->text(ENUM_DEVICE_PUBLISH_HEADE_DISPLAYER_VERSION); - if(strtemp.isEmpty()) - return; - - } - else if(strApkName=="com.xixun.xy.conn") - { - QString strtemp=this->text(ENUM_DEVICE_PUBLISH_HEADE_CONNECTION_VERSION); - if(strtemp.isEmpty()) - return; - - } - else if(strApkName=="com.xixun.xy.update") - { - QString strtemp=this->text(ENUM_DEVICE_PUBLISH_HEADE_UPDATE_VERSION); - if(strtemp.isEmpty()) - return; - } - OnSendStatusTip(tr("uninstalling"),Qt::blue); -} -void wUpgradeApkItem::onCheckRuningState(QString strApkName) -{ - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "IsSoftwareRunning"); - json.insert("packageName", strApkName); - m_strUrl="http://"+m_pLedCard->m_strCardIp+":2016/settings"; - HttpPostByTypeJsonObject(pHpptClient,m_strUrl,json); - OnSendStatusTip(tr("IsSoftwareRunning"),Qt::blue); -} - -void wUpgradeApkItem::onUpgradeApk(QString strFileName) -{ - if(m_pLedCard->bPassword) - { - if(m_pLedCard->m_bLockStatus&&m_lockFlag == true) - { - OnSendStatusTip(tr("This screen is encrypted"),Qt::red); - return; - } - } - - if(m_iSendingFlag==1) - { - return; - } - m_strApkFilePathName=strFileName; - OnSendStatusTip(tr("Start upgrading"),Qt::blue); - - /* 发送连接请求 */ - ThreadUpgradeApk *m_pThreadSendPro=nullptr; - QString url="http://"+m_pLedCard->m_strCardIp+":2016/upload?type=software"; - m_pThreadSendPro = new ThreadUpgradeApk(strFileName,url,0); - this->moveToThread(m_pThreadSendPro); - - connect(m_pThreadSendPro,SIGNAL(sigSetLableText(QString)),this,SLOT(OnSendStatusTip(QString))); - connect(m_pThreadSendPro,SIGNAL(sigSetProgressValue(int)),m_pProgress,SLOT(setValue(int))); - connect(m_pThreadSendPro,SIGNAL(sigTimerOut()),m_pProgress,SLOT(slotTimeout())); - - - m_pProgress->setMaximum(100); - // connect(m_pThreadSendPro,SIGNAL(sigSetProgressMax(int)),m_pProgress,SLOT(setMaximum(int))); - connect(m_pThreadSendPro,SIGNAL(sigFinished()),this,SLOT(OnThreadFinished())); - connect(this,SIGNAL(sigUpgradeSuccess()),m_pThreadSendPro,SLOT(OnUpgradeSuccess())); - connect(this,SIGNAL(sigUpgradeFail()),m_pThreadSendPro,SLOT(OnUpgradeFail())); - m_iSendingFlag=1; - m_pProgress->setValue(0); - m_pThreadSendPro->start(); - } -void wUpgradeApkItem::onUpgradeFpga(QString strFileName) -{ - if(m_pLedCard->bPassword) - { - if(m_pLedCard->m_bLockStatus&&m_lockFlag == true) - { - OnSendStatusTip(tr("This screen is encrypted"),Qt::red); - return; - } - } - - if(m_iSendingFlag==1) - { - return; - } - m_strFpgaFilePathName=strFileName; - OnSendStatusTip(tr("Start upgrading"),Qt::blue); - /* 发送连接请求 */ - ThreadUpgradeApk *m_pThreadSendPro=nullptr; - QString url="http://"+m_pLedCard->m_strCardIp+":2016/upload?type=hardware"; - - m_pThreadSendPro = new ThreadUpgradeApk(strFileName,url,1); - this->moveToThread(m_pThreadSendPro); - connect(m_pThreadSendPro,SIGNAL(sigSetLableText(QString)),this,SLOT(OnSendStatusTip(QString))); - connect(m_pThreadSendPro,SIGNAL(sigSetProgressValue(int)),m_pProgress,SLOT(setValue(int))); - connect(m_pThreadSendPro,SIGNAL(sigTimerOut()),m_pProgress,SLOT(slotTimeout())); - m_pProgress->setMaximum(100); - // connect(m_pThreadSendPro,SIGNAL(sigSetProgressMax(int)),m_pProgress,SLOT(setMaximum(int))); - connect(m_pThreadSendPro,SIGNAL(sigFpgaFinished()),this,SLOT(OnThreadFpgaFinished())); - connect(this,SIGNAL(sigUpgradeSuccess()),m_pThreadSendPro,SLOT(OnUpgradeSuccess())); - connect(this,SIGNAL(sigUpgradeFail()),m_pThreadSendPro,SLOT(OnUpgradeFail())); - m_iSendingFlag=1; - m_pProgress->setValue(0); - m_pThreadSendPro->start(); - } - -void wUpgradeApkItem::slotTimeout() -{ - OnSendStatusTip(tr("Timeout")); - m_iSendingFlag=0; - OnCheckSoftVersions(); - OnCheckFpgaVersions(); -} -void wUpgradeApkItem::OnSendStatusTip(QString strTip) -{ - QCoreApplication::processEvents(); - - setData(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, 0, strTip); - this->setTextColor(ENUM_DEVICE_PUBLISH_HEADE_REMARKS,Qt::blue); - if(strTip==tr("Timeout")) - { - - } - -} -void wUpgradeApkItem::OnSendStatusTip(QString strTip,QColor cr) -{ - QCoreApplication::processEvents(); - - setData(ENUM_DEVICE_PUBLISH_HEADE_REMARKS, 0, strTip); - this->setTextColor(ENUM_DEVICE_PUBLISH_HEADE_REMARKS,cr); - -} -void wUpgradeApkItem::OnThreadFinished() -{ - m_iSendingFlag=0; - m_pProgress->setValue(100); - qDebug()<<"OnThreadFinished"; - QFileInfo file(m_strApkFilePathName); - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "UpgradeSoftware"); - json.insert("fileName", file.fileName()); - json.insert("isCustom", true); - HttpPostByTypeJsonObject(pHpptClient,m_strUrl,json); - OnSendStatusTip(tr("install start..."),Qt::blue); - HttpPostByTypeJsonObject(pHpptClient,m_strUrl,json); - -} -void wUpgradeApkItem::OnThreadFpgaFinished() -{ - m_iSendingFlag=0; - m_pProgress->setValue(100); - qDebug()<<"OnThreadFinished"; - QJsonObject json; - json.insert("_id", getRandomString(10)); - json.insert("_type", "SynchronousHardwareVersion"); - HttpPostByTypeJsonObject(pHpptClient,m_strUrl,json); - OnSendStatusTip(tr("SynchronousHardwareVersion"),Qt::blue); -} - -void wUpgradeApkItem::SetItemParam(LedCard *p) -{ - setData(ENUM_DEVICE_PUBLISH_HEADE_SCREEN_ID, 0, p->m_strCardId); - setData(ENUM_DEVICE_PUBLISH_HEADE_SCREEN_IP, 0, p->m_strCardIp); - m_pLedCard->m_strCardId=p->m_strCardId; - m_pLedCard->m_strCardIp=p->m_strCardIp; - m_pLedCard->m_bOnLine=p->m_bOnLine; - // setData(ENUM_DEVICE_PUBLISH_HEADE_SCREEN_SIZE, 0, QString("%1 x %2").arg(p->m_iWidth).arg(p->m_iHeight)); - if(m_pLedCard->m_bOnLine) - { - m_ImageOnline->setPixmap(QPixmap(":/res/DeviceManager/O_Online.png")); - } - else - { - m_ImageOnline->setPixmap(QPixmap(":/res/DeviceManager/O_Offline.png")); - } - SetPasswordItem(m_pLedCard); - setData(ENUM_DEVICE_PUBLISH_HEADE_REMARK_NAME, 0, p->m_strCardRemarkName); - OnCheckSoftVersions(); - OnCheckFpgaVersions(); -// //progresss.append(progress); -// QTableWidgetItem *topLevelItem = new QTableWidgetItem(); //创建一个 TreeItem 容器用于后来装载控件 -// topLevelItem->setData(0,listProgramName->at(i)); -// topLevelItem->setFlags(topLevelItem->flags() & ~Qt::ItemIsEnabled & ~Qt::ItemIsSelectable); -// /*上面用到的两个枚举中:~Qt::ItemIsEnabled可以保证单击该Item时不会被选中,但是在启用Ctrl + A时,全选操作会导致Item被选中。 -// * ~Qt::ItemIsSelectable的使用可以保证全选状态下也不会被选中,但是在单独使用时出现了虚线框,没有真正实现“不存在”的效果。所以必须两个同用。*/ -// ctrlProgramList->setItem(i,0,topLevelItem); -// ctrlProgramList->setCellWidget(i, 1, progress); - -} - - - -QString wUpgradeApkItem::getRandomString(int length) -{ - qsrand(QDateTime::currentMSecsSinceEpoch()); - - const char ch[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; - int size = sizeof(ch); - - char* str = new char[length + 1]; - - int num = 0; - for (int i = 0; i < length; ++i) - { - num = rand() % (size - 1); - str[i] = ch[num]; - } - - QString res(str); - return res; -} -///////////////////////////////////////////////// - -void wUpgradeApkItem::OnProHttpResponse(QString url, QString postMD5, QByteArray data) -{ - Q_UNUSED(postMD5) - //qDebug()<< url + "\r\n"+m_strUrl; - if(url == m_strUrl) - { -// qDebug()<<"POST"; - //qDebug()<m_strCardId +"---------"+ strType; - if(strType=="TaskCommand" )//发送节目命令应答 - { - qDebug()<<"commandXixunPlayer response successed!"; - } - - else if(strType == "HasControllerPassword") - { - //if(m_pLedCard->bPassword!=jsonObject["result"].toBool()) - { - m_pLedCard->bPassword=jsonObject["result"].toBool(); - SetPasswordItem(m_pLedCard); - } - } - else if(strType == "VerifyPassword") - { - bool bStatus=jsonObject["result"].toBool(); - if(bStatus)//解密成功 - { - qDebug()<<"解密成功"; - m_pLedCard->m_bLockStatus=false; - } - else - { - qDebug()<<"解密失败"; - m_pLedCard->m_bLockStatus=true; - X_UIMsgBoxOk *mb = new X_UIMsgBoxOk(tr("Tip Info"),tr("password is wrong"), m_pWnd,0); - mb->exec(); - - } - SetPasswordItem(m_pLedCard); - } - else if(strType == "UninstallSoftware") - { - OnSendStatusTip(tr("UninstallSoftware")+tr("Success")+"!",Qt::green); - } - else if(strType == "IsSoftwareRunning") - { - if(jsonObject["running"].toBool()) - { - OnSendStatusTip(tr("Running")+"!",Qt::green); - - } - else { - OnSendStatusTip(tr("NoRunning")+"!",Qt::red); - - } - - } - else if(strType =="UpgradeSoftware") - { - emit sigUpgradeSuccess(); - OnSendStatusTip(tr("install success"),Qt::green); - OnCheckSoftVersions(); - - - } - else if(strType == "SynchronousHardwareVersion"){ - emit sigUpgradeSuccess(); - OnSendStatusTip(tr("SynchronousHardwareVersion")+tr("Success"),Qt::green); - OnCheckFpgaVersions(); - - } - else if(strType =="CheckHardwareVersions") - { - QString strtempVer=""; - int itempVerCount=0; - foreach(QJsonValue value, jsonObject["versions"].toArray()) { - QString strtempIcount=QString::number(itempVerCount); - if(itempVerCount==0) - strtempVer += "["+strtempIcount+"]:"+value.toString(); - else - strtempVer +="\r\n["+strtempIcount+"]:"+value.toString(); - itempVerCount++; - - } - setData(ENUM_DEVICE_PUBLISH_HEADE_FPAG_VERSION, 0, strtempVer); - } - else if(strType == "CheckSoftVersions"){ - QString strTip=""; - QStringList strtempApkPackList; - foreach(QJsonValue value, jsonObject["apps"].toArray()) { - QJsonObject oApp = value.toObject(); - QString strtempApkPackageName=oApp["packageName"].toString(); - QString strtempVersion=oApp["versionName"].toString(); - if(strtempApkPackageName=="com.xixun.xixunplayer") - setData(ENUM_DEVICE_PUBLISH_HEADE_XIXUNPLAYER_VERSION, 0, strtempVersion); - else if(strtempApkPackageName=="com.xixun.joey.cardsystem") - setData(ENUM_DEVICE_PUBLISH_HEADE_CARDSYSTEM_VERSION, 0, strtempVersion); - else if(strtempApkPackageName=="net.sysolution.starter") - setData(ENUM_DEVICE_PUBLISH_HEADE_STARTER_VERSION, 0, strtempVersion); - else if(strtempApkPackageName=="net.sysolution.taxiapp") - setData(ENUM_DEVICE_PUBLISH_HEADE_TAXIAPP_VERSION, 0, strtempVersion); - else if(strtempApkPackageName=="com.xixun.display") - setData(ENUM_DEVICE_PUBLISH_HEADE_DISPLAYER_VERSION, 0, strtempVersion); - else if(strtempApkPackageName=="com.xixun.xy.conn") - setData(ENUM_DEVICE_PUBLISH_HEADE_CONNECTION_VERSION, 0, strtempVersion); - else if(strtempApkPackageName=="com.xixun.xy.update") - setData(ENUM_DEVICE_PUBLISH_HEADE_UPDATE_VERSION, 0, strtempVersion); -// else if(strtempApkPackageName=="net.sysolution.basicapp") -// setData(ENUM_DEVICE_PUBLISH_HEADE_BASICAPP_VERSION, 0, strtempVersion); - - strtempApkPackList.append(strtempApkPackageName); - - } - - } - } - else//失败应答,打印失败和错误信息 - { - if(strType == "UninstallSoftware") - { - OnSendStatusTip(tr("UninstallSoftware")+tr("Fail")+"!",Qt::red); - } - else if(strType == "IsSoftwareRunning") - { - OnSendStatusTip(tr("IsSoftwareRunning")+tr("Fail")+"!",Qt::red); - } - else if(strType =="UpgradeSoftware") - { - emit sigUpgradeFail(); - OnCheckSoftVersions(); - - } - else if(strType =="SynchronousHardwareVersion") - { - emit sigUpgradeFail(); - OnCheckFpgaVersions(); - - } - } - - } -} diff --git a/LedOK/wDevicesManager/wupgradeapkitem.h b/LedOK/wDevicesManager/wupgradeapkitem.h deleted file mode 100644 index 5ead936..0000000 --- a/LedOK/wDevicesManager/wupgradeapkitem.h +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef WUPGRADEAPKITEM_H -#define WUPGRADEAPKITEM_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "threadupgradeapk.h" -#include -#include - -class wUpgradeApkItem : public QObject, public QTreeWidgetItem { - Q_OBJECT -public: - explicit wUpgradeApkItem(LedCard *pLedCard, LoQTreeWidget *parent = nullptr,QWidget *pWnd=nullptr); - ~wUpgradeApkItem(); - - void refreshLable(); - void SetItemParam(LedCard *p); - void onUpgradeApk(QString strFileName); - void onUpgradeFpga(QString strFileName); - void onUninstallApk(QString strApkName); - void onCheckRuningState(QString strApkName); - void SetLockFlagFalse(); - - LedCard *m_pLedCard = nullptr; -signals: - void sigUpgradeSuccess(); - void sigUpgradeFail(); - -public slots: - void OnProHttpResponse(QString url, QString postMD5, QByteArray data); - void OnThreadFinished(); - void OnThreadFpgaFinished(); - void OnSendStatusTip(QString); - void onVerifyLockPassword(); - void slotTimeout(); - void OnCheckSoftVersions(); - void OnCheckFpgaVersions(); - -private: - void init(); - QString getRandomString(int length); - void SetPasswordItem(LedCard *p); - bool m_lockFlag=true; - void OnSendStatusTip(QString,QColor cr); - - QLabel *m_ImageOnline=nullptr; - LoQTreeWidget *m_parent = nullptr; - QString m_strUrl=""; - QWidget *m_pWnd=nullptr; - HpptClient *pHpptClient = nullptr; - QProgressBar *m_pProgress=nullptr; - int m_iSendingFlag=0; - QPushButton *m_bnLock = nullptr;// - QString m_strApkFilePathName=""; - QString m_strFpgaFilePathName=""; - - void postFileTask(const QString& strUrl, const QString& strFilePath);//需要的数据 -}; -enum ENUM_DEVICE_PUBLISH_HEADERITEM -{ - ENUM_DEVICE_PUBLISH_HEADE_CHECK=0, - ENUM_DEVICE_PUBLISH_HEADE_SCREEN_ID, - ENUM_DEVICE_PUBLISH_HEADE_ONLINE, - ENUM_DEVICE_PUBLISH_HEADE_SCREEN_IP, - ENUM_DEVICE_PUBLISH_HEADE_ENCRYPT, - ENUM_DEVICE_PUBLISH_HEADE_PROGRESS, - ENUM_DEVICE_PUBLISH_HEADE_XIXUNPLAYER_VERSION, - ENUM_DEVICE_PUBLISH_HEADE_CARDSYSTEM_VERSION, - ENUM_DEVICE_PUBLISH_HEADE_STARTER_VERSION, - ENUM_DEVICE_PUBLISH_HEADE_TAXIAPP_VERSION, - ENUM_DEVICE_PUBLISH_HEADE_DISPLAYER_VERSION, - ENUM_DEVICE_PUBLISH_HEADE_FPAG_VERSION, - ENUM_DEVICE_PUBLISH_HEADE_REMARKS, - ENUM_DEVICE_PUBLISH_HEADE_REMARK_NAME, - ENUM_DEVICE_PUBLISH_HEADE_CONNECTION_VERSION, - ENUM_DEVICE_PUBLISH_HEADE_UPDATE_VERSION, -// ENUM_DEVICE_PUBLISH_HEADE_BASICAPP_VERSION, - ENUM_DEVICE_PUBLISH_HEADE_END, -}; - - -#endif // WPROGRAMPUBLISHITEM_H diff --git a/LedOK/wProgramManager/eaclock.h b/LedOK/wProgramManager/eaclock.h deleted file mode 100644 index 5ea7339..0000000 --- a/LedOK/wProgramManager/eaclock.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef EACLOCK_H -#define EACLOCK_H - -#include "ebase.h" -#include "base/locolorselector.h" -#include -#include -#include -#include -#include -#include -#include - -class eAClock : public EBase { - Q_OBJECT -public: - struct Data { - QByteArray timeZoneId; - int hourMark;//时针 - int hourMarkSize;//时针大小 - QColor hourMarkColor;//时针颜色 - int minMark;//分针 - int minMarkSize;//分针大小 - QColor minMarkColor;//分针颜色 - QColor hourHandColor;//秒针 - QColor minHandColor;//秒针大小 - QColor secHandColor;//秒针颜色 - QString text;//标题 - QFont textFont;//标题字体 - QColor textColor;//标题字体颜色 - int playDuration=10;// - QString path=""; - QString name=""; - QString selfCreateDialName; - bool hasDialImg; - }; - - explicit eAClock(EBase *multiWin = nullptr); - explicit eAClock(const QJsonObject &json, EBase *multiWin = nullptr); - - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; - int type() const override { return EBase::AClock; } - QWidget* attrWgt() override; - bool save(const QString &pRoot) override; - QJsonObject attrJson() const override; - -protected: - void drawMarkCircular (QPainter *painter, const QPointF &pos, const QColor &color, qreal diameter); - void drawMarkRectangle(QPainter *painter, const QPointF &pos, const QColor &color, qreal len, qreal rotate); - void drawMarkNumber (QPainter *painter, const QPointF &pos, const QColor &color, qreal len, int num); - void drawHand (QPainter *painter, qreal angle, const QColor &color, qreal len, qreal base); - void paintDial(QPainter *painter); - void paintText(QPainter *painter); - - qreal radiusHour() const; - qreal radiusMin() const; - qreal radius() const { return radiusHour() < radiusMin() ? radiusHour() : radiusMin(); } - - void init(); - - Data m_attr; - QImage dial_img; - QTime time; -}; - -#endif // EACLOCK_H diff --git a/LedOK/wProgramManager/etext.cpp b/LedOK/wProgramManager/etext.cpp deleted file mode 100644 index 25b47f7..0000000 --- a/LedOK/wProgramManager/etext.cpp +++ /dev/null @@ -1,1644 +0,0 @@ -#include "etext.h" -#include "base/locolorselector.h" -#include "cfg.h" -#include "globaldefine.h" -#include "tools.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -EText::EText(EBase *multiWin) : EBase(multiWin) { - mType = EBase::Text; - m_attr.text = tr("Enter your text"); - m_attr.cBackground = Qt::transparent; - m_attr.opt.setAlignment(Qt::AlignCenter); - m_attr.opt.setWrapMode(QTextOption::WrapAnywhere); - //Play - m_attr.playStyle = Flip; - m_attr.rolling.headTailConnected = true; - m_attr.rolling.headTailSpacing = 10; - m_attr.rolling.rollingSpeed = 50; - m_attr.rolling.rollingStyle = Left2Right; - m_attr.rolling.playDuration = 30; - connect(this, SIGNAL(sizeChanged()), this, SLOT(RefreshBigPixmap())); - RefreshBigPixmap(); -} -EText::EText(const QJsonObject &json, EBase *multiWin) : EBase(multiWin) { - mType = EBase::Text; - setBaseAttr(json); - setElement(json, m_attr); - connect(this, SIGNAL(sizeChanged()), this, SLOT(RefreshBigPixmap())); - RefreshBigPixmap(); -} - -void EText::setElement(const QJsonObject &json, Data &attr) { - auto widget = json["widget"]; - attr.text = widget["text"].toString(); - attr.lineSpacing = widget["lineSpacing"].toInt(); - attr.letterSpacing = widget["wordSpacing"].toInt(); - attr.opt.setAlignment(static_cast(widget["align"].toInt())); - attr.cBackground = Tools::int2Color(widget["cBackground"].toInt()); - attr.iPageCount = widget["iPageCount"].toInt(); - auto play = json["play"]; - attr.playStyle = play["style"].toInt(); - auto turning = play["turning"]; - attr.turning.effect = turning["strEffect"].toString(); - attr.turning.pageDuration = turning["iEffectTime"].toInt(); - attr.turning.effectDuration = turning["iEffectSpeed"].toInt(); - attr.turning.playDuration = turning["playDuration"].toInt(); - auto rolling = play["rolling"]; - attr.rolling.rollingStyle = rolling["rollingStyle"].toInt(); - attr.rolling.rollingSpeed = rolling["rollingSpeed"].toInt(); - attr.rolling.headTailConnected = rolling["headTailConnected"].toBool(); - attr.rolling.headTailSpacing = rolling["headTailSpacing"].toInt(); - attr.rolling.playDuration = rolling["playDuration"].toInt(); - attr.playDuration = play["static"]["playDuration"].toInt(); -} - -class TTextEdit : public QTextEdit { -public: - explicit TTextEdit(const QString &text) : QTextEdit(text){} - QSize minimumSizeHint() const override { - return sizeHint(); - }; - QSize sizeHint() const override { - auto size = QTextEdit::sizeHint(); - auto minH = minimumHeight(); - if(minH > 0) size.setHeight(minH+0xfff); - return size; - }; -}; -QWidget* EText::attrWgt() { - auto wgtAttr = new QWidget; - auto vBox = new QVBoxLayout(wgtAttr); - vBox->setContentsMargins(4, 0, 4, 0); - vBox->setSpacing(3); - - addBaseAttrWgt(vBox); - - auto hBox = new QHBoxLayout; - hBox->addWidget(new QLabel(tr("Basic Properties"))); - - auto line = new QFrame; - line->setFrameShape(QFrame::HLine); - line->setFrameShadow(QFrame::Sunken); - hBox->addWidget(line, 1); - - vBox->addLayout(hBox); - - hBox = new QHBoxLayout; - - auto fdText = new TTextEdit(m_attr.text); - - auto fdFontFamily = new QFontComboBox; - fdFontFamily->setEditable(false); - connect(fdFontFamily, &QFontComboBox::currentFontChanged, fdText, [fdText](const QFont &f) { - QTextCharFormat fmt; - fmt.setFontFamily(f.family()); - Tools::mergeFormat(fdText, fmt); - }); - hBox->addWidget(fdFontFamily); - - hBox->addStretch(); - - auto fdFontSize = new QSpinBox; - fdFontSize->setRange(4, 9999); - fdFontSize->setValue(16); - connect(fdFontSize, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, fdText, [fdText](int value) { - if(value <= 0) return; - QTextCharFormat fmt; - fmt.setProperty(QTextFormat::FontPixelSize, value); - Tools::mergeFormat(fdText, fmt); - }); - hBox->addWidget(fdFontSize); - - vBox->addLayout(hBox); - - hBox = new QHBoxLayout; - hBox->setSpacing(3); - - auto wTextAlignHL = new QPushButton(); - wTextAlignHL->setFixedSize(QSize(24, 24)); - wTextAlignHL->setIconSize(QSize(24, 24)); - QIcon icon3(":/res/ProgramManager/EditProgram/DocAlignHL_u.png"); - icon3.addFile(":/res/ProgramManager/EditProgram/DocAlignHL_s.png", QSize(), QIcon::Normal, QIcon::On); - wTextAlignHL->setIcon(icon3); - wTextAlignHL->setFlat(true); - wTextAlignHL->setCheckable(true); - wTextAlignHL->setChecked(true); - hBox->addWidget(wTextAlignHL); - - auto wTextAlignHC = new QPushButton(); - wTextAlignHC->setFixedSize(QSize(24, 24)); - wTextAlignHC->setIconSize(QSize(24, 24)); - QIcon icon4(":/res/ProgramManager/EditProgram/DocAlignHC_u.png"); - icon4.addFile(":/res/ProgramManager/EditProgram/DocAlignHC_s.png", QSize(), QIcon::Normal, QIcon::On); - wTextAlignHC->setIcon(icon4); - wTextAlignHC->setFlat(true); - wTextAlignHC->setCheckable(true); - hBox->addWidget(wTextAlignHC); - - auto wTextAlignHR = new QPushButton(); - wTextAlignHR->setFixedSize(QSize(24, 24)); - wTextAlignHR->setIconSize(QSize(24, 24)); - QIcon icon5(":/res/ProgramManager/EditProgram/DocAlignHR_u.png"); - icon5.addFile(":/res/ProgramManager/EditProgram/DocAlignHR_s.png", QSize(), QIcon::Normal, QIcon::On); - wTextAlignHR->setIcon(icon5); - wTextAlignHR->setFlat(true); - wTextAlignHR->setCheckable(true); - hBox->addWidget(wTextAlignHR); - - hBox->addStretch(); - - auto wFontBold = new QPushButton; - wFontBold->setFixedSize(QSize(24, 24)); - wFontBold->setIconSize(QSize(24, 24)); - QIcon icon(":/res/ProgramManager/EditProgram/FontBold_u.png"); - icon.addFile(":/res/ProgramManager/EditProgram/FontBold_s.png", QSize(), QIcon::Normal, QIcon::On); - wFontBold->setIcon(icon); - wFontBold->setFlat(true); - wFontBold->setCheckable(true); - connect(wFontBold, &QPushButton::toggled, fdText, [fdText](bool checked) { - QTextCharFormat fmt; - fmt.setFontWeight(checked ? QFont::Bold : QFont::Normal); - Tools::mergeFormat(fdText, fmt); - }); - hBox->addWidget(wFontBold); - - auto fdFontItalic = new QPushButton; - fdFontItalic->setFixedSize(24, 24); - fdFontItalic->setIconSize(QSize(24, 24)); - icon = QIcon(":/res/ProgramManager/EditProgram/FontItalics_u.png"); - icon.addFile(":/res/ProgramManager/EditProgram/FontItalics_s.png", QSize(), QIcon::Normal, QIcon::On); - fdFontItalic->setIcon(icon); - fdFontItalic->setFlat(true); - fdFontItalic->setCheckable(true); - connect(fdFontItalic, &QPushButton::toggled, fdText, [fdText](bool checked) { - QTextCharFormat fmt; - fmt.setFontItalic(checked); - Tools::mergeFormat(fdText, fmt); - }); - hBox->addWidget(fdFontItalic); - - auto wFontUnderline = new QPushButton; - wFontUnderline->setFixedSize(24, 24); - wFontUnderline->setIconSize(QSize(24, 24)); - icon = QIcon(":/res/ProgramManager/EditProgram/FontUnderline_u.png"); - icon.addFile(":/res/ProgramManager/EditProgram/FontUnderline_s.png", QSize(), QIcon::Normal, QIcon::On); - wFontUnderline->setIcon(icon); - wFontUnderline->setFlat(true); - wFontUnderline->setCheckable(true); - connect(wFontUnderline, &QPushButton::toggled, fdText, [fdText](bool checked) { - QTextCharFormat fmt; - fmt.setFontUnderline(checked); - Tools::mergeFormat(fdText, fmt); - }); - hBox->addWidget(wFontUnderline); - - hBox->addStretch(); - - auto fdTextColor = new LoColorSelector(tr("Font Color"), Qt::white); - fdTextColor->setFixedHeight(24); - connect(fdTextColor, &LoColorSelector::sColorChanged, fdText, [fdText](const QColor &color) { - if(! color.isValid()) return; - QTextCharFormat fmt; - fmt.setForeground(color); - Tools::mergeFormat(fdText, fmt); - }); - hBox->addWidget(fdTextColor); - - auto fdBackColor = new LoColorSelector(tr("Back Color"), m_attr.cBackground); - fdBackColor->setFixedHeight(24); - connect(fdBackColor, &LoColorSelector::sColorChanged, this, [this](const QColor &color) { - if(! color.isValid()) return; - m_attr.cBackground = color; - update(); - RefreshBigPixmap(); - }); - hBox->addWidget(fdBackColor); - - vBox->addLayout(hBox); - - hBox = new QHBoxLayout; - hBox->setSpacing(3); - - auto wTextAlignVT = new QPushButton; - wTextAlignVT->setFixedSize(QSize(24, 24)); - wTextAlignVT->setIconSize(QSize(24, 24)); - QIcon icon6(":/res/ProgramManager/EditProgram/DocAlignVT_u.png"); - icon6.addFile(":/res/ProgramManager/EditProgram/DocAlignVT_s.png", QSize(), QIcon::Normal, QIcon::On); - wTextAlignVT->setIcon(icon6); - wTextAlignVT->setFlat(true); - wTextAlignVT->setCheckable(true); - wTextAlignVT->setChecked(true); - hBox->addWidget(wTextAlignVT); - - auto wTextAlignVC = new QPushButton(); - wTextAlignVC->setFixedSize(QSize(24, 24)); - wTextAlignVC->setIconSize(QSize(24, 24)); - QIcon icon7(":/res/ProgramManager/EditProgram/DocAlignVC_u.png"); - icon7.addFile(":/res/ProgramManager/EditProgram/DocAlignVC_s.png", QSize(), QIcon::Normal, QIcon::On); - wTextAlignVC->setIcon(icon7); - wTextAlignVC->setFlat(true); - wTextAlignVC->setCheckable(true); - hBox->addWidget(wTextAlignVC); - - auto wTextAlignVB = new QPushButton(); - wTextAlignVB->setFixedSize(QSize(24, 24)); - wTextAlignVB->setIconSize(QSize(24, 24)); - QIcon icon8(":/res/ProgramManager/EditProgram/DocAlignVB_u.png"); - icon8.addFile(":/res/ProgramManager/EditProgram/DocAlignVB_s.png", QSize(), QIcon::Normal, QIcon::On); - wTextAlignVB->setIcon(icon8); - wTextAlignVB->setFlat(true); - wTextAlignVB->setCheckable(true); - hBox->addWidget(wTextAlignVB); - - hBox->addStretch(); - - hBox->addWidget(new QLabel(tr("Kerning"))); - - auto fdLetterSpacing = new QSpinBox(); - fdLetterSpacing->setMaximum(999); - fdLetterSpacing->setValue(m_attr.letterSpacing); - connect(fdLetterSpacing, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this](int value) { - m_attr.letterSpacing = value; - update(); - RefreshBigPixmap(); - }); - hBox->addWidget(fdLetterSpacing); - - hBox->addWidget(new QLabel(tr("Line Spacing"))); - - auto fdLineSpacing = new QSpinBox(); - fdLineSpacing->setMaximum(999); - fdLineSpacing->setValue(m_attr.lineSpacing); - connect(fdLineSpacing, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this](int value) { - m_attr.lineSpacing = value; - update(); - RefreshBigPixmap(); - }); - hBox->addWidget(fdLineSpacing); - - vBox->addLayout(hBox); - - auto wTextAlignH = new QButtonGroup(wgtAttr); - wTextAlignH->addButton(wTextAlignHL, Qt::AlignLeft); - wTextAlignH->addButton(wTextAlignHC, Qt::AlignHCenter); - wTextAlignH->addButton(wTextAlignHR, Qt::AlignRight); - connect(wTextAlignH, &QButtonGroup::idClicked, this, [this](int value) { - int res = m_attr.opt.alignment(); - res &= ~Qt::AlignHorizontal_Mask; - res |= value; - m_attr.opt.setAlignment(static_cast(res)); - update(); - RefreshBigPixmap(); - }); - - auto wTextAlignV = new QButtonGroup(wgtAttr); - wTextAlignV->addButton(wTextAlignVT, Qt::AlignTop); - wTextAlignV->addButton(wTextAlignVC, Qt::AlignVCenter); - wTextAlignV->addButton(wTextAlignVB, Qt::AlignBottom); - connect(wTextAlignV, &QButtonGroup::idClicked, this, [this](int value) { - int res = m_attr.opt.alignment(); - res &= ~Qt::AlignVertical_Mask; - res |= value; - m_attr.opt.setAlignment(static_cast(res)); - update(); - RefreshBigPixmap(); - }); - - auto align = m_attr.opt.alignment(); - auto h_align = align & Qt::AlignHorizontal_Mask; - if(h_align==Qt::AlignLeft) wTextAlignHL->setChecked(true); - if(h_align==Qt::AlignHCenter) wTextAlignHC->setChecked(true); - if(h_align==Qt::AlignRight) wTextAlignHR->setChecked(true); - auto v_align = align & Qt::AlignVertical_Mask; - if(v_align==Qt::AlignTop) wTextAlignVT->setChecked(true); - if(v_align==Qt::AlignVCenter) wTextAlignVC->setChecked(true); - if(v_align==Qt::AlignBottom) wTextAlignVB->setChecked(true); - - fdText->setMinimumHeight(160); - auto font = fdText->font(); - font.setPixelSize(16); - fdText->setFont(font); - auto pal = fdText->palette(); - pal.setColor(QPalette::Base, Qt::black); - pal.setColor(QPalette::Text, Qt::white); - fdText->setPalette(pal); - fdText->setFrameShape(QFrame::NoFrame); - fdText->setAcceptRichText(false); - connect(fdText, &QTextEdit::textChanged, this, [this, fdText] { - QString plain = fdText->toPlainText(); - if(plain.isEmpty()) { - fdText->selectAll(); - QTextCharFormat fmt; - fmt.setForeground(Qt::white); - Tools::mergeFormat(fdText, fmt); - } - m_attr.text = fdText->toHtml(); - update(); - RefreshBigPixmap(); - }); - vBox->addWidget(fdText); - - hBox = new QHBoxLayout; - hBox->addStretch(); - hBox->addWidget(new QLabel(tr("PageCount:"))); - - auto fdPageCnt = new QLabel(QString::number(m_attr.iPageCount)); - hBox->addWidget(fdPageCnt); - - hBox->addSpacing(20); - hBox->addWidget(new QLabel(tr("page"))); - - auto fdPageIdx = new QSpinBox(); - fdPageIdx->setRange(1, m_attr.iPageCount); - connect(fdPageIdx, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, &EText::OnPageIndexPreview); - hBox->addWidget(fdPageIdx); - hBox->addStretch(); - - auto btnImport = new QPushButton(tr("Import txt File")); - btnImport->setProperty("ssType", "progManageTool"); - connect(btnImport, &QPushButton::clicked, fdText, [fdText] { - auto filePath = QFileDialog::getOpenFileName(gMainWin, tr("Select File"), gFileHome, "Txt(*.txt)"); - if(filePath.isEmpty()) return; - QFile file(filePath); - if(! file.open(QFile::ReadOnly)) { - QMessageBox::critical(gMainWin, tr("Fail"), tr("File Open Fail")); - return; - } - auto data = file.readAll(); - file.close(); - QTextCodec::ConverterState state; - QString text = QTextCodec::codecForName("UTF-8")->toUnicode(data.constData(), data.size(), &state); - if(state.invalidChars > 0) text = QString::fromLocal8Bit(data); - fdText->setText(text); - }); - hBox->addWidget(btnImport); - - vBox->addLayout(hBox); - - hBox = new QHBoxLayout; - hBox->addWidget(new QLabel(tr("Play Properties"))); - - line = new QFrame(); - line->setFrameShape(QFrame::HLine); - line->setFrameShadow(QFrame::Sunken); - hBox->addWidget(line, 1); - - vBox->addLayout(hBox); - - hBox = new QHBoxLayout; - hBox->addStretch(); - - auto fdFlip = new QRadioButton(tr("Flip")); - hBox->addWidget(fdFlip); - hBox->addStretch(); - - auto fdScroll = new QRadioButton(tr("Scroll")); - fdScroll->setChecked(true); - hBox->addWidget(fdScroll); - hBox->addStretch(); - - auto fdStatic = new QRadioButton(tr("Static")); - hBox->addWidget(fdStatic); - hBox->addStretch(); - - vBox->addLayout(hBox); - - auto wPlayStyle = new QButtonGroup(wgtAttr); - wPlayStyle->addButton(fdFlip, EText::Flip); - wPlayStyle->addButton(fdScroll, EText::Scroll); - wPlayStyle->addButton(fdStatic, EText::Static); - if(m_attr.playStyle==EText::Flip) fdFlip->setChecked(true); - else if(m_attr.playStyle==EText::Scroll) fdScroll->setChecked(true); - else if(m_attr.playStyle==EText::Static) fdStatic->setChecked(true); - - auto wgtAttrFlip = new QWidget(); - { - auto vBox = new QVBoxLayout(wgtAttrFlip); - vBox->setContentsMargins(2, 0, 2, 0); - vBox->setSpacing(3); - - hBox = new QHBoxLayout; - - auto label = new QLabel(tr("Play Duration")); - label->setMinimumWidth(100); - hBox->addWidget(label); - - auto fdDur = new QTimeEdit(QTime::fromMSecsSinceStartOfDay(m_attr.turning.playDuration*1000)); - fdDur->setReadOnly(true); - fdDur->setButtonSymbols(QAbstractSpinBox::NoButtons); - fdDur->setDisplayFormat("H:mm:ss"); - fdDur->setStyleSheet("QTimeEdit{background-color:#ddd;}"); - connect(fdDur, &QTimeEdit::timeChanged, this, [this](const QTime &time) { - m_attr.turning.playDuration = time.msecsSinceStartOfDay()/1000; - }); - hBox->addWidget(fdDur); - hBox->addStretch(); - - vBox->addLayout(hBox); - - hBox = new QHBoxLayout(); - - label = new QLabel(tr("Duration/Page")); - label->setMinimumWidth(100); - hBox->addWidget(label); - - auto fdPageDur = new QTimeEdit(QTime::fromMSecsSinceStartOfDay(m_attr.turning.pageDuration*1000)); - fdPageDur->setDisplayFormat("H:mm:ss"); - fdPageDur->setCurrentSection(QTimeEdit::SecondSection); - hBox->addWidget(fdPageDur); - hBox->addStretch(); - - vBox->addLayout(hBox); - - hBox = new QHBoxLayout(); - - label = new QLabel(tr("Entrance Effect")); - label->setMinimumWidth(100); - hBox->addWidget(label); - - auto fdEff = new QComboBox(); - fdEff->addItem(tr("no"), "no"); - fdEff->addItem(tr("random"), "random"); - fdEff->addItem(tr("right to left"), "right to left"); - fdEff->addItem(tr("bottom to top"), "bottom to top"); - fdEff->addItem(tr("left to right"), "left to right"); - fdEff->addItem(tr("top to bottom"), "top to bottom"); - int idx = fdEff->findData(m_attr.turning.effect); - if(idx!=-1) fdEff->setCurrentIndex(idx); - connect(fdEff, (void(QComboBox::*)(int))&QComboBox::currentIndexChanged, this, [this, fdEff] { - m_attr.turning.effect = fdEff->currentData().toString(); - update(); - }); - hBox->addWidget(fdEff); - hBox->addStretch(); - - vBox->addLayout(hBox); - - hBox = new QHBoxLayout(); - - label = new QLabel(tr("Effect time")); - label->setMinimumWidth(100); - hBox->addWidget(label); - - auto wEffectSpeed = new QSpinBox(); - wEffectSpeed->setValue(m_attr.turning.effectDuration); - hBox->addWidget(wEffectSpeed); - hBox->addWidget(new QLabel(tr("s"))); - hBox->addStretch(); - - vBox->addLayout(hBox); - vBox->addStretch(); - - connect(fdPageDur, &QTimeEdit::timeChanged, this, [this, wEffectSpeed, fdPageDur, fdDur](const QTime &time) { - int effDur = wEffectSpeed->value(); - int pageDur = time.msecsSinceStartOfDay()/1000; - if(pageDur < effDur) { - QMessageBox::warning(gMainWin, tr("Tip Info"), tr("Effect time cannot be longer than duration time")); - pageDur = effDur; - fdPageDur->setTime(QTime::fromMSecsSinceStartOfDay(pageDur*1000)); - fdPageDur->setFocus(); - } - m_attr.turning.pageDuration = pageDur; - m_attr.turning.playDuration = pageDur * m_attr.iPageCount; - fdDur->setTime(QTime::fromMSecsSinceStartOfDay(m_attr.turning.playDuration*1000)); - }); - connect(wEffectSpeed, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this, wEffectSpeed, fdPageDur](int value) { - int pageDur = fdPageDur->time().msecsSinceStartOfDay()/1000; - if(value > pageDur) { - QMessageBox::warning(gMainWin, tr("Tip Info"), tr("Effect time cannot be longer than duration time")); - if(pageDur>1) value = pageDur-1; - else value = 0; - wEffectSpeed->setValue(value); - wEffectSpeed->setFocus(); - } - m_attr.turning.effectDuration = value; - }); - connect(this, &EText::sPageCountChanged, wgtAttr, [this, fdPageCnt, fdPageIdx, fdPageDur, fdDur] { - fdPageCnt->setText(QString::number(m_attr.iPageCount)); - fdPageIdx->setRange(1, m_attr.iPageCount); - fdPageIdx->setValue(1); - fdDur->setTime(QTime::fromMSecsSinceStartOfDay(fdPageDur->time().msecsSinceStartOfDay()*m_attr.iPageCount)); - }); - } - auto wgtAttrScroll = new QWidget(); - { - auto vBox = new QVBoxLayout(wgtAttrScroll); - vBox->setContentsMargins(2, 0, 2, 0); - vBox->setSpacing(3); - - auto hBox = new QHBoxLayout(); - - auto label = new QLabel(tr("Play Duration")); - label->setMinimumWidth(100); - hBox->addWidget(label); - - auto timeEdit = new QTimeEdit(QTime::fromMSecsSinceStartOfDay(m_attr.rolling.playDuration*1000)); - timeEdit->setDisplayFormat("H:mm:ss"); - timeEdit->setCurrentSectionIndex(2); - connect(timeEdit, &QTimeEdit::timeChanged, this, [this](const QTime &time) { - m_attr.rolling.playDuration = time.msecsSinceStartOfDay()/1000; - }); - hBox->addWidget(timeEdit); - hBox->addStretch(); - - vBox->addLayout(hBox); - - hBox = new QHBoxLayout(); - - label = new QLabel(tr("Head-Tail Connected")); - label->setMinimumWidth(100); - hBox->addWidget(label); - - auto wHeadTailConnected = new QCheckBox(); - wHeadTailConnected->setLayoutDirection(Qt::LeftToRight); - wHeadTailConnected->setStyleSheet("QCheckBox::indicator{width: 16px; height: 16px;}"); - hBox->addWidget(wHeadTailConnected); - - auto lHeadTailSpacing = new QLabel(tr("Head-Tail Spacing")); - hBox->addWidget(lHeadTailSpacing); - - auto wHeadTailSpacing = new QSpinBox(); - wHeadTailSpacing->setMaximum(9999); - wHeadTailSpacing->setValue(m_attr.rolling.headTailSpacing); - connect(wHeadTailSpacing, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this](int value) { - m_attr.rolling.headTailSpacing = value; - }); - hBox->addWidget(wHeadTailSpacing); - hBox->addStretch(); - - vBox->addLayout(hBox); - - if(m_attr.rolling.headTailConnected) wHeadTailConnected->setChecked(true); - else { - lHeadTailSpacing->setVisible(false); - wHeadTailSpacing->setVisible(false); - } - connect(wHeadTailConnected, &QCheckBox::toggled, this, [this, lHeadTailSpacing, wHeadTailSpacing](bool checked) { - m_attr.rolling.headTailConnected = checked; - lHeadTailSpacing->setVisible(checked); - wHeadTailSpacing->setVisible(checked); - }); - - hBox = new QHBoxLayout(); - - label = new QLabel(tr("Scroll Style")); - label->setMinimumWidth(100); - hBox->addWidget(label); - - auto wRollingStyle = new QComboBox(); - wRollingStyle->addItem(tr("Right -> Left")); - wRollingStyle->addItem(tr("Bottom -> Top")); - wRollingStyle->addItem(tr("Left -> Right")); - wRollingStyle->addItem(tr("Top -> Bottom")); - wRollingStyle->setCurrentIndex(m_attr.rolling.rollingStyle); - connect(wRollingStyle, (void(QComboBox::*)(int))&QComboBox::currentIndexChanged, this, [this](int index) { - m_attr.rolling.rollingStyle = index; - update(); - RefreshBigPixmap(); - }); - hBox->addWidget(wRollingStyle); - hBox->addStretch(); - - vBox->addLayout(hBox); - - hBox = new QHBoxLayout(); - - label = new QLabel(tr("Scroll Speed")); - label->setMinimumWidth(100); - hBox->addWidget(label); - - auto wRollingSpeed = new QSpinBox(); - wRollingSpeed->setMaximum(9999); - wRollingSpeed->setValue(m_attr.rolling.rollingSpeed); - connect(wRollingSpeed, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this](int value) { - m_attr.rolling.rollingSpeed = value; - }); - hBox->addWidget(wRollingSpeed); - hBox->addStretch(); - - vBox->addLayout(hBox); - vBox->addStretch(); - } - auto wgtAttrStatic = new QWidget(); - { - auto vBox = new QVBoxLayout(wgtAttrStatic); - vBox->setContentsMargins(2, 0, 2, 0); - vBox->setSpacing(3); - - hBox = new QHBoxLayout(); - auto label = new QLabel(tr("Play Duration")); - label->setMinimumWidth(100); - hBox->addWidget(label); - - auto timeEdit = new QTimeEdit(QTime::fromMSecsSinceStartOfDay(m_attr.playDuration*1000)); - timeEdit->setDisplayFormat("H:mm:ss"); - timeEdit->setCurrentSectionIndex(2); - connect(timeEdit, &QTimeEdit::timeChanged, this, [this](const QTime &time) { - m_attr.playDuration = time.msecsSinceStartOfDay() / 1000; - }); - hBox->addWidget(timeEdit); - hBox->addStretch(); - - vBox->addLayout(hBox); - vBox->addStretch(); - } - auto stackBox = new QStackedLayout; - vBox->addLayout(stackBox); - stackBox->addWidget(wgtAttrFlip); - stackBox->addWidget(wgtAttrScroll); - stackBox->addWidget(wgtAttrStatic); - stackBox->setCurrentIndex(m_attr.playStyle); - connect(wPlayStyle, &QButtonGroup::idClicked, this, [this, stackBox](int value) { - m_attr.playStyle = value; - update(); - RefreshBigPixmap(); - stackBox->setCurrentIndex(value); - }); - return wgtAttr; -} - -bool EText::save(const QString &pRoot) { - m_pRootPath=pRoot; - QString strDir = QString("%1%2%3%4%5").arg(zValue()).arg((int)x()).arg((int)y()).arg((int)mWidth).arg((int)mHeight); - //保存图片元素到相应目录 - QDir dirTemp(m_pRootPath+MACRO_FENGEFU+strDir); - if(dirTemp.exists()) - { - if(dirTemp.removeRecursively()) - { - int iReTryCount=0; - QDir dRoot(m_pRootPath); - while(!dRoot.mkdir(strDir)) - { - QThread::sleep(1); - iReTryCount++; - if(iReTryCount>10) - break; - } - } - } - else { - int iReTryCount=0; - QDir dRoot(m_pRootPath); - while(!dRoot.mkdir(strDir)) - { - QThread::sleep(1); - iReTryCount++; - if(iReTryCount>10) - break; - } - } - - - -// QDir dRoot(m_pRootPath); -// if(dRoot.exists(strDir)) { -// QDir dirTemp(m_pRootPath+MACRO_FENGEFU+strDir); -// if(dirTemp.exists()) -// { - -// } -// dRoot.removeRecursively() -// if(dRoot.remove(strDir)) -// { -// removeRecursively -// } -// } -// int iReTryCount=0; -// while(!dRoot.mkdir(strDir)) -// { -// QThread::sleep(1); -// iReTryCount++; -// if(iReTryCount>10) -// break; - -// } - QString strPath=m_pRootPath+ MACRO_FENGEFU +strDir; - if(m_attr.playStyle==EText::Flip)//生成多张图 - { - for (int i=0;i(m_attr.opt.alignment()); - oColor["background"] = Tools::color2Int(m_attr.cBackground); - oWidget["lineSpacing"] = m_attr.lineSpacing; - oWidget["wordSpacing"] = m_attr.letterSpacing; - oWidget["cBackground"] = Tools::color2Int(m_attr.cBackground); - - QJsonObject QJOPngObject; - QJsonArray QJArrayPngItems; - QString strDir=QString("%1%2%3%4%5").arg(zValue()).arg((int)x()).arg((int)y()).arg((int)mWidth).arg((int)mHeight); - if(m_attr.playStyle==EText::Flip)//生成多张图 - { - - for (int i=0;isave(); - painter->drawPixmap(innerRect(), mRenderImg, QRectF()); - painter->restore(); - EBase::paint(painter, option, widget); -} - -void EText::CreateBigOnePixBmp(){ - QPainter painter; - QTextDocument doc; - doc.setDefaultTextOption(m_attr.opt); - doc.setDocumentMargin(0); - doc.setTextWidth(rect().width()); - - QFont font; - if(gTextAntialiasing) font.setHintingPreference(QFont::PreferNoHinting); - else { - font.setLetterSpacing(QFont::AbsoluteSpacing, m_attr.letterSpacing); - font.setStyleStrategy(QFont::NoAntialias); - } - font.setPixelSize(16); - doc.setDefaultFont(font); - m_lineH = m_attr.lineSpacing + QFontMetrics(doc.defaultFont()).lineSpacing(); - doc.setHtml("
"+m_attr.text+"
"); - - int iwidth=this->rect().toRect().width(); - QRectF OutPutBmpRect = QRectF(0, 0, iwidth, doc.size().height());//实际绘制文本的矩形大小 - int iheight=OutPutBmpRect.toRect().height(); - - QPixmap map(iwidth, iheight); - - map.fill(m_attr.cBackground); - painter.begin(&map); - doc.drawContents(&painter, OutPutBmpRect); - painter.end(); - m_bigOnePixBmp=map.copy(OutPutBmpRect.toRect()); -} - -void EText::RefreshBigPixmap(){ - if(m_attr.playStyle==EText::Flip){//生成多张图 - CreateBigOnePixBmp(); - if(m_bigOnePixBmp.height()>6) { - QImage tempQImage=m_bigOnePixBmp.toImage(); - m_ImageBkColor=tempQImage.pixelColor(0,0); - m_list.clear(); - GetPagesPosList(); - } - if(m_list.count()>0) OnPageIndexPreview(1); - m_attr.iPageCount=m_list.count(); - emit sPageCountChanged(m_list.count()); - } - else if(m_attr.playStyle==EText::Scroll)//生成一张大图 - { - if(m_attr.rolling.rollingStyle==0||m_attr.rolling.rollingStyle==2)//上下滚动,生成一张纵向长图 - { - MakeBigMoveLeftOrRightOnePngToDir(); - } - else if(m_attr.rolling.rollingStyle==1||m_attr.rolling.rollingStyle==3)//上下滚动,生成一张纵向长图 - { - MakeBigMoveUpOrDownOnePngToDir(); - } - m_attr.iPageCount=1; - emit sPageCountChanged(1); - } - else if(m_attr.playStyle==EText::Static)//生成一张图 - { - CreateBigOnePixBmp(); - if(m_bigOnePixBmp.height()>6){ - QImage tempQImage=m_bigOnePixBmp.toImage(); - m_ImageBkColor=tempQImage.pixelColor(0,0); - m_list.clear(); - GetPagesPosList(); - } - m_attr.iPageCount=1; - OnPageIndexPreview(1); - emit sPageCountChanged(1); - } -} - -int EText::GetPagesPosList(){ - int iIndex=0; - for (;;) { - if(ClearPixmapTopAndBottomBlack()<=0) return m_list.count(); - txtBmpPage temp=GetFirstPagePixmap(); - if(temp.index==-1) {//表示到最后,bigpixmap已经没有内容了 - temp.index=iIndex; - iIndex++; - m_list.append(temp); - return m_list.count(); - } else { - temp.index=iIndex; - m_list.append(temp); - iIndex++; - if(iIndex > 100) break; - } - } - return m_list.count(); -} -//去除上下的黑边,返回去掉黑边图像的高度 -int EText::ClearPixmapTopAndBottomBlack() -{ - QImage tempQImage=m_bigOnePixBmp.toImage(); - int iFirst=0; - int iEnd=m_bigOnePixBmp.height(); - bool bFirst=false; - bool bEnd=false; - for(int y=0;y=0;m--) - { - for (int n=0;n1) - { - int iCopyHeight=iEnd-iFirst+1; - m_bigOnePixBmp=m_bigOnePixBmp.copy(0,iFirst,m_bigOnePixBmp.width(),iCopyHeight+1); - return iCopyHeight; - } - else { - //空的没有文字的部分 - return -1; - } -} - -txtBmpPage EText::GetFirstPagePixmap() -{ - QImage tempQImage=m_bigOnePixBmp.toImage(); -// tempQImage.save("f://a.png","PNG"); - txtBmpPage tempPageClass; - int iWidth=m_bigOnePixBmp.width(); - int iHeight=m_bigOnePixBmp.height(); - int iRectHeight=rect().height(); - if(iRectHeight>iHeight) iRectHeight=iHeight; - int iType=0; - //判断底边是不是黑 - for (int x=0;x=0;y--) - { - bool bFinished=false; - for (int x=0;x=0;y--) - { - bool bFinished=false; - for (int x=0;xiRectHeight) - m_bigOnePixBmp=m_bigOnePixBmp.copy(0,iRectHeight,iWidth,iHeight-iRectHeight); - else - { - tempPageClass.index=-1; - return tempPageClass; - } - } - else if(iSubType==1) - { - for (int y=iSubEnd;y>=0;y--) - { - bool bFinished=false; - for (int x=0;x=0) { - if(m_list.count()>0 && iPageIndexdiv{color:#fff; line-height:"+QString::number(m_attr.lineSpacing + lineSpacing)+"px; white-space:pre-wrap;}
"+m_attr.text+"
"); - - int iwidth=this->rect().toRect().width(); - QRectF OutPutBmpRect = QRectF(0, 0, iwidth, doc.size().height());//实际绘制文本的矩形大小 - int iheight=OutPutBmpRect.toRect().height(); - - QPixmap map(iwidth,iheight); - map.fill(m_attr.cBackground); - painter.begin(&map); - doc.drawContents(&painter, OutPutBmpRect); - painter.end(); - mRenderImg = QPixmap(rect().size().toSize()); - mRenderImg.fill(m_attr.cBackground); - painter.begin(&mRenderImg); - if(rect().height()>map.height()) { - QBrush bshBackground = Tools::getBrush(m_attr.cBackground); - if(bshBackground != Qt::NoBrush) painter.fillRect(0,map.height(),rect().width(),rect().height()-map.height(), bshBackground); - painter.drawPixmap(map.rect(), map,map.rect()); - } else { - QRectF rectSource(0,0,rect().width(),rect().height()); - painter.drawPixmap(rect(),map,rectSource); - } - painter.end(); - update(); -} -void EText::MakeBigMoveLeftOrRightOnePngToDir() { - QPainter painter; - QTextDocument doc; - //m_attr.opt.setAlignment(Qt::AlignJustify); - m_attr.opt.setAlignment(Qt::AlignLeft); - doc.setDefaultTextOption(m_attr.opt); - doc.setDocumentMargin(0); - // doc.setTextWidth(rect().width()); - doc.setTextWidth(3800); - - QFont font; - if(gTextAntialiasing) font.setHintingPreference(QFont::PreferNoHinting); - else { - font.setLetterSpacing(QFont::AbsoluteSpacing, m_attr.letterSpacing); - font.setStyleStrategy(QFont::NoAntialias); - } - font.setPixelSize(16); - doc.setDefaultFont(font); - - const int lineSpacing = QFontMetrics(doc.defaultFont()).lineSpacing(); - int lineH = m_attr.lineSpacing + lineSpacing; - doc.setHtml("
"+m_attr.text+"
"); - - //int iwidth=this->rect().toRect().width(); - int iwidth=3800; - QRectF OutPutBmpRect = QRectF(0, 0, iwidth, doc.size().height());//实际绘制文本的矩形大小 - int iheight=OutPutBmpRect.toRect().height(); - - QPixmap map(iwidth,iheight); - map.fill(m_attr.cBackground); - painter.begin(&map); - doc.drawContents(&painter, OutPutBmpRect); - painter.end(); - QPixmap bigOnePixmap=map.copy(OutPutBmpRect.toRect()); - //获取 - m_linelist.clear(); - //获取到长图的每页添加到list,并返回最大高度 - GetLinePng(bigOnePixmap); - //把list中的图片拼接起来 - if(m_linelist.count()>0) { - QBrush bshBackground = Tools::getBrush(m_attr.cBackground); - //把长图的开头拷贝到输出pixmap预览 - mRenderImg = QPixmap(rect().size().toSize()); - mRenderImg.fill(m_attr.cBackground); - painter.begin(&mRenderImg); - - txtBmpLine tmpLine=m_linelist.at(0); - int itempHeight=tmpLine.bitmap.height();//tmpLine.iEnd-tmpLine.iStart; - - int iTopOffset=(rect().height()-itempHeight)/2; - painter.fillRect(0,0,rect().width(),iTopOffset, bshBackground); - painter.fillRect(0,iTopOffset+itempHeight,rect().width(),rect().height()-iTopOffset-itempHeight, bshBackground); - - QRectF rectDest(0,iTopOffset,rect().width(),itempHeight); - QRectF rectSource(0,0,rect().width(),itempHeight); - painter.drawPixmap(rectDest,tmpLine.bitmap,rectSource); - painter.end(); - } - update(); -} - -int EText::GetLinePng(QPixmap bigOnePixmap) -{ - QImage tempQImage=bigOnePixmap.toImage(); - m_ImageBkColor=tempQImage.pixelColor(0,0); -// int iFirst=0; -// int iEnd=bigOnePixmap.height(); - bool bLineFlag=false; -// bool bEnd=false; - int iIndex=0; - txtBmpLine tmp; - int iMaxHeight=0; - for(int y=0;y2) - { - if(ipicHeight>iMaxHeight) - iMaxHeight=ipicHeight; - tmp.bitmap=bigOnePixmap.copy(0,tmp.iStart,bigOnePixmap.width(),tmp.iEnd-tmp.iStart); - m_linelist.append(tmp); - bLineFlag=false; - } - } - } - - else //文字行向下判断到了一个背景色的行,扫描了一行也没有发现文字颜色,都是背景色 - { - - tmp.iEnd=y; - int ipicHeight=tmp.iEnd-tmp.iStart; - if(ipicHeight>2) - { - if(ipicHeight>iMaxHeight) - iMaxHeight=ipicHeight; - tmp.bitmap=bigOnePixmap.copy(0,tmp.iStart,bigOnePixmap.width(),tmp.iEnd-tmp.iStart); - m_linelist.append(tmp); - bLineFlag=false; - } - - } - } - } - } - - return iMaxHeight; -} -//生成左右滚动图片素材 -void EText::MakeBigMoveLeftOrRightOnePngToDir(QString strPngPathAndName) { - QPainter painter; - GetPagesPosList(); - QTextDocument doc; - m_attr.opt.setAlignment(Qt::AlignLeft); - doc.setDefaultTextOption(m_attr.opt); - doc.setDocumentMargin(0); - doc.setTextWidth(3800); - QFont font; - if(gTextAntialiasing) font.setHintingPreference(QFont::PreferNoHinting); - else { - font.setLetterSpacing(QFont::AbsoluteSpacing, m_attr.letterSpacing); - font.setStyleStrategy(QFont::NoAntialias); - } - font.setPixelSize(16); - doc.setDefaultFont(font); - - const int lineSpacing = QFontMetrics(doc.defaultFont()).lineSpacing(); - int lineH = m_attr.lineSpacing + lineSpacing; - doc.setHtml("
"+m_attr.text+"
"); - - //int iwidth=this->rect().toRect().width()*iAllPagesTemp; - int iwidth=3800; - QRectF OutPutBmpRect = QRectF(0, 0, iwidth, doc.size().height());//实际绘制文本的矩形大小 - int iheight=OutPutBmpRect.toRect().height(); - - QPixmap map(iwidth,iheight); - map.fill(m_attr.cBackground); - painter.begin(&map); - doc.drawContents(&painter,OutPutBmpRect); - painter.end(); - QPixmap bigOnePixmap=map.copy(OutPutBmpRect.toRect()); - //获取 - bigOnePixmap.save("f:/a.png","PNG"); - m_linelist.clear(); - //获取到长图的每页添加到list,并返回最大高度 - GetLinePng(bigOnePixmap); - //把list中的图片拼接起来 - int iMaxHeight=rect().height(); - if(m_linelist.count()>0) - { - QBrush bshBackground(m_attr.cBackground);// = LoAppTools::getInstance()->getBrush(m_attr.cBackground); - QList listPageWidth; - int iPicLongSize=0; - for (int j=0;j4096-rect().width()) - { - listPageWidth.append(iPicLongSize); -// iPicLongSize=0; - } - } -// if(iPicLongSize!=0) -// { -// listPageWidth.append(iPicLongSize); -// } - - int iIOffset=0; - for (int m=0;mbegin(&bigOneLongPixmap); - iPicLongSize=0; - for (int i=iIOffset;ifillRect((i-iIOffset)*iwidth,0,rect().width(),iTopOffset, bshBackground); - pPainterTemp->fillRect((i-iIOffset)*iwidth,iTopOffset+itempHeight,rect().width(),iMaxHeight-iTopOffset-itempHeight, bshBackground); - } - - QRectF rectDest((i-iIOffset)*iwidth,(iMaxHeight-itempHeight)/2,iwidth,itempHeight); - pPainterTemp->drawPixmap(rectDest,tmpLine.bitmap,tmpLine.bitmap.rect()); - if(iPicLongSize==itempWidth) - { - - pPainterTemp->end(); - delete pPainterTemp; - if(m==listPageWidth.count()-1) - { - //如果启用了首位相接,根据间隔值处理吧文字后边的黑边流出来。 - if(m_attr.rolling.headTailConnected) - { - int itempSpace=GetWordSpaceRealInBmp(bigOneLongPixmap); - ProcessLastStartEndLianJie(bigOneLongPixmap,strPngPathAndName+QString::number(m)+".png",itempSpace+m_attr.rolling.headTailSpacing); - - } - else { - int itempSpace=GetWordSpaceRealInBmp(bigOneLongPixmap); - ProcessLastStartEndLianJie(bigOneLongPixmap,strPngPathAndName+QString::number(m)+".png",itempSpace); - //bigOneLongPixmap.save(strPngPathAndName+QString::number(m)+".png","PNG"); - - } - } - else { - int itempSpace=GetWordSpaceRealInBmp(bigOneLongPixmap); - ProcessLastStartEndLianJie(bigOneLongPixmap,strPngPathAndName+QString::number(m)+".png",itempSpace); - //bigOneLongPixmap.save(strPngPathAndName+QString::number(m)+".png","PNG"); - - } - iIOffset=i+1; - break; - } - else { - pPainterTemp->end(); - delete pPainterTemp; - - } - } - } - } - -} -void EText::ProcessLastStartEndLianJie(QPixmap bmp,QString strPngFilePathName,int iLastRightNoWordWidth) { - QImage tempQImage=bmp.toImage(); - int iWidth = bmp.width(); - for (int x=iWidth-1;x>0;x--) { - for(int y=0;ybegin(&returnBmp); - pPainterTemp->drawPixmap(bmp.rect(),bmp,bmp.rect()); - pPainterTemp->end(); - if(m_attr.rolling.headTailConnected) - { - if(returnBmp.width()>=rect().width())//如果图片的宽大于区域的宽 - { - returnBmp.save(strPngFilePathName,"PNG"); - } - else { - int iBeiShu=rect().width()/returnBmp.width(); - int iTempWidth=returnBmp.width(); - QPixmap returnNewBmp(iTempWidth*(iBeiShu+1),bmp.height()); - returnNewBmp.fill(m_ImageBkColor); - QPainter painter; - painter.begin(&returnNewBmp); - for (int ii=0;ii=rect().width())//如果图片的宽大于区域的宽 - { - returnBmp.save(strPngFilePathName,"PNG"); - - } - else { - int iTempWidth=returnBmp.width(); - QPixmap returnNewBmp(rect().width(),bmp.height()); - returnNewBmp.fill(m_ImageBkColor); - QPainter painter; - painter.begin(&returnNewBmp); - QBrush bshBackground = Tools::getBrush(m_attr.cBackground); - - painter.fillRect(returnNewBmp.rect(),bshBackground); - QRect tempRc(0,0,iTempWidth,returnBmp.height()); - painter.drawPixmap(tempRc,returnBmp,returnBmp.rect()); - returnNewBmp.save(strPngFilePathName,"PNG"); - } - - } - - delete pPainterTemp; - return; - } - } - } -} - - -int EText::GetWordSpaceRealInBmp(QPixmap bmp) -{ - QImage tempQImage=bmp.toImage(); -// m_ImageBkColor=tempQImage.pixelColor(0,0); - int iWidth= bmp.width(); - int iLastX = iWidth; - int iCount=0; - for (int x=iWidth-1;x>0;x--) - { - int iAllSameFlag=0; - for(int y=0;ydiv{color:#fff; line-height:"+QString::number(lineH)+"px; white-space:pre-wrap;}
"+m_attr.text+"
"); - int iwidth = innerRect().width(); - QRectF OutPutBmpRect(0, 0, iwidth, doc.size().height());//实际绘制文本的矩形大小 - int iheight = OutPutBmpRect.toRect().height(); - - QPixmap map(iwidth,iheight); - map.fill(m_attr.cBackground); - QPainter painter; - painter.begin(&map); - doc.drawContents(&painter, OutPutBmpRect); - painter.end(); - - QPixmap pRenderPixmap = QPixmap(rect().size().toSize()); - pRenderPixmap.fill(m_attr.cBackground); - painter.begin(&pRenderPixmap); - if(rect().height()>map.height()) { - QBrush bshBackground = Tools::getBrush(m_attr.cBackground); - if(bshBackground != Qt::NoBrush) painter.fillRect(0,map.height(),rect().width(),rect().height()-map.height(), bshBackground); - painter.drawPixmap(map.rect(),map,map.rect()); - pRenderPixmap.save(strPngPathAndName); - } else { - QRectF rectSource(0,0,rect().width(),rect().height()); - painter.drawPixmap(rect(),map,rectSource); - map.copy(OutPutBmpRect.toRect()).save(strPngPathAndName); - } - painter.end(); -} -//生成翻页和静态图片素材 -void EText::MakeMuliPngToDir(int iPageIndex,QString strPngPathAndName){ - iPageIndex=iPageIndex-1; - if(iPageIndex<0) iPageIndex=0; - if(iPageIndex>=0){ - if(m_list.count()>0&&iPageIndex -#include -#include -#include -#include "ebase.h" -#include "QTime" - -//这条语句害死人,加了这条语句文字就不能做到无反锯齿 MYFONT.setHintingPreference(QFont::PreferNoHinting); - -class txtBmpPage{ -public: - int index=0; - QPixmap bitmap; -}; - -class txtBmpLine{ -public: - int index=0; - int iStart=0; - int iEnd=0; - QPixmap bitmap; -}; - -class EText : public EBase { - Q_OBJECT -public: - enum PlayStyle { - Flip = 0, - Scroll, - Static - }; - - enum RollingStyle { - Left2Right = 0, - Right2Left, - Top2Bottom, - Bottom2Top - }; - struct Turning { - int playDuration{10}; - int pageDuration{10}; - QString effect{"no"}; - int effectDuration{3}; - }; - struct Rolling { - int playDuration{10}; - int rollingStyle; - int rollingSpeed; - bool headTailConnected; - int headTailSpacing=10; - }; - struct Data { - QString text; - QTextOption opt; - int lineSpacing = 0; - int letterSpacing = 0; - QColor cBackground; - int iPageCount=1; - int playStyle; - Turning turning; - Rolling rolling; - int playDuration{10}; - }; - - static void setElement(const QJsonObject &json, Data &attr); - - explicit EText(EBase *multiWin = nullptr); - explicit EText(const QJsonObject &json, EBase *multiWin = nullptr); - - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; - int type() const override { return EBase::Text; } - QWidget* attrWgt() override; - bool save(const QString &pRoot) override; - QJsonObject attrJson() const override; -signals: - void sPageCountChanged(int); - -public slots: // Widget - void RefreshBigPixmap(); - void OnPageIndexPreview(int iPageIndex); - -private: - int ClearPixmapTopAndBottomBlack(); - void MakeMuliPngToDir(int iPageIndex,QString strPngPathAndName) ; - void MakeBigMoveUpOrDownOnePngToDir() ; - void MakeBigMoveLeftOrRightOnePngToDir() ; - void MakeBigMoveUpOrDownOnePngToDir(QString strPngPathAndName) ; - void MakeBigMoveLeftOrRightOnePngToDir(QString strPngPathAndName) ; - void CreateBigOnePixBmp(); - int GetPagesPosList(); - txtBmpPage GetFirstPagePixmap(); - int GetLinePng(QPixmap bigOnePixmap) ; - void ProcessLastStartEndLianJie(QPixmap bmp,QString strPngFilePathName,int iLastRightNoWordWidth); - int GetWordSpaceRealInBmp(QPixmap bmp); - -private: // Interior - QPointF m_pText; - QRectF m_rClip; - Data m_attr; - int m_lineH; - QPixmap mRenderImg; - QPixmap m_bigOnePixBmp; - - QList m_list; - qreal m_oldWidth=0; - qreal m_oldHeight=0; - QColor m_ImageBkColor; - QString m_pRootPath; - QList m_linelist; - -}; - -#endif // ETEXT_H diff --git a/LedOK/wProgramManager/threadexportprogrampro.cpp b/LedOK/wProgramManager/threadexportprogrampro.cpp deleted file mode 100644 index 443676e..0000000 --- a/LedOK/wProgramManager/threadexportprogrampro.cpp +++ /dev/null @@ -1,161 +0,0 @@ -#include "threadexportprogrampro.h" -#include -#include -#include -#include -#include -#include - -ThreadExportProgramPro::ThreadExportProgramPro() -{ - m_createfile = new QDir(); - -} -ThreadExportProgramPro::~ThreadExportProgramPro() -{ - if(m_createfile) { - m_createfile = Q_NULLPTR; - delete m_createfile; - } - -} -void ThreadExportProgramPro::SetSourceDirAndDestDir(QString strSource,QString strDest) -{ - - m_strSource=strSource; - m_strDest=strDest; - -} -void ThreadExportProgramPro::run(){ - totalCopySize=0; - copyDirectoryFiles(m_strSource,m_strDest,true); -} -bool ThreadExportProgramPro::copyFileToPath(QString sourceDir, QString toDir, bool coverFileIfExist){ - if (sourceDir == toDir){ - return true; - } - if (!QFile::exists(sourceDir)){ - return false; - } - bool exist = m_createfile->exists(toDir); - if (exist){ - if(coverFileIfExist){ - m_createfile->remove(toDir); - } - } - - - if(!QFile::copy(sourceDir, toDir)) { - return false; - } - return true; -} - - -bool ThreadExportProgramPro::copyDirectoryFiles(const QString &fromDir, const QString &toDir, bool coverFileIfExist) -{ - QDir sourceDir(fromDir); - QDir targetDir(toDir); - qDebug() << "copyDirectoryFiles:" << fromDir << toDir; - if(!targetDir.exists()){ - if(!targetDir.mkdir(targetDir.absolutePath())) { - return false; - } - } - QFileInfoList fileInfoList = sourceDir.entryInfoList(); - - - if(m_firstRead) { - int isfileTMP = 0; - qDebug() << "a copyDirectoryFiles:" << fileInfoList.count(); - foreach(QFileInfo fileInfo, fileInfoList){ - if(fileInfo.isFile()) { - isfileTMP++; - } - } - m_total = fileInfoList.count() - 2 - isfileTMP; // 2为.和.. - m_value = 0; - m_firstRead = false; - qDebug() << "a copyDirectoryFiles:" << fileInfoList.count() < m_total) || (m_value == m_total)) { - m_firstRead = true; - emit sigCopyDirOver(); - } - } - foreach(QFileInfo fileInfo, fileInfoList){ - if(fileInfo.fileName() == "." || fileInfo.fileName() == "..") { - continue; - } - if(fileInfo.isDir()){ //< 当为目录时,递归的进行copy - if(!copyDirectoryFiles(fileInfo.filePath(), targetDir.filePath(fileInfo.fileName()), coverFileIfExist)) { - return false; - } - } else{ //当允许覆盖操作时,将旧文件进行删除操作 - if(coverFileIfExist && targetDir.exists(fileInfo.fileName())){ - targetDir.remove(fileInfo.fileName()); - } - /// 进行文件copy - if(!QFile::copy(fileInfo.filePath(), targetDir.filePath(fileInfo.fileName()))){ - return false; - } - else { - totalCopySize+=fileInfo.size(); - emit sigSendExportProgressValue(totalCopySize); - } -// if(!copyFile(fromDir+MACRO_FENGEFU+fileInfo.fileName(),toDir+MACRO_FENGEFU+fileInfo.fileName())){ -// return false; -// } - } - } - return true; -} -bool ThreadExportProgramPro::copyFile(const QString &fromFIleName, const QString &toFileName) -{ - char* byteTemp = new char[4096];//字节数组 - int fileSize = 0; - QFile tofile; - int iCurFileSize=0; - tofile.setFileName(toFileName); - QDataStream out(&tofile); - out.setVersion(QDataStream::Qt_4_8); - - QFile fromfile; - fromfile.setFileName(fromFIleName); - if(!fromfile.open(QIODevice::ReadOnly)){ - qDebug() << "open fromfile failed!!!"; - return false; - } - fileSize = fromfile.size(); - QDataStream in(&fromfile); - - in.setVersion(QDataStream::Qt_4_8); - while(!in.atEnd()) - { - int readSize = 0; - //读入字节数组,返回读取的字节数量,如果小于4096,则到了文件尾 - readSize = in.readRawData(byteTemp, 4096); - out.writeRawData(byteTemp, readSize); - totalCopySize += readSize; - iCurFileSize+=readSize; - emit sigSendExportProgressValue(totalCopySize); - } - if(iCurFileSize == fileSize){ - tofile.setPermissions(QFile::ExeUser); - fromfile.close(); - tofile.close(); - return true; - } - else - return false; -} diff --git a/LedOK/wProgramManager/threadexportprogrampro.h b/LedOK/wProgramManager/threadexportprogrampro.h deleted file mode 100644 index 71b0eb4..0000000 --- a/LedOK/wProgramManager/threadexportprogrampro.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef THREADEXPORTPROGRAMPRO_H -#define THREADEXPORTPROGRAMPRO_H -#include -#include -class ThreadExportProgramPro:public QThread -{ - Q_OBJECT -public: - ThreadExportProgramPro(); - ~ThreadExportProgramPro(); - void run(); - void SetSourceDirAndDestDir(QString strSource,QString strDest); -private: - bool copyFileToPath(QString sourceDir ,QString toDir, bool coverFileIfExist); - bool copyDirectoryFiles(const QString &fromDir, const QString &toDir, bool coverFileIfExist); - bool copyFile(const QString &fromFIleName, const QString &toFileName); -signals: - void sigSendExportProgressValue(int); -signals: - void sigCopyDirStation(float); - void sigCopyDirOver(); -private: - QDir * m_createfile = Q_NULLPTR; - float m_total = 0; - float m_value = 0; - bool m_firstRead = true; - QString m_strSource; - QString m_strDest; - int totalCopySize = 0; - -}; -#endif // THREADEXPORTPROGRAMPRO_H diff --git a/LedOK/wProgramManager/wexportprogramitem.cpp b/LedOK/wProgramManager/wexportprogramitem.cpp deleted file mode 100644 index f8102d8..0000000 --- a/LedOK/wProgramManager/wexportprogramitem.cpp +++ /dev/null @@ -1,64 +0,0 @@ -#include "wexportprogramitem.h" -#include -#include "globaldefine.h" -#include - -wExportProgramItem::wExportProgramItem(QTableWidget *parent,QString strProgramName,int iIndex): - QObject(parent), - QTableWidgetItem(UserType) -{ - /*上面用到的两个枚举中:~Qt::ItemIsEnabled可以保证单击该Item时不会被选中,但是在启用Ctrl + A时,全选操作会导致Item被选中。 - * ~Qt::ItemIsSelectable的使用可以保证全选状态下也不会被选中,但是在单独使用时出现了虚线框,没有真正实现“不存在”的效果。所以必须两个同用。*/ - m_parent=parent; - m_iIndex=iIndex; - setFlags(flags() & ~Qt::ItemIsEnabled & ~Qt::ItemIsSelectable); - progress= new QProgressBar(parent); - progress->setValue(0); - setData(0,strProgramName); - parent->setCellWidget(iIndex, 1, progress); - //ThreadExportProgramPro *pThread = new ThreadExportProgramPro(strSourceDir,strDestPath); - //connect(pItem) - pThread = new ThreadExportProgramPro(); -// connect(pThread,SIGNAL(sigCopyDirStation(float)),this,SLOT(OnProgressSet(float))); -// connect(pThread,SIGNAL(sigCopyDirOver()),this,SLOT(OnCopyDirOver())); - connect(pThread,SIGNAL(sigSendExportProgressValue(int)),this,SLOT(OnSendExportProgressValue(int))); -} -wExportProgramItem::~wExportProgramItem() -{ - if(pThread!=nullptr) - delete pThread; - m_parent->removeCellWidget(m_iIndex,1); - // delete progress; - -} -extern QWidget *gMainWin; -bool wExportProgramItem::ExportPro(QString strDestPath,QString strSourceDir) -{ - strSourceDir= strSourceDir+MACRO_FENGEFU+text(); - strDestPath=strDestPath+MACRO_FENGEFU+text(); - int iAllSize=dirFileSize(strSourceDir); - progress->setRange(0,iAllSize); - progress->setValue(0); - pThread->SetSourceDirAndDestDir(strSourceDir,strDestPath); - - QDir DirDest(strDestPath); - if(DirDest.exists()) { - auto res = QMessageBox::information(gMainWin, tr("Tip Info"), text()+tr(":solution(s) already exist.are you sure you want to overwrite the existing solution(s)?"), QMessageBox::Ok, QMessageBox::Cancel); - if(res == QMessageBox::Ok) pThread->start(); - else return false; - } - else pThread->start(); - return true; -} -void wExportProgramItem::OnProgressSet(float num) -{ - progress->setValue(num); -} -void wExportProgramItem::OnCopyDirOver() -{ - progress->setValue(100); -} -void wExportProgramItem::OnSendExportProgressValue(int iValue) -{ - progress->setValue(iValue); -} diff --git a/LedOK/wProgramManager/wexportprogramitem.h b/LedOK/wProgramManager/wexportprogramitem.h deleted file mode 100644 index f8a0b93..0000000 --- a/LedOK/wProgramManager/wexportprogramitem.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef WEXPORTPROGRAMITEM_H -#define WEXPORTPROGRAMITEM_H -#include -#include -#include -class wExportProgramItem:public QObject, public QTableWidgetItem -{ - Q_OBJECT -public: - wExportProgramItem(QTableWidget *parent = nullptr,QString strProgramName="",int iIndex=0); - ~wExportProgramItem(); - bool ExportPro(QString strDestPath,QString strSourceDir); -protected slots: - void OnProgressSet(float); - void OnCopyDirOver(); - void OnSendExportProgressValue(int); -private: - QProgressBar *progress =nullptr; - ThreadExportProgramPro *pThread=nullptr; - QTableWidget *m_parent=nullptr; - int m_iIndex=0; -}; - -#endif // WEXPORTPROGRAMITEM_H diff --git a/LedOK/x_uimsgonlyclosebtn.cpp b/LedOK/x_uimsgonlyclosebtn.cpp index b98b246..2f68392 100644 --- a/LedOK/x_uimsgonlyclosebtn.cpp +++ b/LedOK/x_uimsgonlyclosebtn.cpp @@ -1,14 +1,14 @@ -#include "x_uimsgonlyclosebtn.h" -#include "ui_x_uimsgonlyclosebtn.h" - -x_uiMsgOnlyCloseBtn::x_uiMsgOnlyCloseBtn(QWidget *parent) : - QDialog(parent), - ui(new Ui::x_uiMsgOnlyCloseBtn) -{ - ui->setupUi(this); -} - -x_uiMsgOnlyCloseBtn::~x_uiMsgOnlyCloseBtn() -{ - delete ui; -} +#include "x_uimsgonlyclosebtn.h" +#include "ui_x_uimsgonlyclosebtn.h" + +x_uiMsgOnlyCloseBtn::x_uiMsgOnlyCloseBtn(QWidget *parent) : + QDialog(parent), + ui(new Ui::x_uiMsgOnlyCloseBtn) +{ + ui->setupUi(this); +} + +x_uiMsgOnlyCloseBtn::~x_uiMsgOnlyCloseBtn() +{ + delete ui; +} diff --git a/LedOK/x_uimsgonlyclosebtn.h b/LedOK/x_uimsgonlyclosebtn.h index 8102318..2bc1006 100644 --- a/LedOK/x_uimsgonlyclosebtn.h +++ b/LedOK/x_uimsgonlyclosebtn.h @@ -1,22 +1,22 @@ -#ifndef X_UIMSGONLYCLOSEBTN_H -#define X_UIMSGONLYCLOSEBTN_H - -#include - -namespace Ui { -class x_uiMsgOnlyCloseBtn; -} - -class x_uiMsgOnlyCloseBtn : public QDialog -{ - Q_OBJECT - -public: - explicit x_uiMsgOnlyCloseBtn(QWidget *parent = nullptr); - ~x_uiMsgOnlyCloseBtn(); - -private: - Ui::x_uiMsgOnlyCloseBtn *ui; -}; - -#endif // X_UIMSGONLYCLOSEBTN_H +#ifndef X_UIMSGONLYCLOSEBTN_H +#define X_UIMSGONLYCLOSEBTN_H + +#include + +namespace Ui { +class x_uiMsgOnlyCloseBtn; +} + +class x_uiMsgOnlyCloseBtn : public QDialog +{ + Q_OBJECT + +public: + explicit x_uiMsgOnlyCloseBtn(QWidget *parent = nullptr); + ~x_uiMsgOnlyCloseBtn(); + +private: + Ui::x_uiMsgOnlyCloseBtn *ui; +}; + +#endif // X_UIMSGONLYCLOSEBTN_H diff --git a/LedOK/x_uimsgonlyclosebtn.ui b/LedOK/x_uimsgonlyclosebtn.ui index b48d8ab..c6c3d87 100644 --- a/LedOK/x_uimsgonlyclosebtn.ui +++ b/LedOK/x_uimsgonlyclosebtn.ui @@ -1,19 +1,19 @@ - - - x_uiMsgOnlyCloseBtn - - - - 0 - 0 - 400 - 300 - - - - Dialog - - - - - + + + x_uiMsgOnlyCloseBtn + + + + 0 + 0 + 400 + 300 + + + + Dialog + + + + + diff --git a/LedOK/y50 param/1080x1920(30hz)/rk_lcd_parameters b/LedOK/y50 param/1080x1920(30hz)/rk_lcd_parameters new file mode 100644 index 0000000..6d0fb64 --- /dev/null +++ b/LedOK/y50 param/1080x1920(30hz)/rk_lcd_parameters @@ -0,0 +1,35 @@ +##ע +#ע +# 0 - DSI; 1 - EDP; 2 - LVDS; 3 - RGB +panel-type = 3; + +# panel info +unprepare-delay-ms = 20; +enable-delay-ms = 20; +disable-delay-ms = 20; +prepare-delay-ms = 20; +reset-delay-ms = 100; +init-delay-ms = 100; +width-mm = 154; +height-mm = 86; + +# panel timing +clock-frequency = 72400000; +hactive = 1080; +hfront-porch = 30; +hsync-len = 10; +hback-porch = 58; +vactive = 1920; +vfront-porch = 30; +vsync-len = 11; +vback-porch = 88; +hsync-active = 0; +vsync-active = 0; +de-active = 0; +pixelclk-active = 0; + +# for dsi panel +#dsi,flags = 0; +#dsi,format = 0; +#dsi,lanes = 4; +#panel-init-sequence = 29 00 06 14 01 08 00 00 00 ff aa 01 02 03 04 05 06 07 ff aa AA bb ff; \ No newline at end of file diff --git a/LedOK/y50 param/1280x720(60hz)/rk_lcd_parameters b/LedOK/y50 param/1280x720(60hz)/rk_lcd_parameters new file mode 100644 index 0000000..1a70eef --- /dev/null +++ b/LedOK/y50 param/1280x720(60hz)/rk_lcd_parameters @@ -0,0 +1,35 @@ +##ע +#ע +# 0 - DSI; 1 - EDP; 2 - LVDS; 3 - RGB +panel-type = 3; + +# panel info +unprepare-delay-ms = 20; +enable-delay-ms = 20; +disable-delay-ms = 20; +prepare-delay-ms = 20; +reset-delay-ms = 100; +init-delay-ms = 100; +width-mm = 154; +height-mm = 86; + +# panel timing +clock-frequency = 72400000; +hactive = 1280; +hfront-porch = 30; +hsync-len = 10; +hback-porch = 99; +vactive = 720; +vfront-porch = 30; +vsync-len = 10; +vback-porch = 90; +hsync-active = 0; +vsync-active = 0; +de-active = 0; +pixelclk-active = 0; + +# for dsi panel +#dsi,flags = 0; +#dsi,format = 0; +#dsi,lanes = 4; +#panel-init-sequence = 29 00 06 14 01 08 00 00 00 ff aa 01 02 03 04 05 06 07 ff aa AA bb ff; \ No newline at end of file diff --git a/LedOK/y50 param/1920x1080(30hz)/rk_lcd_parameters b/LedOK/y50 param/1920x1080(30hz)/rk_lcd_parameters new file mode 100644 index 0000000..b87f02a --- /dev/null +++ b/LedOK/y50 param/1920x1080(30hz)/rk_lcd_parameters @@ -0,0 +1,35 @@ +##ע +#ע +# 0 - DSI; 1 - EDP; 2 - LVDS; 3 - RGB +panel-type = 3; + +# panel info +unprepare-delay-ms = 20; +enable-delay-ms = 20; +disable-delay-ms = 20; +prepare-delay-ms = 20; +reset-delay-ms = 100; +init-delay-ms = 100; +width-mm = 154; +height-mm = 86; + +# panel timing +clock-frequency = 72400000; +hactive = 1920; +hfront-porch = 40; +hsync-len = 20; +hback-porch = 22; +vactive = 1080; +vfront-porch = 100; +vsync-len = 6; +vback-porch = 22; +hsync-active = 0; +vsync-active = 0; +de-active = 0; +pixelclk-active = 0; + +# for dsi panel +#dsi,flags = 0; +#dsi,format = 0; +#dsi,lanes = 4; +#panel-init-sequence = 29 00 06 14 01 08 00 00 00 ff aa 01 02 03 04 05 06 07 ff aa AA bb ff; \ No newline at end of file diff --git a/LedOK/y50 param/1920x512(60hz)/rk_lcd_parameters b/LedOK/y50 param/1920x512(60hz)/rk_lcd_parameters new file mode 100644 index 0000000..fcad60e --- /dev/null +++ b/LedOK/y50 param/1920x512(60hz)/rk_lcd_parameters @@ -0,0 +1,35 @@ +##ע +#ע +# 0 - DSI; 1 - EDP; 2 - LVDS; 3 - RGB +panel-type = 3; + +# panel info +unprepare-delay-ms = 20; +enable-delay-ms = 20; +disable-delay-ms = 20; +prepare-delay-ms = 20; +reset-delay-ms = 100; +init-delay-ms = 100; +width-mm = 154; +height-mm = 86; + +# panel timing +clock-frequency = 72400000; +hactive = 1920; +hfront-porch = 30; +hsync-len = 10; +hback-porch = 99; +vactive = 512; +vfront-porch = 30; +vsync-len = 10; +vback-porch = 34; +hsync-active = 0; +vsync-active = 0; +de-active = 0; +pixelclk-active = 0; + +# for dsi panel +#dsi,flags = 0; +#dsi,format = 0; +#dsi,lanes = 4; +#panel-init-sequence = 29 00 06 14 01 08 00 00 00 ff aa 01 02 03 04 05 06 07 ff aa AA bb ff; \ No newline at end of file diff --git a/LedOK/y50 param/512x1920(60hz)/rk_lcd_parameters b/LedOK/y50 param/512x1920(60hz)/rk_lcd_parameters new file mode 100644 index 0000000..424e92e --- /dev/null +++ b/LedOK/y50 param/512x1920(60hz)/rk_lcd_parameters @@ -0,0 +1,35 @@ +##ע +#ע +# 0 - DSI; 1 - EDP; 2 - LVDS; 3 - RGB +panel-type = 3; + +# panel info +unprepare-delay-ms = 20; +enable-delay-ms = 20; +disable-delay-ms = 20; +prepare-delay-ms = 20; +reset-delay-ms = 100; +init-delay-ms = 100; +width-mm = 154; +height-mm = 86; + +# panel timing +clock-frequency = 72400000; +hactive = 512; +hfront-porch = 30; +hsync-len = 34; +hback-porch = 10; +vactive = 1920; +vfront-porch = 30; +vsync-len = 10; +vback-porch = 99; +hsync-active = 0; +vsync-active = 0; +de-active = 0; +pixelclk-active = 0; + +# for dsi panel +#dsi,flags = 0; +#dsi,format = 0; +#dsi,lanes = 4; +#panel-init-sequence = 29 00 06 14 01 08 00 00 00 ff aa 01 02 03 04 05 06 07 ff aa AA bb ff; \ No newline at end of file diff --git a/LedOK/y50 param/720x1280(60hz)/rk_lcd_parameters b/LedOK/y50 param/720x1280(60hz)/rk_lcd_parameters new file mode 100644 index 0000000..80a938d --- /dev/null +++ b/LedOK/y50 param/720x1280(60hz)/rk_lcd_parameters @@ -0,0 +1,35 @@ +##ע +#ע +# 0 - DSI; 1 - EDP; 2 - LVDS; 3 - RGB +panel-type = 3; + +# panel info +unprepare-delay-ms = 20; +enable-delay-ms = 20; +disable-delay-ms = 20; +prepare-delay-ms = 20; +reset-delay-ms = 100; +init-delay-ms = 100; +width-mm = 154; +height-mm = 86; + +# panel timing +clock-frequency = 72400000; +hactive = 720; +hfront-porch = 30; +hsync-len = 10; +hback-porch = 90; +vactive = 1280; +vfront-porch = 30; +vsync-len = 10; +vback-porch = 99; +hsync-active = 0; +vsync-active = 0; +de-active = 0; +pixelclk-active = 0; + +# for dsi panel +#dsi,flags = 0; +#dsi,format = 0; +#dsi,lanes = 4; +#panel-init-sequence = 29 00 06 14 01 08 00 00 00 ff aa 01 02 03 04 05 06 07 ff aa AA bb ff; \ No newline at end of file diff --git a/LedOK/y50 param/768x1280(60hz)/rk_lcd_parameters b/LedOK/y50 param/768x1280(60hz)/rk_lcd_parameters new file mode 100644 index 0000000..e927ecc --- /dev/null +++ b/LedOK/y50 param/768x1280(60hz)/rk_lcd_parameters @@ -0,0 +1,35 @@ +##ע +#ע +# 0 - DSI; 1 - EDP; 2 - LVDS; 3 - RGB +panel-type = 3; + +# panel info +unprepare-delay-ms = 20; +enable-delay-ms = 20; +disable-delay-ms = 20; +prepare-delay-ms = 20; +reset-delay-ms = 100; +init-delay-ms = 100; +width-mm = 154; +height-mm = 86; + +# panel timing +clock-frequency = 72400000; +hactive = 768; +hfront-porch = 24; +hsync-len = 8; +hback-porch = 57; +vactive = 1280; +vfront-porch = 31; +vsync-len = 11; +vback-porch = 86; +hsync-active = 0; +vsync-active = 0; +de-active = 0; +pixelclk-active = 0; + +# for dsi panel +#dsi,flags = 0; +#dsi,format = 0; +#dsi,lanes = 4; +#panel-init-sequence = 29 00 06 14 01 08 00 00 00 ff aa 01 02 03 04 05 06 07 ff aa AA bb ff; \ No newline at end of file

vdHLE2|1>^($^} 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 N002ovPDHLkV1f^6(dz&J diff --git a/LedOK/res/ProgramManager/EditProgram/AClock/AClock/Aclock7.png b/LedOK/res/ProgramManager/EditProgram/AClock/AClock/Aclock7.png deleted file mode 100644 index a4bd364981a56df4375c6bcba8193d49414c088c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 215941 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 K8C)r09Qc2|Qc>0b diff --git a/LedOK/res/ProgramManager/EditProgram/AClock/AClock/Aclock9.png b/LedOK/res/ProgramManager/EditProgram/AClock/AClock/Aclock9.png deleted file mode 100644 index d4f2194e1f1e239ca7947907be26a249bfa026e8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 92283 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