From 323a5cf9ea6439ac170b83d1ffd2cdcfc5680d58 Mon Sep 17 00:00:00 2001 From: luozheng <1732036298@qq.com> Date: Thu, 7 Mar 2024 11:06:19 +0800 Subject: [PATCH] =?utf8?q?=E5=B0=86=E5=BD=95=E9=9F=B3=E5=88=A0=E9=99=A4?= =?utf8?q?=E8=A7=86=E5=9B=BE=E4=BF=AE=E6=94=B9=E4=B8=BA=E5=BD=95=E9=9F=B3?= =?utf8?q?=E8=A7=86=E5=9B=BE=E7=9A=84=E5=AD=90=E8=A7=86=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .../wearable/fd230app/CMakeLists.txt | 2 - .../nativelauncher/include/AppViewIDs.h | 1 - .../nativelauncher/include/NativeLauncher.h | 2 - .../nativelauncher/src/NativeLauncher.cpp | 16 +- .../record/include/RecordDeletePresenter.h | 36 --- .../record/include/RecordDeleteView.h | 47 ++-- .../record/include/RecordingPresenter.h | 24 +- .../nativeui/record/include/RecordingView.h | 4 +- .../record/src/RecordDeletePresenter.cpp | 91 ------- .../nativeui/record/src/RecordDeleteView.cpp | 244 +++++++++++------- .../nativeui/record/src/RecordGoingView.cpp | 2 +- .../record/src/RecordingPresenter.cpp | 39 ++- .../nativeui/record/src/RecordingView.cpp | 42 ++- .../res/record/RECORD_DELETE_BACKGROUND.bin | Bin 146040 -> 0 bytes 14 files changed, 267 insertions(+), 283 deletions(-) delete mode 100644 code/sdk/application/wearable/fd230app/nativeui/record/include/RecordDeletePresenter.h delete mode 100644 code/sdk/application/wearable/fd230app/nativeui/record/src/RecordDeletePresenter.cpp delete mode 100644 code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/record/RECORD_DELETE_BACKGROUND.bin diff --git a/code/sdk/application/wearable/fd230app/CMakeLists.txt b/code/sdk/application/wearable/fd230app/CMakeLists.txt index aca22488b..1b9228f3e 100644 --- a/code/sdk/application/wearable/fd230app/CMakeLists.txt +++ b/code/sdk/application/wearable/fd230app/CMakeLists.txt @@ -312,9 +312,7 @@ set(SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/nativeui/classicbluetooth/src/ClassicBlueToothView.cpp #录音 - ${CMAKE_CURRENT_SOURCE_DIR}/nativeui/record/src/RecordDeletePresenter.cpp ${CMAKE_CURRENT_SOURCE_DIR}/nativeui/record/src/RecordDeleteView.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/nativeui/record/src/RecordGoingView.cpp ${CMAKE_CURRENT_SOURCE_DIR}/nativeui/record/src/RecordingPlayerView.cpp ${CMAKE_CURRENT_SOURCE_DIR}/nativeui/record/src/RecordingListAdapter.cpp diff --git a/code/sdk/application/wearable/fd230app/nativelauncher/include/AppViewIDs.h b/code/sdk/application/wearable/fd230app/nativelauncher/include/AppViewIDs.h index bf6d21100..26f609361 100644 --- a/code/sdk/application/wearable/fd230app/nativelauncher/include/AppViewIDs.h +++ b/code/sdk/application/wearable/fd230app/nativelauncher/include/AppViewIDs.h @@ -57,7 +57,6 @@ typedef enum : uint16_t VIEW_FAST_TRAINING_ATTENTION, // 快速训练项目选择超出提示 /* ----------------------------------- 录音 ----------------------------------- */ VIEW_RECORD, - VIEW_RECORD_DELETE, /* ---------------------------------- 界面 ---------------------------------- */ VIEW_DIAL, // 切换表盘 VIEW_MESSAGE, // 信息通知 diff --git a/code/sdk/application/wearable/fd230app/nativelauncher/include/NativeLauncher.h b/code/sdk/application/wearable/fd230app/nativelauncher/include/NativeLauncher.h index 3c204b419..13ac2e994 100644 --- a/code/sdk/application/wearable/fd230app/nativelauncher/include/NativeLauncher.h +++ b/code/sdk/application/wearable/fd230app/nativelauncher/include/NativeLauncher.h @@ -32,8 +32,6 @@ namespace OHOS void InitUISampleSlice(void); /* ----------------------------------- 录音 ----------------------------------- */ void InitRecordingSlice(void); - void InitRecordingPlaySlice(void); - void InitRecordingDeleteSlice(void); /* ----------------------------------- 天气 ----------------------------------- */ void InitWeatherSlice(void); void InitWeatherReportSlice(void); diff --git a/code/sdk/application/wearable/fd230app/nativelauncher/src/NativeLauncher.cpp b/code/sdk/application/wearable/fd230app/nativelauncher/src/NativeLauncher.cpp index da6d71b28..79b9aac07 100644 --- a/code/sdk/application/wearable/fd230app/nativelauncher/src/NativeLauncher.cpp +++ b/code/sdk/application/wearable/fd230app/nativelauncher/src/NativeLauncher.cpp @@ -100,8 +100,6 @@ #include "record/include/RecordingPresenter.h" #include "record/include/RecordingView.h" -#include "record/include/RecordDeletePresenter.h" -#include "record/include/RecordDeleteView.h" #include "BluetoothHeadsetEvent.h" #include "graphic_hardware_config.h" @@ -163,8 +161,7 @@ namespace OHOS {VIEW_FAST_TRAINING_ATTENTION, &NativeLauncher::InitFastTrainingAttentionSlice}, {VIEW_RECORD, &NativeLauncher::InitRecordingSlice}, // 录音实例化地址 - {VIEW_RECORD_DELETE, &NativeLauncher::InitRecordingDeleteSlice}, - + {VIEW_MESSAGE, &NativeLauncher::InitMessageSlice}, {VIEW_ROTATE, &NativeLauncher::InitRotateSlice}, {VIEW_DIALUPDATE, &NativeLauncher::InitDialUpdateSlice}, @@ -651,16 +648,5 @@ namespace OHOS } NativeAbility::GetInstance().AddSliceProxy(VIEW_RECORD, record); } - - void NativeLauncher::InitRecordingDeleteSlice(void) - { - SliceProxy *recorddelete = new AbilitySliceProxy; - if (recorddelete == nullptr) - { - return; - } - NativeAbility::GetInstance().AddSliceProxy(VIEW_RECORD_DELETE, recorddelete); - } - } diff --git a/code/sdk/application/wearable/fd230app/nativeui/record/include/RecordDeletePresenter.h b/code/sdk/application/wearable/fd230app/nativeui/record/include/RecordDeletePresenter.h deleted file mode 100644 index e43232efd..000000000 --- a/code/sdk/application/wearable/fd230app/nativeui/record/include/RecordDeletePresenter.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef RECORD_DELETE_PRESENTER_H -#define RECORD_DELETE_PRESENTER_H - -#include "Presenter.h" -#include "RecordDeleteView.h" -#include -#include -#include -namespace OHOS -{ - class RecordDeleteView; - - class RecordDeletePresenter : public Presenter, - public UIView::OnClickListener, - public UIView::OnDragListener - { - public: - RecordDeletePresenter(); - virtual ~RecordDeletePresenter(); - - void OnStart() override; - void OnPause() override; - void OnResume() override; - void OnStop() override; - - static RecordDeletePresenter *GetInstance(); - void deleteFile(const char *filepath); - - private: - // 因为继承了OnClickListener,所以有OnClick属性,至于参数,原函数也这样直接继承; - bool OnClick(UIView &view, const ClickEvent &event) override; - bool OnDrag(UIView &view, const DragEvent &event) override; - }; -} // namespace OHOS - -#endif // SLEEPDETAIL_PRESENTER_H \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230app/nativeui/record/include/RecordDeleteView.h b/code/sdk/application/wearable/fd230app/nativeui/record/include/RecordDeleteView.h index e210c4185..048776003 100644 --- a/code/sdk/application/wearable/fd230app/nativeui/record/include/RecordDeleteView.h +++ b/code/sdk/application/wearable/fd230app/nativeui/record/include/RecordDeleteView.h @@ -4,38 +4,45 @@ #include "BaseView.h" #include "View.h" -#include "components/ui_view_group.h" +#include "components/ui_scroll_view.h" #include "components/ui_image_view.h" #include "components/ui_button.h" +#include "components/ui_label_ext.h" namespace OHOS { - static const char *RECORD_DELETE_ON_BUTTON_VIEWID = "RECORD_DELETE_ON_BUTTON"; // 录音删除 - static const char *RECORD_DELETE_OFF_BUTTON_VIEWID = "RECORD_DELETE_OFF_BUTTON"; // 录音不删除 - class RecordDeletePresenter; - class RecordDeleteView : public View + + class RecordDeleteView { public: + struct LabelConfig + { + int16_t left; + int16_t top; + int16_t width; + int16_t height; + int16_t fontSize; // 字体大小 + int16_t lineHeigh; // 行高 + const char *text; // 文本 + uint8_t lineBreakMode; // 断行模式。 + }; RecordDeleteView(); virtual ~RecordDeleteView(); static RecordDeleteView *GetInstance(void); - - void OnStart() override; - void OnSetUpView() override; - void OnTearDownView() override; - void OnStop() override; + UIScrollView *RecordDeleteViewInit(void); + void ClearAll(void); private: - void InitView(void); - void DeInitView(void); - - UIViewGroup *container_ = nullptr; - UIImageView *RECORD_DELETE_BACKGROUND_IMAGE = nullptr; - UIButton *RECORD_DELETE_ON_BUTTON = nullptr; // 是否删除录音:是 - UIButton *RECORD_DELETE_OFF_BUTTON = nullptr; // 是否删除录音:否 - - UIView::OnClickListener *RECORD_DELETE_ON_BUTTON_CLICK{nullptr}; //删除录音按钮点击回调 - UIView::OnClickListener *RECORD_DELETE_OFF_BUTTON_CLICK{nullptr};//不删除录音按钮点击回调 + bool SetUpScrollView(void); + UILabelExt *SetUpLabel(LabelConfig &labelconfig); // 设置标签 + bool SetRecordDeleteViewLabel(void); + bool SetUpButton(void); + UIScrollView *RecordDeleteViewScrollView{nullptr}; + UILabelExt *TitleLabel{nullptr}; + UILabelExt *AttentionLabel[2]{nullptr}; + UIButton *RECORD_DELETE_ON_BUTTON{nullptr}; // 是否删除录音:是 + UIButton *RECORD_DELETE_OFF_BUTTON{nullptr}; // 是否删除录音:否 + bool initViewStatus{false}; }; } // namespace OHOS #endif \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230app/nativeui/record/include/RecordingPresenter.h b/code/sdk/application/wearable/fd230app/nativeui/record/include/RecordingPresenter.h index c93de5b32..0b9e42738 100644 --- a/code/sdk/application/wearable/fd230app/nativeui/record/include/RecordingPresenter.h +++ b/code/sdk/application/wearable/fd230app/nativeui/record/include/RecordingPresenter.h @@ -14,10 +14,17 @@ namespace OHOS RECORDINGLISTVIEW, // 录音列表视图(subView) RECORDGOINGVIEW, // 正在录音视图(subView) RECORDINGPLAYERVIEW, // 录音播放视图(subView) + RECORDINGDELETEVIEW, // 录音删除视图(subView) MAX_RECORDINGVIEWID, } RECORDINGVIEWID; - static const char *RECORD_GOING_BUTTON_VIEWID = "RECORD_GOING_BUTTON"; // 停止录音按钮id - static const char *RECORD_BUTTON = "RecordButton"; // 录音按钮id + + /*正在录音视图*/ + static const char *RECORD_GOING_BUTTON_VIEWID = "RECORD_GOING_BUTTON"; // 停止录音按钮id + + /*录音视图*/ + static const char *RECORD_BUTTON = "RecordButton"; // 录音按钮id + + /*录音播放视图*/ static const char *RECORD_PLAY_PAUSE_CHECKBOX_VIEWID = "RECORD_PLAY_PAUSE_CHECKBOX"; // 播放和暂停复选框视图id static const char *RECORD_PLAY_PROVE_BUTTON_VIEWID = "RECORD_PLAY_PROVE_BUTTON"; // 上一首按钮的视图id static const char *RECORD_PLAY_NEXT_BUTTON_VIEWID = "RECORD_PLAY_NEXT_BUTTON"; // 下一首按钮的视图id @@ -25,9 +32,13 @@ namespace OHOS static const char *RECORD_PLAY_VOLUME_BUTTON_VIEWID = "RECORD_PLAY_VOLUME_BUTTON"; // 音量按钮的视图id static const char *RECORD_PLAY_PLAYERPROGRESSBAR = "RECORD_PLAY_PLAYERPROGRESSBAR"; // 播放进度条视图id + /*录音删除视图*/ + static const char *RECORD_DELETE_ON_BUTTON_VIEWID = "RECORD_DELETE_ON_BUTTON"; // 录音删除 + static const char *RECORD_DELETE_OFF_BUTTON_VIEWID = "RECORD_DELETE_OFF_BUTTON"; // 录音不删除 + /* - *录音播放器界面点击监听类 - */ + *录音播放器界面点击监听类 + */ class RecordingPlayerViewOnClickListener : public UIView::OnClickListener { public: @@ -39,8 +50,8 @@ namespace OHOS }; /* - *录音列表点击监听类 - */ + *录音列表点击监听类 + */ class RecordListViewOnClickListener : public UIView::OnClickListener { public: @@ -69,6 +80,7 @@ namespace OHOS static RecordingPresenter *GetInstance(); int convertNumericDateTime(const char *numericDateTime, char *formattedDateTime); + void deleteFile(const char *filepath); private: // 因为继承了OnClickListener,所以有OnClick属性,至于参数,原函数也这样直接继承; diff --git a/code/sdk/application/wearable/fd230app/nativeui/record/include/RecordingView.h b/code/sdk/application/wearable/fd230app/nativeui/record/include/RecordingView.h index 437ab5df0..846eb1ada 100644 --- a/code/sdk/application/wearable/fd230app/nativeui/record/include/RecordingView.h +++ b/code/sdk/application/wearable/fd230app/nativeui/record/include/RecordingView.h @@ -14,11 +14,11 @@ #include "record/include/RecordListView.h" #include "record/include/RecordGoingView.h" #include "record/include/RecordingPlayerView.h" +#include "record/include/RecordDeleteView.h" #define NUM_MAX_RECORDINGVIEWSCROLLVIEW 10 namespace OHOS { - class RecordingPresenter; class RecordingView : public View { @@ -41,6 +41,7 @@ namespace OHOS bool ChangeRecordListView(int16_t thisView); // 切换到"录音列表"视图 bool ChangeRecordGoingView(int16_t thisView); // 切换到“正在录音”视图 bool ChangeRecordingPlayerView(int16_t thisView); // 切换到“录音播放”视图 + bool ChangeRecordDeleteView(int16_t thisView); // 切换到“录音删除”视图 bool ClickFunc(int16_t interface); void ChangeView(int16_t hideView, int16_t showView); UIScrollView *GetRecordingViewScrollView(int i); @@ -55,6 +56,7 @@ namespace OHOS RecordListView *p_RecordListView{nullptr}; RecordGoingView *p_RecordGoingView{nullptr}; RecordingPlayerView *p_RecordingPlayerView{nullptr}; + RecordDeleteView *p_RecordDeleteView{nullptr}; private: void RecordingViewInit(void); diff --git a/code/sdk/application/wearable/fd230app/nativeui/record/src/RecordDeletePresenter.cpp b/code/sdk/application/wearable/fd230app/nativeui/record/src/RecordDeletePresenter.cpp deleted file mode 100644 index bef41c095..000000000 --- a/code/sdk/application/wearable/fd230app/nativeui/record/src/RecordDeletePresenter.cpp +++ /dev/null @@ -1,91 +0,0 @@ -#include "AppViewIDs.h" -#include "NativeAbility.h" -#include "graphic_math.h" -#include "string.h" -#include "record/include/RecordDeletePresenter.h" - -namespace OHOS -{ - - // 当前Presenter属性实例化的内存指针 - static RecordDeletePresenter *g_pRecordDeletePresenter = nullptr; - - RecordDeletePresenter::RecordDeletePresenter() - { - - g_pRecordDeletePresenter = this; - } - - RecordDeletePresenter::~RecordDeletePresenter() - { - - g_pRecordDeletePresenter = nullptr; - } - - RecordDeletePresenter *RecordDeletePresenter::GetInstance() - { - - return g_pRecordDeletePresenter; - } - - void RecordDeletePresenter::OnStart() - { - - Presenter::OnStart(); - } - - void RecordDeletePresenter::OnPause(void) - { - - Presenter::OnPause(); - } - - void RecordDeletePresenter::OnResume(void) - { - - Presenter::OnResume(); - } - - void RecordDeletePresenter::OnStop(void) - { - - Presenter::OnStop(); - } - - bool RecordDeletePresenter::OnDrag(UIView &view, const DragEvent &event) - { - UNUSED(view); - UNUSED(event); - } - - // 删除文件 - void RecordDeletePresenter::deleteFile(const char *filepath) - { - if (std::remove(filepath) == 0) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Deleted file: %s", filepath); - } - else - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to delete file!"); - } - } - - bool RecordDeletePresenter::OnClick(UIView &view, const ClickEvent &event) - { - UNUSED(event); - // 根据控件id查找是哪个控件触发了点击回调 - if (strcmp(view.GetViewId(), RECORD_DELETE_ON_BUTTON_VIEWID) == 0) - { - deleteFile("/user/res/record/recording/record_test.mp3"); - //NativeAbility::GetInstance().ChangeSlice(VIEW_RECORD_PLAY); - return true; - } - else if (strcmp(view.GetViewId(), RECORD_DELETE_OFF_BUTTON_VIEWID) == 0) - { - //NativeAbility::GetInstance().ChangeSlice(VIEW_RECORD_PLAY); - return true; - } - return false; - } -} \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230app/nativeui/record/src/RecordDeleteView.cpp b/code/sdk/application/wearable/fd230app/nativeui/record/src/RecordDeleteView.cpp index b48232a01..ba4bacfc9 100644 --- a/code/sdk/application/wearable/fd230app/nativeui/record/src/RecordDeleteView.cpp +++ b/code/sdk/application/wearable/fd230app/nativeui/record/src/RecordDeleteView.cpp @@ -1,150 +1,198 @@ #include "record/include/RecordDeleteView.h" -#include "record/include/RecordDeletePresenter.h" - -#include "UiConfig.h" +#include "record/include/RecordingPresenter.h" +#include "wearable_log.h" namespace OHOS { - static constexpr const char *PNG_RECORD_DELETE_BACKGROUND_IMAGE = APP_RES_PATH "/record/RECORD_DELETE_BACKGROUND.bin"; // 删除录音的背景图 static RecordDeleteView *g_pRecordDeleteView{nullptr}; RecordDeleteView::RecordDeleteView() { - + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "RecordDeleteView::RecordDeleteView"); g_pRecordDeleteView = this; } RecordDeleteView::~RecordDeleteView() { - DeInitView(); + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "RecordDeleteView::~RecordDeleteView"); + ClearAll(); g_pRecordDeleteView = nullptr; } RecordDeleteView *RecordDeleteView::GetInstance() { - return g_pRecordDeleteView; } - void RecordDeleteView::InitView() + void RecordDeleteView::ClearAll() { - if (container_ == nullptr) + if (initViewStatus == true) { - container_ = new UIViewGroup(); - container_->SetPosition(0, 0, 466, 466); - container_->SetStyle(STYLE_BACKGROUND_OPA, 0); - } + RecordDeleteViewScrollView->RemoveAll(); - // Add ImageView to App - if (RECORD_DELETE_BACKGROUND_IMAGE == nullptr) - { - RECORD_DELETE_BACKGROUND_IMAGE = new UIImageView(); - } - RECORD_DELETE_BACKGROUND_IMAGE->SetPosition(0, 0); - RECORD_DELETE_BACKGROUND_IMAGE->Resize(466, 466); - RECORD_DELETE_BACKGROUND_IMAGE->SetViewId("RECORD_DELETE_BACKGROUND_IMAGE"); - RECORD_DELETE_BACKGROUND_IMAGE->SetSrc(PNG_RECORD_DELETE_BACKGROUND_IMAGE); + delete TitleLabel; + TitleLabel = nullptr; - // Add to rootView - container_->Add(RECORD_DELETE_BACKGROUND_IMAGE); - RECORD_DELETE_BACKGROUND_IMAGE->SetVisible(true); + for (int i = 0; i < 2; i++) + { + delete AttentionLabel[i]; + AttentionLabel[i] = nullptr; + } - // Add Button to App - if (RECORD_DELETE_ON_BUTTON == nullptr) - { - RECORD_DELETE_ON_BUTTON = new UIButton(); + delete RECORD_DELETE_ON_BUTTON; + RECORD_DELETE_ON_BUTTON = nullptr; + + delete RECORD_DELETE_OFF_BUTTON; + RECORD_DELETE_OFF_BUTTON = nullptr; + + delete RecordDeleteViewScrollView; + RecordDeleteViewScrollView = nullptr; } - RECORD_DELETE_ON_BUTTON->SetPosition(254, 299); - RECORD_DELETE_ON_BUTTON->Resize(100, 100); - RECORD_DELETE_ON_BUTTON->SetViewId(RECORD_DELETE_ON_BUTTON_VIEWID); - RECORD_DELETE_ON_BUTTON->SetStyle(STYLE_BACKGROUND_COLOR, 0xff191919); - RECORD_DELETE_ON_BUTTON->SetStyle(STYLE_BORDER_COLOR, 0xffffffff); - RECORD_DELETE_ON_BUTTON->SetImageSrc(PNG_SYSTEM_CHECK_ON_IMAGE, nullptr); - RECORD_DELETE_ON_BUTTON->SetStyleForState(STYLE_BACKGROUND_COLOR, 0xffffffff, UIButton::PRESSED); - RECORD_DELETE_ON_BUTTON->SetStyleForState(STYLE_BACKGROUND_OPA, 0x2b, UIButton::PRESSED); - RECORD_DELETE_ON_BUTTON->SetStyleForState(STYLE_BORDER_COLOR, 0xff0b1928, UIButton::PRESSED); - - // Add the CallBack about events - RECORD_DELETE_ON_BUTTON_CLICK = static_cast(RecordDeletePresenter::GetInstance()); - RECORD_DELETE_ON_BUTTON->SetOnClickListener(RECORD_DELETE_ON_BUTTON_CLICK); - // Add to rootView - container_->Add(RECORD_DELETE_ON_BUTTON); - RECORD_DELETE_ON_BUTTON->SetVisible(true); - - // Add Button to App - if (RECORD_DELETE_OFF_BUTTON == nullptr) + } + + bool RecordDeleteView::SetUpScrollView(void) + { + RecordDeleteViewScrollView = new UIScrollView(); + if (RecordDeleteViewScrollView == nullptr) { - RECORD_DELETE_OFF_BUTTON = new UIButton(); + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "RecordDeleteView::RecordDeleteViewScrollView new fail!"); + return false; } - RECORD_DELETE_OFF_BUTTON->SetPosition(111, 299); - RECORD_DELETE_OFF_BUTTON->Resize(100, 100); - RECORD_DELETE_OFF_BUTTON->SetViewId(RECORD_DELETE_OFF_BUTTON_VIEWID); - RECORD_DELETE_OFF_BUTTON->SetStyle(STYLE_BACKGROUND_COLOR, 0xff191919); - RECORD_DELETE_OFF_BUTTON->SetStyle(STYLE_BORDER_COLOR, 0xffffffff); - RECORD_DELETE_OFF_BUTTON->SetImageSrc(PNG_SYSTEM_CHECK_OFF_IMAGE, nullptr); - RECORD_DELETE_OFF_BUTTON->SetStyleForState(STYLE_BACKGROUND_COLOR, 0xffffffff, UIButton::PRESSED); - RECORD_DELETE_OFF_BUTTON->SetStyleForState(STYLE_BACKGROUND_OPA, 0x2b, UIButton::PRESSED); - RECORD_DELETE_OFF_BUTTON->SetStyleForState(STYLE_BORDER_COLOR, 0xff0b1928, UIButton::PRESSED); - - // Add the CallBack about events - RECORD_DELETE_OFF_BUTTON_CLICK = static_cast(RecordDeletePresenter::GetInstance()); - RECORD_DELETE_OFF_BUTTON->SetOnClickListener(RECORD_DELETE_OFF_BUTTON_CLICK); - // Add to rootView - container_->Add(RECORD_DELETE_OFF_BUTTON); - RECORD_DELETE_OFF_BUTTON->SetVisible(true); + RecordDeleteViewScrollView->SetPosition(0, 0, Screen::GetInstance().GetWidth(), Screen::GetInstance().GetHeight()); + RecordDeleteViewScrollView->SetTouchable(true); + RecordDeleteViewScrollView->SetDraggable(true); + return true; } - void RecordDeleteView::DeInitView() + UILabelExt *RecordDeleteView::SetUpLabel(LabelConfig &labelconfig) // 设置标签 { - if (container_ != nullptr) + UILabelExt *label = new UILabelExt(); + if (label == nullptr) { - container_->RemoveAll(); + return nullptr; } - if (RECORD_DELETE_BACKGROUND_IMAGE != nullptr) + label->SetPosition(labelconfig.left, labelconfig.top, labelconfig.width, labelconfig.height); // 位置大小 + label->SetStyle(STYLE_TEXT_FONT, labelconfig.fontSize); // 字体大小 + label->SetStyle(STYLE_LINE_HEIGHT, labelconfig.lineHeigh); // 字体行高 + label->SetText(labelconfig.text); // 内容 + label->SetLineBreakMode(labelconfig.lineBreakMode); // 断行模式。 + label->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER); + label->SetFont(DEFAULT_VECTOR_FONT_FILENAME, labelconfig.fontSize); + return label; + } + + bool RecordDeleteView::SetRecordDeleteViewLabel(void) + { + LabelConfig labelconfig = { + .left = 173, + .top = 52, + .width = 200, + .height = 40, + .fontSize = 30, + .lineHeigh = 35, + .text = "删除录音", + .lineBreakMode = UILabel::LINE_BREAK_ADAPT, + }; + TitleLabel = SetUpLabel(labelconfig); + if (nullptr == TitleLabel) { - delete RECORD_DELETE_BACKGROUND_IMAGE; - RECORD_DELETE_BACKGROUND_IMAGE = nullptr; + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "RecordDeleteView::TitleLabel is nullptr!"); + return false; } - if (RECORD_DELETE_ON_BUTTON != nullptr) + + labelconfig = { + .left = 33, + .top = 145, + .width = 400, + .height = 124, + .fontSize = 30, + .lineHeigh = 35, + .text = "此操作将 该录音\n\n是否确认?", + .lineBreakMode = UILabel::LINE_BREAK_ELLIPSIS, + }; + + AttentionLabel[0] = SetUpLabel(labelconfig); + if (nullptr == AttentionLabel[0]) { - delete RECORD_DELETE_ON_BUTTON; - RECORD_DELETE_ON_BUTTON = nullptr; + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "RecordDeleteView::AttentionLabel[0] is nullptr!"); + return false; } - if (RECORD_DELETE_OFF_BUTTON != nullptr) + + labelconfig = { + .left = 188, + .top = 154, + .width = 200, + .height = 40, + .fontSize = 30, + .lineHeigh = 35, + .text = "永久删除", + .lineBreakMode = UILabel::LINE_BREAK_ADAPT, + }; + AttentionLabel[1] = SetUpLabel(labelconfig); + AttentionLabel[1]->SetTextColor(Color::GetColorFromRGBA(0xff, 0x5a, 0x36, 0xff)); + if (nullptr == AttentionLabel[1]) { - delete RECORD_DELETE_OFF_BUTTON; - RECORD_DELETE_OFF_BUTTON = nullptr; + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "RecordDeleteView::AttentionLabel[1] is nullptr!"); + return false; } - delete container_; - container_ = nullptr; - } - void RecordDeleteView::OnStart() - { - View::OnStart(); - InitView(); - RootView::GetInstance()->Add(container_); + return true; } - void RecordDeleteView::OnSetUpView() + bool RecordDeleteView::SetUpButton(void) { + UIView::OnClickListener *clickLister = static_cast(RecordingPresenter::GetInstance()); + RECORD_DELETE_OFF_BUTTON = new UIButton(); + if (RECORD_DELETE_OFF_BUTTON == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "RecordDeleteView::RECORD_DELETE_OFF_BUTTON is new fail!"); + return false; + } + RECORD_DELETE_OFF_BUTTON->SetPosition(111, 299, 100, 100); + RECORD_DELETE_OFF_BUTTON->SetViewId(RECORD_DELETE_OFF_BUTTON_VIEWID); + RECORD_DELETE_OFF_BUTTON->SetStyle(STYLE_BACKGROUND_COLOR, 0xff191919); + RECORD_DELETE_OFF_BUTTON->SetImageSrc("/user/res/SYSTEM_CheckOff.bin", "/user/res/SYSTEM_CheckOff.bin"); + RECORD_DELETE_OFF_BUTTON->SetOnClickListener(clickLister); - View::OnSetUpView(); - Draw(); - } - - void RecordDeleteView::OnTearDownView() - { + RECORD_DELETE_ON_BUTTON = new UIButton(); + if (RECORD_DELETE_ON_BUTTON == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "RecordDeleteView::RECORD_DELETE_ON_BUTTON is new fail!"); + return false; + } + RECORD_DELETE_ON_BUTTON->SetPosition(256, 299, 100, 100); + RECORD_DELETE_ON_BUTTON->SetViewId(RECORD_DELETE_ON_BUTTON_VIEWID); + RECORD_DELETE_ON_BUTTON->SetStyle(STYLE_BACKGROUND_COLOR, 0xff191919); + RECORD_DELETE_ON_BUTTON->SetImageSrc("/user/res/SYSTEM_CheckOn.bin", "/user/res/SYSTEM_CheckOn.bin"); + RECORD_DELETE_ON_BUTTON->SetOnClickListener(clickLister); - View::OnTearDownView(); - return; + return true; } - void RecordDeleteView::OnStop() + UIScrollView *RecordDeleteView::RecordDeleteViewInit(void) { + if (!SetUpScrollView()) + { + return nullptr; + } - View::OnStop(); - RootView::GetInstance()->RemoveAll(); - return; + if (!SetRecordDeleteViewLabel()) + { + return nullptr; + } + + if (!SetUpButton()) + { + return nullptr; + } + /* ----------------------------------- Add ---------------------------------- */ + RecordDeleteViewScrollView->Add(TitleLabel); + RecordDeleteViewScrollView->Add(AttentionLabel[0]); + RecordDeleteViewScrollView->Add(AttentionLabel[1]); + RecordDeleteViewScrollView->Add(RECORD_DELETE_ON_BUTTON); + RecordDeleteViewScrollView->Add(RECORD_DELETE_OFF_BUTTON); + initViewStatus = true; + return RecordDeleteViewScrollView; } + } \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230app/nativeui/record/src/RecordGoingView.cpp b/code/sdk/application/wearable/fd230app/nativeui/record/src/RecordGoingView.cpp index ac2ebfc5f..23de4b75c 100644 --- a/code/sdk/application/wearable/fd230app/nativeui/record/src/RecordGoingView.cpp +++ b/code/sdk/application/wearable/fd230app/nativeui/record/src/RecordGoingView.cpp @@ -104,7 +104,7 @@ namespace OHOS TitleLabel = SetUpLabel(labelconfig); if (nullptr == TitleLabel) { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "RecordGoingView::SetRecordGoingViewLabel is nullptr!"); + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "RecordGoingView::TitleLabel is nullptr!"); return false; } labelconfig.top = 370; diff --git a/code/sdk/application/wearable/fd230app/nativeui/record/src/RecordingPresenter.cpp b/code/sdk/application/wearable/fd230app/nativeui/record/src/RecordingPresenter.cpp index 833fba404..84160cc1c 100644 --- a/code/sdk/application/wearable/fd230app/nativeui/record/src/RecordingPresenter.cpp +++ b/code/sdk/application/wearable/fd230app/nativeui/record/src/RecordingPresenter.cpp @@ -120,6 +120,21 @@ namespace OHOS return 1; // 转换成功 } + /* + * @brief 删除文件 + */ + void RecordingPresenter::deleteFile(const char *filepath) + { + if (std::remove(filepath) == 0) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Deleted file: %s", filepath); + } + else + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to delete file!"); + } + } + #ifdef __cplusplus extern "C" { @@ -187,6 +202,17 @@ namespace OHOS RecordingModel::GetInstance()->Recording_StopTimer(); return true; } + else if (strcmp(view.GetViewId(), RECORD_DELETE_ON_BUTTON_VIEWID) == 0) + { + deleteFile("/user/res/record/recording/record_test.mp3"); + p_RecordingView->ChangeView(RECORDINGDELETEVIEW, RECORDINGPLAYERVIEW); + return true; + } + else if (strcmp(view.GetViewId(), RECORD_DELETE_OFF_BUTTON_VIEWID) == 0) + { + p_RecordingView->ChangeView(RECORDINGDELETEVIEW, RECORDINGPLAYERVIEW); + return true; + } return true; } @@ -245,27 +271,30 @@ namespace OHOS bool RecordingPlayerViewOnClickListener::OnClick(UIView &view, const ClickEvent &event) { + RecordingView *p_RecordingView = RecordingView::GetInstance(); + if (p_RecordingView == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "RecordingView GetInstance fail"); + return false; + } + if (strcmp(view.GetViewId(), RECORD_PLAY_PROVE_BUTTON_VIEWID) == 0) { WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "recording player prove button being clicked!"); - } else if (strcmp(view.GetViewId(), RECORD_PLAY_NEXT_BUTTON_VIEWID) == 0) { WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "recording player next button being clicked!"); - } else if (strcmp(view.GetViewId(), RECORD_PLAY_DELETE_BUTTON_VIEWID) == 0) { WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "recording player delete button being clicked!"); - NativeAbility::GetInstance().ChangeSlice(VIEW_RECORD_DELETE); - + p_RecordingView->ChangeView(RECORDINGPLAYERVIEW, RECORDINGDELETEVIEW); } else if (strcmp(view.GetViewId(), RECORD_PLAY_VOLUME_BUTTON_VIEWID) == 0) { WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "recording player volume button being clicked!"); NativeAbility::GetInstance().ChangeSlice(VIEW_SYSTEM_VOLUME); - } return true; } diff --git a/code/sdk/application/wearable/fd230app/nativeui/record/src/RecordingView.cpp b/code/sdk/application/wearable/fd230app/nativeui/record/src/RecordingView.cpp index 122d20441..5314e2116 100644 --- a/code/sdk/application/wearable/fd230app/nativeui/record/src/RecordingView.cpp +++ b/code/sdk/application/wearable/fd230app/nativeui/record/src/RecordingView.cpp @@ -60,6 +60,9 @@ namespace OHOS delete p_RecordingPlayerView; p_RecordingPlayerView = nullptr; + delete p_RecordDeleteView; + p_RecordDeleteView = nullptr; + delete RecordingViewScrollView[RECORDINGVIEW]; RecordingViewScrollView[RECORDINGVIEW] = nullptr; } @@ -197,7 +200,9 @@ namespace OHOS return RecordingViewScrollView[i]; } - // 切换到“录音”视图 + /* + * @brief 切换到“录音”视图 + */ bool RecordingView::ChangeRecordingView(int16_t thisView) { if (RecordingViewScrollView[thisView] == nullptr) @@ -208,7 +213,9 @@ namespace OHOS return true; } - // 切换到录音列表视图 + /* + * @brief 切换到录音列表视图 + */ bool RecordingView::ChangeRecordListView(int16_t thisView) { if (RecordingViewScrollView[thisView] == nullptr) @@ -230,7 +237,9 @@ namespace OHOS return true; } - // 切换到“正在录音”视图 + /* + * @brief 切换到“正在录音”视图 + */ bool RecordingView::ChangeRecordGoingView(int16_t thisView) { if (RecordingViewScrollView[thisView] == nullptr) @@ -248,7 +257,9 @@ namespace OHOS return true; } - // 切换到“录音播放”视图 + /* + * @brief 切换到“录音播放”视图 + */ bool RecordingView::ChangeRecordingPlayerView(int16_t thisView) { if (RecordingViewScrollView[thisView] == nullptr) @@ -265,6 +276,26 @@ namespace OHOS } return true; } + + /* + * @brief 切换到“录音删除”视图 + */ + bool RecordingView::ChangeRecordDeleteView(int16_t thisView) + { + if (RecordingViewScrollView[thisView] == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "RecordingView::ChangeRecordDeleteView"); + p_RecordDeleteView = new RecordDeleteView(); + if (p_RecordDeleteView == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "RecordingView:: new scrollView[%d] fail", thisView); + return false; + } + RecordingViewScrollView[thisView] = p_RecordDeleteView->RecordDeleteViewInit(); + RootView::GetInstance()->Add(RecordingViewScrollView[thisView]); + } + return true; + } /* -------------------------------------------------------------------------- */ // 1.RecordingViewMapper:结构体定义了一个将视图ID映射到特定成员函数指针的映射表。 struct RecordingViewMapper @@ -278,7 +309,8 @@ namespace OHOS {RECORDINGVIEW, &RecordingView::ChangeRecordingView}, {RECORDINGLISTVIEW, &RecordingView::ChangeRecordListView}, {RECORDGOINGVIEW, &RecordingView::ChangeRecordGoingView}, - {RECORDINGPLAYERVIEW,&RecordingView::ChangeRecordingPlayerView}, + {RECORDINGPLAYERVIEW, &RecordingView::ChangeRecordingPlayerView}, + {RECORDINGDELETEVIEW, &RecordingView::ChangeRecordDeleteView}, }; // 3.根据传入的interface参数执行相应视图ID关联的成员函数。 diff --git a/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/record/RECORD_DELETE_BACKGROUND.bin b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/res/record/RECORD_DELETE_BACKGROUND.bin deleted file mode 100644 index 6948674881b55a2e519a14991b3dd0109e10460d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 146040 zcmeHw3t$sf_V<}&noioZNmCvzpdHdy8n#LwDn)@zl8P;^OOv{ay9z;3>G~?@%0nbm zKyAc@7P|tge~CO?>SHagt0=4;s0u6~5BC9!N<>^iSxG6ccha=X^wY}HLR;ph zl-|tDoqNwc_jk`Z_ug~B4zP#XLy1~uPyQ{b5Kc{}MJcKI5CwWWJqE{2(@QNirLpAy zO^0bFAz%dHQmfN3?~1#b;TtKSVfaJUW`Gj&DjlRV$W0LZ|54t)BNoSvfSdRznViPODOYJSKYy1y?a-GB63 zF}{2`jZbp7;4gqf4{zF{X8?E#EE-Wfde}BvSN3E|)4{2=o7`#&UmrFm5$S(jRlTn%iFzg@Kp<^eR6m*!f`MH5mq-2b_)w~+Y& zMqM+ySOXfcqx=aTB(?DJpI*i!f4_=1Dm{8O-gI{VQ8Cj71B)ME%o&ZMi1^hH@$3Y^ zmV)5^Pv^LZytNAAplp+9=&MM7ureg{6`tM3|R}3klQ++pXL0emVdF)!|9vK%!`Dmv|Cq2 z=paJUFDIz_Wy^YW@5dWCzn}m1x~(@dAkYB@_wyY4BDvw?DHaO%|8dX|$)ljB%6Hvd zzmxONh3_vn;u+ZwP}TH~_v%Q4YA=)V&-owUa{f@?@5mp|z?Fz>87S8_?K~~v-4w`$ z!;ylDcNZQ%*LOkW#DR*|C|2meIyd~P2At4+W*7*n^ioK^K18`hZ64``HxcY zE$XsH!DvE5ioE_8e!QvmIn&sI%}FF77` zT)&V$tML$h_CeHVCA|A63Ha-U7?Y~c_By%^U6ld;|*tKdej^0>1C68u$WhAA?eWY`!3$*GkP`k8SNN&)=fQyh zX}DwNLety1b{zjbg%v5H=8}qC==xmf_q%TWHFcPxg_28{hnpL+3#9XA91=!7Z${Wd z!57Q4~aln^dYo9RyBv2qw1!EdEGZ&hl&iDJBl^>z)`Dl_!o1VCeqGIgd z#6f~FrDB|8X3F#HwRaaz1%AQfF|(*6*RBw4gY%s;lOXL?JpVNqKapC9*8-kKCy5oc zutjvgb7g>m96jq9G5(_^+JwTbIsSO~6O4nu8c*0@u|o@*6U(778oV?d10eYvFU>W^ z!0`iMYIk1WG4oE~`cQ!H2x@GgE!2eG$Ids2Vs-sz%Dgl29yt2M&rN<~ntpu+AETtF zz1$CgJ>EdJPY8A3@|BUl@f+|w;O@6aGe4V=%{R?QpX*z(n z0vt_(HA@lImF4&Lyt^oZfn?l|k}-O|aUGcC?N!o4&7W`jxTYEzTrJ;{1g9RFc2n*} z$DeX~i(>rG_TXp@CV|i&|BC?gkynW$BQp9SxUzYT=9^aobxA}%6C=n^E1q%9Iw-5A zTJtUV)|wZZHBeP8;aBw?6MwhsL1-8U-$&aQutLO)y?P^G3gsF$rqCA;hH}j*aUukx zIWM@2R-hpFeG-@kv0B`=>ZZc@Da2N3QND(79xGVj)hYAtBY(x#1P0>f|EG;#Jk+j# zu{@5n4Q5{}{byg04I`r`#cMLP{4)`3jBCxSWNV@%k8%y@KV|Jh;3@fQwfDi%pgXKN z)cQO-T6$hd&)%LV^1-F8_UB`wtH^?r9S4x5Da-jlU7wKmf7j!?-IYnfSO6Zmk-K3q zP5S4(*8UMM`tweOQzv;MRx!5NHA_o3z;TW9R6MME!q-2|dfiHTEnP+AE7VZGAL2d{ zU4}pQsrv}t=_H9KVd11!JPXTjMWqOgjcB0WALzG^dVo9+9+Y_+vzXK3jb4|lhAh{a z0!g3|3Yu+1o@z)6;VH0(8yzEt3UM%Z1tg#cfsC4wZkIbCMslWt*(2ci9Ds@2eAttS z$0+(W;dv#^{@<`B;4hnDgQnNDbw{%pi}{1({xOfaeHj}-cY z!bKt)r7!e0_tBENFT?U5#|)Mf@s9FRd+_1BTsSG>kDQ;|>*Kxsy2E-Siq<;pQ?%FB zj%#W?PjPHH=!C8x-*Wo){`ZB>bK=B*Y`K8s1xHbGnEs+oJP|La$Hm8w%Jw_=rFcH* zKR&=3S*i-29YDtKv0cL+lzzOAdR-&N2QqlZ_B><>=Adbvo8VUiA{;+3pj$_Mt;Dz1 z{2B7wYv1V}tfj2SqakCMec#ss5%H~|u`UrP6YcaZ2X1^_(x$A`)hCxind6-+U>EQy z!3n&!35-PkbKHQ!V=Oer0t-->|ES-Dt3S|I>oljN@`c5#$75s#%aiG|h}6y7R! z7*9k7QQU(<3J-CH5>4!bZeJ4|Ci3WTA*NW%QEuNNqMs5Oq;mULb*EfgUVtVkPaZ1v zy0uV7TAbmnJMNdU5>lxYy1=Cqv8Kvc=gI1Q`|>hC*$1&?y^4VkLL|` z*7oB^Qb(Jq3`phs@a9%L3(Ie7uLGDRQn%PfaIt0DLxtt{!=Za-Xq&0g)FIujfzHf( zAgAP;=9rYo6kUamE?lb#M8xGqR*9Sblz1(3)L#1+6w2UmBd#}qiGfyqFq_~FE$O@d z`U9tJ8t=l`>&hlNPcfb+Xu(8N^rVy}Wo6D~(XjH#Pvc=Q#Y35CqO!lu*2QpwNN<=j zwA;ZQmjVy#_>Er3SZ?Hjb(Ko?IK(?lsQwfW;$27duuqLfXN?*djs)he5A9EDvk$2Hr<{K6@tnwO`%jF6<`_7w zgL(tWH~00P{^x`Be;-!8YZ%ElOsqT+2`8fQM{wuQ2RMAp2wR?%SlaHJN8~ZdUIj3h zCGr+DYVhZYM$NHCjdSMJ@T#uLoUUI*r8x4QDJ;4jkx+B`QliwPLBP58b`-GYp2ih~ zGP<;1X`wY9&|$9N)f|on8#FkyoQAKBnIm2=e#IPPz#cssHW+Oogo-wmy2}47z5j53 zU>%@C{dx?{k1R_}hsg;q>1xc5cZPugz)zur#*a~{R^pr4<%7eC(12~gyMR5=vR)Dt z`#VSjTk$Pp^v(JRPQ|wlcdd5^&QVnQ(HmlD=wQKEEpILGVi=G-A`eNoC91@)?h(op@bLE=NZ_@HLU(K)7kC z*<9!(Y9g#zky8kk_jQh$qx^AUc!Ov`!Z*C0&V*17^Jx7fiN`~1K1u$PvQR&q5k-S* zT{*!gOh?I!bSSU!ROklsdjQF|WnqA0_e6jwFyjgYz~-RQKJ%|AUp5eF58Y?*0cHE# zm9L>Zc$8cRSW2yMt*ya7P(#HPQ=yEbP+!LKnn=J1V)2`c>lMNo@1N$x_X*!NBL3b@ zvAEG&S-zV8asE=$M_PZy^NeLMx=gnY*2%B8AKw?-b$2Dj=y2((YEH=|Y^0JN?d20W zebnnJJHD<;xk)2U{@mrJP>fAKzSSZ)f0p3Ut6lW#BnB z`Tjt4|C+o%ReV?J@#A>V+vwxAqJJMA0#PGJFE@U^@|3)N-5=lF);QuX-fw6cm=x$A zRPAf3eN7s`xMGe;#dG<1R_RfgM=^#bT!IJ)#sEZiJAJkFe5kmHsMFxEJ}jMAiU7Y zJ}M1hBGdmAd$NjmD&Cz9-er}KK=)eEhZ}+pWr7qd=bv+z=alEGT-JwM&&~$Vl>8#azq6O-LcBgBMdL4(Uq5$za~Ivh=tiM$)ZzS~Dx9I^ z<*VaYrH49x&t?3o{PW}dBjMY!(%jF@*0CvbmvlP5Ich)F@zEe?VYWaS1dZAsKi(fI zeN_6Wc=yxS6V7(LxN4`9czN7F_>$7R&no0CrTo=#epB({D1vT~3X4Y8ZBhNRsrEJr zz$9~IsfIxjxlVIck%v0xs{~&tIHj(XuSCaT9E%A#P(BL*gWqZu771;QOP=sKu z0QSmP&xl800z1Z|!}u&T-h^jLM6E1eBWlC(op^Etm&N@vXZqvDV7W;vvJSanPve>Y{LBQr4%VynWe8QWFChuvQ6AP|m3|aQ{ha9ITxTZ)&l=))RO& zkVtL<8>7MYqc<*0{MF=lyZ3#3cpeRNUZJKyLqwBq3e=>{&MbKCZ+US!ca@~@5wIt( z@p$%-T=J+ygO2J~=v#dJUVKet!|+{3Yy|t zi~x}ogyI`Yp|45t?eeb7H;@nONrc$qbsw~UKk}a-JxG3`{~qG6J)9@;V2S_vyXzi= z=3&rq00K`bugjj#XkWgv{#~7SWX{)NH}Du!(m=7GkhhfeYoB-MqmVyhp;%|EBK_Od z^*z_}-Id>AJS2<<*M!kaFtx^iY90=}7z3`B_~-=8SY$9~3%=3l!~m(p6aK`w#=u`k zo<{!B>!Cj^6url`RcN^fz>#SqJg2q2s?7lR2rD}3gTc(S(G6Oj^0@UP!d!h4 z%x*SjU<5q#nf!#WbZq^S#CO7xIXr{#m$NnpxNnnk;y_obDTBp@mA7C#c*|q^P%3(K zn2_YyLgIn8M1&GwhD|x4c%Ny*&r(slRt}^;e#1+EWdl zYLfTYuZP*?7RQ@ zHHYJ#;EgZGpx{@G-?Vo0(YFVjc)X(TZLvVx2f1qIY@>>WlmQ8k>n{6TIP5->o}T*s zC^J2Q?;nVm@n3Dx7g!(fw#y7yok&)r$z1TC1OILsR;s};)12{yedgsy^Qa-$6>~Yh z+=M6Yx7R$e_f3FuIw6LygN$$7`I+gdv*!E?JfpvQ@;N)@s%hRvl|{h8C^kQaTWqkG zJGQg5$E5K*`)pDM#sk|O4Q1;m9Pv$Nc;pF*6VA8Y>pZs=ccoM^hjD#f6qWtwrjzA~eR6e$^kFFip zM~a8CL2Rr~Y7k?CLm+6kzDA-8OLH%d`AzQHbnrxolO`8HABcE(xjSEab=D@`ud;6YwBLtj^}jRVyE7hRqz@EL${`AuLK>SfBBzB zZAAI%6p1ksBRFa+h89=C^N!NxlD|J^<-Dwd%Oe1Z#=}wwy7YH$zbReA>`j>Tx8gDm zHf4NZfRewjv^=#E(J>>aY`@vM2k{DPhZxAjakTkJdR*0ATKqfgkChqViiabAvPkdq$;^iyUnv5})I~NR1en^;NuhHziN|Umfvn2Ws zF~T}W{`KkiK2ydGPi@*MzA_66tqX}f3fBi3W2V^PTRX<%=sJ;76M2|eJEsw*XCYVV4Ym9zP!|V|g zKYCjW&ZoxlVo6eNsmYS^FTJ2M$E^ao4;&^jfk=EsiGL&uMDF_{ctlsuUa1_7;ZPDZ z=Ui|+Ao}H;)_Cs6#E+&X#*vBiG9)6-lL~(x?eWb%b2*8-`yn+W8fe4D3*H_jzbo@f zd<*BHMSeSjALxvE4ypf;Pq5)A)$`xAv!8_e_Zu-48g(SXo|OOHXQwY0PyFt{i5P~= zmyK(aW>CZQe|!$1!fEw`Q1?wzTG3-e;7xb~}Rk>{(qfz`XJt80_I;sX0C z1uzm3#gHH{0~c8S;l}u#I6L-1A9+S0G6>_onU83L@s=?aOtyftd<0Hb_&yAA1-zEU z@<@DSEP>a-$tQut<7=RfHB;#|FOBSHiZ9$c0Ro?C$m5zpqfUxgKGAg;m<>rnBqyMJ z$&rgv;(@hqy>$2T=t#J4z6N-q{xMh0>{qD38b~wi$EIw$?{3HLXAObLZ)7i6v8~o{ z+GRxiLVfM{pB#RO-MedNJ9~w5>pe#;^9rV5u+q!l=u_TK9xFVof7O30&%M3yd!KQ1 z$Nps`{1LwAhu-|V8&-Y1J4MQ){PuFc1$ike7CkEA5pU5xuwqBb;+$y*lh=N5Suth* z5_LiYJgpt0l;0dh%+q!s;&ESr8YE<*Jc#nyZSw~~aRel5!Dl`~*CzT_CzRc#g&Z>8 zecE*YbDKY01!9Z<2Ep$7)BrgKnjbP`#p(=T-7X7!FNze)B8{!bza;&g0-TrO#3&A@ zLi-IPg@{rEr0iRO^?Se6{<9$gdIlUy+qD(SnB?Uc-rqO; z$@42QiP%4YZjt9%XmYL{hwjG?H&Iq@6?bLDV!KZW&7b7q&Cuk+c-j{5KruHA=ZjIr zZr_rY_}9o|5d3dg{u?$QCk&1mtjxQQ%qRTFK*s1rMyMFuir1uk;1%-H`Iq06G}x&+&dHHAArJ02c?|!T@RPp zw_O1vV_mZYr%8Q)KB^T=Ds)F0Z92m5na@T_cn1q3_(E54`ji)<3VqKUzgGjhZ18=wV1q*)@k7lTDzo5n zdn%Ro!Ic8SuDxdNt#3j1 ztRv}1?&E=#P*SlE&LHu!$V@cc$FdHyj6Mhe=I z5?+E&%kL5H9u)XPjC1Q1M=f&;))>-srfi)!vQrIfq4s6R(U9i{*{ASl&Qk4S%LjuXmw6WY8eO4+wY2Z>|yJ z10#Y_rB?!5d<_SG?Wlh*^!2RWM-ZzxkSFvh~fe97}M||1Rn&K7IlH*_j7+`^7Xs=zc{{pPa*#h zX&e(yVSCE5as5Cr(5T(zdf;xt4=t+;AnCV>|AKEXA$Q^%>@diE>y0ofIfv3uThu(T zx|Yaij{133Z`!K3#bOwKo@!gDG%{YN<{u|hi|p7;Yo(%5)lza_>+lTE|~C z_BBE;zMqrsCBJa|IrMszPsUR7p{Y3Oa2)Z3<$7$-S?LjpNfjZ(xW!xFT}Ika(Ki` zt1oNM9V;RV)7~iVXh;+*j$phEOyeY=i9y>N;j2&g;k;arHt}o&TBWxhoo2#$k z8buWQg!*>zeVwk`aH!Hvm4kC7mX^wcEJzUj^#@MdG|mxvm_+NVc#elbrpa#mD=9)m zLaI3;Egyczz*DmI02ccj`LAX6l=M%cuR;Q`r{Ve<)SYT)fAcLxZp0Z7=Xc>Tq1(x8 zO8nVb`)Y{y`E_wAzr9nTZvu>qj?xomfV>y-gc2p*U3mObwnv$_FSrx!SvXWrjJj;G z^BU>^7#8{%d)SYoD(bYFZxGeuVrdQop?E}$Nd8iCbrDDcGLTz@~cpXq@d~mQzhm7 zG#r10*o(Qkj_}QVCcga-@zj<0=FCj??5Ai}12m44GAPU+2J8~YO>ciGiv1gHL>}ZM z>PWvRc8_WI&|(Unk1|nU3gk5AK@n(yC75}#19KU8E zjq3-W6M2_M*td^(`I_QHUiZzMTxtdIcZTo^zJsf*se8s8ylT&smB;^Y>==ATN*T)j zb59 z!!Kp+nBvTL-v8TBH+l=;Rr-rNyZ!m38y}j7vfIssWU#5}U+wU1 zMX?qw&Kge+l5`XfQzieYdCAx+N(2O4f0W_FC&XUQg|11zc_qCR*A19w&%7VYV2bknXPei!nu)Fwh`3`gR;)l1fA|T+rZAoXd$#3uxBJbzw_tl-PQC-> zYYo~kJG*}J{>GmwHrw%CGHWQO8;$Ky+0o_fDZ5BYqc(nF;O zp@0OMC?9k-KcK&nC@6cEh7Gne{Ecw9wPq2Ku;IqKR|kaNJzLA~J@9E?HVypk{f8NrM@a}kAC1iVgQZz{ea1yp<| z6zF;L+ZDg9(1GU#viS%4;Ua@&{89}BR)o5f<5hf9@lC}y72kR+zH9LOeSnOFQJ}W}Ik% zbnl~Ho7ek@w^^l^oL(wDI+q^Q{%I^rv;}VXdZ^Np{qzFKN{MZMex}7==q{X*rKIc+ zyL6ttWt$M%70yGJS;L*?Z#h>9&*Jlhc~rUM0V%`OY2BolQ?y z@jNh}K>re$xSR1je6aB#ItOWL90;_gz^ikWmeJ@xKukh+BP{00dBo$x;P`{Nc+7Ca z`t{2CxUGM{qt@g!snED_$&x5MkBH~1C4U0=20V}G%7x-cv4op4>Z=dG!c+Ik>v+B& zpO(&a#RRlt-LC6EL!GAB;pr1U!t%)b1xr?yDB=&7n@jR{i+Zt|u7403W5BU>F~HGN z`2L-u_;M6Xd}td)g}e=;-#v|V{`VLff})^tGrV~W{c|*;w^{;S3{UfI{!D{-ih4HM zT-?Nef`o7A=9Sm@mF+F`O%(>hhEI%5whXdypfJB5#DhtUIV>6v+29kz+W>wYO00^H zO8Tk!?u`#Uy?@%BmtJ-d@u3ch-gpT*_??INM)DH=0l~M#dq5aja<`p+Y*$^=&JN?% z;`sLrgq$X0b4;;GpulM-8km^;vck8DMGIu07c#egGWwQhdWiV4M59 z-zf|*AHqRHHXkbt5#~t#Do)toO%Z);qe$uWEoP45HJj{8Ux!A}zbFda{=DcpT~-~(Mj zB+S0QR*cLKx=K+#gIGj2OoB#-{v*&4WJo_1-kkuhcf5WU01wf#T#k^yDch^eyNiAo zIFL+g!hNs5edL^9rAAKmK#y9vrV6Dz3yE0D>zClu*9F;@8Jo8 zPX_>gO-3{W|BMOybFHrbjC@7>TciIS)IevCCfV=IF5kh%#zx#@)UX`BsA+KP|3&=h zp=KzMd2)_>Cc4^5ZlFx2csjD&Ioo`u|GIZe9w_upggzU!5G>n{(Fa6v@G~qs=;$PW zB(Hz2980mkgI?cJ{yHw!q1s5-DCJcwk8i~v9{ty0{ZEdA?_!`n7DS96^UdslZU)3h zB;>>VXjrP`S2xDr0e%x@$`-J?+ll`qFc{!a-FK+-v!w@>_pA8}%kO7PfBVsS5_dNY zgp8p>ZMIf?yE+;BofpowJoWzb+y9PzL{vi;*>rReqEX(;yxoIt#|Bd@`oAsHCb$xB z31q^-3FrZio1W8fCDB*Wo)*G4)K@1?-3I@O$0A5#Vq4?!1g}K_9*?z1^3l=wkbDF% z4gGBj(!HTy)9l1wouMJ=1bQomxokWChwdYu+&C zm)1|gd?~VNaOvh7e~tU!Saj?vrN3`f@`IW`zxdS=y&WTd?m>9sU}V$B+E0U&b9XK@ zlo%VW5gC{BS3>aPbq}y~)B(QaL?jATycY4PRo^21r|nwFp0&H>5OOKwa4?#fKHFr1&tAsv+#{SAsUYC~Zxh2Q9u_}kr zy4G$XoOXyH80wGXo#olkL>aED9E>uh2}~%zN&XsxNykxsdtws7bI+9&B<SKBc0)}?0P zh`BfcXF+~;N6)L*FKmAkeTx(#nc z-5668{G}bfDft8CGvGL^GDdL005@Pi@&wj5AuJzivg1-<#6cq|F8JJ`akr8BolJ@% z2c${b=tg~1`b+vX2plsX<_fN)c>WsvA~I-1dl}nyy*)lT-sFpHV<#jcGVfp=R>F=stM5b;UzTiQ(!I^V=cFXyC?Hpjr?r5iPoNf8){XL5x z)c#WYi%=kh?>+B4mXd!bz7sxQKPr*tE8d*g>OTaP8UF7NDDPMED*yK;{#W_Ack}Z{ zYwM)*^<>cqwVdOQtq!z3$HEj^3~H-`k!t_7t0Vs2@!d^vL~z61AO$+0U2X9f{6nDX)Q*mx zSFfw%=VBf|D*tzH{-3y@CElq4)l@30;iIYZqJaMtWjFwicaK#2uY32O+COUlsPjwP zddO#))jBBEz|uDm!piJ3R&{) z$4LN4IZJ5uJBmCEU-^#6kRM(!^!z0~3^$y>#i zpL0BP`TJCPPo>A%@vllRm0pAbKQzDM`X~cs=p2hng`Aq~X>xvPk8f@gFHnGhVK&%= z1GQhu?^p3jrH4A+er&v{{BeHy1N|e!f*#Mfc%mT!<}2)L?eQ%nzv*CwmLE?}=cxU4 ze*3FN1DEak2l{epNt-ly_#DJ)ZA(7>oB941BQTTJ_uu3zJWq)WMeKx@%W8j}qdfuX zIRMJS=dsa$<~Q@<4kUiYJ#{)lLmP_L$7r(eW z`?($WJ@R-gY_u#pl|JEWvAOYBHU5eYKc6V2HvS3c_duc9jUOCil{XEIxWQ@N#tzmB zkY>$X%`XE#j#n(7oh1bn!WV_h!#^>#m3Oh^o%-YGU@2M4Xlbd*&aIzePY6_+H8pi| zt`VG6_N7_)!Tjn~6&3x$^a|5knRino*c|-8vHHf-bDlYX^U>9K_ILX5>C@TAB4JgC z{_eX&XS`MVhw1mf@|&wNoxx+%0GDcuz0F>)9sQA$l=|{%EsPvhafhCh*d_e)B`) zCtUvjdL7T>|2!mtos@@0^v3f%lYXH)LN8I0=A*%GPD! zhY%lA(z(*Nqv!2f9m?M+i}NhLl*P=|J_+yG9e2Z)7|6q66@H$u!^Jq?oNfCZzS$_R zjYI!n=tir_sK6s7Jv+|ZYo{~t8G6&gwbj@Ib*Im^J{Q~ldx{Y>1}EP+Si5&eEYb|| zEF%j)E$rLncowGj585qwF|)^zxlwWjD0o-5LX|lByVfUdr@9`3~Dd@FW_Y zo^K{?aB2HxL0M_8#q7&Vv6M%J+xJ8C>FVo+R3EHg2wX+mNzq-j0zCe~S}*Om0^I3Kdd4FyXqpQmHX+xgpB|3sj4w);(`UxGi|3Y7v=wDX)zQvq4HpTI5DT)8Z z2M(grr9)}I`_n&6zYz7ioti7TI7YrcFV0P1GqO@>GMN)66S~Qdfi#{I5$}9!SxGj1(a)dh3k91`1fqz*Ft~u zbq6z3v|N18r@!x+5dEzstDp(~aJKa5ZTGwKX$o@CKo(q7jN5U&7GiJPyK#F<`b6H| zj`2)+zdcTmRss!w4;th+4h+N|H|HX@#|?g^#KWVYR@@JWI??U)&v5_!ulVV(E&*;5 z>aT!69$a)9o|3t@c;^VX?gZ zN_w1o-ky1D9E{a^KF1Rdu(@8L|DJz-m$$d;-ygEq)8cXv$APGC<+mT=*KqxM>UDR1 z30jAE9805lO+d*%T~F^Y{jdU<(EdW!OC-vRG+BQRU+<~(?Wq3P-tF+_dMH>A+` zN3x&$;J&x2_CatRy^9jJBBB6};ccc{Ohb$}QMXdX>9g8Y45k3U`gK8$ZXQuq}E89xI^ zk7%P`XN@O2^-$I{{7C(emQJU&iA~N<*1<6QA?VxweRk@Zti|{V-|x`={2>94=hfW< zEH0dPI{ww@-$`R9M_Pdjyg)_wR1_lMc_ zDVv;}ymA=Er-MLSe6jzvd}aL{Pdx=345r~WTry_c$I}VlFVzS2`JR@?{T~=nC=R|& z;*7yv=f3|#-u|}n5u#7WdDqrt99BGlMT7e4j2wA+J&(T1`lJ6(6jhUJID~M%VRNVJ zLw3rU<-ku1y=i-GJ!{RjW=T67HrJi97p=hYVhu$s&0xT;_u=)H{SP}cX*cGRf0m8c zbso^MosMr|dW6R(;thcr9-$rucu~S>ro;{%o%!{qyim4Jg#UjP!pc{5*b#sppS3S6n88 zTR(u|Pf;{vaPszbj7Ob)zr)&}g7<}zKZ-bo_jhDOm_mjKZWY@ z@nx^{x8WI>4ED-@5j-OX0e}Nyo!z&j?Rw5JuS}jp+zIz@7>_zTkMzLvN5ErfX%CLC z!{PF!`gOth3eg`=3*w4yF1|GUzRqf&J@Gp>+1X^9$9&fh=22kZI_aB~Yq$R5jfbx} z{UpvO%Jo%=H+(k-mKr?Cq$3V?~fMx ze}bf_1K_H|_3JA7cXj!Dg7f?F?}9*q2cl?>lE1I5zgy_p+8-AxZ(oMzSBqgRAQqT< z!TKul(`ey&+(h~n4ckYY2YgfLpZ3Zp+3YaB0b{psUD<|rqm5sL`JuDMdq?F-`%zI{ z#KX+QEYXUmT{XTW`VT_O=MaGHi1HoP?`*H5ey_oRB%1-e1`s2`;d{pOz3mI!0aUlS zDZ{v3sejt1F7&^2S_qMJtb`}52+tc~|JF!JS z-H5_U!k_C~?HOH#CrbSj^C`*J>}(S6ozM74B>HNrJh!vHQK`R%>Csj7YuSHBED}20 zkQE5OudDiZ;zRR~$D0-ZoH|2Yz_V8egx8?xBKXOoYTU|Asa|7_Ce^!Rj z4TZ|F--O%WRrFSt@Al2}4@OxQ=NDe%haP7SvfqgNb;p9|!>Ko2_e)GJ>%)j|9Bw~C zi4^C}aC=FHr0$k)^#@#Fll%cE=Rb<|*F%mjC3V%C6+Lc!8|TZBum{~6LzxvOxA|}H zEPi&kt}h7E86$@)lTEf}WLx8lYj9ZEl=`Pqe7!ihR8YCp#T~H(K_MywCVn zWYce6dF`!#|K=5>2l`_oNdue~{Br*5{P{(qe**BEpp1q?ZT#L@^bglRT%OCigHIdX zV&BAZNAL}W3$AhVo1zyzOmwyWsjQDO?}}T2%L?2^+^++$DM5h;olpPp`=u`L1p9+S zpBR?cjN;zzFR#hl-^PC-dZ5=Hvi=~Te{?TDNLXImUw(fN=nvdaiZjbNfMakz_LH{Z zokYP^VS0tfpE9qwKUR7DT=Q=IQ-Vc{nviMq!f{{JoeG!NS^VBnd5CXhB@zVu;J`-z zQ4-$%ah5ZLx8di1h(102x^jL&T(b~*kmLslhTA87(Fyp|+2xV*PVY(f_+}yoiw?4% z?Mk%OXAlF2aj*P+?eU|#U&r%Z7>|(RQ}IX>PKSnxx4vYCWYQb9SdIy{${XFae^4Jo z>yMN?#0r{8-I(xm{E%s@xZjN5XIQg?*>8CJg2#`<^<}@MMxb~c zB5;O3o8C?Tg#Ayyu_JT;?CJ|n|1iHxBjP9Esk;*KOn?C68T|+2=gRr9=i!;W{q5@? z@<$Q@EAHU87})aG{h2?NUh?wKzx?OOFM)ut5w(Ng7xevQ!SBQM>D}WCJ)ZL0;S*!o z1s`8d>oXwW`Pei_NnAx&bm;%Hr}s~2evwGe{oAnig3~`t&!0M8-Ib9} zX6V3B05J;tVEgeef4=u!m-JO)OMzWzFx8Rxs}wXelMT$%ruKmNt4`lD;P+d!>F_W$ zIii9N_g7CDU#|T5VSk(j#J^TpULf$zMZw>~?FsX5cgs5~{Sy5dxB@D)eLOOM$p_lz z$L`u6vihP4-g)FX@Z*XO+N{?kJPu{ujo!-o*hk=g*LA>a6DTe+<6DJ2z4zgjy!~h2 zKDRGEq_0oolRU;?oV>g?e(f&fO?Lhp58#&9?^D&DPEWU7k!|myA zd9oe~XRL?1i*SDgt`}Beg$*2)BCqe+kN@8OyhJ}hfli8t^X|*8+Ub;_%{`q@_(X+UuSk9tG3?MNgl8@AT=@!_QwR`jh&A=TYvl>2G0e zrccNHFX8ohQsuef`i1J>{rKC}kVkoN_jBM<)=ULww9>PM-mUgfH6NmYyg%FHy}Obn z>k*!)Y`%|QyG7f!pQdNT^J>%g5Jx=yA(X#_^3+{*_5Pwix2}hE)_BA9fdN_gVTYwk z>jTcpDq#}JlX&3Z!zl;$?(c1QCg-2_c;KXf4UaW)4k$$bc<}rYuHJvwpLcZjemacr zI3j(5?)vb4Xt#Aeo;TpJ3N-x)?vLncc;@io`Estm7^h=j+>Yb z3fNPmv>N8TUF`m$pk z4H!RlaI%)exBw#|%Y|Ncv45og;7v0wbo`!-b-h3qPwM>R`R?(*M!egFXH_^d&x~lZfA$RhRmF?mjTha$e^->fhVD~H;(j3n zd5mwVL)UT~>I^pWrAc1@^FO}T_n$dFa6cMZe?`v#u*5)2H{%w`%*&?0>a? zJK_f^-X2*1W%zCu;&YjDz z0E_vJy!!?#<5#HTTi*XFJ$gDlK4vg}@f7$4TGYz4jkT&h?E>4=}RJ5O=y&0}BZT_;R zLDE-PTp5t`m6yMk_m_%47dt(ac$d8URRaj|z*C^br~^HIf4{tcRlM$L^l%b9OThCy z#U=hgMfqY0&rlsv@eFBzN#37oz9V|H>a)Z@JnFNKtqG{#5_xZUu)kQR%6Bq*hKiSR zemZ-45WEV-p9}4;&92N~bQ2K1P^<7<+va~hG@8}%E2p7WVirxrWWAIMR%q9~7LR{0(pwAnH{H%_DdH?i&dbo?;Mn1qFp^}`r z1DAd@>H|E$r6eo3<@8X;uS$3f- z+WcXXJ9aXCNse!Nn)m*|)L8T-v#Ytf@Y0$c;fOF;A4G;ip9I*$%G$oX{je1M#O z-EaJ=^*cL!mD_{S{}b7dM*$xR{9bK(`PVMjr+8il5C8drn>x!jO-|p74==iV`$PSA z$C$sEeR(OC^3pbctpIV0-c`h3R>!ZrKUI2MZ1iYd&nU+Ic&O9v-1qeW$)g!}DS8v= z1989n6!jTQaTGeZQ1XY0e{y~~cY3(>$&3z8H@y%M|^7ZMM+JX zuUPC4bw38-N`?JJ&CB^wrAJ5fXv4oD$W5FktpB3*W_Kc+yUG<8$MB~p(DTclDZa() zm6vz!XgC9D2vw##ULyXEKHD}yPsXW*b>x=9@cAl! zot=In=MQx}tMuqv{vr4ml5KC2yayy=q>iPuGr5mA>bfzLLD+!I9r`UYFX2=NI8c{Kw%>W0qs9 zUJu{K;}*ar#rh>do5r<*;GqY>BC_v8Swrlu-6YR@0gm2eH?_mZ#W{Ovygs!r{-U3^ zgE@2M0N~%l-0Wo9PfgK;o@cSV+&(uwy<_*T2^4>txWx9Dyak@A#J)9N!fSj4j#jJu Maen!ur_uZW0iJQSI{*Lx -- 2.17.1