// // Created by Krad on 2021/12/16. // #include "RollingMessageWidget.h" #include #include #include #include namespace { const int WAIT_TIMES = 60; const int LABEL_MARGIN_TOP = 2; const int LABEL_MARGIN_LEFT = 5; const int LABEL_FONT_WIDTH = 16; const int MOVING_STEP = 2; } RollingMessageWidget::RollingMessageWidget(QWidget *parent) : QWidget(parent) , mCurrentLabel(new QLabel(this)) , mNextLabel(new QLabel(this)) { this->setFixedHeight(36); this->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Preferred); } RollingMessageWidget::~RollingMessageWidget() { if (mTimerId >= 0) killTimer(mTimerId); } void RollingMessageWidget::timerEvent(QTimerEvent *e) { if (!this->isVisible()) return; //滚动 if (mRolling) { //end rolling, reset next if (mRolledDistance == TOTAL_ROLL_DISTANCE){ mWaitStep = 0; mRolling = false; QPoint p3 = {TOTAL_ROLL_DISTANCE + LABEL_MARGIN_LEFT, LABEL_MARGIN_TOP}; mCurrentLabel->move(p3); std::swap(mCurrentLabel, mNextLabel); return; } //rolling mRolledDistance += 2; QPoint p1 = {TOTAL_ROLL_DISTANCE + LABEL_MARGIN_LEFT - mRolledDistance, LABEL_MARGIN_TOP}; mNextLabel->move(p1); if (p1.x() - mCurrentLabel->geometry().x() <= mCurrentLabel->width() + 20) { QPoint p2 = {mCurrentLabel->geometry().x() - MOVING_STEP, LABEL_MARGIN_TOP}; mCurrentLabel->move(p2); } return ; } else{ //有等待的高优先级消息时,不停顿 if (mWaitStep == WAIT_TIMES || (mWaitPriorityCount > 0 && mWaitStep == WAIT_TIMES / 3)){ mLocker.lock(); mNextLabel->setText(getNextMessage()); mNextLabel->setFixedWidth(mNextLabel->text().length() * LABEL_FONT_WIDTH); mLocker.unlock(); } else{ mWaitStep++; } } } void RollingMessageWidget::setMessageList(const QStringList &message) { //empty, don't set if (message.isEmpty()) return; mMessages.clear(); // set default label mCurrentLabel->setText(message[0]); mMessages.push_back({0, message[0], 0}); //add list if (message.length()>0) { for (int k = 1; k < message.length(); ++k) { mMessages.push_front({k, message[k], -1}); } } } void RollingMessageWidget::updateMessagePriority(int innerIndex, int priority) { //lock thread mLocker.lock(); //高优先级,需要插入 if (priority > 0) { int idx = -1, insertIdx = -1; for (int i = 0; i < mMessages.length(); ++i) { if (mMessages[i].innerId == innerIndex) { mMessages[i].priority = priority; idx = i; } else if (insertIdx < 0 && mMessages[i].priority < 1) { insertIdx = i; } if (idx>=0 && insertIdx >= 0) break; } insertIdx = insertIdx == -1 ? 0 : insertIdx; //move if(insertIdx < idx)mMessages.move(idx, insertIdx); mWaitPriorityCount++; } // 低优先级,更新状态即可 else{ for (WarnMessage & message : mMessages) { if (message.innerId == innerIndex) { message.priority = -1; break; } } } mLocker.unlock(); } QString RollingMessageWidget::getNextMessage() { QString ret = "No message"; int retryCount = 0; bool priorityFlag = false; while (retryCount < mMessages.length()){ mMessages.move(0, mMessages.length() - 1); retryCount++; if(mMessages.last().priority >= 0) { priorityFlag = mMessages.last().priority > 0; ret = mMessages.last().msg; mMessages.last().priority = 0; break; } } if (priorityFlag && mWaitPriorityCount > 0) mWaitPriorityCount--; mRolledDistance = 0; mRolling = true; mWaitStep = 0; return ret; } void RollingMessageWidget::showEvent(QShowEvent *event) { QWidget::showEvent(event); if (!mInitFlag) { TOTAL_ROLL_DISTANCE = this->width(); QPoint p1 = {LABEL_MARGIN_LEFT,LABEL_MARGIN_TOP}; mCurrentLabel->setFixedHeight(30); mCurrentLabel->show(); mCurrentLabel->move(p1); mCurrentLabel->setText(tr("Message of warn!")); mCurrentLabel->setFixedWidth(mCurrentLabel->text().length() * LABEL_FONT_WIDTH); QPoint p2 = {TOTAL_ROLL_DISTANCE + LABEL_MARGIN_LEFT, LABEL_MARGIN_TOP}; mNextLabel->setFixedHeight(30); mNextLabel->show(); mNextLabel->move(p2); mNextLabel->setText(tr("Message2 of warn!")); mNextLabel->setFixedWidth(mNextLabel->text().length() * LABEL_FONT_WIDTH); mTimerId = startTimer(40); mInitFlag = true; } }