播放器浮动控制窗绘制正常了。

pull/175/head^2
Apex Liu 2019-09-09 03:30:31 +08:00
parent f17c1cf59a
commit 00c79c47e2
11 changed files with 776 additions and 155 deletions

View File

@ -1,57 +1,551 @@
#include "bar.h"
#include <QPainter>
#include <QDebug>
#define FONT_SIZE_DEFAULT 12
#define TIME_STR_PIXEL_SIZE 16
#define TEXT_COLOR QColor(255,255,255,153)
typedef struct RES_MAP {
RES_ID id;
const char* name;
}RES_MAP;
static RES_MAP img_res[res__max] = {
{res_bg_left, "bg-left"},
{res_bg_mid, "bg-mid"},
{res_bg_right, "bg-right"},
{res_bs_left, "btn-left"},
{res_bs_mid, "btn-mid"},
{res_bs_right, "btn-right"},
{res_bsh_left, "btnsel-left"},
{res_bsh_mid, "btnsel-mid"},
{res_bsh_right, "btnsel-right"},
{res_pbh_left, "prgbarh-left"},
{res_pbh_mid, "prgbarh-mid"},
{res_pb_mid, "prgbar-mid"},
{res_pb_right, "prgbar-right"},
// {res_pp, "prgpt"},
// {res_pph, "prgpt-hover"},
{res_cb, "select"},
{res_cbh, "selected"},
// {res_play, "play"},
// {res_play_hover, "play-hover"},
// {res_pause, "pause"},
// {res_pause_hover, "pause-hover"}
};
typedef struct SPEED_MAP {
int id;
const char* title;
}SPEED_MAP;
static SPEED_MAP speed[speed_count] = {
{speed_1x, "1x"},
{speed_2x, "2x"},
{speed_4x, "4x"},
{speed_8x, "8x"},
{speed_16x, "16x"}
};
static inline int min(int a, int b){
return a < b ? a : b;
}
static inline int max(int a, int b){
return a > b ? a : b;
}
Bar::Bar() {
m_img_ready = false;
m_width = 0;
m_height = 0;
m_str_total_time = "00:00";
m_str_passed_time = "00:00";
m_str_passed_time_last_draw = "--:--";
m_percent = 0;
m_percent_last_draw = -1;
m_play_hover = false;
m_playing = true; // 0=play, 2=pause
m_speed_selected = speed_1x;
m_speed_hover = speed_count; // speed_count=no-hover
m_skip_selected = true;
}
Bar::~Bar() {
}
bool Bar::init(QWidget* owner, int width) {
bool Bar::init(QWidget* owner) {
m_owner = owner;
// 加载所需的图像资源
if(!m_bg_left.load(":/tp-player/res/bar/bg-left.png")
|| !m_bg_mid.load(":/tp-player/res/bar/bg-mid.png")
|| !m_bg_right.load(":/tp-player/res/bar/bg-right.png")
|| !m_btn_left.load(":/tp-player/res/bar/btn-left.png")
|| !m_btn_mid.load(":/tp-player/res/bar/btn-mid.png")
|| !m_btn_right.load(":/tp-player/res/bar/btn-right.png")
|| !m_btnsel_left.load(":/tp-player/res/bar/btnsel-left.png")
|| !m_btnsel_mid.load(":/tp-player/res/bar/btnsel-mid.png")
|| !m_btnsel_right.load(":/tp-player/res/bar/btnsel-right.png")
|| !m_prgbarh_left.load(":/tp-player/res/bar/prgbarh-left.png")
|| !m_prgbarh_mid.load(":/tp-player/res/bar/prgbarh-mid.png")
|| !m_prgbar_left.load(":/tp-player/res/bar/prgbar-left.png")
|| !m_prgbar_mid.load(":/tp-player/res/bar/prgbar-mid.png")
|| !m_prgbar_right.load(":/tp-player/res/bar/prgbar-right.png")
|| !m_prgpt.load(":/tp-player/res/bar/prgpt.png")
|| !m_prgpt_hover.load(":/tp-player/res/bar/prgpt-hover.png")
|| !m_select.load(":/tp-player/res/bar/select.png")
|| !m_selected.load(":/tp-player/res/bar/selected.png")
|| !m_play.load(":/tp-player/res/bar/play.png")
|| !m_play_hover.load(":/tp-player/res/bar/play-hover.png")
)
int i = 0;
for(i = 0; i < res__max; ++i) {
QString name;
name.sprintf(":/tp-player/res/bar/%s.png", img_res[i].name);
if(!m_res[i].load(name))
return false;
}
// 无需合成的图像
if(!m_img_btn_play[play_running][widget_normal].load(":/tp-player/res/bar/play.png")
|| !m_img_btn_play[play_running][widget_hover].load(":/tp-player/res/bar/play-hover.png")
|| !m_img_btn_play[play_paused][widget_normal].load(":/tp-player/res/bar/pause.png")
|| !m_img_btn_play[play_paused][widget_hover].load(":/tp-player/res/bar/pause-hover.png")
|| !m_img_progress_pointer[widget_normal].load(":/tp-player/res/bar/prgpt.png")
|| !m_img_progress_pointer[widget_hover].load(":/tp-player/res/bar/prgpt-hover.png")
) {
return false;
}
// 创建背景图像
m_bg = QPixmap(width, m_bg_left.height());
m_bg.fill(Qt::transparent);//用透明色填充
QPainter pp(&m_bg);
pp.drawPixmap(0, 0, m_bg_left, 0, 0, m_bg_left.width(), m_bg_left.height());
pp.drawPixmap(m_bg_left.width(), 0, m_bg.width() - m_bg_left.width() - m_bg_right.width(), m_bg_left.height(), m_bg_mid);
pp.drawPixmap(m_bg.width()-m_bg_right.width(), 0, m_bg_right, 0, 0, m_bg_right.width(), m_bg_right.height());
//pp.drawPixmap(10, 10, m_prgpt, 0, 0, m_prgpt.width(), m_prgpt.height());
pp.drawPixmap(10, 10, m_play.width(), m_play.height(), m_play);
m_height = m_res[res_bg_left].height();
return true;
}
void Bar::draw(QPainter& painter, const QRect& rc){
painter.drawPixmap(10, 150, m_bg, 0, 0, m_bg.width(), m_bg.height());
void Bar::start(uint32_t total_ms, int width) {
bool is_first_start = (m_width == 0);
m_width = width;
m_total_ms = total_ms;
_ms_to_str(total_ms, m_str_total_time);
// 首次播放时调整位置左右居中距窗口顶部10点处。
if(is_first_start) {
_init_imgages();
QRect rc = m_owner->rect();
m_rc = QRect(0, 0, m_width, m_height);
m_rc.moveTo((rc.width() - m_width)/2, 10);
//m_rc.moveTo(10, 600);
qDebug("m_rc (%d,%d)-(%d,%d)", m_rc.left(), m_rc.top(), m_rc.right(), m_rc.bottom());
}
}
void Bar::end() {
if(m_passed_ms != m_total_ms)
update_passed_time(m_total_ms);
}
void Bar::_init_imgages() {
m_img_bg = QPixmap(m_width, m_height);
m_img_bg.fill(Qt::transparent);//用透明色填充
QPainter pp(&m_img_bg);
QFont font = pp.font();
// 合成背景图像
{
pp.drawPixmap(0, 0, m_res[res_bg_left].width(), m_res[res_bg_left].height(), m_res[res_bg_left]);
pp.drawPixmap(m_res[res_bg_left].width(), 0, m_width - m_res[res_bg_left].width() - m_res[res_bg_right].width(), m_height, m_res[res_bg_mid]);
pp.drawPixmap(m_width-m_res[res_bg_right].width(), 0, m_res[res_bg_right].width(), m_height, m_res[res_bg_right]);
}
{
m_rc_btn_play = QRect(15, (m_height - m_img_btn_play[play_running][widget_normal].height())/2 , m_img_btn_play[play_running][widget_normal].width(), m_img_btn_play[play_running][widget_normal].height());
}
// 合成速度按钮
{
int w = 42, h = m_res[res_bs_left].height();
QRect rc(0, 0, w, h);
QPixmap btn[widget__max];
// 未选中状态
btn[widget_normal] = QPixmap(w, h);
btn[widget_normal].fill(Qt::transparent);//用透明色填充
QPainter pn(&btn[widget_normal]);
pn.drawPixmap(0, 0, m_res[res_bs_left].width(), m_res[res_bs_left].height(), m_res[res_bs_left]);
pn.drawPixmap(m_res[res_bs_left].width(), 0, w - m_res[res_bs_left].width() - m_res[res_bs_right].width(), h, m_res[res_bs_mid]);
pn.drawPixmap(w-m_res[res_bs_right].width(), 0, m_res[res_bs_right].width(), h, m_res[res_bs_right]);
// 选中状态
btn[widget_hover] = QPixmap(w, h);
btn[widget_hover].fill(Qt::transparent);//用透明色填充
QPainter ph(&btn[widget_hover]);
ph.drawPixmap(0, 0, m_res[res_bsh_left].width(), m_res[res_bsh_left].height(), m_res[res_bsh_left]);
ph.drawPixmap(m_res[res_bsh_left].width(), 0, w - m_res[res_bsh_left].width() - m_res[res_bsh_right].width(), h, m_res[res_bsh_mid]);
ph.drawPixmap(w-m_res[res_bsh_right].width(), 0, m_res[res_bsh_right].width(), h, m_res[res_bsh_right]);
for(int i = 0; i < widget__max; ++i) {
for(int j = 0; j < speed_count; ++j) {
m_img_btn_speed[j][i] = QPixmap(w, h);
m_img_btn_speed[j][i].fill(Qt::transparent);
QPainter ps(&m_img_btn_speed[j][i]);
ps.setPen(TEXT_COLOR);
QFont font = ps.font();
font.setFamily("consolas");
font.setPixelSize(FONT_SIZE_DEFAULT);
ps.setFont(font);
ps.drawPixmap(0, 0, w, h, btn[i]);
ps.drawText(rc, Qt::AlignCenter, speed[j].title);
}
}
}
// 合成跳过无操作选项
{
// 计算显示跳过无操作选项字符串的宽高
font.setFamily("微软雅黑");
font.setBold(false);
font.setPixelSize(FONT_SIZE_DEFAULT);
pp.setFont(font);
QFontMetrics fm = pp.fontMetrics();
{
int h = fm.height();
if(h < m_res[res_cb].height())
h = m_res[res_cb].height();
m_rc_skip = QRect(0, 0, fm.width("无操作则跳过")+8+m_res[res_cb].width(), h);
}
int w = m_rc_skip.width();
int h = m_rc_skip.height();
int chkbox_top = (m_rc_skip.height() - m_res[res_cb].height()) / 2;
int text_left = m_res[res_cb].width() + 8;
int text_top = (m_rc_skip.height() - fm.height()) / 2;
{
m_img_skip[widget_normal] = QPixmap(w,h);
m_img_skip[widget_normal].fill(Qt::transparent);
QPainter ps(&m_img_skip[widget_normal]);
ps.setPen(TEXT_COLOR);
QFont font = ps.font();
font.setFamily("微软雅黑");
font.setPixelSize(FONT_SIZE_DEFAULT);
ps.setFont(font);
ps.drawPixmap(0, chkbox_top, m_res[res_cb].width(), m_res[res_cb].height(), m_res[res_cb]);
ps.drawText(QRect(text_left, text_top, w-text_left, h-text_top), Qt::AlignCenter, "无操作则跳过");
}
{
m_img_skip[widget_hover] = QPixmap(w,h);
m_img_skip[widget_hover].fill(Qt::transparent);
QPainter ps(&m_img_skip[widget_hover]);
ps.setPen(TEXT_COLOR);
QFont font = ps.font();
font.setFamily("微软雅黑");
font.setPixelSize(FONT_SIZE_DEFAULT);
ps.setFont(font);
ps.drawPixmap(0, chkbox_top, m_res[res_cbh].width(), m_res[res_cbh].height(), m_res[res_cbh]);
ps.drawText(QRect(text_left, text_top, w-text_left, h-text_top), Qt::AlignCenter, "无操作则跳过");
}
}
{
// 计算显示时间所需的宽高
font.setFamily("consolas");
font.setBold(true);
font.setPixelSize(TIME_STR_PIXEL_SIZE);
pp.setFont(font);
{
QFontMetrics fm = pp.fontMetrics();
m_rc_time_passed = QRect(0, 0, fm.width("00:00:00"), fm.height());
m_rc_time_total = m_rc_time_passed;
}
m_img_time_total = QPixmap(m_rc_time_total.width(), m_rc_time_total.height());
m_img_time_total.fill(Qt::transparent);
QPainter pp(&m_img_time_total);
pp.setPen(TEXT_COLOR);
QFont font = pp.font();
font.setFamily("consolas");
font.setBold(true);
font.setPixelSize(TIME_STR_PIXEL_SIZE);
pp.setFont(font);
pp.drawText(m_rc_time_total, Qt::AlignLeft, m_str_total_time);
// 定位时间字符串的位置
m_rc_time_passed.moveTo(15+m_img_btn_play[play_running][widget_normal].width()+10, 18);
m_rc_time_total.moveTo(m_width - 15 - m_rc_time_total.width(), 18);
int prog_width = m_rc_time_total.left() - 10 - 10 - m_rc_time_passed.right();// - m_img_progress_pointer[widget_normal].width();
int prog_height = max(m_res[res_pbh_left].height(), m_img_progress_pointer->height());
m_rc_progress = QRect(0, 0, prog_width, prog_height);
m_rc_progress.moveTo(m_rc_time_passed.right() + 10, m_rc_time_passed.height() + (m_rc_time_passed.height() - prog_height)/2);
qDebug("prog: %d,%d w:%d,h:%d", m_rc_progress.left(), m_rc_progress.top(), prog_width, prog_height);
}
// 定位速度按钮
{
int left = m_rc_time_passed.right() + 10;
int top = m_rc_time_passed.bottom() + 8;
for(int i = 0; i < speed_count; i++) {
m_rc_btn_speed[i] = QRect(left, top, m_img_btn_speed[i][widget_normal].width(), m_img_btn_speed[i][widget_normal].height());
left += m_img_btn_speed[i][widget_normal].width() + 8;
}
}
// 定位跳过选项
{
int left = m_rc_time_total.left() - m_rc_skip.width() - 10;
int top = m_rc_time_passed.bottom() + 10;
m_rc_skip.moveTo(left, top);
}
m_img_ready = true;
}
void Bar::_ms_to_str(uint32_t ms, QString& str) {
int h = 0, m = 0, s = 0;
s = ms / 1000;
if(ms % 1000 > 500)
s += 1;
h = s / 3600;
s = s % 3600;
m = s / 60;
s = s % 60;
if(h > 0)
str.sprintf("%02d:%02d:%02d", h, m, s);
else
str.sprintf("%02d:%02d", m, s);
}
void Bar::update_passed_time(uint32_t ms) {
QString str_passed;
_ms_to_str(ms, str_passed);
if(m_str_passed_time != str_passed)
{
m_str_passed_time = str_passed;
m_owner->update(m_rc.left()+m_rc_time_passed.left(), m_rc.top()+m_rc_time_passed.top(), m_rc_time_passed.width(), m_rc_time_passed.height());
}
int percent = 0;
if(ms > m_total_ms) {
percent = 100;
m_passed_ms = m_total_ms;
}
else {
m_passed_ms = ms;
percent = (int)(((double)m_passed_ms / (double)m_total_ms) * 100);
}
if(percent != m_percent) {
m_percent = percent;
m_owner->update(m_rc.left()+m_rc_progress.left(), m_rc.top()+m_rc_progress.top(), m_rc_progress.width(), m_rc_progress.height());
}
}
void Bar::onMouseMove(int x, int y) {
// 映射鼠标坐标点到本浮动窗内部的相对位置
QPoint pt(x-m_rc.left(), y-m_rc.top());
bool play_hover = m_rc_btn_play.contains(pt);
if(play_hover != m_play_hover) {
m_play_hover = play_hover;
m_owner->update(m_rc.left()+m_rc_btn_play.left(), m_rc.top()+m_rc_btn_play.top(), m_rc_btn_play.width(), m_rc_btn_play.height());
}
if(play_hover)
return;
int speed_hover = speed_count;
for(int i = 0; i < speed_count; ++i) {
if(m_rc_btn_speed[i].contains(pt)) {
speed_hover = i;
break;
}
}
if(m_speed_hover != speed_hover) {
if(m_speed_hover != speed_count) {
m_owner->update(m_rc.left()+m_rc_btn_speed[m_speed_hover].left(), m_rc.top()+m_rc_btn_speed[m_speed_hover].top(), m_rc_btn_speed[m_speed_hover].width(), m_rc_btn_speed[m_speed_hover].height());
}
m_speed_hover = speed_hover;
if(m_speed_hover != speed_count) {
m_owner->update(m_rc.left()+m_rc_btn_speed[m_speed_hover].left(), m_rc.top()+m_rc_btn_speed[m_speed_hover].top(), m_rc_btn_speed[m_speed_hover].width(), m_rc_btn_speed[m_speed_hover].height());
}
}
// TODO: more hover detect.
}
void Bar::draw(QPainter& painter, const QRect& rc_draw){
if(!m_width)
return;
if(!rc_draw.intersects(m_rc))
return;
// 绘制背景
{
QRect rc(m_rc);
//rc.moveTo(m_rc.left()+rc.left(), m_rc.top() + rc.top());
int from_x = max(rc_draw.left(), m_rc.left()) - m_rc.left();
int from_y = max(rc_draw.top(), m_rc.top()) - m_rc.top();
int w = min(m_rc.right(), rc_draw.right()) - rc.left() - from_x + 1;
int h = min(m_rc.bottom(), rc_draw.bottom()) - rc.top() - from_y + 1;
int to_x = m_rc.left() + from_x;
int to_y = m_rc.top() + from_y;
painter.drawPixmap(to_x, to_y, m_img_bg, from_x, from_y, w, h);
}
// 绘制播放按钮
{
QRect rc(m_rc_btn_play);
rc.moveTo(m_rc.left()+rc.left(), m_rc.top() + rc.top());
if(rc_draw.intersects(rc)) {
int from_x = max(rc_draw.left(), rc.left()) - rc.left();
int from_y = max(rc_draw.top(), rc.top()) - rc.top();
int w = min(rc.right(), rc_draw.right()) - rc.left() - from_x + 1;
int h = min(rc.bottom(), rc_draw.bottom()) - rc.top() - from_y + 1;
int to_x = rc.left() + from_x;
int to_y = rc.top() + from_y;
if(m_playing){
if(m_play_hover)
painter.drawPixmap(to_x, to_y, m_img_btn_play[play_running][widget_hover], from_x, from_y, w, h);
else
painter.drawPixmap(to_x, to_y, m_img_btn_play[play_running][widget_normal], from_x, from_y, w, h);
} else {
if(m_play_hover)
painter.drawPixmap(to_x, to_y, m_img_btn_play[play_paused][widget_hover], from_x, from_y, w, h);
else
painter.drawPixmap(to_x, to_y, m_img_btn_play[play_paused][widget_normal], from_x, from_y, w, h);
}
}
}
// 绘制已播放时间
{
QRect rc(m_rc_time_passed);
rc.moveTo(m_rc.left()+rc.left(), m_rc.top() + rc.top());
if(rc_draw.intersects(rc)) {
if(m_str_passed_time != m_str_passed_time_last_draw) {
m_img_time_passed = QPixmap(m_rc_time_passed.width(), m_rc_time_passed.height());
m_img_time_passed.fill(Qt::transparent);
QPainter pp(&m_img_time_passed);
pp.setPen(TEXT_COLOR);
QFont font = pp.font();
font.setFamily("consolas");
font.setBold(true);
font.setPixelSize(TIME_STR_PIXEL_SIZE);
pp.setFont(font);
pp.drawText(QRect(0,0,m_rc_time_passed.width(), m_rc_time_passed.height()), Qt::AlignRight, m_str_passed_time);
m_str_passed_time_last_draw = m_str_passed_time;
}
int from_x = max(rc_draw.left(), rc.left()) - rc.left();
int from_y = max(rc_draw.top(), rc.top()) - rc.top();
int w = min(rc.right(), rc_draw.right()) - rc.left() - from_x + 1;
int h = min(rc.bottom(), rc_draw.bottom()) - rc.top() - from_y + 1;
int to_x = rc.left() + from_x;
int to_y = rc.top() + from_y;
painter.drawPixmap(to_x, to_y, m_img_time_passed, from_x, from_y, w, h);
}
}
// 绘制总时间
{
QRect rc(m_rc_time_total);
rc.moveTo(m_rc.left()+rc.left(), m_rc.top() + rc.top());
if(rc_draw.intersects(rc)) {
int from_x = max(rc_draw.left(), rc.left()) - rc.left();
int from_y = max(rc_draw.top(), rc.top()) - rc.top();
int w = min(rc.right(), rc_draw.right()) - rc.left() - from_x + 1;
int h = min(rc.bottom(), rc_draw.bottom()) - rc.top() - from_y + 1;
int to_x = rc.left() + from_x;
int to_y = rc.top() + from_y;
painter.drawPixmap(to_x, to_y, m_img_time_total, from_x, from_y, w, h);
}
}
// 绘制进度条
{
QRect rc(m_rc_progress);
rc.moveTo(m_rc.left()+rc.left(), m_rc.top() + rc.top());
if(rc_draw.intersects(rc)) {
if(m_percent_last_draw != m_percent) {
m_img_progress = QPixmap(m_rc_progress.width(), m_rc_progress.height());
m_img_progress.fill(Qt::transparent);
QPainter pp(&m_img_progress);
// 进度条
int top = (rc.height() - m_res[res_pbh_left].height())/2;
int passed_width = rc.width() * m_percent / 100; // 已经播放的进度条宽度
int remain_width = rc.width() - passed_width; // 剩下未播放的进度条宽度
if(passed_width >= m_res[res_pbh_left].width())
pp.drawPixmap(0, top , m_res[res_pbh_left].width(), m_res[res_pbh_left].height(), m_res[res_pbh_left]);
if(passed_width > 0) {
//pp.drawPixmap(m_res[res_pbh_left].width(), top, passed_width - m_res[res_pbh_left].width(), m_res[res_pbh_mid].height(), m_res[res_pbh_mid]);
if(remain_width > m_res[res_pb_right].width())
pp.drawPixmap(m_res[res_pbh_left].width(), top, passed_width - m_res[res_pbh_left].width(), m_res[res_pbh_mid].height(), m_res[res_pbh_mid]);
else
pp.drawPixmap(m_res[res_pbh_left].width(), top, passed_width - m_res[res_pbh_left].width() - m_res[res_pb_right].width(), m_res[res_pbh_mid].height(), m_res[res_pbh_mid]);
}
if(remain_width > 0)
pp.drawPixmap(passed_width, top, remain_width - m_res[res_pb_right].width(), m_res[res_pb_mid].height(), m_res[res_pb_mid]);
if(remain_width >= m_res[res_pb_right].width())
pp.drawPixmap(rc.width() - m_res[res_pb_right].width(), top , m_res[res_pb_right].width(), m_res[res_pb_right].height(), m_res[res_pb_right]);
// 进度位置指示
int left = passed_width - m_img_progress_pointer->width() / 2;
if(left < 0)
left = 0;
if(left + m_img_progress_pointer->width() > rc.width())
left = rc.width() - m_img_progress_pointer->width();
top = (rc.height() - m_img_progress_pointer[widget_normal].height())/2;
pp.drawPixmap(left, top , m_img_progress_pointer[widget_normal].width(), m_img_progress_pointer[widget_normal].height(), m_img_progress_pointer[widget_normal]);
m_percent_last_draw = m_percent;
}
int from_x = max(rc_draw.left(), rc.left()) - rc.left();
int from_y = max(rc_draw.top(), rc.top()) - rc.top();
int w = min(rc.right(), rc_draw.right()) - rc.left() - from_x + 1;
int h = min(rc.bottom(), rc_draw.bottom()) - rc.top() - from_y + 1;
int to_x = rc.left() + from_x;
int to_y = rc.top() + from_y;
painter.drawPixmap(to_x, to_y, m_img_progress, from_x, from_y, w, h);
}
}
// 绘制速度按钮
{
for(int i = 0; i < speed_count; i++) {
QRect rc(m_rc_btn_speed[i]);
rc.moveTo(m_rc.left()+rc.left(), m_rc.top() + rc.top());
if(rc_draw.intersects(rc)) {
int from_x = max(rc_draw.left(), rc.left()) - rc.left();
int from_y = max(rc_draw.top(), rc.top()) - rc.top();
int w = min(rc.right(), rc_draw.right()) - rc.left() - from_x + 1;
int h = min(rc.bottom(), rc_draw.bottom()) - rc.top() - from_y + 1;
int to_x = rc.left() + from_x;
int to_y = rc.top() + from_y;
if(m_speed_selected == i || m_speed_hover == i)
painter.drawPixmap(to_x, to_y, m_img_btn_speed[i][widget_hover], from_x, from_y, w, h);
else
painter.drawPixmap(to_x, to_y, m_img_btn_speed[i][widget_normal], from_x, from_y, w, h);
}
}
}
// 绘制跳过选项
{
QRect rc(m_rc_skip);
rc.moveTo(m_rc.left()+rc.left(), m_rc.top() + rc.top());
if(rc_draw.intersects(rc)) {
int from_x = max(rc_draw.left(), rc.left()) - rc.left();
int from_y = max(rc_draw.top(), rc.top()) - rc.top();
int w = min(rc.right(), rc_draw.right()) - rc.left() - from_x + 1;
int h = min(rc.bottom(), rc_draw.bottom()) - rc.top() - from_y + 1;
int to_x = rc.left() + from_x;
int to_y = rc.top() + from_y;
//qDebug("skip (%d,%d), (%d,%d)/(%d,%d)", to_x, to_y, from_x, from_y, w, h);
if(m_skip_selected)
painter.drawPixmap(to_x, to_y, m_img_skip[widget_hover], from_x, from_y, w, h);
else
painter.drawPixmap(to_x, to_y, m_img_skip[widget_normal], from_x, from_y, w, h);
}
}
}

View File

@ -5,49 +5,128 @@
#include <QPixmap>
#include <QWidget>
typedef enum {
res_bg_left = 0, // 背景左侧
res_bg_mid, // 背景中间,拉伸填充
res_bg_right, // 背景右侧
res_bs_left, // 速度按钮(未选中)左侧
res_bs_mid, // 速度按钮(未选中)中间,拉伸填充
res_bs_right, // 速度按钮(未选中)右侧
res_bsh_left, // 速度按钮(选中)左侧
res_bsh_mid, // 速度按钮(选中)中间,拉伸填充
res_bsh_right, // 速度按钮(选中)右侧
res_pbh_left, // 进度条(已经过)左侧
res_pbh_mid, // 进度条(已经过)中间,拉伸填充
res_pb_mid, // 进度条(未到达)中间,拉伸填充
res_pb_right, // 进度条(未到达)右侧
// res_pp, // 进度条上的指示点,未选中
// res_pph, // 进度条上的指示点,选中高亮
res_cb, // 复选框,未选中
res_cbh, // 复选框,已勾选
// res_play,
// res_play_hover,
// res_pause,
// res_pause_hover,
res__max
}RES_ID;
typedef enum {
widget_normal = 0,
widget_hover,
widget__max
}WIDGET_STAT;
typedef enum {
play_running = 0,
play_paused,
play__max
}PLAY_STAT;
//typedef enum {
// speed_1x = 0,
// speed_2x,
// speed_4x,
// speed_8x,
// speed_16x,
// speed__max,
//}SPEED;
#define speed_1x 0
#define speed_2x 1
#define speed_4x 2
#define speed_8x 3
#define speed_16x 4
#define speed_count 5
class Bar {
public:
Bar();
~Bar();
bool init(QWidget* owner, int width);
bool init(QWidget* owner);
void start(uint32_t total_ms, int width);
void end();
void draw(QPainter& painter, const QRect& rc);
void update_passed_time(uint32_t ms);
QRect rc(){return m_rc;}
void onMouseMove(int x, int y);
private:
void _init_imgages();
void _ms_to_str(uint32_t ms, QString& str);
private:
QWidget* m_owner;
uint32_t m_total_ms; // 录像的总时长
uint32_t m_passed_ms; // 已经播放了的时长
int m_percent; // 已经播放了的百分比0~100
int m_percent_last_draw;
QString m_str_total_time;
QString m_str_passed_time;
QString m_str_passed_time_last_draw;
bool m_img_ready;
// 从资源中加载的原始图像
QPixmap m_res[res__max];
QPixmap m_img_progress_pointer[widget__max];
int m_width;
int m_height;
// 此浮动窗相对于父窗口的坐标和大小
QRect m_rc;
// 尺寸和定位(此浮动窗内部的相对坐标)
QRect m_rc_btn_play;
QRect m_rc_btn_speed[speed_count];
QRect m_rc_time_passed;
QRect m_rc_time_total;
QRect m_rc_progress;
QRect m_rc_skip;
QPixmap m_bg;
// 画布,最终输出的图像
//QPixmap m_canvas;
QPixmap m_bg_left;
QPixmap m_bg_mid;
QPixmap m_bg_right;
// 合成的图像
QPixmap m_img_bg;
QPixmap m_img_btn_play[play__max][widget__max];
QPixmap m_img_btn_speed[speed_count][widget__max];
QPixmap m_img_progress;
QPixmap m_img_skip[widget__max];
QPixmap m_img_time_passed;
QPixmap m_img_time_total;
QPixmap m_btn_left;
QPixmap m_btn_mid;
QPixmap m_btn_right;
QPixmap m_btnsel_left;
QPixmap m_btnsel_mid;
QPixmap m_btnsel_right;
QPixmap m_prgbarh_left;
QPixmap m_prgbarh_mid;
QPixmap m_prgbar_left;
QPixmap m_prgbar_mid;
QPixmap m_prgbar_right;
QPixmap m_prgpt;
QPixmap m_prgpt_hover;
QPixmap m_select;
QPixmap m_selected;
QPixmap m_play;
QPixmap m_play_hover;
// 各种状态
bool m_play_hover;
bool m_playing; // 0=play, 2=pause
int m_speed_selected;
int m_speed_hover; // speed__max=no-hover
bool m_skip_selected;
//bool m_skip_hover;
};
#endif // BAR_H

View File

@ -41,10 +41,6 @@ bool rdpimg2QImage(QImage& out, int w, int h, int bitsPerPixel, bool isCompresse
uint8 r = ((a & 0xf800) >> 11) * 255 / 31;
uint8 g = ((a & 0x07e0) >> 5) * 255 / 63;
uint8 b = (a & 0x001f) * 255 / 31;
// r = r * 255 / 31;
// g = g * 255 / 63;
// b = b * 255 / 31;
out.setPixelColor(x, y, QColor(r,g,b));
}
}
@ -72,15 +68,17 @@ MainWindow::MainWindow(QWidget *parent) :
ui(new Ui::MainWindow)
{
m_shown = false;
m_show_bg = true;
m_bg = QImage(":/tp-player/res/bg");
m_pt_normal = QImage(":/tp-player/res/cursor.png");
m_show_default = true;
m_bar_shown = false;
memset(&m_pt, 0, sizeof(TS_RECORD_RDP_POINTER));
qDebug() << m_pt_normal.width() << "x" << m_pt_normal.height();
ui->setupUi(this);
ui->centralWidget->setMouseTracking(true);
setMouseTracking(true);
//qRegisterMetaType<update_data*>("update_data");
// frame-less window.
@ -91,15 +89,13 @@ MainWindow::MainWindow(QWidget *parent) :
// setWindowFlags(Qt::FramelessWindowHint | Qt::MSWindowsFixedSizeDialogHint | windowFlags());
//#endif //__APPLE__
//m_canvas = QPixmap(m_bg.width(), m_bg.height());
m_canvas.load(":/tp-player/res/bg");
resize(m_bg.width(), m_bg.height());
m_pt_normal.load(":/tp-player/res/cursor.png");
m_default_bg.load(":/tp-player/res/bg.png");
setWindowFlags(windowFlags()&~Qt::WindowMaximizeButtonHint); // 禁止最大化按钮
setFixedSize(m_bg.width(), m_bg.height()); // 禁止拖动窗口大小
setFixedSize(m_default_bg.width(), m_default_bg.height()); // 禁止拖动窗口大小
if(!m_bar.init(this, 480))
if(!m_bar.init(this))
return;
connect(&m_thr_play, SIGNAL(signal_update_data(update_data*)), this, SLOT(on_update_data(update_data*)));
@ -112,49 +108,43 @@ MainWindow::~MainWindow()
delete ui;
}
void MainWindow::paintEvent(QPaintEvent *pe)
void MainWindow::paintEvent(QPaintEvent *e)
{
QPainter painter(this);
painter.drawPixmap(pe->rect(), m_canvas, pe->rect());
if(m_show_default) {
painter.drawPixmap(e->rect(), m_default_bg, e->rect());
}
else {
painter.drawPixmap(e->rect(), m_canvas, e->rect());
if(!m_pt_history.empty()) {
for(int i = 0; i < m_pt_history.count(); i++) {
//qDebug("pt clean %d,%d", m_pt_history[i].x, m_pt_history[i].y);
QRect rcpt(m_pt_normal.rect());
rcpt.moveTo(m_pt_history[i].x - m_pt_normal.width()/2, m_pt_history[i].y-m_pt_normal.height()/2);
//painter.drawPixmap(rcpt, m_canvas, rcpt);
qDebug("pt ---- (%d,%d), (%d,%d)", rcpt.x(), rcpt.y(), rcpt.width(), rcpt.height());
painter.fillRect(rcpt, QColor(255, 255, 0, 128));
QRect rcpt(m_pt_normal.rect());
rcpt.moveTo(m_pt.x - m_pt_normal.width()/2, m_pt.y-m_pt_normal.height()/2);
if(e->rect().intersects(rcpt)) {
painter.drawPixmap(m_pt.x-m_pt_normal.width()/2, m_pt.y-m_pt_normal.height()/2, m_pt_normal);
}
m_pt_history.clear();
// 绘制浮动控制窗
if(m_bar_shown)
m_bar.draw(painter, e->rect());
}
QRect rcpt(m_pt_normal.rect());
rcpt.moveTo(m_pt.x - m_pt_normal.width()/2, m_pt.y-m_pt_normal.height()/2);
if(pe->rect().intersects(rcpt)) {
qDebug("pt draw (%d,%d), (%d,%d)", m_pt.x-m_pt_normal.width()/2, m_pt.y-m_pt_normal.height()/2, m_pt_normal.width(), m_pt_normal.height());
painter.drawImage(m_pt.x-m_pt_normal.width()/2, m_pt.y-m_pt_normal.height()/2, m_pt_normal);
if(!m_shown) {
m_shown = true;
m_thr_play.start();
}
m_bar.draw(painter, pe->rect());
// if(!m_shown) {
// m_shown = true;
// m_thr_play.start();
// }
}
void MainWindow::on_update_data(update_data* dat) {
if(!dat)
return;
UpdateDataHelper data_helper(dat);
if(dat->data_type() == TYPE_DATA) {
m_show_bg = false;
if(dat->data_len() <= sizeof(TS_RECORD_PKG)) {
qDebug() << "invalid record package(1).";
delete dat;
return;
}
@ -163,25 +153,21 @@ void MainWindow::on_update_data(update_data* dat) {
if(pkg->type == TS_RECORD_TYPE_RDP_POINTER) {
if(dat->data_len() != sizeof(TS_RECORD_PKG) + sizeof(TS_RECORD_RDP_POINTER)) {
qDebug() << "invalid record package(2).";
delete dat;
return;
}
// 将现有虚拟鼠标信息放入历史队列,这样下一次绘制界面时就会将其清除掉
m_pt_history.push_back(m_pt);
TS_RECORD_RDP_POINTER pt;
memcpy(&pt, &m_pt, sizeof(TS_RECORD_RDP_POINTER));
// 更新虚拟鼠标信息,这样下一次绘制界面时就会在新的位置绘制出虚拟鼠标
memcpy(&m_pt, dat->data_buf() + sizeof(TS_RECORD_PKG), sizeof(TS_RECORD_RDP_POINTER));
//qDebug("pt new position %d,%d", m_pt.x, m_pt.y);
//setUpdatesEnabled(false);
update(m_pt.x - m_pt_normal.width()/2, m_pt.y - m_pt_normal.width()/2, m_pt_normal.width(), m_pt_normal.height());
//setUpdatesEnabled(true);
update(pt.x - m_pt_normal.width()/2, pt.y - m_pt_normal.width()/2, m_pt_normal.width(), m_pt_normal.height());
}
else if(pkg->type == TS_RECORD_TYPE_RDP_IMAGE) {
if(dat->data_len() <= sizeof(TS_RECORD_PKG) + sizeof(TS_RECORD_RDP_IMAGE_INFO)) {
qDebug() << "invalid record package(3).";
delete dat;
return;
}
@ -189,53 +175,57 @@ void MainWindow::on_update_data(update_data* dat) {
uint8_t* img_dat = dat->data_buf() + sizeof(TS_RECORD_PKG) + sizeof(TS_RECORD_RDP_IMAGE_INFO);
uint32_t img_len = dat->data_len() - sizeof(TS_RECORD_PKG) - sizeof(TS_RECORD_RDP_IMAGE_INFO);
rdpimg2QImage(m_img_update, info->width, info->height, info->bitsPerPixel, (info->format == TS_RDP_IMG_BMP) ? true : false, img_dat, img_len);
QImage img_update;
rdpimg2QImage(img_update, info->width, info->height, info->bitsPerPixel, (info->format == TS_RDP_IMG_BMP) ? true : false, img_dat, img_len);
m_img_update_x = info->destLeft;
m_img_update_y = info->destTop;
m_img_update_w = info->destRight - info->destLeft + 1;
m_img_update_h = info->destBottom - info->destTop + 1;
int x = info->destLeft;
int y = info->destTop;
int w = info->destRight - info->destLeft + 1;
int h = info->destBottom - info->destTop + 1;
setUpdatesEnabled(false);
QPainter pp(&m_canvas);
pp.drawImage(m_img_update_x, m_img_update_y, m_img_update, 0, 0, m_img_update_w, m_img_update_h, Qt::AutoColor);
pp.drawImage(x, y, img_update, 0, 0, w, h, Qt::AutoColor);
update(m_img_update_x, m_img_update_y, m_img_update_w, m_img_update_h);
setUpdatesEnabled(true);
update(x, y, w, h);
}
delete dat;
return;
}
if(dat->data_type() == TYPE_TIMER) {
m_bar.update_passed_time(dat->passed_ms());
return;
}
if(dat->data_type() == TYPE_HEADER_INFO) {
if(dat->data_len() != sizeof(TS_RECORD_HEADER)) {
qDebug() << "invalid record header.";
delete dat;
return;
}
memcpy(&m_rec_hdr, dat->data_buf(), sizeof(TS_RECORD_HEADER));
delete dat;
qDebug() << "resize (" << m_rec_hdr.basic.width << "," << m_rec_hdr.basic.height << ")";
if(m_rec_hdr.basic.width > 0 && m_rec_hdr.basic.height > 0) {
m_canvas = QPixmap(m_rec_hdr.basic.width, m_rec_hdr.basic.height);
m_canvas.fill(QColor(38, 73, 111));
//m_win_board_w = frameGeometry().width() - geometry().width();
//m_win_board_h = frameGeometry().height() - geometry().height();
m_win_board_w = frameGeometry().width() - geometry().width();
m_win_board_h = frameGeometry().height() - geometry().height();
QDesktopWidget *desktop = QApplication::desktop(); // =qApp->desktop();也可以
qDebug("desktop w:%d,h:%d, this w:%d,h:%d", desktop->width(), desktop->height(), width(), height());
//move((desktop->width() - this->width())/2, (desktop->height() - this->height())/2);
move(10, (desktop->height() - m_rec_hdr.basic.height)/2);
//setFixedSize(m_rec_hdr.basic.width + m_win_board_w, m_rec_hdr.basic.height + m_win_board_h);
//resize(m_rec_hdr.basic.width + m_win_board_w, m_rec_hdr.basic.height + m_win_board_h);
//resize(m_rec_hdr.basic.width, m_rec_hdr.basic.height);
setFixedSize(m_rec_hdr.basic.width, m_rec_hdr.basic.height);
resize(m_rec_hdr.basic.width, m_rec_hdr.basic.height);
QDesktopWidget *desktop = QApplication::desktop(); // =qApp->desktop();也可以
qDebug("desktop width: %d", desktop->width());
//move((desktop->width() - this->width())/2, (desktop->height() - this->height())/2);
move(10, (desktop->height() - this->height())/2);
m_show_default = false;
repaint();
m_bar.start(m_rec_hdr.info.time_ms, 640);
}
QString title;
@ -250,5 +240,30 @@ void MainWindow::on_update_data(update_data* dat) {
}
delete dat;
if(dat->data_type() == TYPE_END) {
m_bar.end();
return;
}
}
void MainWindow::mouseMoveEvent(QMouseEvent *e) {
if(!m_show_default) {
QRect rc = m_bar.rc();
if(e->y() > rc.top() - 20 && e->y() < rc.bottom() + 20) {
if(!m_bar_shown) {
m_bar_shown = true;
update(rc);
}
if(rc.contains(QPoint(e->x(), e->y())))
m_bar.onMouseMove(e->x(), e->y());
}
else {
if(m_bar_shown) {
m_bar_shown = false;
update(rc);
}
}
}
}

View File

@ -2,7 +2,6 @@
#define MAINWINDOW_H
#include <QMainWindow>
#include <QVector>
#include "bar.h"
#include "thr_play.h"
#include "update_data.h"
@ -21,16 +20,19 @@ public:
~MainWindow();
private:
void paintEvent(QPaintEvent *);
void paintEvent(QPaintEvent *e);
void mouseMoveEvent(QMouseEvent *e);
private slots:
void on_update_data(update_data*);
private:
Ui::MainWindow *ui;
QImage m_bg;
//QImage m_bg;
bool m_shown;
bool m_show_default;
bool m_bar_shown;
QPixmap m_default_bg;
ThreadPlay m_thr_play;
@ -38,21 +40,10 @@ private:
Bar m_bar;
bool m_show_bg;
TS_RECORD_HEADER m_rec_hdr;
QImage m_pt_normal;
QPixmap m_pt_normal;
TS_RECORD_RDP_POINTER m_pt;
QVector<TS_RECORD_RDP_POINTER> m_pt_history;
QImage m_img_update;
int m_win_board_w;
int m_win_board_h;
int m_img_update_x;
int m_img_update_y;
int m_img_update_w;
int m_img_update_h;
};
#endif // MAINWINDOW_H

View File

@ -6,6 +6,8 @@
#define TYPE_HEADER_INFO 0
#define TYPE_DATA 1
#define TYPE_TIMER 2
#define TYPE_END 3
#define TS_RECORD_TYPE_RDP_POINTER 0x12 // 鼠标坐标位置改变,用于绘制虚拟鼠标

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -18,6 +18,9 @@ void ThreadPlay::stop() {
}
void ThreadPlay::run() {
sleep(1);
qint64 read_len = 0;
uint32_t total_pkg = 0;
@ -59,6 +62,7 @@ void ThreadPlay::run() {
}
uint32_t time_pass = 0;
uint32_t time_last_pass = 0;
qint64 time_begin = QDateTime::currentMSecsSinceEpoch();
@ -87,6 +91,14 @@ void ThreadPlay::run() {
}
time_pass = (uint32_t)(QDateTime::currentMSecsSinceEpoch() - time_begin);
if(time_pass - time_last_pass > 1000) {
update_data* _passed_ms = new update_data;
_passed_ms->data_type(TYPE_TIMER);
_passed_ms->passed_ms(time_pass);
// qDebug("--- 1 %d", time_pass);
emit signal_update_data(_passed_ms);
time_last_pass = time_pass;
}
if(time_pass >= pkg.time_ms) {
//time_pass = pkg.time_ms;
@ -99,8 +111,8 @@ void ThreadPlay::run() {
uint32_t wait_this_time = 0;
for(;;) {
wait_this_time = time_wait;
if(wait_this_time > 5)
wait_this_time = 5;
if(wait_this_time > 10)
wait_this_time = 10;
if(m_need_stop) {
qDebug() << "stop, user cancel (2).";
@ -109,8 +121,15 @@ void ThreadPlay::run() {
msleep(wait_this_time);
//time_pass += wait_this_time;
//time_pass = pkg.time_ms;
uint32_t _time_pass = (uint32_t)(QDateTime::currentMSecsSinceEpoch() - time_begin);
if(_time_pass - time_last_pass > 1000) {
update_data* _passed_ms = new update_data;
_passed_ms->data_type(TYPE_TIMER);
_passed_ms->passed_ms(_time_pass);
// qDebug("--- 2 %d", _time_pass);
emit signal_update_data(_passed_ms);
time_last_pass = _time_pass;
}
time_wait -= wait_this_time;
if(time_wait == 0) {
@ -118,8 +137,9 @@ void ThreadPlay::run() {
break;
}
}
// emit signal_update_data(dat);
// msleep(15);
}
update_data* _end = new update_data;
_end->data_type(TYPE_END);
emit signal_update_data(_end);
}

View File

@ -13,7 +13,8 @@
<file>res/bar/btnsel-right.png</file>
<file>res/bar/play-hover.png</file>
<file>res/bar/play.png</file>
<file>res/bar/prgbar-left.png</file>
<file>res/bar/pause-hover.png</file>
<file>res/bar/pause.png</file>
<file>res/bar/prgbar-mid.png</file>
<file>res/bar/prgbar-right.png</file>
<file>res/bar/prgbarh-left.png</file>

View File

@ -19,6 +19,9 @@ public:
uint8_t* data_buf() {return m_data_buf;}
uint32_t data_len() const {return m_data_len;}
void passed_ms(uint32_t ms) {m_passed_ms = ms;}
uint32_t passed_ms() {return m_passed_ms;}
signals:
public slots:
@ -28,6 +31,22 @@ private:
int m_data_type;
uint8_t* m_data_buf;
uint32_t m_data_len;
uint32_t m_passed_ms;
};
class UpdateDataHelper {
public:
UpdateDataHelper(update_data* data) {
m_data = data;
}
~UpdateDataHelper() {
if(m_data)
delete m_data;
}
private:
update_data* m_data;
};
#endif // UPDATE_DATA_H