KDAv1.0 测试版本发布

This commit is contained in:
nikola 2023-07-21 21:46:24 +08:00
commit 5599bb19b8
33 changed files with 5693 additions and 0 deletions

73
.gitignore vendored Normal file
View File

@ -0,0 +1,73 @@
# This file is used to ignore files which are generated
# ----------------------------------------------------------------------------
*~
*.autosave
*.a
*.core
*.moc
*.o
*.obj
*.orig
*.rej
*.so
*.so.*
*_pch.h.cpp
*_resource.rc
*.qm
.#*
*.*#
core
!core/
tags
.DS_Store
.directory
*.debug
Makefile*
*.prl
*.app
moc_*.cpp
ui_*.h
qrc_*.cpp
Thumbs.db
*.res
*.rc
/.qmake.cache
/.qmake.stash
# qtcreator generated files
*.pro.user*
# xemacs temporary files
*.flc
# Vim temporary files
.*.swp
# Visual Studio generated files
*.ib_pdb_index
*.idb
*.ilk
*.pdb
*.sln
*.suo
*.vcproj
*vcproj.*.*.user
*.ncb
*.sdf
*.opensdf
*.vcxproj
*vcxproj.*
# MinGW generated files
*.Debug
*.Release
# Python byte code
*.pyc
# Binaries
# --------
*.dll
*.exe

BIN
KDA_Logo.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 KiB

464
Keil5_disp_size_bar.c Normal file
View File

@ -0,0 +1,464 @@
#if 0
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#define APP_NAME "Keil5_disp_size_bar V0.5"
typedef struct mcu_8051_size
{
uint32_t iram_size;
uint32_t xram_size;
uint32_t irom_size;
uint32_t iram_max;
uint32_t xram_max;
uint32_t irom_max;
} mcu_8051_size_t;
mcu_8051_size_t mcu_8051 = {0};
void print_msg(const char *tag, const char *format, ...);
FILE *find_file_in_dir_by_name(const char *dir_name, const char *file_name);
int64_t file_sreach_string_get_pos(FILE *fp, char *sub_str, int seek, uint32_t offset);
void prtint_percentage_bar(char *label, uint8_t cnt, uint32_t val, uint32_t max);
uint32_t str_get_hex(char *str, char *str_hex);
void process_execution_region(FILE *fp_map);
float str_get_dec(char *str, char *str_dec);
uint8_t find_8051(void);
void find_project_size_define(void);
uint32_t ram_max_from_porject = 0;
uint32_t rom_max_from_porject = 0;
// argv[0] 是当前exe文件的路径
// exe放在工程文件的同一目录下就可以获取到工程目录了
int main2(int argc, char *argv[])
{
DIR *dir;
char *path = NULL;
FILE *fp_map;
// 打开当前目录
int64_t pos = 0;
if (find_8051())
return;
find_project_size_define();
print_msg(APP_NAME, "find map file start");
fp_map = find_file_in_dir_by_name("./", ".map");
process_execution_region(fp_map);
fclose(fp_map);
return 0;
}
void print_msg(const char *tag, const char *format, ...)
{
printf("[%s]: ", tag);
va_list args;
va_start(args, format);
vprintf(format, args);
va_end(args);
printf("\n");
}
FILE *find_file_in_dir_by_name(const char *dir_name, const char *file_name)
{
FILE *fp;
DIR *dir;
struct dirent *st;
struct stat sta;
int ret = 0;
char tmp_name[1024] = {0};
if ((dir = opendir(dir_name)) == NULL)
{
printf("%s: Open dir error\n", APP_NAME);
return NULL;
}
while ((st = readdir(dir)) != NULL)
{
strcpy(tmp_name, dir_name);
strcat(tmp_name, "/");
strcat(tmp_name, st->d_name); // 新文件路径名
ret = stat(tmp_name, &sta); // 查看目录下文件属性
if (ret < 0)
{
print_msg(APP_NAME "Read stat failed for %s", tmp_name);
continue;
}
if (S_ISDIR(sta.st_mode))
{ // 如果为目录文件
if (strcmp("..", st->d_name) == 0 || strcmp(".", st->d_name) == 0)
{
continue; // 忽略当前目录和上一层目录
}
else
{
fp = find_file_in_dir_by_name(tmp_name, file_name); // 递归读取
if (fp)
{
closedir(dir);
return fp;
}
}
}
else
{ // 不为目录则打印文件路径名
if (strstr(tmp_name, file_name))
{
fp = fopen(tmp_name, "r+");
if (!fp)
{
// print_msg(APP_NAME, "Failed to open file: %s", tmp_name);
return NULL;
}
else
{
print_msg(APP_NAME, "Found file: %s", tmp_name);
closedir(dir);
return fp;
}
}
}
}
closedir(dir);
return NULL;
}
int64_t file_sreach_string_get_pos(FILE *fp, char *sub_str, int seek, uint32_t offset)
{
char str[1000];
int64_t pos = 0;
fseek(fp, offset, seek);
while (NULL != fgets(str, 1000, fp))
{
if (strstr(str, sub_str))
{
// printf("%s", str);
pos = ftell(fp) - strlen(str);
fseek(fp, pos, SEEK_SET);
return pos;
}
}
return -1;
}
void prtint_percentage_bar(char *label, uint8_t cnt, uint32_t val, uint32_t max)
{
uint8_t i;
printf("%5d KB %5s%u:|", (uint32_t)(max / 1024.0f), label, cnt);
for (i = 0; i < 20; i++)
{
if (i < (uint8_t)((val / 1.0) / (max / 1.0) * 20))
{
printf("");
}
else
{
printf("_");
}
}
printf("|%6.2f %% (%8.2f KB / %8.2f KB)", (val / 1.0) / (max / 1.0) * 100, val / 1024.0f, max / 1024.0f);
printf(" [%u B]\n", max - val);
}
uint32_t str_get_hex(char *str, char *str_hex)
{
char *str_buf;
uint32_t hex;
str_buf = strstr(str, str_hex);
if (str_buf == NULL)
return 0;
str_buf += strlen(str_hex);
sscanf(str_buf, "%x", &hex);
// printf("%s:%#x\n", str_hex,hex);
return hex;
}
float str_get_dec(char *str, char *str_dec)
{
char *str_buf;
float dec;
str_buf = strstr(str, str_dec);
if (str_buf == NULL)
return 0;
str_buf += strlen(str_dec);
sscanf(str_buf, "%f", &dec);
// printf("%s:%#x\n", str_hex,hex);
return dec;
}
void process_execution_region(FILE *fp_map)
{
int64_t pos = 0;
char str[1000];
char *ch_p = NULL;
uint32_t exec_base = 0, load_base = 0, size = 0, max = 0;
uint8_t ram_cnt = 0, flash_cnt = 0;
uint8_t cnt = 0;
uint32_t ram_size[30];
uint32_t flash_size[30];
uint32_t ram_max[30];
uint32_t flash_max[30];
while (1)
{
pos = file_sreach_string_get_pos(fp_map, "Execution Region", SEEK_SET, pos);
if (-1 == pos)
{
print_msg(APP_NAME, "map file read end\n");
break;
}
fseek(fp_map, pos, SEEK_SET);
fgets(str, 1000, fp_map);
if (strstr(str, "RAM"))
{
ram_size[ram_cnt] = str_get_hex(str, "Size: ");
pos += strstr(str, "Size: ") - str;
fseek(fp_map, pos, SEEK_SET);
ram_max[ram_cnt] = str_get_hex(str, "Max: ");
if (ram_max[ram_cnt] > 100 * 1024 * 1024)
ram_max[ram_cnt] = ram_max_from_porject;
pos += strstr(str, "Max: ") - str;
fseek(fp_map, pos, SEEK_SET);
if (ram_cnt < 30)
ram_cnt++;
// prtint_percentage_bar("ram",ram_cnt, size, max);
}
else if (strstr(str, "ER$$") ||strstr(str, "RW_")|| strstr(str, "ER_RW") || strstr(str, "ER_ZI"))
{
ram_size[ram_cnt] = str_get_hex(str, "Size: ");
pos += strstr(str, "Size: ") - str;
fseek(fp_map, pos, SEEK_SET);
ram_max[ram_cnt] = str_get_hex(str, "Max: ");
if (ram_max[ram_cnt] > 100 * 1024 * 1024)
ram_max[ram_cnt] = ram_max_from_porject;
print_msg(APP_NAME,"RAMMAX:%d\n",ram_max[ram_cnt]);
pos += strstr(str, "Max: ") - str;
fseek(fp_map, pos, SEEK_SET);
if (ram_cnt < 30)
ram_cnt++;
// prtint_percentage_bar("ram",ram_cnt, size, max);
}
else
{
flash_size[flash_cnt] = str_get_hex(str, "Size: ");
pos += strstr(str, "Size: ") - str;
fseek(fp_map, pos, SEEK_SET);
flash_max[flash_cnt] = str_get_hex(str, "Max: ");
if (flash_max[flash_cnt] > 100 * 1024 * 1024)
flash_max[flash_cnt] = rom_max_from_porject;
pos += strstr(str, "Max: ") - str;
fseek(fp_map, pos, SEEK_SET);
if (flash_cnt < 30)
flash_cnt++;
// prtint_percentage_bar("flash",flash_cnt, size, max);
}
}
printf("ram:\n");
for (cnt = 0; cnt < ram_cnt; cnt++)
{
prtint_percentage_bar("ram", cnt + 1, ram_size[cnt], ram_max[cnt]);
}
printf("flash:\n");
for (cnt = 0; cnt < flash_cnt; cnt++)
{
prtint_percentage_bar("flash", cnt + 1, flash_size[cnt], flash_max[cnt]);
}
printf(" \n");
}
uint8_t find_8051(void)
{
FILE *fp_project=NULL;
FILE *fp_m51=NULL;
int64_t pos = 0;
char str[1000];
uint8_t cnt = 0;
print_msg(APP_NAME, "find project satrt!");
fp_project = find_file_in_dir_by_name("./", ".uvproj");
if (fp_project == NULL)
{
print_msg(APP_NAME, "find project fail!");
fp_project = find_file_in_dir_by_name("./", ".uvprojx");
if (fp_project == NULL)
{
print_msg(APP_NAME, "find project fail!");
return 0;
}
}
while (1)
{
pos = file_sreach_string_get_pos(fp_project, "<Cpu>", SEEK_SET, pos);
if (-1 == pos)
{
print_msg(APP_NAME, "found cup info fail\n");
return 0;
}
fseek(fp_project, pos - 8, SEEK_SET);
fgets(str, 1000, fp_project);
if (strstr(str, "IRAM(0-"))
{
print_msg(APP_NAME, "cup is 8051\n");
mcu_8051.iram_max = str_get_hex(str, "IRAM(0-");
if(strstr(str, "XRAM(0-"))
mcu_8051.xram_max = str_get_hex(str, "XRAM(0-");
else
mcu_8051.xram_max = mcu_8051.iram_max;
mcu_8051.irom_max = str_get_hex(str, "IROM(0-");
// printf("iram_max:%d,xram_max:%d,irom_max:%d\n",mcu_8051.iram_max,mcu_8051.xram_max,mcu_8051.irom_max);
fclose(fp_project); // 关闭文件
fp_m51 = find_file_in_dir_by_name("./", ".m51");
pos = file_sreach_string_get_pos(fp_m51, "Program Size:", SEEK_SET, pos);
fgets(str, 1000, fp_project);
mcu_8051.iram_size = str_get_dec(str, "data=");
mcu_8051.irom_size = str_get_dec(str, "code=");
// printf("iram_size:%d,xram_size:%d,irom_size:%d\n",mcu_8051.iram_size,mcu_8051.xram_size,mcu_8051.irom_size);
prtint_percentage_bar("flash", 1, mcu_8051.irom_size, mcu_8051.irom_max);
prtint_percentage_bar("iram", 1, mcu_8051.iram_size, mcu_8051.iram_max);
if(strstr(str, "xdata="))
{
mcu_8051.xram_size = str_get_dec(str, "xdata=");
prtint_percentage_bar("xram", 1, mcu_8051.xram_size, mcu_8051.xram_max);
}
return 1;
}
else
{
return 0;
}
}
return 0;
}
void find_project_size_define(void)
{
FILE *fp_project=NULL;
int64_t pos = 0;
char str[1000];
char *ch_p = NULL;
// print_msg(APP_NAME, "find project satrt!");
fp_project = find_file_in_dir_by_name("./", ".uvproj");
if (fp_project == NULL)
{
fp_project = find_file_in_dir_by_name("./", ".uvprojx");
if (fp_project == NULL)
{
// print_msg(APP_NAME, "find project fail!");
return ;
}
}
while (1)
{
pos = file_sreach_string_get_pos(fp_project, "<Cpu>", SEEK_SET, pos);
if (-1 == pos)
{
print_msg(APP_NAME, "found cup info fail\n");
return;
}
fseek(fp_project, pos - 8, SEEK_SET);
fgets(str, 1000, fp_project);
if (ch_p = strstr(str, "IRAM("))
{
if(strstr(ch_p, ","))
{
ram_max_from_porject = str_get_hex(ch_p, ",");
ch_p = strstr(ch_p, ",");
ch_p++;
rom_max_from_porject = str_get_hex(ch_p, ",");
}
else if(strstr(ch_p, "-"))
{
ram_max_from_porject = str_get_hex(ch_p, "-");
ch_p = strstr(ch_p, "-");
ch_p++;
rom_max_from_porject = str_get_hex(ch_p, "-");
}
// print_msg(APP_NAME,"IARM:%d,IROM:%d\n",ram_max_from_porject,rom_max_from_porject);
return;
}
else
{
return;
}
}
fclose(fp_project); // 关闭文件
}
#endif

6
R.qrc Normal file
View File

@ -0,0 +1,6 @@
<RCC>
<qresource prefix="/">
<file>KDA_Logo.ico</file>
<file>gitee.png</file>
</qresource>
</RCC>

40
find_path.cpp Normal file
View File

@ -0,0 +1,40 @@
#include "find_path.h"
#include <QFile>
#include <QDebug>
#include <QDomDocument>
#include <QFileInfoList>
#include <QDir>
find_path::find_path()
{
}
QString find_path::find_file_path(const QString& dir_path,const QString& key_world)
{
QFileInfoList fileInfoList;
QString file_path="";
QDir dir(dir_path);
foreach(QFileInfo info,dir.entryInfoList(QDir::NoDotAndDotDot | QDir::Dirs)){
// qDebug()<<"dir:"<<info.filePath();
file_path=find_file_path(info.filePath(),key_world);
if(file_path!="")
return file_path;
}
foreach(QFileInfo info,dir.entryInfoList(QDir::Files)){
fileInfoList.append(info);
if(info.fileName().contains(key_world))
{
file_path=info.path()+"/"+info.fileName();
// qDebug()<<info.path()+"/"+info.fileName();
return file_path;
}
}
return file_path;
}

13
find_path.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef FIND_PATH_H
#define FIND_PATH_H
#include <QString>
class find_path
{
public:
find_path();
static QString find_file_path(const QString& dir_path,const QString& key_world);
};
#endif // FIND_PATH_H

170
flatui.cpp Normal file
View File

