#include "Menu.h" #include "Constant.h" #include "DatabaseManager.h" #include "Log.h" #include "ui_Menu.h" #include #include #include #include #define CONTENT_ROW 6 // 列表行 #define CONTENT_COLUMN 6 // 列表列 #define CONTENT_CELL_HEIGHT 56 // 单元格高度 Menu::Menu(QWidget* parent) : QWidget(parent) , FocusWindow() , ui(new Ui::Menu) { ui->setupUi(this); setAttribute(Qt::WA_WState_WindowOpacitySet); setWindowFlags(windowFlags() | Qt::FramelessWindowHint); setWindowOpacity(0.5); setFixedSize(800, 600); ui->stackedWidget->setCurrentIndex(0); ui->btnChannelSetting->setFocus(); QDesktopWidget* deskdop = QApplication::desktop(); QWidget::move((deskdop->width() - this->width()) / 2, (deskdop->height() - this->height()) / 2); ui->cmbYear->setView(new QListView()); ui->cmbMonth->setView(new QListView()); ui->cmbDay->setView(new QListView()); // 默认设置当前操作选择主通道 curSelectChannel = DatabaseManager::MainChannel; curPlayChannel = DatabaseManager::MainChannel; db = DatabaseManager::getInstace(); if (!db->open()) return; // 设置ScrollArea为栅格布局 QGridLayout* layout = new QGridLayout(ui->scrollArea); ui->scrollAreaWidgetContents->setLayout(layout); connect(ui->cmbYear, &QComboBox::currentTextChanged, [=](QString text) { renderComboBoxMonth(); }); connect(ui->cmbMonth, &QComboBox::currentTextChanged, [=](QString text) { renderComboBoxDay(); }); } Menu::~Menu() { delete ui; } /** * @brief 重写菜单show方法 */ void Menu::show() { QWidget::show(); renderComboBoxYear(); getContents(); } /** * @brief 设置是否显示通道选择 * @param visible */ void Menu::setChannelSelectVisible(bool visible) { channelSelectVisible = visible; ui->widget_chnSelect->setVisible(visible); } /** * @brief 渲染年份 */ void Menu::renderComboBoxYear() { QStringList years = db->getAllYears(curSelectChannel); ui->cmbYear->clear(); for (auto& str : years) { ui->cmbYear->addItem(str); } ui->cmbYear->setCurrentIndex(0); } /** * @brief 渲染月份 */ void Menu::renderComboBoxMonth() { QString year = ui->cmbYear->currentText(); if (year.isEmpty()) { return; } QStringList months = db->getAllMonths(curSelectChannel, year); ui->cmbMonth->clear(); for (auto& str : months) { ui->cmbMonth->addItem(str); } ui->cmbMonth->setCurrentIndex(0); } /** * @brief 渲染天数 */ void Menu::renderComboBoxDay() { QString year = ui->cmbYear->currentText(); QString month = ui->cmbMonth->currentText(); if (year.isEmpty() || year.isEmpty()) { return; } QStringList days = db->getAllDays(curSelectChannel, year, month); ui->cmbDay->clear(); for (auto& str : days) { ui->cmbDay->addItem(str); } ui->cmbDay->setCurrentIndex(0); } /** * @brief 获取数据 */ void Menu::getContents() { QVariantMap params; params["channel"] = curSelectChannel; params["year"] = ui->cmbYear->currentText(); params["month"] = ui->cmbMonth->currentText(); params["day"] = ui->cmbDay->currentText(); contentList = db->get(params); renderContents(); } /** * @brief 将视频名称列表渲染成一堆按钮放到ScrollArea中,6*6 */ void Menu::renderContents() { QGridLayout* layout = qobject_cast(ui->scrollAreaWidgetContents->layout()); // 清除原来的控件防止内存泄漏 QList widgets = ui->scrollAreaWidgetContents->findChildren(); for (QWidget* w : widgets) { delete w; } // 重新生成若干个按钮 for (int i = 0; i < contentList.length(); i++) { // 文件名格式: hhmmss,只将时分秒显示到界面上 DatabaseManager::File file = contentList.at(i); QString text = QString("%1:%2:%3").arg(file.time.mid(0, 2)).arg(file.time.mid(2, 2)).arg(file.time.mid(4, 2)); QPushButton* btn = new QPushButton(text, ui->scrollArea); btn->setProperty("name", file.filename); btn->setMinimumHeight(CONTENT_CELL_HEIGHT); btn->setStyleSheet("QPushButton{border-radius: 5px;}"); btn->setCheckable(true); btn->setAutoExclusive(true); btn->setObjectName(QString("btn_video_%1").arg(i)); if (file.filename == curPlayFilename) { btn->setChecked(true); btn->setFocus(); } int row = i / CONTENT_COLUMN; int column = i % CONTENT_COLUMN; layout->addWidget(btn, row, column); } // 少于36个用空的widget占位置 if (contentList.length() < CONTENT_ROW * CONTENT_COLUMN) { int lastRow = (contentList.length() - 1) / CONTENT_COLUMN; int lastColum = (contentList.length() - 1) % CONTENT_COLUMN; for (int i = lastRow; i < CONTENT_ROW; i++) { for (int j = 0; j < CONTENT_COLUMN; j++) { if (i == lastRow && j <= lastColum) { continue; } QWidget* widget = new QWidget(ui->scrollArea); widget->setMinimumHeight(CONTENT_CELL_HEIGHT); layout->addWidget(widget, i, j); } } } } /** * @brief 移动 * @param direction */ void Menu::move(Direction direction) { QWidget* focusWidget = QApplication::focusWidget(); // 当前焦点是否在展开后的ComboBox上 bool isCmbPopup = (strcmp(focusWidget->metaObject()->className(), "QListView") == 0); // 下拉框展开,则只进行上下选择 if (isCmbPopup) { // 随便赋值一个不影响功能的按键 Qt::Key key = Qt::Key_Right; if (direction == Up) { key == Qt::Key_Up; } else if (direction == Down) { key == Qt::Key_Down; } QKeyEvent pressEvent(QEvent::KeyPress, key, Qt::NoModifier); QApplication::sendEvent(focusWidget, &pressEvent); QKeyEvent releaseEvent(QEvent::KeyRelease, key, Qt::NoModifier); QApplication::sendEvent(focusWidget, &releaseEvent); } else { focusNext(direction); focusWidget = QApplication::focusWidget(); int drawedHeight = focusWidget->visibleRegion().boundingRect().height(); int height = focusWidget->height(); // 绘制的高度小于实际高度,则表示控件显示不完全 if (drawedHeight < height) { ui->scrollArea->ensureWidgetVisible(focusWidget); } if (focusWidget == ui->btnChannelSetting) { ui->btnChannelSetting->setChecked(true); ui->stackedWidget->setCurrentIndex(0); } else if (focusWidget == ui->btnPlayback) { ui->btnPlayback->setChecked(true); ui->stackedWidget->setCurrentIndex(1); } } } /** * @brief 确认 */ void Menu::confirm() { int index = ui->stackedWidget->currentIndex(); QWidget* focusWidget = QApplication::focusWidget(); switch (index) { // 通道设置界面 case 0: { QPushButton* btn = qobject_cast(focusWidget); btn->setChecked(true); if (btn == ui->btn_hdmi_1) { emit btnHdmi1Checked(); } else if (btn == ui->btn_hdmi_2) { emit btnHdmi2Checked(); } else if (btn == ui->btn_vga_1) { emit btnVga1Checked(); } else if (btn == ui->btn_vga_2) { emit btnVga2Checked(); } break; } // 回放界面 case 1: { // 通道选择时按下确认 if (focusWidget == ui->btn_channel_1 || focusWidget == ui->btn_channel_2) { QPushButton* btn = qobject_cast(focusWidget); btn->setChecked(true); if (btn == ui->btn_channel_1) { curSelectChannel = DatabaseManager::MainChannel; } else { curSelectChannel = DatabaseManager::SecondaryChannel; } renderComboBoxYear(); } // 下拉框未展开时按下确认 else if (strcmp(focusWidget->metaObject()->className(), "QComboBox") == 0) { QComboBox* cmb = qobject_cast(focusWidget); cmb->showPopup(); } // 下拉框展开时按下确认 else if (strcmp(focusWidget->metaObject()->className(), "QListView") == 0) { // QComboBox的层级 // QComboBox // |- QComboBoxPrivateContainer(Popup widget) // |- QListView(or QListWidget) // |-QViewPort(Child of QListView) QComboBox* cmb = static_cast(focusWidget->parent()->parent()); if (cmb) { cmb->hidePopup(); } } // 选择视频时按下确认 else if (focusWidget->objectName().contains("btn_video")) { QPushButton* btn = qobject_cast(focusWidget); btn->setChecked(true); QString filename = btn->property("name").toString(); emit btnVideoClicked(filename); // 记录当前正在回放的通道和文件名 curPlayFilename = filename; curPlayChannel = curSelectChannel; } // 确认按钮按下确认 else if (focusWidget->objectName() == "btn_done") { getContents(); } break; } default: break; } } /** * @brief 点击查找当前列表中的上一个视频和下一个视频 */ void Menu::clickPreOrNext(QString type) { // 重新获取当前正在回放通道的视频 QVariantMap params; params["channel"] = curPlayChannel; params["year"] = ui->cmbYear->currentText(); params["month"] = ui->cmbMonth->currentText(); params["day"] = ui->cmbDay->currentText(); QList list = db->get(params); // 搜索当前播放视频的位置 int index = -1; for (int i = 0; i < list.length(); i++) { DatabaseManager::File file = list[i]; if (file.filename == curPlayFilename) { index = i; break; } } Log::info("find file filename: {}, index: {}", curPlayFilename.toStdString(), index); // 查找目标文件名 QString filename; if (type == "previous") { // 已经是第一个视频了 if (index == 0) { emit btnVideoClicked("first"); return; } index -= 1; } else { // 已经是最后一个视频 if (index == list.length() - 1) { emit btnVideoClicked("last"); return; } index += 1; } filename = list[index].filename; Log::info("type: {}, index: {}, filename", type.toStdString(), index, filename.toStdString()); emit btnVideoClicked(filename); curPlayFilename = filename; // 单通道回放 if (channelSelectVisible) { // 选中通道和回放通道不是同一个时不处理 if (curPlayChannel != curSelectChannel) { return; } } // 双通道同时回放 else { if (curPlayChannel != DatabaseManager::MainChannel) { return; } } // 选中要播放的按钮 QList btns = ui->scrollArea->findChildren(); for (QPushButton* btn : btns) { if (btn->property("name").toString() == filename) { btn->setChecked(true); btn->setFocus(); } } } /** * @brief 遍历当前窗体可以获取焦点的所有控件 */ QList Menu::getAllFocusabelWidget() { QList list = findChildren(); QList result; for (int i = 0; i < list.length(); i++) { QWidget* w = list.at(i); if (w->focusPolicy() == Qt::NoFocus || !w->isVisible()) continue; else { result.push_back(w); } } return result; } /** * @brief 录制完毕一个视频 * @param channelName */ void Menu::onAppendOneVideo(QString channelName) { // 单通道 if (channelSelectVisible) { // 只有生成新视频的通道和当前选择的通道一致时重新获取文件列表 if ((channelName == Constant::MainChannel && curSelectChannel == DatabaseManager::MainChannel) || (channelName == Constant::SecondaryChannel && curSelectChannel == DatabaseManager::SecondaryChannel)) { renderContents(); } } // 双通道 else { if (channelName == Constant::MainChannel) { renderContents(); } } } /** * @brief 获取当前正在回放的通道 * @return */ DatabaseManager::Channel Menu::getCurPlayChannel() { return curSelectChannel; }