@ -0,0 +1,170 @@
#pragma execution_character_set("utf-8")
#include "flatui.h"
#include "qpushbutton.h"
#include "qlineedit.h"
#include "qprogressbar.h"
#include "qslider.h"
#include "qradiobutton.h"
#include "qcheckbox.h"
#include "qscrollbar.h"
#include "qdebug.h"
QString FlatUI::setPushButtonQss(QPushButton *btn, int radius, int padding,
const QString &normalColor,
const QString &normalTextColor,
const QString &hoverColor,
const QString &hoverTextColor,
const QString &pressedColor,
const QString &pressedTextColor)
{
QStringList list;
list.append(QString("QPushButton{border-style:none;padding:%1px;border-radius:%2px;color:%3;background:%4;}")
.arg(padding).arg(radius).arg(normalTextColor).arg(normalColor));
list.append(QString("QPushButton:hover{color:%1;background:%2;}")
.arg(hoverTextColor).arg(hoverColor));
list.append(QString("QPushButton:pressed{color:%1;background:%2;}")
.arg(pressedTextColor).arg(pressedColor));
QString qss = list.join("");
btn->setStyleSheet(qss);
return qss;
}
QString FlatUI::setLineEditQss(QLineEdit *txt, int radius, int borderWidth,
const QString &normalColor,
const QString &focusColor)
{
QStringList list;
list.append(QString("QLineEdit{border-style:none;padding:3px;border-radius:%1px;border:%2px solid %3;}")
.arg(radius).arg(borderWidth).arg(normalColor));
list.append(QString("QLineEdit:focus{border:%1px solid %2;}")
.arg(borderWidth).arg(focusColor));
QString qss = list.join("");
txt->setStyleSheet(qss);
return qss;
}
QString FlatUI::setProgressQss(QProgressBar *bar, int barHeight,
int barRadius, int fontSize,
const QString &normalColor,
const QString &chunkColor)
{
QStringList list;
list.append(QString("QProgressBar{color:#FFFFFF;font:%1px;background:%2;max-height:%3px;border-radius:%4px;text-align:center;border:1px solid %2;}")
.arg(fontSize).arg(normalColor).arg(barHeight).arg(barRadius));
list.append(QString("QProgressBar:chunk{border-radius:%2px;background-color:%1;}")
.arg(chunkColor).arg(barRadius));
QString qss = list.join("");
bar->setStyleSheet(qss);
return qss;
}
QString FlatUI::setSliderQss(QSlider *slider, int sliderHeight,
const QString &normalColor,
const QString &grooveColor,
const QString &handleBorderColor,
const QString &handleColor)
{
int sliderRadius = sliderHeight / 2;
int handleWidth = (sliderHeight * 3) / 2 + (sliderHeight / 5);
int handleRadius = handleWidth / 2;
int handleOffset = handleRadius / 2;
QStringList list;
list.append(QString("QSlider::horizontal{min-height:%1px;}").arg(sliderHeight * 2));
list.append(QString("QSlider::groove:horizontal{background:%1;height:%2px;border-radius:%3px;}")
.arg(normalColor).arg(sliderHeight).arg(sliderRadius));
list.append(QString("QSlider::add-page:horizontal{background:%1;height:%2px;border-radius:%3px;}")
.arg(normalColor).arg(sliderHeight).arg(sliderRadius));
list.append(QString("QSlider::sub-page:horizontal{background:%1;height:%2px;border-radius:%3px;}")
.arg(grooveColor).arg(sliderHeight).arg(sliderRadius));
list.append(QString("QSlider::handle:horizontal{width:%3px;margin-top:-%4px;margin-bottom:-%4px;border-radius:%5px;"
"background:qradialgradient(spread:pad,cx:0.5,cy:0.5,radius:0.5,fx:0.5,fy:0.5,stop:0.6 %1,stop:0.8 %2);}")
.arg(handleColor).arg(handleBorderColor).arg(handleWidth).arg(handleOffset).arg(handleRadius));
//偏移一个像素
handleWidth = handleWidth + 1;
list.append(QString("QSlider::vertical{min-width:%1px;}").arg(sliderHeight * 2));
list.append(QString("QSlider::groove:vertical{background:%1;width:%2px;border-radius:%3px;}")
.arg(normalColor).arg(sliderHeight).arg(sliderRadius));
list.append(QString("QSlider::add-page:vertical{background:%1;width:%2px;border-radius:%3px;}")
.arg(grooveColor).arg(sliderHeight).arg(sliderRadius));
list.append(QString("QSlider::sub-page:vertical{background:%1;width:%2px;border-radius:%3px;}")
.arg(normalColor).arg(sliderHeight).arg(sliderRadius));
list.append(QString("QSlider::handle:vertical{height:%3px;margin-left:-%4px;margin-right:-%4px;border-radius:%5px;"
"background:qradialgradient(spread:pad,cx:0.5,cy:0.5,radius:0.5,fx:0.5,fy:0.5,stop:0.6 %1,stop:0.8 %2);}")
.arg(handleColor).arg(handleBorderColor).arg(handleWidth).arg(handleOffset).arg(handleRadius));
QString qss = list.join("");
slider->setStyleSheet(qss);
return qss;
}
QString FlatUI::setRadioButtonQss(QRadioButton *rbtn, int indicatorRadius,
const QString &normalColor,
const QString &checkColor)
{
int indicatorWidth = indicatorRadius * 2;
QStringList list;
list.append(QString("QRadioButton::indicator{border-radius:%1px;width:%2px;height:%2px;}")
.arg(indicatorRadius).arg(indicatorWidth));
list.append(QString("QRadioButton::indicator::unchecked{background:qradialgradient(spread:pad,cx:0.5,cy:0.5,radius:0.5,fx:0.5,fy:0.5,"
"stop:0.6 #FFFFFF,stop:0.7 %1);}").arg(normalColor));
list.append(QString("QRadioButton::indicator::checked{background:qradialgradient(spread:pad,cx:0.5,cy:0.5,radius:0.5,fx:0.5,fy:0.5,"
"stop:0 %1,stop:0.3 %1,stop:0.4 #FFFFFF,stop:0.6 #FFFFFF,stop:0.7 %1);}").arg(checkColor));
QString qss = list.join("");
rbtn->setStyleSheet(qss);
return qss;
}
QString FlatUI::setScrollBarQss(QWidget *scroll, int radius, int min, int max,
const QString &bgColor,
const QString &handleNormalColor,
const QString &handleHoverColor,
const QString &handlePressedColor)
{
//滚动条离背景间隔
int padding = 0;
QStringList list;
//handle:指示器,滚动条拉动部分 add-page:滚动条拉动时增加的部分 sub-page:滚动条拉动时减少的部分 add-line:递增按钮 sub-line:递减按钮
//横向滚动条部分
list.append(QString("QScrollBar:horizontal{background:%1;padding:%2px;border-radius:%3px;min-height:%4px;max-height:%4px;}")
.arg(bgColor).arg(padding).arg(radius).arg(max));
list.append(QString("QScrollBar::handle:horizontal{background:%1;min-width:%2px;border-radius:%3px;}")
.arg(handleNormalColor).arg(min).arg(radius));
list.append(QString("QScrollBar::handle:horizontal:hover{background:%1;}")
.arg(handleHoverColor));
list.append(QString("QScrollBar::handle:horizontal:pressed{background:%1;}")
.arg(handlePressedColor));
list.append(QString("QScrollBar::add-page:horizontal{background:none;}"));
list.append(QString("QScrollBar::sub-page:horizontal{background:none;}"));
list.append(QString("QScrollBar::add-line:horizontal{background:none;}"));
list.append(QString("QScrollBar::sub-line:horizontal{background:none;}"));
//纵向滚动条部分
list.append(QString("QScrollBar:vertical{background:%1;padding:%2px;border-radius:%3px;min-width:%4px;max-width:%4px;}")
.arg(bgColor).arg(padding).arg(radius).arg(max));
list.append(QString("QScrollBar::handle:vertical{background:%1;min-height:%2px;border-radius:%3px;}")
.arg(handleNormalColor).arg(min).arg(radius));
list.append(QString("QScrollBar::handle:vertical:hover{background:%1;}")
.arg(handleHoverColor));
list.append(QString("QScrollBar::handle:vertical:pressed{background:%1;}")
.arg(handlePressedColor));
list.append(QString("QScrollBar::add-page:vertical{background:none;}"));
list.append(QString("QScrollBar::sub-page:vertical{background:none;}"));
list.append(QString("QScrollBar::add-line:vertical{background:none;}"));
list.append(QString("QScrollBar::sub-line:vertical{background:none;}"));
QString qss = list.join("");
scroll->setStyleSheet(qss);
return qss;
}

85
flatui.h Normal file
View File

@ -0,0 +1,85 @@
#ifndef FLATUI_H
#define FLATUI_H
/**
* FlatUI辅助类 :feiyangqingyun(QQ:517216493) 2016-12-16
* 1.
* 2.
* 3.
* 4.
* 5.
* 6.
* 7.
* 8.
*/
#include <QObject>
class QPushButton;
class QLineEdit;
class QProgressBar;
class QSlider;
class QRadioButton;
class QCheckBox;
class QScrollBar;
#ifdef quc
class Q_DECL_EXPORT FlatUI
#else
class FlatUI
#endif
{
public:
//设置按钮样式
static QString setPushButtonQss(QPushButton *btn, //按钮对象
int radius = 5, //圆角半径
int padding = 8, //间距
const QString &normalColor = "#34495E", //正常颜色
const QString &normalTextColor = "#FFFFFF", //文字颜色
const QString &hoverColor = "#4E6D8C", //悬停颜色
const QString &hoverTextColor = "#F0F0F0", //悬停文字颜色
const QString &pressedColor = "#2D3E50", //按下颜色
const QString &pressedTextColor = "#B8C6D1"); //按下文字颜色
//设置文本框样式
static QString setLineEditQss(QLineEdit *txt, //文本框对象
int radius = 3, //圆角半径
int borderWidth = 2, //边框大小
const QString &normalColor = "#DCE4EC", //正常颜色
const QString &focusColor = "#34495E"); //选中颜色
//设置进度条样式
static QString setProgressQss(QProgressBar *bar,
int barHeight = 8, //进度条高度
int barRadius = 5, //进度条半径
int fontSize = 12, //文字字号
const QString &normalColor = "#E8EDF2", //正常颜色
const QString &chunkColor = "#E74C3C"); //进度颜色
//设置滑块条样式
static QString setSliderQss(QSlider *slider, //滑动条对象
int sliderHeight = 8, //滑动条高度
const QString &normalColor = "#E8EDF2", //正常颜色
const QString &grooveColor = "#1ABC9C", //滑块颜色
const QString &handleBorderColor = "#1ABC9C", //指示器边框颜色
const QString &handleColor = "#FFFFFF"); //指示器颜色
//设置单选框样式
static QString setRadioButtonQss(QRadioButton *rbtn, //单选框对象
int indicatorRadius = 8, //指示器圆角角度
const QString &normalColor = "#D7DBDE", //正常颜色
const QString &checkColor = "#34495E"); //选中颜色
//设置滚动条样式
static QString setScrollBarQss(QWidget *scroll, //滚动条对象
int radius = 6, //圆角角度
int min = 120, //指示器最小长度
int max = 12, //滚动条最大长度
const QString &bgColor = "#606060", //背景色
const QString &handleNormalColor = "#34495E", //指示器正常颜色
const QString &handleHoverColor = "#1ABC9C", //指示器悬停颜色
const QString &handlePressedColor = "#E74C3C"); //指示器按下颜色
};
#endif // FLATUI_H

View File

@ -0,0 +1,9 @@
HEADERS += \
$$PWD/framelessdialog.h \
$$PWD/framelessmainwindow.h \
$$PWD/framelesswidget.h
SOURCES += \
$$PWD/framelessdialog.cpp \
$$PWD/framelessmainwindow.cpp \
$$PWD/framelesswidget.cpp

View File

@ -0,0 +1,377 @@
#include "framelessdialog.h"
#include "qdatetime.h"
#include "qevent.h"
#include "qdebug.h"
#ifdef Q_OS_WIN
#include "windows.h"
#include "windowsx.h"
#pragma comment (lib,"user32.lib")
#endif
#define TIMEMS qPrintable(QTime::currentTime().toString("HH:mm:ss zzz"))
FramelessDialog::FramelessDialog(QWidget *parent) : QDialog(parent)
{
padding = 8;
moveEnable = true;
resizeEnable = true;
mousePressed = false;
mousePoint = QPoint(0, 0);
mouseRect = QRect(0, 0, 0, 0);
for (int i = 0; i < 8; ++i) {
pressedArea << false;
pressedRect << QRect(0, 0, 0, 0);
}
isMin = false;
flags = this->windowFlags();
titleBar = 0;
//设置背景透明 官方在5.3以后才彻底修复 WA_TranslucentBackground+FramelessWindowHint 并存不绘制的bug
#if (QT_VERSION >= QT_VERSION_CHECK(5,3,0))
this->setAttribute(Qt::WA_TranslucentBackground);
#endif
//设置无边框属性
this->setWindowFlags(flags | Qt::FramelessWindowHint);
//安装事件过滤器识别拖动
this->installEventFilter(this);
//设置属性产生win窗体效果,移动到边缘半屏或者最大化等
//设置以后会产生标题栏需要在下面拦截消息重新去掉
#ifdef Q_OS_WIN
HWND hwnd = (HWND)this->winId();
DWORD style = ::GetWindowLong(hwnd, GWL_STYLE);
::SetWindowLong(hwnd, GWL_STYLE, style | WS_MAXIMIZEBOX | WS_THICKFRAME | WS_CAPTION);
#endif
}
void FramelessDialog::showEvent(QShowEvent *event)
{
//解决有时候窗体重新显示的时候假死不刷新的bug
setAttribute(Qt::WA_Mapped);
QDialog::showEvent(event);
}
void FramelessDialog::doWindowStateChange(QEvent *event)
{
//非最大化才能移动和拖动大小
if (windowState() == Qt::WindowNoState) {
moveEnable = true;
resizeEnable = true;
} else {
moveEnable = false;
resizeEnable = false;
}
//发出最大化最小化等改变事件,以便界面上更改对应的信息比如右上角图标和文字
emit windowStateChange(!moveEnable);
//解决mac系统上无边框最小化失效的bug
#ifdef Q_OS_MACOS
if (windowState() & Qt::WindowMinimized) {
isMin = true;
} else {
if (isMin) {
//设置无边框属性
this->setWindowFlags(flags | Qt::FramelessWindowHint);
this->setVisible(true);
isMin = false;
}
}
#endif
}
void FramelessDialog::doResizeEvent(QEvent *event)
{
//非win系统的无边框拉伸,win系统上已经采用了nativeEvent来处理拉伸
//为何不统一用计算的方式因为在win上用这个方式往左拉伸会发抖妹的
#ifndef Q_OS_WIN
if (event->type() == QEvent::Resize) {
//重新计算八个描点的区域,描点区域的作用还有就是计算鼠标坐标是否在某一个区域内
int width = this->width();
int height = this->height();
//左侧描点区域
pressedRect[0] = QRect(0, padding, padding, height - padding * 2);
//右侧描点区域
pressedRect[1] = QRect(width - padding, padding, padding, height - padding * 2);
//上侧描点区域
pressedRect[2] = QRect(padding, 0, width - padding * 2, padding);
//下侧描点区域
pressedRect[3] = QRect(padding, height - padding, width - padding * 2, padding);
//左上角描点区域
pressedRect[4] = QRect(0, 0, padding, padding);
//右上角描点区域
pressedRect[5] = QRect(width - padding, 0, padding, padding);
//左下角描点区域
pressedRect[6] = QRect(0, height - padding, padding, padding);
//右下角描点区域
pressedRect[7] = QRect(width - padding, height - padding, padding, padding);
} else if (event->type() == QEvent::HoverMove) {
//设置对应鼠标形状,这个必须放在这里而不是下面,因为可以在鼠标没有按下的时候识别
QHoverEvent *hoverEvent = (QHoverEvent *)event;
QPoint point = hoverEvent->pos();
if (resizeEnable) {
if (pressedRect.at(0).contains(point)) {
this->setCursor(Qt::SizeHorCursor);
} else if (pressedRect.at(1).contains(point)) {
this->setCursor(Qt::SizeHorCursor);
} else if (pressedRect.at(2).contains(point)) {
this->setCursor(Qt::SizeVerCursor);
} else if (pressedRect.at(3).contains(point)) {
this->setCursor(Qt::SizeVerCursor);
} else if (pressedRect.at(4).contains(point)) {
this->setCursor(Qt::SizeFDiagCursor);
} else if (pressedRect.at(5).contains(point)) {
this->setCursor(Qt::SizeBDiagCursor);
} else if (pressedRect.at(6).contains(point)) {
this->setCursor(Qt::SizeBDiagCursor);
} else if (pressedRect.at(7).contains(point)) {
this->setCursor(Qt::SizeFDiagCursor);
} else {
this->setCursor(Qt::ArrowCursor);
}
}
//根据当前鼠标位置,计算XY轴移动了多少
int offsetX = point.x() - mousePoint.x();
int offsetY = point.y() - mousePoint.y();
//根据按下处的位置判断是否是移动控件还是拉伸控件
if (moveEnable && mousePressed) {
this->move(this->x() + offsetX, this->y() + offsetY);
}
if (resizeEnable) {
int rectX = mouseRect.x();
int rectY = mouseRect.y();
int rectW = mouseRect.width();
int rectH = mouseRect.height();
if (pressedArea.at(0)) {
int resizeW = this->width() - offsetX;
if (this->minimumWidth() <= resizeW) {
this->setGeometry(this->x() + offsetX, rectY, resizeW, rectH);
}
} else if (pressedArea.at(1)) {
this->setGeometry(rectX, rectY, rectW + offsetX, rectH);
} else if (pressedArea.at(2)) {
int resizeH = this->height() - offsetY;
if (this->minimumHeight() <= resizeH) {
this->setGeometry(rectX, this->y() + offsetY, rectW, resizeH);
}
} else if (pressedArea.at(3)) {
this->setGeometry(rectX, rectY, rectW, rectH + offsetY);
} else if (pressedArea.at(4)) {
int resizeW = this->width() - offsetX;
int resizeH = this->height() - offsetY;
if (this->minimumWidth() <= resizeW) {
this->setGeometry(this->x() + offsetX, this->y(), resizeW, resizeH);
}
if (this->minimumHeight() <= resizeH) {
this->setGeometry(this->x(), this->y() + offsetY, resizeW, resizeH);
}
} else if (pressedArea.at(5)) {
int resizeW = rectW + offsetX;
int resizeH = this->height() - offsetY;
if (this->minimumHeight() <= resizeH) {
this->setGeometry(this->x(), this->y() + offsetY, resizeW, resizeH);
}
} else if (pressedArea.at(6)) {
int resizeW = this->width() - offsetX;
int resizeH = rectH + offsetY;
if (this->minimumWidth() <= resizeW) {
this->setGeometry(this->x() + offsetX, this->y(), resizeW, resizeH);
}
if (this->minimumHeight() <= resizeH) {
this->setGeometry(this->x(), this->y(), resizeW, resizeH);
}
} else if (pressedArea.at(7)) {
int resizeW = rectW + offsetX;
int resizeH = rectH + offsetY;
this->setGeometry(this->x(), this->y(), resizeW, resizeH);
}
}
} else if (event->type() == QEvent::MouseButtonPress) {
//记住鼠标按下的坐标+窗体区域
QMouseEvent *mouseEvent = (QMouseEvent *)event;
mousePoint = mouseEvent->pos();
mouseRect = this->geometry();
//判断按下的手柄的区域位置
if (pressedRect.at(0).contains(mousePoint)) {
pressedArea[0] = true;
} else if (pressedRect.at(1).contains(mousePoint)) {
pressedArea[1] = true;
} else if (pressedRect.at(2).contains(mousePoint)) {
pressedArea[2] = true;
} else if (pressedRect.at(3).contains(mousePoint)) {
pressedArea[3] = true;
} else if (pressedRect.at(4).contains(mousePoint)) {
pressedArea[4] = true;
} else if (pressedRect.at(5).contains(mousePoint)) {
pressedArea[5] = true;
} else if (pressedRect.at(6).contains(mousePoint)) {
pressedArea[6] = true;
} else if (pressedRect.at(7).contains(mousePoint)) {
pressedArea[7] = true;
} else {
mousePressed = true;
}
} else if (event->type() == QEvent::MouseMove) {
//改成用HoverMove识别
} else if (event->type() == QEvent::MouseButtonRelease) {
//恢复所有
this->setCursor(Qt::ArrowCursor);
mousePressed = false;
for (int i = 0; i < 8; ++i) {
pressedArea[i] = false;
}
}
#endif
}
bool FramelessDialog::eventFilter(QObject *watched, QEvent *event)
{
if (watched == this) {
if (event->type() == QEvent::WindowStateChange) {
doWindowStateChange(event);
} else {
doResizeEvent(event);
}
} else if (watched == titleBar) {
//双击标题栏发出双击信号给主界面
//下面的 *result = HTCAPTION; 标志位也会自动识别双击标题栏
#ifndef Q_OS_WIN
if (event->type() == QEvent::MouseButtonDblClick) {
emit titleDblClick();
} else if (event->type() == QEvent::NonClientAreaMouseButtonDblClick) {
emit titleDblClick();
}
#endif
}
return QDialog::eventFilter(watched, event);
}
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
bool FramelessDialog::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
#else
bool FramelessDialog::nativeEvent(const QByteArray &eventType, void *message, long *result)
#endif
{
if (eventType == "windows_generic_MSG") {
#ifdef Q_OS_WIN
MSG *msg = static_cast<MSG *>(message);
//qDebug() << TIMEMS << "nativeEvent" << msg->wParam << msg->message;
//不同的消息类型和参数进行不同的处理
if (msg->message == WM_NCCALCSIZE) {
*result = 0;
return true;
} else if (msg->message == WM_SYSKEYDOWN) {
//屏蔽alt键按下
} else if (msg->message == WM_SYSKEYUP) {
//屏蔽alt键松开
} else if (msg->message == WM_NCHITTEST) {
//计算鼠标对应的屏幕坐标
//这里最开始用的 LOWORD HIWORD 在多屏幕的时候会有问题
//官方说明在这里 https://docs.microsoft.com/zh-cn/windows/win32/inputdev/wm-nchittest
long x = GET_X_LPARAM(msg->lParam);
long y = GET_Y_LPARAM(msg->lParam);
QPoint pos = mapFromGlobal(QPoint(x, y));
//判断当前鼠标位置在哪个区域
bool left = pos.x() < padding;
bool right = pos.x() > width() - padding;
bool top = pos.y() < padding;
bool bottom = pos.y() > height() - padding;
//鼠标移动到四个角,这个消息是当鼠标移动或者有鼠标键按下时候发出的
*result = 0;
if (resizeEnable) {
if (left && top) {
*result = HTTOPLEFT;
} else if (left && bottom) {
*result = HTBOTTOMLEFT;
} else if (right && top) {
*result = HTTOPRIGHT;
} else if (right && bottom) {
*result = HTBOTTOMRIGHT;
} else if (left) {
*result = HTLEFT;
} else if (right) {
*result = HTRIGHT;
} else if (top) {
*result = HTTOP;
} else if (bottom) {
*result = HTBOTTOM;
}
}
//先处理掉拉伸
if (0 != *result) {
return true;
}
//识别标题栏拖动产生半屏全屏效果
if (titleBar && titleBar->rect().contains(pos)) {
QWidget *child = titleBar->childAt(pos);
if (!child) {
*result = HTCAPTION;
return true;
}
}
} else if (msg->wParam == PBT_APMSUSPEND && msg->message == WM_POWERBROADCAST) {
//系统休眠的时候自动最小化可以规避程序可能出现的问题
this->showMinimized();
} else if (msg->wParam == PBT_APMRESUMEAUTOMATIC) {
//休眠唤醒后自动打开
this->showNormal();
}
#endif
} else if (eventType == "NSEvent") {
#ifdef Q_OS_MACOS
#endif
} else if (eventType == "xcb_generic_event_t") {
#ifdef Q_OS_LINUX
#endif
}
return false;
}
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#ifdef Q_OS_WIN
bool FramelessDialog::winEvent(MSG *message, long *result)
{
return nativeEvent("windows_generic_MSG", message, result);
}
#endif
#endif
void FramelessDialog::setPadding(int padding)
{
this->padding = padding;
}
void FramelessDialog::setMoveEnable(bool moveEnable)
{
this->moveEnable = moveEnable;
}
void FramelessDialog::setResizeEnable(bool resizeEnable)
{
this->resizeEnable = resizeEnable;
}
void FramelessDialog::setTitleBar(QWidget *titleBar)
{
this->titleBar = titleBar;
this->titleBar->installEventFilter(this);
}

View File

@ -0,0 +1,96 @@
#ifndef FRAMELESSDIALOG_H
#define FRAMELESSDIALOG_H
/**
* :feiyangqingyun(QQ:517216493) 2021-07-27
* 1. Qt4-Qt6Qt4.7Qt6.2
* 2. mingwmsvcgcc等
* 3. windowslinuxmac
* 4. QMainWindowQWidgetQDialog
* 5. 使
* 6.
* 7. windows下不抖动
* 8. windows下具有移动到边缘半屏
* 9. mac系统上无边框最小化最大化失效的bug
* 10. bug
* 11. bug
* 12. 1300
* 13.
* 14. Qt版本可正常编译运行
*/
#include <QDialog>
#ifdef quc
class Q_DECL_EXPORT FramelessDialog : public QDialog
#else
class FramelessDialog : public QDialog
#endif
{
Q_OBJECT
public:
explicit FramelessDialog(QWidget *parent = 0);
protected:
//窗体显示的时候触发
void showEvent(QShowEvent *event);
//事件过滤器识别拖动拉伸等
void doWindowStateChange(QEvent *event);
void doResizeEvent(QEvent *event);
bool eventFilter(QObject *watched, QEvent *event);
//拦截系统事件用于修复系统休眠后唤醒程序的bug
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result);
#else
bool nativeEvent(const QByteArray &eventType, void *message, long *result);
#endif
//Qt4的写法
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#ifdef Q_OS_WIN
bool winEvent(MSG *message, long *result);
#endif
#endif
private:
//边距+可移动+可拉伸
int padding;
bool moveEnable;
bool resizeEnable;
//标题栏控件
QWidget *titleBar;
//鼠标是否按下+按下坐标+按下时窗体区域
bool mousePressed;
QPoint mousePoint;
QRect mouseRect;
//鼠标是否按下某个区域+按下区域的大小
//依次为 左侧+右侧+上侧+下侧+左上侧+右上侧+左下侧+右下侧
QList<bool> pressedArea;
QList<QRect> pressedRect;
//记录是否最小化
bool isMin;
//存储窗体默认的属性
Qt::WindowFlags flags;
public Q_SLOTS:
//设置边距+可拖动+可拉伸
void setPadding(int padding);
void setMoveEnable(bool moveEnable);
void setResizeEnable(bool resizeEnable);
//设置标题栏控件
void setTitleBar(QWidget *titleBar);
Q_SIGNALS:
void titleDblClick();
void windowStateChange(bool max);
};
#endif // FRAMELESSDIALOG_H

View File

@ -0,0 +1,375 @@
#include "framelessmainwindow.h"
#include "qdatetime.h"
#include "qevent.h"
#include "qdebug.h"
#ifdef Q_OS_WIN
#include "windows.h"
#include "windowsx.h"
#pragma comment (lib,"user32.lib")
#endif
#define TIMEMS qPrintable(QTime::currentTime().toString("HH:mm:ss zzz"))
FramelessMainWindow::FramelessMainWindow(QWidget *parent) : QMainWindow(parent)
{
padding = 8;
moveEnable = true;
resizeEnable = true;
mousePressed = false;
mousePoint = QPoint(0, 0);
mouseRect = QRect(0, 0, 0, 0);
for (int i = 0; i < 8; ++i) {
pressedArea << false;
pressedRect << QRect(0, 0, 0, 0);
}
isMin = false;
flags = this->windowFlags();
titleBar = 0;
//设置背景透明 官方在5.3以后才彻底修复 WA_TranslucentBackground+FramelessWindowHint 并存不绘制的bug
#if (QT_VERSION >= QT_VERSION_CHECK(5,3,0))
this->setAttribute(Qt::WA_TranslucentBackground);
#endif
//设置无边框属性
this->setWindowFlags(flags | Qt::FramelessWindowHint);
//安装事件过滤器识别拖动
this->installEventFilter(this);
//设置属性产生win窗体效果,移动到边缘半屏或者最大化等
//设置以后会产生标题栏,需要在下面拦截消息WM_NCCALCSIZE重新去掉
#ifdef Q_OS_WIN
HWND hwnd = (HWND)this->winId();
DWORD style = ::GetWindowLong(hwnd, GWL_STYLE);
::SetWindowLong(hwnd, GWL_STYLE, style | WS_MAXIMIZEBOX | WS_THICKFRAME | WS_CAPTION);
#endif
}
void FramelessMainWindow::showEvent(QShowEvent *event)
{
//解决有时候窗体重新显示的时候假死不刷新的bug
setAttribute(Qt::WA_Mapped);
QMainWindow::showEvent(event);
}
void FramelessMainWindow::doWindowStateChange(QEvent *event)
{
//非最大化才能移动和拖动大小
if (windowState() == Qt::WindowNoState) {
moveEnable = true;
resizeEnable = true;
} else {
moveEnable = false;
resizeEnable = false;
}
//发出最大化最小化等改变事件,以便界面上更改对应的信息比如右上角图标和文字
emit windowStateChange(!moveEnable);
//解决mac系统上无边框最小化失效的bug
#ifdef Q_OS_MACOS
if (windowState() & Qt::WindowMinimized) {
isMin = true;
} else {
if (isMin) {
//设置无边框属性
this->setWindowFlags(flags | Qt::FramelessWindowHint);
this->setVisible(true);
isMin = false;
}
}
#endif
}
void FramelessMainWindow::doResizeEvent(QEvent *event)
{
//非win系统的无边框拉伸,win系统上已经采用了nativeEvent来处理拉伸
//为何不统一用计算的方式因为在win上用这个方式往左拉伸会发抖妹的
#ifndef Q_OS_WIN
if (event->type() == QEvent::Resize) {
//重新计算八个描点的区域,描点区域的作用还有就是计算鼠标坐标是否在某一个区域内
int width = this->width();
int height = this->height();
//左侧描点区域
pressedRect[0] = QRect(0, padding, padding, height - padding * 2);
//右侧描点区域
pressedRect[1] = QRect(width - padding, padding, padding, height - padding * 2);
//上侧描点区域
pressedRect[2] = QRect(padding, 0, width - padding * 2, padding);
//下侧描点区域
pressedRect[3] = QRect(padding, height - padding, width - padding * 2, padding);
//左上角描点区域
pressedRect[4] = QRect(0, 0, padding, padding);
//右上角描点区域
pressedRect[5] = QRect(width - padding, 0, padding, padding);
//左下角描点区域
pressedRect[6] = QRect(0, height - padding, padding, padding);
//右下角描点区域
pressedRect[7] = QRect(width - padding, height - padding, padding, padding);
} else if (event->type() == QEvent::HoverMove) {
//设置对应鼠标形状,这个必须放在这里而不是下面,因为可以在鼠标没有按下的时候识别
QHoverEvent *hoverEvent = (QHoverEvent *)event;
QPoint point = hoverEvent->pos();
if (resizeEnable) {
if (pressedRect.at(0).contains(point)) {
this->setCursor(Qt::SizeHorCursor);
} else if (pressedRect.at(1).contains(point)) {
this->setCursor(Qt::SizeHorCursor);
} else if (pressedRect.at(2).contains(point)) {
this->setCursor(Qt::SizeVerCursor);
} else if (pressedRect.at(3).contains(point)) {
this->setCursor(Qt::SizeVerCursor);
} else if (pressedRect.at(4).contains(point)) {
this->setCursor(Qt::SizeFDiagCursor);
} else if (pressedRect.at(5).contains(point)) {
this->setCursor(Qt::SizeBDiagCursor);
} else if (pressedRect.at(6).contains(point)) {
this->setCursor(Qt::SizeBDiagCursor);
} else if (pressedRect.at(7).contains(point)) {
this->setCursor(Qt::SizeFDiagCursor);
} else {
this->setCursor(Qt::ArrowCursor);
}
}
//根据当前鼠标位置,计算XY轴移动了多少
int offsetX = point.x() - mousePoint.x();
int offsetY = point.y() - mousePoint.y();
//根据按下处的位置判断是否是移动控件还是拉伸控件
if (moveEnable && mousePressed) {
this->move(this->x() + offsetX, this->y() + offsetY);
}
if (resizeEnable) {
int rectX = mouseRect.x();
int rectY = mouseRect.y();
int rectW = mouseRect.width();
int rectH = mouseRect.height();
if (pressedArea.at(0)) {
int resizeW = this->width() - offsetX;
if (this->minimumWidth() <= resizeW) {
this->setGeometry(this->x() + offsetX, rectY, resizeW, rectH);
}
} else if (pressedArea.at(1)) {
this->setGeometry(rectX, rectY, rectW + offsetX, rectH);
} else if (pressedArea.at(2)) {
int resizeH = this->height() - offsetY;
if (this->minimumHeight() <= resizeH) {
this->setGeometry(rectX, this->y() + offsetY, rectW, resizeH);
}
} else if (pressedArea.at(3)) {
this->setGeometry(rectX, rectY, rectW, rectH + offsetY);
} else if (pressedArea.at(4)) {
int resizeW = this->width() - offsetX;
int resizeH = this->height() - offsetY;
if (this->minimumWidth() <= resizeW) {
this->setGeometry(this->x() + offsetX, this->y(), resizeW, resizeH);
}
if (this->minimumHeight() <= resizeH) {
this->setGeometry(this->x(), this->y() + offsetY, resizeW, resizeH);
}
} else if (pressedArea.at(5)) {
int resizeW = rectW + offsetX;
int resizeH = this->height() - offsetY;
if (this->minimumHeight() <= resizeH) {
this->setGeometry(this->x(), this->y() + offsetY, resizeW, resizeH);
}
} else if (pressedArea.at(6)) {
int resizeW = this->width() - offsetX;
int resizeH = rectH + offsetY;
if (this->minimumWidth() <= resizeW) {
this->setGeometry(this->x() + offsetX, this->y(), resizeW, resizeH);
}
if (this->minimumHeight() <= resizeH) {
this->setGeometry(this->x(), this->y(), resizeW, resizeH);
}
} else if (pressedArea.at(7)) {
int resizeW = rectW + offsetX;
int resizeH = rectH + offsetY;
this->setGeometry(this->x(), this->y(), resizeW, resizeH);
}
}
} else if (event->type() == QEvent::MouseButtonPress) {
//记住鼠标按下的坐标+窗体区域
QMouseEvent *mouseEvent = (QMouseEvent *)event;
mousePoint = mouseEvent->pos();
mouseRect = this->geometry();
//判断按下的手柄的区域位置
if (pressedRect.at(0).contains(mousePoint)) {
pressedArea[0] = true;
} else if (pressedRect.at(1).contains(mousePoint)) {
pressedArea[1] = true;
} else if (pressedRect.at(2).contains(mousePoint)) {
pressedArea[2] = true;
} else if (pressedRect.at(3).contains(mousePoint)) {
pressedArea[3] = true;
} else if (pressedRect.at(4).contains(mousePoint)) {
pressedArea[4] = true;
} else if (pressedRect.at(5).contains(mousePoint)) {
pressedArea[5] = true;
} else if (pressedRect.at(6).contains(mousePoint)) {
pressedArea[6] = true;
} else if (pressedRect.at(7).contains(mousePoint)) {
pressedArea[7] = true;
} else {
mousePressed = true;
}
} else if (event->type() == QEvent::MouseMove) {
//改成用HoverMove识别
} else if (event->type() == QEvent::MouseButtonRelease) {
//恢复所有
this->setCursor(Qt::ArrowCursor);
mousePressed = false;
for (int i = 0; i < 8; ++i) {
pressedArea[i] = false;
}
}
#endif
}
bool FramelessMainWindow::eventFilter(QObject *watched, QEvent *event)
{
if (watched == this) {
if (event->type() == QEvent::WindowStateChange) {
doWindowStateChange(event);
} else {
doResizeEvent(event);
}
} else if (watched == titleBar) {
//双击标题栏发出双击信号给主界面
//下面的 *result = HTCAPTION; 标志位也会自动识别双击标题栏
#ifndef Q_OS_WIN
if (event->type() == QEvent::MouseButtonDblClick) {
emit titleDblClick();
} else if (event->type() == QEvent::NonClientAreaMouseButtonDblClick) {
emit titleDblClick();
}
#endif
}
return QMainWindow::eventFilter(watched, event);
}
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
bool FramelessMainWindow::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
#else
bool FramelessMainWindow::nativeEvent(const QByteArray &eventType, void *message, long *result)
#endif
{
if (eventType == "windows_generic_MSG") {
#ifdef Q_OS_WIN
MSG *msg = static_cast<MSG *>(message);
//qDebug() << TIMEMS << "nativeEvent" << msg->wParam << msg->message;
//不同的消息类型和参数进行不同的处理
if (msg->message == WM_NCCALCSIZE) {
*result = 0;
return true;
} else if (msg->message == WM_SYSKEYDOWN) {
//屏蔽alt键按下
} else if (msg->message == WM_SYSKEYUP) {
//屏蔽alt键松开
} else if (msg->message == WM_NCHITTEST) {
//计算鼠标对应的屏幕坐标
//这里最开始用的 LOWORD HIWORD 在多屏幕的时候会有问题
//官方说明在这里 https://docs.microsoft.com/zh-cn/windows/win32/inputdev/wm-nchittest
long x = GET_X_LPARAM(msg->lParam);
long y = GET_Y_LPARAM(msg->lParam);
QPoint pos = mapFromGlobal(QPoint(x, y));
//判断当前鼠标位置在哪个区域
bool left = pos.x() < padding;
bool right = pos.x() > width() - padding;
bool top = pos.y() < padding;
bool bottom = pos.y() > height() - padding;
//鼠标移动到四个角,这个消息是当鼠标移动或者有鼠标键按下时候发出的
*result = 0;
if (resizeEnable) {
if (left && top) {
*result = HTTOPLEFT;
} else if (left && bottom) {
*result = HTBOTTOMLEFT;
} else if (right && top) {
*result = HTTOPRIGHT;
} else if (right && bottom) {
*result = HTBOTTOMRIGHT;
} else if (left) {
*result = HTLEFT;
} else if (right) {
*result = HTRIGHT;
} else if (top) {
*result = HTTOP;
} else if (bottom) {
*result = HTBOTTOM;
}
}
//先处理掉拉伸
if (0 != *result) {
return true;
}
//识别标题栏拖动产生半屏全屏效果
if (titleBar && titleBar->rect().contains(pos)) {
QWidget *child = titleBar->childAt(pos);
if (!child) {
*result = HTCAPTION;
return true;
}
}
} else if (msg->wParam == PBT_APMSUSPEND && msg->message == WM_POWERBROADCAST) {
//系统休眠的时候自动最小化可以规避程序可能出现的问题
this->showMinimized();
} else if (msg->wParam == PBT_APMRESUMEAUTOMATIC) {
//休眠唤醒后自动打开
this->showNormal();
}
#endif
} else if (eventType == "NSEvent") {
#ifdef Q_OS_MACOS
#endif
} else if (eventType == "xcb_generic_event_t") {
#ifdef Q_OS_LINUX
#endif
}
return false;
}
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#ifdef Q_OS_WIN
bool FramelessMainWindow::winEvent(MSG *message, long *result)
{
return nativeEvent("windows_generic_MSG", message, result);
}
#endif
#endif
void FramelessMainWindow::setPadding(int padding)
{
this->padding = padding;
}
void FramelessMainWindow::setMoveEnable(bool moveEnable)
{
this->moveEnable = moveEnable;
}
void FramelessMainWindow::setResizeEnable(bool resizeEnable)
{
this->resizeEnable = resizeEnable;
}
void FramelessMainWindow::setTitleBar(QWidget *titleBar)
{
this->titleBar = titleBar;
this->titleBar->installEventFilter(this);
}

View File

@ -0,0 +1,96 @@
#ifndef FRAMELESSMAINWINDOW_H
#define FRAMELESSMAINWINDOW_H
/**
* :feiyangqingyun(QQ:517216493) 2021-07-27
* 1. Qt4-Qt6Qt4.7Qt6.2
* 2. mingwmsvcgcc等
* 3. windowslinuxmac
* 4. QMainWindowQWidgetQDialog
* 5. 使
* 6.
* 7. windows下不抖动
* 8. windows下具有移动到边缘半屏
* 9. mac系统上无边框最小化最大化失效的bug
* 10. bug
* 11. bug
* 12. 1300
* 13.
* 14. Qt版本可正常编译运行
*/
#include <QMainWindow>
#ifdef quc
class Q_DECL_EXPORT FramelessMainWindow : public QMainWindow
#else
class FramelessMainWindow : public QMainWindow
#endif
{
Q_OBJECT
public:
explicit FramelessMainWindow(QWidget *parent = 0);
protected:
//窗体显示的时候触发
void showEvent(QShowEvent *event);
//事件过滤器识别拖动拉伸等
void doWindowStateChange(QEvent *event);
void doResizeEvent(QEvent *event);
bool eventFilter(QObject *watched, QEvent *event);
//拦截系统事件用于修复系统休眠后唤醒程序的bug
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result);
#else
bool nativeEvent(const QByteArray &eventType, void *message, long *result);
#endif
//Qt4的写法
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#ifdef Q_OS_WIN
bool winEvent(MSG *message, long *result);
#endif
#endif
private:
//边距+可移动+可拉伸
int padding;
bool moveEnable;
bool resizeEnable;
//标题栏控件
QWidget *titleBar;
//鼠标是否按下+按下坐标+按下时窗体区域
bool mousePressed;
QPoint mousePoint;
QRect mouseRect;
//鼠标是否按下某个区域+按下区域的大小
//依次为 左侧+右侧+上侧+下侧+左上侧+右上侧+左下侧+右下侧
QList<bool> pressedArea;
QList<QRect> pressedRect;
//记录是否最小化
bool isMin;
//存储窗体默认的属性
Qt::WindowFlags flags;
public Q_SLOTS:
//设置边距+可拖动+可拉伸
void setPadding(int padding);
void setMoveEnable(bool moveEnable);
void setResizeEnable(bool resizeEnable);
//设置标题栏控件
void setTitleBar(QWidget *titleBar);
Q_SIGNALS:
void titleDblClick();
void windowStateChange(bool max);
};
#endif // FRAMELESSMAINWINDOW_H

View File

@ -0,0 +1,377 @@
#include "framelesswidget.h"
#include "qdatetime.h"
#include "qevent.h"
#include "qdebug.h"
#ifdef Q_OS_WIN
#include "windows.h"
#include "windowsx.h"
#pragma comment (lib,"user32.lib")
#endif
#define TIMEMS qPrintable(QTime::currentTime().toString("HH:mm:ss zzz"))
FramelessWidget::FramelessWidget(QWidget *parent) : QWidget(parent)
{
padding = 8;
moveEnable = true;
resizeEnable = true;
mousePressed = false;
mousePoint = QPoint(0, 0);
mouseRect = QRect(0, 0, 0, 0);
for (int i = 0; i < 8; ++i) {
pressedArea << false;
pressedRect << QRect(0, 0, 0, 0);
}
isMin = false;
flags = this->windowFlags();
titleBar = 0;
//设置背景透明 官方在5.3以后才彻底修复 WA_TranslucentBackground+FramelessWindowHint 并存不绘制的bug
#if (QT_VERSION >= QT_VERSION_CHECK(5,3,0))
this->setAttribute(Qt::WA_TranslucentBackground);
#endif
//设置无边框属性
this->setWindowFlags(flags | Qt::FramelessWindowHint);
//安装事件过滤器识别拖动
this->installEventFilter(this);
//设置属性产生win窗体效果,移动到边缘半屏或者最大化等
//设置以后会产生标题栏需要在下面拦截消息重新去掉
#ifdef Q_OS_WIN
HWND hwnd = (HWND)this->winId();
DWORD style = ::GetWindowLong(hwnd, GWL_STYLE);
::SetWindowLong(hwnd, GWL_STYLE, style | WS_MAXIMIZEBOX | WS_THICKFRAME | WS_CAPTION);
#endif
}
void FramelessWidget::showEvent(QShowEvent *event)
{
//解决有时候窗体重新显示的时候假死不刷新的bug
setAttribute(Qt::WA_Mapped);
QWidget::showEvent(event);
}
void FramelessWidget::doWindowStateChange(QEvent *event)
{
//非最大化才能移动和拖动大小
if (windowState() == Qt::WindowNoState) {
moveEnable = true;
resizeEnable = true;
} else {
moveEnable = false;
resizeEnable = false;
}
//发出最大化最小化等改变事件,以便界面上更改对应的信息比如右上角图标和文字
emit windowStateChange(!moveEnable);
//解决mac系统上无边框最小化失效的bug
#ifdef Q_OS_MACOS
if (windowState() & Qt::WindowMinimized) {
isMin = true;
} else {
if (isMin) {
//设置无边框属性
this->setWindowFlags(flags | Qt::FramelessWindowHint);
this->setVisible(true);
isMin = false;
}
}
#endif
}
void FramelessWidget::doResizeEvent(QEvent *event)
{
//非win系统的无边框拉伸,win系统上已经采用了nativeEvent来处理拉伸
//为何不统一用计算的方式因为在win上用这个方式往左拉伸会发抖妹的
#ifndef Q_OS_WIN
if (event->type() == QEvent::Resize) {
//重新计算八个描点的区域,描点区域的作用还有就是计算鼠标坐标是否在某一个区域内
int width = this->width();
int height = this->height();
//左侧描点区域
pressedRect[0] = QRect(0, padding, padding, height - padding * 2);
//右侧描点区域
pressedRect[1] = QRect(width - padding, padding, padding, height - padding * 2);
//上侧描点区域
pressedRect[2] = QRect(padding, 0, width - padding * 2, padding);
//下侧描点区域
pressedRect[3] = QRect(padding, height - padding, width - padding * 2, padding);
//左上角描点区域
pressedRect[4] = QRect(0, 0, padding, padding);
//右上角描点区域
pressedRect[5] = QRect(width - padding, 0, padding, padding);
//左下角描点区域
pressedRect[6] = QRect(0, height - padding, padding, padding);
//右下角描点区域
pressedRect[7] = QRect(width - padding, height - padding, padding, padding);
} else if (event->type() == QEvent::HoverMove) {
//设置对应鼠标形状,这个必须放在这里而不是下面,因为可以在鼠标没有按下的时候识别
QHoverEvent *hoverEvent = (QHoverEvent *)event;
QPoint point = hoverEvent->pos();
if (resizeEnable) {
if (pressedRect.at(0).contains(point)) {
this->setCursor(Qt::SizeHorCursor);
} else if (pressedRect.at(1).contains(point)) {
this->setCursor(Qt::SizeHorCursor);
} else if (pressedRect.at(2).contains(point)) {
this->setCursor(Qt::SizeVerCursor);
} else if (pressedRect.at(3).contains(point)) {
this->setCursor(Qt::SizeVerCursor);
} else if (pressedRect.at(4).contains(point)) {
this->setCursor(Qt::SizeFDiagCursor);
} else if (pressedRect.at(5).contains(point)) {
this->setCursor(Qt::SizeBDiagCursor);
} else if (pressedRect.at(6).contains(point)) {
this->setCursor(Qt::SizeBDiagCursor);
} else if (pressedRect.at(7).contains(point)) {
this->setCursor(Qt::SizeFDiagCursor);
} else {
this->setCursor(Qt::ArrowCursor);
}
}
//根据当前鼠标位置,计算XY轴移动了多少
int offsetX = point.x() - mousePoint.x();
int offsetY = point.y() - mousePoint.y();
//根据按下处的位置判断是否是移动控件还是拉伸控件
if (moveEnable && mousePressed) {
this->move(this->x() + offsetX, this->y() + offsetY);
}
if (resizeEnable) {
int rectX = mouseRect.x();
int rectY = mouseRect.y();
int rectW = mouseRect.width();
int rectH = mouseRect.height();
if (pressedArea.at(0)) {
int resizeW = this->width() - offsetX;
if (this->minimumWidth() <= resizeW) {
this->setGeometry(this->x() + offsetX, rectY, resizeW, rectH);
}
} else if (pressedArea.at(1)) {
this->setGeometry(rectX, rectY, rectW + offsetX, rectH);
} else if (pressedArea.at(2)) {
int resizeH = this->height() - offsetY;
if (this->minimumHeight() <= resizeH) {
this->setGeometry(rectX, this->y() + offsetY, rectW, resizeH);
}
} else if (pressedArea.at(3)) {
this->setGeometry(rectX, rectY, rectW, rectH + offsetY);
} else if (pressedArea.at(4)) {
int resizeW = this->width() - offsetX;
int resizeH = this->height() - offsetY;
if (this->minimumWidth() <= resizeW) {
this->setGeometry(this->x() + offsetX, this->y(), resizeW, resizeH);
}
if (this->minimumHeight() <= resizeH) {
this->setGeometry(this->x(), this->y() + offsetY, resizeW, resizeH);
}
} else if (pressedArea.at(5)) {
int resizeW = rectW + offsetX;
int resizeH = this->height() - offsetY;
if (this->minimumHeight() <= resizeH) {
this->setGeometry(this->x(), this->y() + offsetY, resizeW, resizeH);
}
} else if (pressedArea.at(6)) {
int resizeW = this->width() - offsetX;
int resizeH = rectH + offsetY;
if (this->minimumWidth() <= resizeW) {
this->setGeometry(this->x() + offsetX, this->y(), resizeW, resizeH);
}
if (this->minimumHeight() <= resizeH) {
this->setGeometry(this->x(), this->y(), resizeW, resizeH);
}
} else if (pressedArea.at(7)) {
int resizeW = rectW + offsetX;
int resizeH = rectH + offsetY;
this->setGeometry(this->x(), this->y(), resizeW, resizeH);
}
}
} else if (event->type() == QEvent::MouseButtonPress) {
//记住鼠标按下的坐标+窗体区域
QMouseEvent *mouseEvent = (QMouseEvent *)event;
mousePoint = mouseEvent->pos();
mouseRect = this->geometry();
//判断按下的手柄的区域位置
if (pressedRect.at(0).contains(mousePoint)) {
pressedArea[0] = true;
} else if (pressedRect.at(1).contains(mousePoint)) {
pressedArea[1] = true;
} else if (pressedRect.at(2).contains(mousePoint)) {
pressedArea[2] = true;
} else if (pressedRect.at(3).contains(mousePoint)) {
pressedArea[3] = true;
} else if (pressedRect.at(4).contains(mousePoint)) {
pressedArea[4] = true;
} else if (pressedRect.at(5).contains(mousePoint)) {
pressedArea[5] = true;
} else if (pressedRect.at(6).contains(mousePoint)) {
pressedArea[6] = true;
} else if (pressedRect.at(7).contains(mousePoint)) {
pressedArea[7] = true;
} else {
mousePressed = true;
}
} else if (event->type() == QEvent::MouseMove) {
//改成用HoverMove识别
} else if (event->type() == QEvent::MouseButtonRelease) {
//恢复所有
this->setCursor(Qt::ArrowCursor);
mousePressed = false;
for (int i = 0; i < 8; ++i) {
pressedArea[i] = false;
}
}
#endif
}
bool FramelessWidget::eventFilter(QObject *watched, QEvent *event)
{
if (watched == this) {
if (event->type() == QEvent::WindowStateChange) {
doWindowStateChange(event);
} else {
doResizeEvent(event);
}
} else if (watched == titleBar) {
//双击标题栏发出双击信号给主界面
//下面的 *result = HTCAPTION; 标志位也会自动识别双击标题栏
#ifndef Q_OS_WIN
if (event->type() == QEvent::MouseButtonDblClick) {
emit titleDblClick();
} else if (event->type() == QEvent::NonClientAreaMouseButtonDblClick) {
emit titleDblClick();
}
#endif
}
return QWidget::eventFilter(watched, event);
}
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
bool FramelessWidget::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
#else
bool FramelessWidget::nativeEvent(const QByteArray &eventType, void *message, long *result)
#endif
{
if (eventType == "windows_generic_MSG") {
#ifdef Q_OS_WIN
MSG *msg = static_cast<MSG *>(message);
//qDebug() << TIMEMS << "nativeEvent" << msg->wParam << msg->message;
//不同的消息类型和参数进行不同的处理
if (msg->message == WM_NCCALCSIZE) {
*result = 0;
return true;
} else if (msg->message == WM_SYSKEYDOWN) {
//屏蔽alt键按下
} else if (msg->message == WM_SYSKEYUP) {
//屏蔽alt键松开
} else if (msg->message == WM_NCHITTEST) {
//计算鼠标对应的屏幕坐标
//这里最开始用的 LOWORD HIWORD 在多屏幕的时候会有问题
//官方说明在这里 https://docs.microsoft.com/zh-cn/windows/win32/inputdev/wm-nchittest
long x = GET_X_LPARAM(msg->lParam);
long y = GET_Y_LPARAM(msg->lParam);
QPoint pos = mapFromGlobal(QPoint(x, y));
//判断当前鼠标位置在哪个区域
bool left = pos.x() < padding;
bool right = pos.x() > width() - padding;
bool top = pos.y() < padding;
bool bottom = pos.y() > height() - padding;
//鼠标移动到四个角,这个消息是当鼠标移动或者有鼠标键按下时候发出的
*result = 0;
if (resizeEnable) {
if (left && top) {
*result = HTTOPLEFT;
} else if (left && bottom) {
*result = HTBOTTOMLEFT;
} else if (right && top) {
*result = HTTOPRIGHT;
} else if (right && bottom) {
*result = HTBOTTOMRIGHT;
} else if (left) {
*result = HTLEFT;
} else if (right) {
*result = HTRIGHT;
} else if (top) {
*result = HTTOP;
} else if (bottom) {
*result = HTBOTTOM;
}
}
//先处理掉拉伸
if (0 != *result) {
return true;
}
//识别标题栏拖动产生半屏全屏效果
if (titleBar && titleBar->rect().contains(pos)) {
QWidget *child = titleBar->childAt(pos);
if (!child) {
*result = HTCAPTION;
return true;
}
}
} else if (msg->wParam == PBT_APMSUSPEND && msg->message == WM_POWERBROADCAST) {
//系统休眠的时候自动最小化可以规避程序可能出现的问题
this->showMinimized();
} else if (msg->wParam == PBT_APMRESUMEAUTOMATIC) {
//休眠唤醒后自动打开
this->showNormal();
}
#endif
} else if (eventType == "NSEvent") {
#ifdef Q_OS_MACOS
#endif
} else if (eventType == "xcb_generic_event_t") {
#ifdef Q_OS_LINUX
#endif
}
return false;
}
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#ifdef Q_OS_WIN
bool FramelessWidget::winEvent(MSG *message, long *result)
{
return nativeEvent("windows_generic_MSG", message, result);
}
#endif
#endif
void FramelessWidget::setPadding(int padding)
{
this->padding = padding;
}
void FramelessWidget::setMoveEnable(bool moveEnable)
{
this->moveEnable = moveEnable;
}
void FramelessWidget::setResizeEnable(bool resizeEnable)
{
this->resizeEnable = resizeEnable;
}
void FramelessWidget::setTitleBar(QWidget *titleBar)
{
this->titleBar = titleBar;
this->titleBar->installEventFilter(this);
}

View File

@ -0,0 +1,96 @@
#ifndef FRAMELESSWIDGET_H
#define FRAMELESSWIDGET_H
/**
* :feiyangqingyun(QQ:517216493) 2021-07-27
* 1. Qt4-Qt6Qt4.7Qt6.2
* 2. mingwmsvcgcc等
* 3. windowslinuxmac
* 4. QMainWindowQWidgetQDialog
* 5. 使
* 6.
* 7. windows下不抖动
* 8. windows下具有移动到边缘半屏
* 9. mac系统上无边框最小化最大化失效的bug
* 10. bug
* 11. bug
* 12. 1300
* 13.
* 14. Qt版本可正常编译运行
*/
#include <QWidget>
#ifdef quc
class Q_DECL_EXPORT FramelessWidget : public QWidget
#else
class FramelessWidget : public QWidget
#endif
{
Q_OBJECT
public:
explicit FramelessWidget(QWidget *parent = 0);
protected:
//窗体显示的时候触发
void showEvent(QShowEvent *event);
//事件过滤器识别拖动拉伸等
void doWindowStateChange(QEvent *event);
void doResizeEvent(QEvent *event);
bool eventFilter(QObject *watched, QEvent *event);
//拦截系统事件用于修复系统休眠后唤醒程序的bug
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result);
#else
bool nativeEvent(const QByteArray &eventType, void *message, long *result);
#endif
//Qt4的写法
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
#ifdef Q_OS_WIN
bool winEvent(MSG *message, long *result);
#endif
#endif
private:
//边距+可移动+可拉伸
int padding;
bool moveEnable;
bool resizeEnable;
//标题栏控件
QWidget *titleBar;
//鼠标是否按下+按下坐标+按下时窗体区域
bool mousePressed;
QPoint mousePoint;
QRect mouseRect;
//鼠标是否按下某个区域+按下区域的大小
//依次为 左侧+右侧+上侧+下侧+左上侧+右上侧+左下侧+右下侧
QList<bool> pressedArea;
QList<QRect> pressedRect;
//记录是否最小化
bool isMin;
//存储窗体默认的属性
Qt::WindowFlags flags;
public Q_SLOTS:
//设置边距+可拖动+可拉伸
void setPadding(int padding);
void setMoveEnable(bool moveEnable);
void setResizeEnable(bool resizeEnable);
//设置标题栏控件
void setTitleBar(QWidget *titleBar);
Q_SIGNALS:
void titleDblClick();
void windowStateChange(bool max);
};
#endif // FRAMELESSWIDGET_H

BIN
gitee.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -0,0 +1,66 @@
QT += core gui xml charts printsupport
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
include($$PWD/framelesscore/framelesscore.pri)
INCLUDEPATH +=$$PWD/framelesscore/
SOURCES += \
find_path.cpp \
flatui.cpp \
main.cpp \
mainwindow.cpp \
only_run_by_file.cpp \
parse_keil_project.cpp \
parse_m51_from_keil.cpp \
parse_map_from_keil.cpp \
use_percentage_bar.cpp
HEADERS += \
find_path.h \
flatui.h \
mainwindow.h \
only_run_by_file.h \
parse_keil_project.h \
parse_m51_from_keil.h \
parse_map_from_keil.h \
use_percentage_bar.h
FORMS += \
mainwindow.ui \
use_percentage_bar.ui
TRANSLATIONS += \
keil_development_assistant_zh_CN.ts
RC_FILE =ico.rc
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
DISTFILES += \
KDA_Logo.ico \
ico.rc \
qcustomplot/GPL.txt \
qcustomplot/changelog.txt
RESOURCES += \
R.qrc

View File

@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="keil_development_assistant_zh_CN"></TS>

58
main.cpp Normal file
View File

@ -0,0 +1,58 @@
#include "mainwindow.h"
#include <QApplication>
#include <QSharedMemory>
#include <QMessageBox>
MainWindow* main_window=nullptr;
#include "only_run_by_file.h"
void onAppExit()
{
// 删除 run 文件
QFile::remove("run");
}
QString project_path;
QString map_path;
bool only_printf=false;
int main(int argc, char *argv[])
{
// for(int i=0;i<argc;i++)
// qDebug() <<argv[i];
if(argc>3)
{
project_path=argv[1];
map_path=argv[2];
only_printf=argv[3];
}else if(argc>2)
{
project_path=map_path=argv[1];
only_printf=argv[2];
}
if(argc>1)
{
project_path="./";
map_path="./";
only_printf=argv[1];
}
QApplication a(argc, argv);
only_run_by_file programController;
QObject::connect(&programController, &only_run_by_file::runFileDeleted, &a, &QCoreApplication::quit);
// 注册程序退出的处理函数
QObject::connect(&a, &QCoreApplication::aboutToQuit, onAppExit);
MainWindow w;
if(!only_printf) w.show();
return a.exec();
}

764
mainwindow.cpp Normal file
View File

@ -0,0 +1,764 @@
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFileDialog>
#include "use_percentage_bar.h"
#include <Qdebug>
#include "flatui.h"
#include <QDebug>
#include <QDesktopServices>
extern MainWindow* main_window;
#pragma execution_character_set("utf-8")
MainWindow::MainWindow(QWidget *parent) : FramelessMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->initForm();
}
MainWindow::~MainWindow()
{
delete cpu;
delete map;
delete ram_chart;
delete flash_chart;
delete ui;
}
void MainWindow::initForm()
{
//设置标题栏控件
ui->labTitle->setText("一个极客开源::keil开发助手");
this->setWindowTitle(ui->labTitle->text());
this->setTitleBar(ui->labTitle);
//关联信号
connect(this, SIGNAL(titleDblClick()), this, SLOT(titleDblClick()));
connect(this, SIGNAL(windowStateChange(bool)), this, SLOT(windowStateChange(bool)));
//设置样式表
QStringList list;
list << "#titleBar{background:#BBBBBB;}";
list << "#titleBar{border-top-left-radius:8px;border-top-right-radius:8px;}";
list << "#widgetMain{border:2px solid #BBBBBB;background:#FFFFFF;}";
//list << "#widgetMain{border-bottom-left-radius:8px;border-bottom-right-radius:8px;}";
this->setStyleSheet(list.join(""));
FlatUI::setScrollBarQss(ui->ram_scrollArea->verticalScrollBar(), 8, 120, 20, "##E5E5E5", "#D0D0D0", "#1ABC9C", "#E74C3C");
FlatUI::setScrollBarQss(ui->ram_scrollArea->horizontalScrollBar(), 8, 120, 20, "#E5E5E5", "#D0D0D0", "#1ABC9C", "#E74C3C");
FlatUI::setScrollBarQss(ui->flash_scrollArea->verticalScrollBar(), 8, 120, 20, "#E5E5E5", "#D0D0D0", "#1ABC9C", "#E74C3C");
FlatUI::setScrollBarQss(ui->flash_scrollArea->horizontalScrollBar(), 8, 120, 20, "#E5E5E5","#D0D0D0", "#1ABC9C", "#E74C3C");
FlatUI::setScrollBarQss(ui->ram_table->horizontalScrollBar(), 8, 120, 20, "#E5E5E5", "#D0D0D0", "#1ABC9C", "#E74C3C");
FlatUI::setScrollBarQss(ui->ram_table->verticalScrollBar(), 8, 120, 20, "#E5E5E5", "#D0D0D0", "#1ABC9C", "#E74C3C");
FlatUI::setScrollBarQss(ui->flash_table->horizontalScrollBar(), 8, 120, 20, "#E5E5E5","#D0D0D0", "#1ABC9C", "#E74C3C");
FlatUI::setScrollBarQss(ui->flash_table->verticalScrollBar(), 8, 120, 20, "#E5E5E5", "#D0D0D0", "#1ABC9C", "#E74C3C");
FlatUI::setProgressQss(ui->ram_used_bar, 20,12,16, "#747976", "#1ABC9C");//#FAEC9C",#FFF5E7
FlatUI::setProgressQss(ui->flash_used_bar, 20,12,16, "#747976", "#1ABC9C");
main_window=this;
map_path="P:/AT32_F403A_FreeRTOS/MDK_Project";
project_path="P:/AT32_F403A_FreeRTOS/MDK_Project";
ui->map_path->setText(map_path);
ui->project_path->setText(project_path);
ram_pieseries=new QPieSeries();
flash_pieseries=new QPieSeries();
cpu= new parse_keil_project(ui->project_path->text());
cpu->to_parse_keil_project(ui->project_path->text());
if(cpu->getCpu_core_name()!="8051")
{
map= new parse_map_from_keil( ui->map_path->text(),cpu->IRAM.getBase_addr(),cpu->IRAM.getMax_size(),cpu->IROM.getBase_addr(),cpu->IROM.getMax_size());
if(map->to_parse_map_from_keil(ui->map_path->text()))
map_calculate_size_by_address(map);
}else {
m51 =new parse_m51_from_keil(ui->map_path->text(),cpu->IRAM.getMax_size(),cpu->XRAM.getMax_size(),cpu->IROM.getMax_size());
}
ram_chart=new QChart();
flash_chart=new QChart();
//QChartView
ram_chart->addSeries(ram_pieseries);
ram_chart->setTitle("文件内存分布饼图");
ram_chart->legend()->hide();
// Set the theme to one of the predefined themes
ram_chart->setTheme(QChart::ChartThemeQt);
ram_chart->setBackgroundBrush(QBrush(Qt::gray));
flash_chart->addSeries(flash_pieseries);
flash_chart->setTitle("文件flash分布饼图");
flash_chart->legend()->hide();
// Set the theme to one of the predefined themes
flash_chart->setTheme(QChart::ChartThemeQt);
flash_chart->setBackgroundBrush(QBrush(Qt::gray));
ui->ram_chart_view->setChart(ram_chart);
ui->ram_chart_view->setRubberBand(QChartView::RectangleRubberBand);
ui->flash_chart_view->setChart(flash_chart);
ui->flash_chart_view->setRubberBand(QChartView::RectangleRubberBand);
update_cpu_info();
if(cpu->getCpu_core_name()!="8051")
{
update_map_info();
}else {
update_m51_info();
}
}
void MainWindow::map_calculate_size_by_address(parse_map_from_keil* map)
{
for(auto ram:map->ram_list)
{
if(ram->getMax_size()>100*1024*1024)
{
uint64_t recent_base=cpu->IRAM.getBase_addr()+cpu->IRAM.getMax_size();
for(auto recent_ram :map->ram_list)
{
if(recent_ram->getBase_addr()>ram->getBase_addr())
{
if(recent_ram->getBase_addr()-ram->getBase_addr()<recent_base-ram->getBase_addr())
recent_base=recent_ram->getBase_addr();
}
}
ram->setMax_size(recent_base-ram->getBase_addr());
}
}
for(auto flash:map->flash_list)
{
if(flash->getMax_size()>100*1024*1024)
{
uint64_t recent_base=cpu->IROM.getBase_addr()+cpu->IROM.getMax_size();
for(auto recent_flash :map->flash_list)
{
if(recent_flash->getBase_addr()>flash->getBase_addr())
{
if(recent_flash->getBase_addr()-flash->getBase_addr()<recent_base-flash->getBase_addr())
recent_base=recent_flash->getBase_addr();
}
}
flash->setMax_size(recent_base-flash->getBase_addr());
}
}
}
void MainWindow::on_btn_set_project_path_clicked()
{
//获取选择的目录路径
QString selectedDir=QFileDialog::getExistingDirectory(this,"选择一个目录","./",QFileDialog::ShowDirsOnly);
//若目录路径不为空
if (!selectedDir.isEmpty())
{
//将路径中的斜杠替换为反斜杠
selectedDir = selectedDir.replace(QRegExp("\\"), "/");
//显示选择的目录路径
ui->project_path->setText(selectedDir);
ui->map_path->setText(selectedDir);
}
}
void MainWindow::set_bar_style(QProgressBar *bar,float per)
{
if( per/1.0>0.85)
{
FlatUI::setProgressQss(bar, 20,12,16, "#747976", "#E74C3C");
}else if( per>0.75)
{
FlatUI::setProgressQss(bar, 20,12,16, "#747976", "#F9D927");
}
else
{
FlatUI::setProgressQss(bar, 20,12,16, "#747976", "#1ABC9C");
}
}
void MainWindow::on_btn_set_map_path_clicked()
{
//获取选择的目录路径
QString selectedDir=QFileDialog::getExistingDirectory(this,"选择一个目录","./",QFileDialog::ShowDirsOnly);
//若目录路径不为空
if (!selectedDir.isEmpty())
{
//将路径中的斜杠替换为反斜杠
selectedDir = selectedDir.replace(QRegExp("\\"), "/");
//显示选择的目录路径
ui->map_path->setText(selectedDir);
}
}
void MainWindow::on_update_info_clicked()
{
if(cpu!=nullptr)
{
delete cpu;
cpu=nullptr;
}
cpu= new parse_keil_project(ui->project_path->text());
if(cpu->to_parse_keil_project(ui->project_path->text()))
update_cpu_info();
if(cpu->getCpu_core_name()!="8051")
{
if(map!=nullptr)
{
delete map;
map=nullptr;
}
map= new parse_map_from_keil(ui->map_path->text(),cpu->IRAM.getBase_addr(),cpu->IRAM.getMax_size(),cpu->IROM.getBase_addr(),cpu->IROM.getMax_size());
if(map->to_parse_map_from_keil(ui->map_path->text()))
map_calculate_size_by_address(map);
update_map_info();
}else {
if(m51!=nullptr)
{
delete m51;
m51=nullptr;
}
m51 =new parse_m51_from_keil(ui->map_path->text(),cpu->IRAM.getMax_size(),cpu->XRAM.getMax_size(),cpu->IROM.getMax_size());
if(m51->to_parse_m51_from_keil(ui->map_path->text()))
update_m51_info();
}
}
void MainWindow::on_ram_table_itemSelectionChanged()
{
QList<QTableWidgetItem*> selectedItems = ui->ram_table->selectedItems();
// Reset all pie slices to not exploded (not highlighted)
foreach (QPieSlice* slice, ram_pieseries->slices()) {
slice->setExploded(false);
slice->setLabelVisible(false);
}
foreach (QTableWidgetItem* item, selectedItems) {
int row = item->row();
// qDebug() << row;
QPieSlice *slice = ram_pieseries->slices().at(row);
slice->setExploded();//突出这一块
slice->setLabelVisible();//设置这一块可见数据
}
}
void MainWindow::on_flash_table_itemSelectionChanged()
{
QList<QTableWidgetItem*> selectedItems = ui->flash_table->selectedItems();
// Reset all pie slices to not exploded (not highlighted)
foreach (QPieSlice* slice, flash_pieseries->slices()) {
slice->setExploded(false);
slice->setLabelVisible(false);
}
foreach (QTableWidgetItem* item, selectedItems) {
int row = item->row();
// qDebug() << row;
QPieSlice *slice = flash_pieseries->slices().at(row);
slice->setExploded();//突出这一块
slice->setLabelVisible();//设置这一块可见数据
}
}
void MainWindow::update_cpu_info(void)
{
ui->cpu_name->setTitle(cpu->getCpu_name());
ui->cpu_core->setText("单片机核心:"+cpu->getCpu_core_name());
ui->cpu_colck->setText(QString().sprintf("最高主频:%.2f MHz",cpu->getCpu_max_clock()/1000000.0));
ui->iram->setText(QString().sprintf("内部ram 地址:%#x 容量:%.2f KB",cpu->IRAM.getBase_addr(),cpu->IRAM.getMax_size()/1024.0));
ui->flash->setText(QString().sprintf("内部flash 地址:%#x 容量:%.2f KB",cpu->IROM.getBase_addr(),cpu->IROM.getMax_size()/1024.0));
}
void MainWindow::clearLayout(QLayout* layout) {
QLayoutItem* item;
while ((item = layout->takeAt(0))) {
QWidget* widget = item->widget();
if (widget) {
layout->removeWidget(widget); // 将小部件从布局中移除
widget->setParent(nullptr); // 设置父对象为nullptr避免悬挂指针问题
delete widget; // 删除小部件并释放内存
}
delete item; // 删除布局项
}
}
void MainWindow::update_m51_info(void)
{
uint64_t ram_all_max_size=0;
uint64_t ram_all_used_size=0;
uint64_t ram_min_base_addr=m51->ram_list.at(0)->getBase_addr();
uint64_t flash_all_max_size=0;
uint64_t flash_all_used_size=0;
uint64_t flash_min_base_addr=m51->flash_list.at(0)->getBase_addr();
uint16_t i;
clearLayout(ui->ram_scrollAreaWidgetContents->layout());
// 移除并释放布局中的所有小部件
clearLayout(ui->flash_scrollAreaWidgetContents->layout());
// 移除并释放布局中的所有小部件
for(i=0;i<m51->ram_list.size();i++)
{
ram_all_used_size+=m51->ram_list.at(i)->getUsed_size();
ram_all_max_size+=m51->ram_list.at(i)->getMax_size();
if(ram_min_base_addr>m51->ram_list.at(0)->getBase_addr())
ram_min_base_addr=m51->ram_list.at(i)->getBase_addr();
ui->ram_scrollAreaWidgetContents->layout()->addWidget(m51->ram_list.at(i));
}
ui->ram_addr->setText(QString().sprintf("地址:%#x",ram_min_base_addr));
ui->ram_used_bar->setRange(0,ram_all_max_size);
ui->ram_used_bar->setValue(ram_all_used_size);
ui->ram_remain->setText(QString().sprintf("剩余:%.2f B",ram_all_max_size/10.0-ram_all_used_size/10.0));
if(ram_all_max_size/10.0<=1024)
{
ui->ram_used->setText(QString().sprintf("占用:%.2f B / (%.2f B)",ram_all_used_size/10.0,ram_all_max_size/10.0));
}else
{
ui->ram_used->setText(QString().sprintf("占用:%.2f B / (%.2f KB)",ram_all_used_size/1024.0,ram_all_max_size/10.0/1024.0));
}
set_bar_style(ui->ram_used_bar,ram_all_used_size/1.0/ram_all_max_size/1.0);
for(i=0;i<m51->flash_list.size();i++)
{
flash_all_used_size+=m51->flash_list.at(i)->getUsed_size();
flash_all_max_size+=m51->flash_list.at(i)->getMax_size();
if(flash_min_base_addr>m51->flash_list.at(0)->getBase_addr())
flash_min_base_addr=m51->flash_list.at(i)->getBase_addr();
ui->flash_scrollAreaWidgetContents->layout()->addWidget(m51->flash_list.at(i));
}
ui->flash_addr->setText(QString().sprintf("地址:%#x",flash_min_base_addr));
ui->flash_used_bar->setRange(0,flash_all_max_size);
ui->flash_used_bar->setValue(flash_all_used_size);
ui->flash_remain->setText(QString().sprintf("剩余:%.2f B",flash_all_max_size/10.0-flash_all_used_size/10.0));
if(flash_all_max_size/10.0<=1024)
{
ui->flash_used->setText(QString().sprintf("占用:%.2f B / (%.2f B)",flash_all_used_size/10.0,flash_all_max_size/10.0));
}else
{
ui->flash_used->setText(QString().sprintf("占用:%.2f B / (%.2f KB)",flash_all_used_size/1024.0,flash_all_max_size/10.0/1024.0));
}
set_bar_style(ui->flash_used_bar,ram_all_used_size/1.0/ram_all_max_size/1.0);
}
void MainWindow::setPieSliceStyle(QPieSlice* slice, qreal percentage, qreal maxPercentage)
{
// Define an array of custom green colors to represent different percentage ranges
QColor colors[] = {
QColor("#D1FF4D"), // Light Green Yellow
QColor("#C0FF3E"), // Greenish Yellow
QColor("#ADFF2F"), // Green Yellow
QColor("#7CFC00"), // Lawn Green
QColor("#00FF00"), // Lime Green
QColor("#008000"), // Green
QColor("#006400"), // Dark Green
};
// Calculate the relative percentage compared to the maxPercentage
qreal relativePercentage = (percentage / maxPercentage) * 100.0;
// Determine the index of the color based on relative percentage
int colorIndex = qMin(int(relativePercentage) / (100 / (sizeof(colors) / sizeof(colors[0]))), sizeof(colors) / sizeof(colors[0]) - 1);
// Set the color of the slice based on the color index
slice->setColor(colors[colorIndex]);
}
void MainWindow::update_map_info(void)
{
uint64_t ram_all_max_size=0;
uint64_t ram_all_used_size=0;
uint64_t ram_min_base_addr=map->ram_list.at(0)->getBase_addr();
uint64_t flash_all_max_size=0;
uint64_t flash_all_used_size=0;
uint64_t flash_min_base_addr=map->flash_list.at(0)->getBase_addr();
uint16_t i;
clearLayout(ui->ram_scrollAreaWidgetContents->layout());
// // 移除并释放布局中的所有小部件
clearLayout(ui->flash_scrollAreaWidgetContents->layout());
// // 移除并释放布局中的所有小部件
for(uint64_t row_cnt=0;row_cnt<ui->ram_table->rowCount();row_cnt++)
{
ui->ram_table->removeRow(row_cnt);
}
ram_pieseries->clear();
for(uint64_t row_cnt=0;row_cnt<ui->flash_table->rowCount();row_cnt++)
{
ui->flash_table->removeRow(row_cnt);
}
flash_pieseries->clear();
for(i=0;i<map->ram_list.size();i++)
{
ram_all_used_size+=map->ram_list.at(i)->getUsed_size();
ram_all_max_size+=map->ram_list.at(i)->getMax_size();
if(ram_min_base_addr>map->ram_list.at(0)->getBase_addr())
ram_min_base_addr=map->ram_list.at(i)->getBase_addr();
ui->ram_scrollAreaWidgetContents->layout()->addWidget(map->ram_list.at(i));
}
ui->ram_addr->setText(QString().sprintf("地址:%#x",ram_min_base_addr));
ui->ram_used_bar->setRange(0,ram_all_max_size);
ui->ram_used_bar->setValue(ram_all_used_size);
ui->ram_remain->setText(QString().sprintf("剩余:%llu B",ram_all_max_size-ram_all_used_size));
if(ram_all_max_size<=1024*1024)
{
ui->ram_used->setText(QString().sprintf("占用:%.2f KB / (%.2f KB)",ram_all_used_size/1024.0,ram_all_max_size/1024.0));
}else
{
ui->ram_used->setText(QString().sprintf("占用:%.4f MB / (%.4f MB)",ram_all_used_size/1024.0/1024.0,ram_all_max_size/1024.0/1024.0));
}
set_bar_style(ui->ram_used_bar,ram_all_used_size/1.0/ram_all_max_size/1.0);
for(i=0;i<map->flash_list.size();i++)
{
flash_all_used_size+=map->flash_list.at(i)->getUsed_size();
flash_all_max_size+=map->flash_list.at(i)->getMax_size();
if(flash_min_base_addr>map->flash_list.at(0)->getBase_addr())
flash_min_base_addr=map->flash_list.at(i)->getBase_addr();
ui->flash_scrollAreaWidgetContents->layout()->addWidget(map->flash_list.at(i));
}
ui->flash_addr->setText(QString().sprintf("地址:%#x",flash_min_base_addr));
ui->flash_used_bar->setRange(0,flash_all_max_size);
ui->flash_used_bar->setValue(flash_all_used_size);
ui->flash_remain->setText(QString().sprintf("剩余:%llu B",flash_all_max_size-flash_all_used_size));
if(flash_all_max_size<=1024*1024)
{
ui->flash_used->setText(QString().sprintf("占用:%.2f KB / (%.2f KB)",flash_all_used_size/1024.0,flash_all_max_size/1024.0));
}else
{
ui->flash_used->setText(QString().sprintf("占用:%.4f MB / (%.4f MB)",flash_all_used_size/1024.0/1024.0,flash_all_max_size/1024.0/1024.0));
}
set_bar_style(ui->flash_used_bar,ram_all_used_size/1.0/ram_all_max_size/1.0);
QList <image_item_t*> info_lsit= map->getInfo_list();
uint64_t all_ram_size = map->getAll_ram_size();
uint64_t all_flash_size =map->getAll_flash_size();
uint64_t ram_row=0;
uint64_t flash_row=0;
for(auto item:info_lsit)
{
if(item->RW_Data.toUInt()+item->ZI_Data.toUInt()!=0)
{
writeTableData(ram_table,ram_row,0,item->Object_Name);
writeTableData(ram_table,ram_row,1,QString::number(item->RW_Data.toUInt()+item->ZI_Data.toUInt()));
writeTableData(ram_table,ram_row,3,item->RW_Data);
writeTableData(ram_table,ram_row,4,item->ZI_Data);
all_ram_size+=item->RW_Data.toUInt()+item->ZI_Data.toUInt();
ram_row++;
}
if(item->Code.toUInt()+item->RO_Data.toUInt()+item->RW_Data.toUInt()!=0)
{
writeTableData(flash_table,flash_row,0,item->Object_Name);
writeTableData(flash_table,flash_row,1,QString::number(item->Code.toUInt()+item->RO_Data.toUInt()+item->RW_Data.toUInt()));
writeTableData(flash_table,flash_row,3,item->Code);
writeTableData(flash_table,flash_row,4,item->RO_Data);
writeTableData(flash_table,flash_row,5,item->RW_Data);
all_flash_size+=item->Code.toUInt()+item->RO_Data.toUInt()+item->RW_Data.toUInt();
flash_row++;
}
}
ui->ram_per->setTitle(QString().sprintf("used_ram=RW+ZI=%llu",all_ram_size));
ui->flash_per->setTitle(QString().sprintf("used_flash=RW+Code+RO=%llu",all_flash_size));
for(uint64_t row_cnt=0;row_cnt<ui->ram_table->rowCount();row_cnt++)
{
writeTableData(ram_table,row_cnt,2,QString().sprintf("%05.2f%%",ui->ram_table->item(row_cnt,1)->text().toUInt()*100.0/all_ram_size/1.0));
}
for(uint64_t row_cnt=0;row_cnt<ui->flash_table->rowCount();row_cnt++)
{
writeTableData(flash_table,row_cnt,2,QString().sprintf("%05.2f%%",ui->flash_table->item(row_cnt,1)->text().toUInt()*100.0/all_flash_size/1.0));
}
ui->ram_table->sortByColumn(2,Qt::SortOrder::DescendingOrder);
ui->flash_table->sortByColumn(2,Qt::SortOrder::DescendingOrder);
for(uint64_t row_cnt=0;row_cnt<ui->ram_table->rowCount();row_cnt++)
{
QPieSlice *slice =ram_pieseries->append(ui->ram_table->item(row_cnt,0)->text()+":"+ui->ram_table->item(row_cnt,2)->text(),ui->ram_table->item(row_cnt,1)->text().toUInt());
setPieSliceStyle(slice,ui->ram_table->item(row_cnt,2)->text().split("%")[0].toFloat(),ui->ram_table->item(0,2)->text().split("%")[0].toFloat());
}
for(uint64_t row_cnt=0;row_cnt<ui->flash_table->rowCount();row_cnt++)
{
QPieSlice *slice =flash_pieseries->append(ui->flash_table->item(row_cnt,0)->text()+":"+ui->flash_table->item(row_cnt,2)->text(),ui->flash_table->item(row_cnt,1)->text().toUInt());
setPieSliceStyle(slice,ui->flash_table->item(row_cnt,2)->text().split("%")[0].toFloat(),ui->flash_table->item(0,2)->text().split("%")[0].toFloat());
}
}
QString MainWindow::readTableData(ui_table_t table,int row, int column)
{
QString data;
QTableWidget* tableWidget ;
if( table==ram_table)tableWidget=ui->ram_table;
else tableWidget=ui->flash_table;
if (row < tableWidget->rowCount() && column <tableWidget->columnCount()) {
QTableWidgetItem *item =tableWidget->item(row, column);
if (item) {
data = item->text();
// qDebug() << "Data at (" << row << ", " << column << "): " << data;
}
}
return data;
}
void MainWindow::writeTableData(ui_table_t table,int row, int column, const QString &data)
{
QTableWidget* tableWidget=nullptr;
if (table == ram_table)
{
tableWidget=ui->ram_table;
}
else if (table == flash_table)
{
tableWidget = ui->flash_table;
}
else
{
qDebug() << "Invalid table specified.";
return;
}
if (row >= tableWidget->rowCount())
{
tableWidget->setRowCount(row + 1);
}
if (column >= tableWidget->columnCount())
{
tableWidget->setColumnCount(column + 1);
}
if (!tableWidget->item(row, column))
{
QTableWidgetItem *newItem = new QTableWidgetItem(data);
tableWidget->setItem(row, column, newItem);
}
else
{
tableWidget->item(row, column)->setText(data);
}
}
void MainWindow::titleDblClick()
{
on_btnMenu_Max_clicked();
}
void MainWindow::windowStateChange(bool max)
{
ui->btnMenu_Max->setText(max ? "还原" : "最大");
}
void MainWindow::on_btnMenu_Min_clicked()
{
#ifdef Q_OS_MACOS
this->setWindowFlags(this->windowFlags() & ~Qt::FramelessWindowHint);
#endif
this->showMinimized();
}
void MainWindow::on_btnMenu_Max_clicked()
{
if (this->isMaximized()) {
this->showNormal();
ui->btnMenu_Max->setText("最大");
} else {
this->showMaximized();
ui->btnMenu_Max->setText("还原");
}
}
void MainWindow::on_btnMenu_Close_clicked()
{
this->close();
}
void MainWindow::on_gitee_index_clicked()
{
QDesktopServices::openUrl(QUrl("https://gitee.com/nikolan")); // Change the URL to the desired webpage
}

68
mainwindow.h Normal file
View File

@ -0,0 +1,68 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include "framelessmainwindow.h"
#include "parse_keil_project.h"
#include "parse_map_from_keil.h"
#include "parse_m51_from_keil.h"
#include <QtCharts>
extern QString project_path;
extern QString map_path;
extern bool only_printf;
QT_CHARTS_USE_NAMESPACE
namespace Ui {
class MainWindow;
}
typedef enum{ram_table,flash_table}ui_table_t;
class MainWindow : public FramelessMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void setPieSliceStyle(QPieSlice* slice, qreal percentage, qreal maxPercentage);
void set_bar_style(QProgressBar *bar,float per);
void update_cpu_info(void);
void update_map_info(void);
void update_m51_info(void);
QString readTableData(ui_table_t table,int row, int column);
void writeTableData(ui_table_t table,int row, int column, const QString &data);
void map_calculate_size_by_address(parse_map_from_keil* map);
Ui::MainWindow *ui;
QPieSeries *ram_pieseries=nullptr;
QPieSeries *flash_pieseries=nullptr;
QChart* ram_chart=nullptr;
QChart* flash_chart=nullptr;
private:
void clearLayout(QLayout* layout);
parse_keil_project* cpu=nullptr;
parse_map_from_keil* map=nullptr;
parse_m51_from_keil* m51=nullptr;
private slots:
void initForm();
void titleDblClick();
void windowStateChange(bool max);
private slots:
void on_btnMenu_Min_clicked();
void on_btnMenu_Max_clicked();
void on_btnMenu_Close_clicked();
void on_btn_set_project_path_clicked();
void on_btn_set_map_path_clicked();
void on_update_info_clicked();
void on_ram_table_itemSelectionChanged();
void on_flash_table_itemSelectionChanged();
void on_gitee_index_clicked();
};
#endif // MAINWINDOW_H

965
mainwindow.ui Normal file
View File

@ -0,0 +1,965 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<property name="styleSheet">
<string notr="true">color:#3f3f3f;
background: #ECF0F1;</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,0">
<property name="spacing">
<number>10</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QWidget" name="titleBar" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>40</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">color:#ffffff;
background:#34495E;
border-top-left-radius:8px;
border-top-right-radius:8px;</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QPushButton" name="pushButton">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="R.qrc">
<normaloff>:/KDA_Logo.ico</normaloff>:/KDA_Logo.ico</iconset>
</property>
<property name="iconSize">
<size>
<width>40</width>
<height>40</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="labTitle">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>一个极客开源::keil开发助手</string>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="widgetMenu" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>28</height>
</size>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>10</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QPushButton" name="btnMenu_Min">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>60</width>
<height>30</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>60</width>
<height>16777215</height>
</size>
</property>
<property name="cursor">
<cursorShape>ArrowCursor</cursorShape>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="toolTip">
<string>最小化</string>
</property>
<property name="styleSheet">
<string notr="true">QPushButton {
border-style: none;
padding: 8px;
border-radius: 5px;
color: #FFFFFF;
background: #3498DB;
}
QPushButton:hover {
color: #FFF5E7;
background: #2E86C1;
}
QPushButton:pressed {
color: #F5A996;
background: #1B4F72;
}
QPushButton:disabled{
background-color: #34495E;
border-color: #D6D6D6;
}
</string>
</property>
<property name="text">
<string>最小</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnMenu_Max">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>60</width>
<height>30</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>60</width>
<height>16777215</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="styleSheet">
<string notr="true">QPushButton{border-style:none;padding:8px;border-radius:5px;color:#E6F8F5;background:#1ABC9C;}
QPushButton:hover{color:#FFFFFF;background:#2EE1C1;}
QPushButton:pressed{color:#A7EEE6;background:#16A086;}
QPushButton:disabled{
background-color: #34495E;
border-color: #D6D6D6;
}
</string>
</property>
<property name="text">
<string>最大</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnMenu_Close">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>60</width>
<height>30</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>60</width>
<height>16777215</height>
</size>
</property>
<property name="cursor">
<cursorShape>ArrowCursor</cursorShape>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="toolTip">
<string>关闭</string>
</property>
<property name="styleSheet">
<string notr="true">QPushButton{border-style:none;padding:8px;border-radius:5px;color:#FFFFFF;background:#E74C3C;}
QPushButton:hover{color:#FFF5E7;background:#EC7064;}
QPushButton:pressed{color:#F5A996;background:#DC2D1A;}
QPushButton:disabled{
background-color: #34495E;
border-color: #D6D6D6;
}
</string>
</property>
<property name="text">
<string>关闭</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QSplitter" name="splitter_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QGroupBox" name="setting">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>手动操作</string>
</property>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<widget class="QPushButton" name="btn_set_project_path">
<property name="styleSheet">
<string notr="true">QPushButton {
border-style: none;
padding: 8px;
border-radius: 5px;
color: #FFFFFF;
background: #3498DB;
}
QPushButton:hover {
color: #FFF5E7;
background: #2E86C1;
}
QPushButton:pressed {
color: #F5A996;
background: #1B4F72;
}
QPushButton:disabled{
background-color: #34495E;
border-color: #D6D6D6;
}
</string>
</property>
<property name="text">
<string>选择目录</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_project_path">
<property name="text">
<string>工程路径:</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLineEdit" name="project_path"/>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="btn_set_map_path">
<property name="styleSheet">
<string notr="true">QPushButton {
border-style: none;
padding: 8px;
border-radius: 5px;
color: #FFFFFF;
background: #3498DB;
}
QPushButton:hover {
color: #FFF5E7;
background: #2E86C1;
}
QPushButton:pressed {
color: #F5A996;
background: #1B4F72;
}
QPushButton:disabled{
background-color: #34495E;
border-color: #D6D6D6;
}
</string>
</property>
<property name="text">
<string>选择目录</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_map_path">
<property name="text">
<string> map文件路径:</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLineEdit" name="map_path"/>
</item>
<item row="1" column="3">
<widget class="QPushButton" name="update_info">
<property name="styleSheet">
<string notr="true">QPushButton{border-style:none;padding:8px;border-radius:5px;color:#E6F8F5;background:#1ABC9C;}
QPushButton:hover{color:#FFFFFF;background:#2EE1C1;}
QPushButton:pressed{color:#A7EEE6;background:#16A086;}
QPushButton:disabled{
background-color: #34495E;
border-color: #D6D6D6;
}
</string>
</property>
<property name="text">
<string>手动更新数据</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QTabWidget" name="tabWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>6</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true">
QTabWidget::pane {
background-color:#34495E;
border-top: 2px solid #C2C7CB;
/* position: absolute;
top: -0.5em; */
border-color: #9B9B9B;
color: rgb(255, 255, 255);
}
QTabWidget::tab-bar {
background-color: #34495E;
color: rgb(255, 255, 255);
/* alignment: center; */
}
QTabBar {
background-color: #34495E;
color: rgb(255, 255, 255);
}
QTabBar::tab:selected {
background-color:#2EE1C1;
color: rgb(255, 255, 255);
}
QTabBar::tab:!selected{
background-color:#34495E;
color: rgb(255, 255, 255);
}
</string>
</property>
<property name="currentIndex">
<number>3</number>
</property>
<widget class="QWidget" name="bulid_info">
<attribute name="title">
<string>构建后信息</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_6">
<item row="0" column="0">
<widget class="QSplitter" name="splitter_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QGroupBox" name="cpu_name">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>mcu_name</string>
</property>
<layout class="QGridLayout" name="gridLayout_8">
<item row="0" column="1">
<widget class="QLabel" name="cpu_colck">
<property name="text">
<string>最高主频:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="flash">
<property name="text">
<string>内部flash 大小:</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="iram">
<property name="text">
<string>内部ram 大小:</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="cpu_core">
<property name="text">
<string>核心:</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QSplitter" name="splitter">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>3</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QGroupBox" name="ram_all">
<property name="title">
<string>按map文件识别的ram</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="0">
<widget class="QScrollArea" name="ram_scrollArea">
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="ram_scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>360</width>
<height>131</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2"/>
</widget>
</widget>
</item>
<item row="0" column="0">
<widget class="QGroupBox" name="ram_name">
<property name="title">
<string> all_ram</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="ram_addr">
<property name="text">
<string>地址0xxxxxx</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QProgressBar" name="ram_used_bar">
<property name="value">
<number>24</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="ram_used">
<property name="text">
<string>占用:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="ram_remain">
<property name="text">
<string>还剩:</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QGroupBox" name="flash_all">
<property name="title">
<string>按map文件识别的flash</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="1" column="0">
<widget class="QScrollArea" name="flash_scrollArea">
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="flash_scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>360</width>
<height>131</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout"/>
</widget>
</widget>
</item>
<item row="0" column="0">
<widget class="QGroupBox" name="flash_name">
<property name="title">
<string>all_flash</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QLabel" name="flash_addr">
<property name="text">
<string>地址0xxxxxx</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QProgressBar" name="flash_used_bar">
<property name="value">
<number>24</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="flash_used">
<property name="text">
<string>占用:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="flash_remain">
<property name="text">
<string>还剩:</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_3">
<attribute name="title">
<string>ram占比</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_10">
<item row="0" column="0">
<widget class="QGroupBox" name="ram_per">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>project::xxx cup:xxxx</string>
</property>
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0">
<widget class="QSplitter" name="splitter_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QTableWidget" name="ram_table">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<column>
<property name="text">
<string>文件名</string>
</property>
</column>
<column>
<property name="text">
<string>占用ram大小B</string>
</property>
</column>
<column>
<property name="text">
<string>占用ram比例%</string>
</property>
</column>
<column>
<property name="text">
<string>RW</string>
</property>
</column>
<column>
<property name="text">
<string>ZI</string>
</property>
</column>
</widget>
<widget class="QGroupBox" name="ram_pie">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>2</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string> 占用饼图</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<layout class="QGridLayout" name="gridLayout_12">
<item row="0" column="0">
<widget class="QChartView" name="ram_chart_view"/>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_4">
<attribute name="title">
<string> flash占比</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_11">
<item row="0" column="0">
<widget class="QGroupBox" name="flash_per">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>project::xxx cup:xxxx</string>
</property>
<layout class="QGridLayout" name="gridLayout_9">
<item row="0" column="0">
<widget class="QSplitter" name="splitter_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QTableWidget" name="flash_table">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<column>
<property name="text">
<string>文件名</string>
</property>
</column>
<column>
<property name="text">
<string>占用flash大小B</string>
</property>
</column>
<column>
<property name="text">
<string>占用flash比例%</string>
</property>
</column>
<column>
<property name="text">
<string>Code</string>
</property>
</column>
<column>
<property name="text">
<string>RO</string>
</property>
</column>
<column>
<property name="text">
<string>RW</string>
</property>
</column>
</widget>
<widget class="QGroupBox" name="flash_pie">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>2</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string> 占用饼图</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<layout class="QGridLayout" name="gridLayout_13">
<item row="0" column="0">
<widget class="QChartView" name="flash_chart_view"/>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string> 更多</string>
</attribute>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<widget class="QTextBrowser" name="textBrowser_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>4</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="html">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'SimSun'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;这是一个开源项目基于GPLv2开源协议。&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;你可以通过来gitee开源仓库地址&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;来反馈BUG或者提供优化代码来帮助维护这个项目&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;或者给予建议或者告诉作者你想要的功能。&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;参与了代码的奉献,实现某些功能或优化了某些代码,&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;会更新到readme的奉献者名单。&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;或者能力赞助该项目开发的,&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;会更新到readme赞助者名单。&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;该软件将永久免费,开源不易,谢谢大家的支持,&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;你的支持是我更新维护项目的动力。&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;留言:ageek_nikola &lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;邮箱2503865771@qq.com&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QGroupBox" name="ageek">
<property name="title">
<string>一个极客ageek开源</string>
</property>
<layout class="QGridLayout" name="gridLayout_7">
<item row="0" column="0">
<widget class="QPushButton" name="icon">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="R.qrc">
<normaloff>:/KDA_Logo.ico</normaloff>:/KDA_Logo.ico</iconset>
</property>
<property name="iconSize">
<size>
<width>60</width>
<height>60</height>
</size>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="gitee_index">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="R.qrc">
<normaloff>:/gitee.png</normaloff>:/gitee.png</iconset>
</property>
<property name="iconSize">
<size>
<width>200</width>
<height>60</height>
</size>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QLabel" name="label">
<property name="text">
<string>点击以上图标跳转到gitee开源地址</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QTextBrowser" name="textBrowser">
<property name="html">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'SimSun'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;KDA&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;keil_development_assistant&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;keil开发助手&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; color:#0055ff;&quot;&gt;主要解决的问题:&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; color:#0055ff;&quot;&gt;无需反复翻查map文件&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; color:#0055ff;&quot;&gt;让你的嵌入式软件能更好的进行优化&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; color:#00aa00;&quot;&gt;主要实现的功能:&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; color:#00aa00;&quot;&gt;- 分析ram和flash占用百分比&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; color:#00aa00;&quot;&gt;- 分析已使用的ram和flash的各文件占比&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</widget>
</widget>
</item>
</layout>
</widget>
</widget>
<customwidgets>
<customwidget>
<class>QChartView</class>
<extends>QGraphicsView</extends>
<header location="global">qchartview.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="R.qrc"/>
</resources>
<connections/>
</ui>

110
only_run_by_file.cpp Normal file
View File

@ -0,0 +1,110 @@
#include "only_run_by_file.h"
only_run_by_file::only_run_by_file(QObject *parent) : QObject(parent),
runFileName("run"),
closeFileName("close")
{
// 如果 run 文件已经存在,则删除
if (QFile::exists(runFileName)) {
QFile::remove(runFileName);
// 检测 close 文件是否存在的定时器
closeTimer = new QTimer(this);
connect(closeTimer, &QTimer::timeout, this, &only_run_by_file::checkCloseFile);
closeTimer->start(300); // 每 300 毫秒执行一次检测
}else
createRunFile();
// 检测 run 文件是否存在的定时器
timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &only_run_by_file::checkRunFile);
timer->start(800); // 每 800 毫秒执行一次检测
}
void only_run_by_file::createCloseFile()
{
// 创建 close 文件
QFile file(closeFileName);
file.open(QIODevice::WriteOnly);
file.close();
}
void only_run_by_file::createRunFile()
{
// 创建 run 文件
QFile file(runFileName);
file.open(QIODevice::WriteOnly);
file.close();
}
void only_run_by_file::deleteCloseFile()
{
// 如果 close 文件已经存在,则删除
if (QFile::exists(closeFileName)) {
QFile::remove(closeFileName);
}
}
void only_run_by_file::deleteRunFile()
{
// 如果 run 文件已经存在,则删除
if (QFile::exists(runFileName)) {
QFile::remove(runFileName);
}
}
void only_run_by_file::checkRunFile()
{
// 检测 run 文件是否存在
if (!QFile::exists(runFileName)) {
// 文件不存在,采集关闭操作并创建 close 文件
deleteCloseFile();
// 创建 close 文件
createCloseFile();
emit runFileDeleted();
}
}
void only_run_by_file::checkCloseFile()
{
static uint8_t cnt=0;
if(cnt<3)
{
cnt++;
// 检测 close 文件是否存在
if (QFile::exists(closeFileName)) {
// 发出信号,通知检测到 close 文件
closeTimer->stop();
// 如果 close 文件已经存在,则删除
deleteCloseFile();
// 创建 run 文件
createRunFile();
emit closeFileDetected();
}
}else
{
cnt=0;
// 如果 close 文件已经存在,则删除
deleteCloseFile();
// 创建 run 文件
createRunFile();
emit closeFileDetected();
}
}

32
only_run_by_file.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef ONLY_RUN_BY_FILE_H
#define ONLY_RUN_BY_FILE_H
#include <QObject>
#include <QFile>
#include <QTimer>
class only_run_by_file : public QObject
{
Q_OBJECT
public:
explicit only_run_by_file(QObject *parent = nullptr);
private:
const QString runFileName;
const QString closeFileName;
void createCloseFile();
void createRunFile();
void deleteCloseFile();
void deleteRunFile();
QTimer* closeTimer;
QTimer* timer ;
signals:
void runFileDeleted();
void closeFileDetected();
public slots:
void checkRunFile();
void checkCloseFile();
};
#endif // ONLY_RUN_BY_FILE_H

260
parse_keil_project.cpp Normal file
View File

@ -0,0 +1,260 @@
#include "parse_keil_project.h"
#include <QFile>
#include <QDomDocument>
#include <Qtxml>
#include <QDebug>
#include <qxmlstream.h>
#include "find_path.h"
QString parse_keil_project::find_project_path(const QString& dir_path)
{
return find_path::find_file_path(dir_path,".uvproj");
}
parse_keil_project::parse_keil_project(QString path)
{
IRAM.setName("IRAM");
XRAM.setName("XRAM");
IROM.setName("IROM");
// to_parse_keil_project(path);
}
bool parse_keil_project::to_parse_keil_project(QString path)
{
project_path=path;
QString file_path;
if(path.contains(".uvproj"))
{
parse_project_file(path);
return true;
}
file_path=find_project_path(project_path);
qDebug()<<file_path;
if(file_path.length()<3)
{
return false;
}
else
{
parse_project_file(file_path);
return true;
}
}
bool parse_keil_project::parse_info_item_max_clock(const QString& info_item)
{
QStringList info_list;
uint64_t data;
bool is_int;
uint8_t data_cnt=0;
info_list= info_item.split("(");//按"\""分割
cpu_max_clock=info_list[1].toInt(&is_int,10);
}
QString parse_keil_project::getCpu_core_name() const
{
return cpu_core_name;
}
uint64_t parse_keil_project::getCpu_max_clock() const
{
return cpu_max_clock;
}
QString parse_keil_project::getProject_path() const
{
return project_path;
}
void parse_keil_project::setProject_path(const QString &value)
{
project_path = value;
}
QString parse_keil_project::getCpu_name() const
{
return cpu_name;
}
bool parse_keil_project::parse_info_item_core_name(const QString& info_item)
{
QStringList info_list;
uint64_t data;
bool is_int;
uint8_t data_cnt=0;
info_list= info_item.split("\"");//按"\""分割
cpu_core_name=info_list[1];
}
bool parse_keil_project::parse_info_item_storage(const QString& info_item,use_percentage_bar& storage )
{
QStringList info_list;
uint64_t data;
bool is_int;
uint8_t data_cnt=0;
QString sp_char=",";
if(info_item.contains("-"))
sp_char="-";
info_list= info_item.split("(");//按"("分割
info_list= info_list[1].split(sp_char);//按","或者"-"分割
data_cnt==0;
for(auto info:info_list)
{
info.remove(QChar(','), Qt::CaseInsensitive);//去除","
info.remove(QChar(')'), Qt::CaseInsensitive);//去除")"
info.remove(QChar('x'), Qt::CaseInsensitive);//去除"0x"的'x'
data=info.toInt(&is_int,16);//转16进制
if(is_int)//判断是否是16进制整数
{
if(data_cnt==0)//第一个16进制数是base地址
{
storage.setBase_addr(data);
data_cnt++;
}else//第二个十六进制数是 max容量大小
{
storage.setMax_size(data);
data_cnt=0;
}
}
}
qDebug()<<QString().sprintf("%s base:%#x size:%.2f KB",storage.getName().toStdString().data(), storage.getBase_addr(),storage.getMax_size()/1024.0);
}
bool parse_keil_project::parse_cpu_info(const QString& cpu_info)
{
QStringList cpu_info_list = cpu_info.split(")");
for(auto info_item:cpu_info_list)
{
// qDebug()<<info_item;
if(info_item.contains("IRAM"))//包含"IRAM"字段
{
parse_info_item_storage(info_item,IRAM);
}
else if(info_item.contains("XRAM"))//包含"XRAM"字段
{
parse_info_item_storage(info_item,XRAM);
}
else if(info_item.contains("IROM"))
{
parse_info_item_storage(info_item,IROM);
}
else if(info_item.contains("CPUTYPE"))
{
parse_info_item_core_name(info_item);
qDebug()<<"core:"<<cpu_core_name;
}
else if(info_item.contains("CLOCK"))
{
parse_info_item_max_clock(info_item);
qDebug()<<"main_clock:"<<cpu_max_clock<<"MHz";
}
}
}
bool parse_keil_project::parse_project_file(QString path)
{
QFile file(path);
if (!file.open(QIODevice::ReadOnly))
{
qDebug()<<"open fail"<<endl;
return 0;
}
QXmlStreamReader reader(&file);
while(!reader.atEnd())
{
if(reader.isStartElement())
{
// qDebug()<<"<"<<reader.name();
if("Cpu"==reader.name())
{
parse_cpu_info(reader.readElementText());
}else if("Device"==reader.name())
{
cpu_name=(reader.readElementText());
}else if("ToolsetName" ==reader.name())
{
if(reader.readElementText().contains("MCS-51"))
cpu_core_name="8051";
}
}
if(reader.isEndElement())
{
// qDebug()<<">"<<reader.name();
}
reader.readNext();
}
if (reader.hasError())
{
qDebug()<<reader.errorString();
}
file.close();
}

51
parse_keil_project.h Normal file
View File

@ -0,0 +1,51 @@
#ifndef PARSE_KEIL_PROJECT_H
#define PARSE_KEIL_PROJECT_H
#include <QString>
#include <use_percentage_bar.h>
class parse_keil_project
{
public:
parse_keil_project(QString path);
bool to_parse_keil_project(QString path);
QString find_project_path(const QString& dir_path);
bool parse_project_file(QString path);
bool parse_cpu_info(const QString& cpu_info);
bool parse_info_item_storage(const QString& info_item,use_percentage_bar& storage );
bool parse_info_item_core_name(const QString& info_item);
bool parse_info_item_max_clock(const QString& info_item);
QString getCpu_core_name() const;
uint64_t getCpu_max_clock() const;
QString getProject_path() const;
void setProject_path(const QString &value);
use_percentage_bar IRAM;
use_percentage_bar IROM;
use_percentage_bar XRAM;
QString getCpu_name() const;
private:
QString project_path;
// uint64_t iram_base;
// uint64_t xram_base;
// uint64_t irom_base;
// uint64_t iram_size;
// uint64_t xram_size;
// uint64_t irom_size;
QString cpu_name;
QString cpu_core_name;
uint64_t cpu_max_clock;
};
#endif // PARSE_KEIL_PROJECT_H

180
parse_m51_from_keil.cpp Normal file
View File

@ -0,0 +1,180 @@
#include "parse_m51_from_keil.h"
#include <QFile>
#include <QDomDocument>
#include "find_path.h"
#include <Qdebug>
parse_m51_from_keil::parse_m51_from_keil(QString path,uint64_t iram_max_size,uint64_t xram_max_size,
uint64_t irom_max_size)
{
iram_max=iram_max_size;
xram_max=xram_max_size;
irom_max=irom_max_size;
//to_parse_m51_from_keil(path);
}
bool parse_m51_from_keil::to_parse_m51_from_keil(QString path)
{
QString file_path=find_m51_path(path);
qDebug()<<file_path;
if(file_path.length()>3){
parse_m51_file(file_path);
return true;
}
else{
qDebug()<<"路径错误";
return false;
}
}
QString parse_m51_from_keil::find_m51_path(const QString &dir_path)
{
QString m51_file_path;
m51_file_path=find_path::find_file_path(dir_path,".m51");
if(m51_file_path.length()<3)
m51_file_path=find_path::find_file_path(dir_path,".M51");
return m51_file_path;
}
bool parse_m51_from_keil::parse_m51_file(QString path)
{
QFile file(path);
iram=new use_percentage_bar(nullptr);
xram=new use_percentage_bar(nullptr);
irom=new use_percentage_bar(nullptr);
iram->setName("iram");
iram->setStorage(mc8051);
iram->setBase_addr(0);
xram->setName("xram");
xram->setStorage(mc8051);
xram->setBase_addr(0);
xram->setMax_size(0);
irom->setName("irom");
irom->setStorage(mc8051);
irom->setBase_addr(0);
iram->setMax_size(iram_max*10.0);
xram->setMax_size(xram_max*10.0);
irom->setMax_size(irom_max*10.0);
bool is_Image_component_sizes=false;
bool is_Totals=false;
// info_list.clear();
for(auto ram:ram_list)
{
delete ram;
}
ram_list.clear();
for(auto flash:flash_list)
{
delete flash;
}
flash_list.clear();
if (!file.open(QIODevice::ReadOnly))
{
qDebug()<<"open fail"<<endl;
return false;
}
while (!file.atEnd())
{
QByteArray line = file.readLine();
QString str(line);
if(str.contains("Program Size"))
{
// qDebug() << str;
// parse_excution_region_info(str);
QStringList str_list= str.split(" ");
for(int i=0;i<str_list.length();i++)
{
// qDebug() << str_list[i];
if(str_list[i].contains("xdata"))
{
xram->setUsed_size((str_list[i].split("=")[1].toFloat())*10.0);
xram->setRemain_size(xram->getMax_size()-xram->getUsed_size());
}else if(str_list[i].contains("XDATA"))
{
xram->setUsed_size((str_list[i].split("=")[1].toFloat())*10.0);
xram->setRemain_size(xram->getMax_size()-xram->getUsed_size());
}else if(str_list[i].contains("data"))
{
iram->setUsed_size((str_list[i].split("=")[1].toFloat())*10.0);
iram->setRemain_size(iram->getMax_size()-iram->getUsed_size());
}else if(str_list[i].contains("DATA"))
{
iram->setUsed_size((str_list[i].split("=")[1].toFloat())*10.0);
iram->setRemain_size(iram->getMax_size()-iram->getUsed_size());
}else if(str_list[i].contains("code"))
{
irom->setUsed_size((str_list[i].split("=")[1].toFloat())*10.0);
irom->setRemain_size(irom->getMax_size()-irom->getUsed_size());
}else if(str_list[i].contains("code"))
{
irom->setUsed_size((str_list[i].split("=")[1].toFloat())*10.0);
irom->setRemain_size(irom->getMax_size()-irom->getUsed_size());
}
}
}
// else if(str.contains("Image component sizes"))
// {
// is_Image_component_sizes=true;
//// qDebug()<<str;
// }
}
file.close();
ram_list.append(iram);
if(xram->getMax_size()>0)
ram_list.append(xram);
flash_list.append(irom);
qDebug()<<"ram:";
for(auto ram:ram_list)
{
ram->print_bar_8051();
}
qDebug()<<"flash:";
for(auto flash:flash_list)
{
flash->print_bar_8051();
}
}

32
parse_m51_from_keil.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef PARSE_M51_FROM_KEIL_H
#define PARSE_M51_FR0M_KEIL_H
#include <QString>
#include "use_percentage_bar.h"
#include <QList>
class parse_m51_from_keil
{
public:
parse_m51_from_keil(QString path,uint64_t iram_max_size,uint64_t xram_max_size,
uint64_t irom_max_size);
uint64_t all_ram_size=0;
uint64_t all_flash_size=0;
uint64_t iram_max;
uint64_t xram_max;
uint64_t irom_max;
use_percentage_bar* iram;
use_percentage_bar* xram;
use_percentage_bar* irom;
QList<use_percentage_bar*>ram_list;
QList<use_percentage_bar*>flash_list;
bool to_parse_m51_from_keil(QString path);
QString find_m51_path(const QString& dir_path);
bool parse_m51_file(QString path);
};
#endif // PARSE_M51_FROM_KEIL_H

330
parse_map_from_keil.cpp Normal file
View File

@ -0,0 +1,330 @@
#include "parse_map_from_keil.h"
#include <QFile>
#include <QDomDocument>
#include <Qtxml>
#include <QDebug>
#include <qxmlstream.h>
#include "find_path.h"
#include <QRegExp>
#include "mainwindow.h"
#include "ui_mainwindow.h"
extern MainWindow* main_window;
QString parse_map_from_keil::find_map_path(const QString& dir_path)
{
QString map_file_path;
map_file_path=find_path::find_file_path(dir_path,".map");
if(map_file_path.length()<3)
map_file_path=find_path::find_file_path(dir_path,".MAP");
return map_file_path;
}
bool parse_map_from_keil::parse_excution_region_info(QString info_string)
{
// storage_type_t storage=ram;
use_percentage_bar* storage=new use_percentage_bar(nullptr);
storage->setStorage(flash);
for(auto keyword:ram_keyword)
{
if(info_string.contains(keyword))
{
// qDebug()<<info_string;
storage->setStorage(ram);
}
}
info_string.remove("Execution Region", Qt::CaseInsensitive);//去除"Execution Region"
info_string.remove(QChar(' '), Qt::CaseInsensitive);//去除" "
storage->setName(info_string.split("(")[0]);
QStringList info_list =info_string.split("(")[1].split(",");
for(auto info :info_list)
{
QStringList info_value;
info.remove(QChar(','), Qt::CaseInsensitive);//去除","
info.remove(QChar(' '), Qt::CaseInsensitive);//去除")"
if(info.contains("Exec")||info.contains("Base"))
{
info_value =info.split(":");
info_value[1].remove(QChar('x'), Qt::CaseInsensitive);//去除"x"
storage->setBase_addr(info_value[1].toUInt(nullptr,16));
// qDebug()<<info_value[1];
if(storage->getBase_addr()>iram_base&&storage->getBase_addr()<iram_base+iram_max_size)
storage->setStorage(ram);
else if(storage->getBase_addr()>irom_base&&storage->getBase_addr()<irom_base+irom_max_size)
storage->setStorage(flash);
}else if(info.contains("Size"))
{
info_value =info.split(":");
info_value[1].remove(QChar('x'), Qt::CaseInsensitive);//去除"x"
storage->setUsed_size(info_value[1].toUInt(nullptr,16));
// qDebug()<<info_value[1];
}else if(info.contains("Max"))
{
info_value =info.split(":");
info_value[1].remove(QChar('x'), Qt::CaseInsensitive);//去除"x"
storage->setMax_size(info_value[1].toUInt(nullptr,16));
// qDebug()<<info_value[1];
}
}
if(storage->getStorage()==ram)
ram_list.append(storage);
else
flash_list.append(storage);
}
bool parse_map_from_keil::parse_map_file(QString path){
QFile file(path);
bool is_Image_component_sizes=false;
bool is_Totals=false;
for(auto info:info_list)
{
delete info;
}
info_list.clear();
for(auto ram:ram_list)
{
delete ram;
}
ram_list.clear();
for(auto flash:flash_list)
{
delete flash;
}
flash_list.clear();
if (!file.open(QIODevice::ReadOnly))
{
qDebug()<<"open fail"<<endl;
return false;
}
while (!file.atEnd())
{
QByteArray line = file.readLine();
QString str(line);
if(str.contains("Execution Region"))
{
// qDebug() << str;
parse_excution_region_info(str);
}else if(str.contains("Image component sizes"))
{
is_Image_component_sizes=true;
// qDebug()<<str;
}
if(is_Image_component_sizes)
{
if(str.contains("----"))
{
if(is_Totals)
{
is_Totals=false;
}else
{
is_Totals=true;
}
}
else if(str.contains("=====")){
is_Image_component_sizes=false;
}else if(str==""||str.length()<10)
{
}
else {
// 使用正则表达式提取数字和单词
QRegExp rx("(\\d+|\\w+)");
// 将多个空格替换为逗号
QString csv_row = str.trimmed().replace(QRegExp("\\s+"), ",");
csv_row+="\n";
// 输出修改后的数据
// qDebug() << csv_row;
QStringList item_data= csv_row.split(",");
if(item_data.length()<=8)
{
bool is_number=false;
if(is_Totals)
{
if(item_data.length()>7&&item_data[7].contains("Totals"))
{
continue;
}
}
item_data[1].toUInt(&is_number);
if(is_number)
{
image_item_t* item=new image_item_t();
item->Code=QString::number(item_data[0].toInt());//item_data[1].toUInt()(inc.data是包含在code内的)
item->RO_Data=item_data[2];
item->RW_Data=item_data[3];
item->ZI_Data=item_data[4];
item->Debug=item_data[5];
item->Object_Name=item_data[6];
if(item->Object_Name.contains(".l"))
continue;
else if (item->Object_Name.contains("(")) {
item->Object_Name=item->Object_Name=item_data[6]+item_data[7];
}
info_list.append(item);
}
}
}
}
}
qDebug()<<"ram:";
for(auto ram:ram_list)
{
ram->print_bar();
}
qDebug()<<"flash:";
for(auto flash:flash_list)
{
flash->print_bar();
}
file.close();
}
QString parse_map_from_keil::getMap_path() const
{
return map_path;
}
void parse_map_from_keil::setMap_path(const QString &value)
{
map_path = value;
}
QList<image_item_t*> parse_map_from_keil::getInfo_list() const
{
return info_list;
}
void parse_map_from_keil::setInfo_list(const QList<image_item_t*> &value)
{
info_list = value;
}
uint64_t parse_map_from_keil::getAll_ram_size() const
{
return all_ram_size;
}
uint64_t parse_map_from_keil::getAll_flash_size() const
{
return all_flash_size;
}
bool parse_map_from_keil::to_parse_map_from_keil(QString path)
{
map_path=path;
QString file_path;
if(path.contains(".map")||path.contains(".MAP"))
{
parse_map_file(path);
return true;
}
file_path=find_map_path(path);
qDebug()<<file_path;
if(file_path.length()>3)
{
parse_map_file(file_path);
return true;
}else
{
qDebug()<<"路径错误";
return false;
}
}
parse_map_from_keil::parse_map_from_keil(QString path, uint64_t to_iram_base,
uint64_t to_iram_max_size,
uint64_t to_irom_base,
uint64_t to_irom_max_size)
{
iram_base=to_iram_base;
iram_max_size=to_iram_base;
irom_base=to_irom_base;
irom_max_size= to_irom_max_size;
//to_parse_map_from_keil(path);
}

74
parse_map_from_keil.h Normal file
View File

@ -0,0 +1,74 @@
#ifndef PARSE_MAP_FROM_KEIL_H
#define PARSE_MAP_FROM_KEIL_H
#include <QString>
#include "use_percentage_bar.h"
#include <QList>
typedef struct {QString fn_name;QString file_name; uint64_t size;}map_item;
typedef struct image_item {
QString Code;
QString RO_Data;
QString RW_Data;
QString ZI_Data;
QString Debug;
QString Object_Name;
}image_item_t;
class parse_map_from_keil
{
public:
bool to_parse_map_from_keil(QString path);
parse_map_from_keil(QString path,
uint64_t to_iram_base,
uint64_t to_iram_max_size,
uint64_t to_irom_base,
uint64_t to_irom_max_size
);
QString find_map_path(const QString& dir_path);
bool parse_excution_region_info(QString info_string);
bool parse_map_file(QString path);
QList<use_percentage_bar*>ram_list;
QList<use_percentage_bar*>flash_list;
QString getMap_path() const;
void setMap_path(const QString &value);
QList<image_item_t*> getInfo_list() const;
void setInfo_list(const QList<image_item_t*> &value);
uint64_t getAll_ram_size() const;
uint64_t getAll_flash_size() const;
private:
uint64_t iram_base;
uint64_t iram_max_size;
uint64_t irom_base;
uint64_t irom_max_size;
uint64_t all_ram_size=0;
uint64_t all_flash_size=0;
//,"HEAP","STACK","heap","stack"
QList<QString> ram_keyword={"ER$$","RW_","ER_RW","ER_ZI"};
QList<QString> flash_keyword={"RO","FLASH","flash","ro","text","TEXT"};
QString map_path;
QList<image_item_t*> info_list;
};
#endif // PARSE_MAP_FROM_KEIL_H

301
use_percentage_bar.cpp Normal file
View File

@ -0,0 +1,301 @@
#include "use_percentage_bar.h"
#include "ui_use_percentage_bar.h"
#include <QDebug>
#include <QString>
#include <flatui.h>
use_percentage_bar::use_percentage_bar(QWidget *parent) :
QWidget(parent),
ui(new Ui::use_percentage_bar)
{
ui->setupUi(this);
FlatUI::setProgressQss(ui->used_bar, 20,12,16, "#747976", "#1ABC9C");
}
void use_percentage_bar::set_bar_style(QProgressBar *bar,float per)
{
if( per/1.0>0.85)
{
FlatUI::setProgressQss(bar, 20,12,16, "#747976", "#E74C3C");
}else if( per>0.75)
{
FlatUI::setProgressQss(bar, 20,12,16, "#747976", "#F9D927");
}
else
{
FlatUI::setProgressQss(bar, 20,12,16, "#747976", "#1ABC9C");
}
}
use_percentage_bar::~use_percentage_bar()
{
delete ui;
}
void use_percentage_bar::print_bar_8051(void)
{
if(max_size==0)
{
qDebug()<<"erro:max=0";
return;
}
uint8_t i;
QString bar_str;
qDebug()<<name<<":0";//<<QString().sprintf("%#x",base_addr);
if(max_size/10.0<=1024)
{
bar_str+=QString().sprintf("%6.2f B %5s:|", max_size/10.0 , name.toStdString().data());
}
else
{
bar_str+=QString().sprintf("%6.2f KB %5s:|", max_size/10.0/1024.0 , name.toStdString().data());
}
for (i = 0; i < 20; i++)
{
if (i < (uint8_t)((used_size / 1.0) / (max_size / 1.0) * 20))
{
bar_str+=QString().sprintf("");
}
else
{
bar_str+=QString().sprintf("_");
}
}
if(max_size/10.0<=1024)
{
bar_str+=QString().sprintf("|%6.2f %% (%8.2f B / %8.2f B)", (used_size/10.0 / 1.0) / (max_size/10.0 / 1.0) * 100, used_size/10.0 , max_size/10.0);
}
else
{
bar_str+=QString().sprintf("|%6.2f %% (%8.2f B / %8.2f KB)", (used_size/10.0 / 1.0) / (max_size/10.0 / 1.0) * 100, used_size/10.0 , max_size/10.0 / 1024.0f);
}
bar_str+=QString().sprintf(" [%u B]", max_size/10.0 - used_size/10.0);
qDebug()<< bar_str;
}
void use_percentage_bar::print_bar(void)
{
if(max_size==0)
{
qDebug()<<"erro:max=0";
return;
}
uint8_t i;
QString bar_str;
qDebug()<<name<<":"<<QString().sprintf("%#x",base_addr);
bar_str+=QString().sprintf("%6.2f KB %5s:|", max_size / 1024.0f, storage==ram?"ram":"flash");
for (i = 0; i < 20; i++)
{
if (i < (uint8_t)((used_size / 1.0) / (max_size / 1.0) * 20))
{
bar_str+=QString().sprintf("");
}
else
{
bar_str+=QString().sprintf("_");
}
}
if(max_size<=1024*1024)
{
bar_str+=QString().sprintf("|%6.2f %% (%8.2f KB / %8.2f KB)", (used_size / 1.0) / (max_size / 1.0) * 100, used_size / 1024.0f, max_size / 1024.0f);
}
else
{
bar_str+=QString().sprintf("|%6.2f %% (%8.4f MB / %8.4f MB)", (used_size / 1.0) / (max_size / 1.0) * 100, used_size / 1024.0f/1024.0f, max_size / 1024.0f/1024.0f);
}
bar_str+=QString().sprintf(" [%u B]", max_size - used_size);
qDebug()<< bar_str;
}
QString use_percentage_bar::getName() const
{
return name;
}
void use_percentage_bar::setName(const QString &value)
{
name = value;
ui->name->setTitle(name);
}
storage_type_t use_percentage_bar::getStorage() const
{
return storage;
}
void use_percentage_bar::setStorage(const storage_type_t &value)
{
storage = value;
}
uint64_t use_percentage_bar::getBase_addr() const
{
return base_addr;
}
void use_percentage_bar::setBase_addr(const uint64_t &value)
{
base_addr = value;
ui->addr->setText(QString().sprintf("地址:%#x", base_addr));
}
uint64_t use_percentage_bar::getLoad_addr() const
{
return load_addr;
}
void use_percentage_bar::setLoad_addr(const uint64_t &value)
{
load_addr = value;
}
uint64_t use_percentage_bar::getLoad_max_size() const
{
return load_max_size;
}
void use_percentage_bar::setLoad_max_size(const uint64_t &value)
{
load_max_size = value;
}
uint64_t use_percentage_bar::getUsed_size() const
{
return used_size;
}
void use_percentage_bar::setUsed_size(const uint64_t &value)
{
used_size = value;
if(max_size!=0)
{
ui->used_bar->setRange(0,max_size);
ui->used_bar->setValue(used_size);
if(storage==mc8051)
{
if(max_size/10.0<=1024)
{
ui->used->setText(QString().sprintf("占用:%.2f B / (%.2f B)",used_size/10.0,max_size/10.0));
}
else
{
ui->used->setText(QString().sprintf("占用:%.2f B / (%.2f KB)",used_size/10.0,max_size/10.0/1024.0));
}
setRemain_size(max_size-used_size);
}else
{
if(max_size<=1024*1024)
{
ui->used->setText(QString().sprintf("占用:%.2f KB / (%.2f KB)",used_size/1024.0,max_size/1024.0));
}
else
{
ui->used->setText(QString().sprintf("占用:%.4f MB / (%.4f MB)",used_size/1024.0/1024.0,max_size/1024.0/1024.0));
}
setRemain_size(max_size-used_size);
}
set_bar_style(ui->used_bar,used_size/1.0/max_size/1.0);
}
}
uint64_t use_percentage_bar::getMax_size() const
{
return max_size;
}
void use_percentage_bar::setMax_size(const uint64_t &value)
{
max_size = value;
if(max_size!=0)
{
ui->used_bar->setRange(0,max_size);
ui->used_bar->setValue(used_size);
if(storage==mc8051)
{
if(max_size/10.0<=1024)
{
ui->used->setText(QString().sprintf("占用:%.2f B / (%.2f B)",used_size/10.0,max_size/10.0));
}else
{
ui->used->setText(QString().sprintf("占用:%.2f B / (%.2f KB)",used_size/10.0,max_size/10.0/1024.0));
}
setRemain_size(max_size-used_size);
}else
{
if(max_size<=1024*1024)
{
ui->used->setText(QString().sprintf("占用:%.2f KB / (%.2f KB)",used_size/1024.0,max_size/1024.0));
}else
{
ui->used->setText(QString().sprintf("占用:%.4f MB / (%.4f MB)",used_size/1024.0/1024.0,max_size/1024.0/1024.0));
}
setRemain_size(max_size-used_size);
}
set_bar_style(ui->used_bar,used_size/1.0/max_size/1.0);
}
}
uint64_t use_percentage_bar::getRemain_size() const
{
return remain_size;
}
void use_percentage_bar::setRemain_size(const uint64_t &value)
{
remain_size = value;
if(storage==mc8051)
{
ui->remain->setText(QString().sprintf("剩余:%.2f B",remain_size/10.0));
}else
{
ui->remain->setText(QString().sprintf("剩余:%llu B",remain_size));
}
}

61
use_percentage_bar.h Normal file
View File

@ -0,0 +1,61 @@
#ifndef USE_PERCENTAGE_BAR_H
#define USE_PERCENTAGE_BAR_H
#include <QWidget>
#include <QProgressBar>
namespace Ui {
class use_percentage_bar;
}
typedef enum storage_type {ram,flash,mc8051 }storage_type_t;
class use_percentage_bar : public QWidget
{
Q_OBJECT
public:
explicit use_percentage_bar(QWidget *parent = nullptr);
~use_percentage_bar();
void print_bar(void);
void print_bar_8051(void);
QString getName() const;
void setName(const QString &value);
storage_type_t getStorage() const;
void setStorage(const storage_type_t &value);
uint64_t getBase_addr() const;
void setBase_addr(const uint64_t &value);
uint64_t getLoad_addr() const;
void setLoad_addr(const uint64_t &value);
uint64_t getLoad_max_size() const;
void setLoad_max_size(const uint64_t &value);
uint64_t getUsed_size() const;
void setUsed_size(const uint64_t &value);
uint64_t getMax_size() const;
void setMax_size(const uint64_t &value);
uint64_t getRemain_size() const;
void setRemain_size(const uint64_t &value);
private:
Ui::use_percentage_bar *ui;
QString name;
storage_type_t storage;
uint64_t base_addr;
uint64_t load_addr;
uint64_t load_max_size;
uint64_t used_size;
uint64_t max_size;
uint64_t remain_size;
void set_bar_style(QProgressBar *bar,float per);
};
#endif // USE_PERCENTAGE_BAR_H

61
use_percentage_bar.ui Normal file
View File

@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>use_percentage_bar</class>
<widget class="QWidget" name="use_percentage_bar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QGroupBox" name="name">
<property name="title">
<string>RAM/Flash</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="addr">
<property name="text">
<string>地址0x0000000</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QProgressBar" name="used_bar">
<property name="value">
<number>24</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="used">
<property name="text">
<string> 占用:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="remain">
<property name="text">
<string> 还剩:</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>