mirror of
https://gitee.com/js-yhsec/energy_storage.git
synced 2026-05-27 18:59:26 +08:00
修改现场设备联调问题
This commit is contained in:
@@ -84,7 +84,7 @@
|
||||
["SOH", "0x0002", "0", " %", "0.1"],
|
||||
["电压", "0x0003", "0.0", " V", "0.1"],
|
||||
["电流", "0x0005", "0.0", " A", "0.1"],
|
||||
["单体最电压", "0x0021", "0.0", " V", "0.001"],
|
||||
["单体最大电压", "0x0021", "0.0", " V", "0.001"],
|
||||
["单体最小电压", "0x0024", "0.0", " V", "0.001"],
|
||||
["单体最大温度", "0x0029", "0.0", " ℃", "0.1"],
|
||||
["单体最小温度", "0x002C", "0.0", " ℃", "0.1"]
|
||||
|
||||
@@ -21,7 +21,7 @@ endmacro(ADD_SOURCE_GROUP)
|
||||
set(PROJECT_NAME ESS)
|
||||
project(${PROJECT_NAME})
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
|
||||
# 【注意】visual studio编译时的字符编码问题,配置属性 --> C/C++ --> 命令行 --> 其它选项: /utf-8 或添加如下指令
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /utf-8")
|
||||
|
||||
@@ -134,6 +134,7 @@ void Application::runThreadStat()
|
||||
//spdlog::info("保存历史数据倒计时: {}", 600 - offset);
|
||||
}
|
||||
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
}
|
||||
}
|
||||
@@ -221,7 +221,10 @@ void Device::setParam(std::string k, int v)
|
||||
else if (k== "28") { ratio = 0.1; }
|
||||
}
|
||||
|
||||
int precision = (ratio != 1.0f) ? 1 : 0;
|
||||
int precision = 0;
|
||||
if (ratio == 0.1f) { precision = 1; }
|
||||
else if (ratio == 0.01f) { precision = 2; }
|
||||
else if (ratio == 0.001f) { precision = 3; }
|
||||
std::string valStr = Utils::toStr(v*ratio, precision);
|
||||
if (type == 106) // 充电桩状态,特殊数据格式
|
||||
{
|
||||
|
||||
@@ -146,23 +146,30 @@ void SysPolicy::getGatewayJsonPeriods(njson& json)
|
||||
{
|
||||
if (vecPeriods1.size()>0)
|
||||
{
|
||||
njson jsonArray = njson::array();
|
||||
map<string, vector<int>> mapT;
|
||||
for (auto& item: vecPeriods1[0])
|
||||
{
|
||||
int h = 0; int m = 0;
|
||||
PeriodsTimeStrToInt(item.first, h, m);
|
||||
if (jsonArray.size() == 0 && h!=0)
|
||||
{
|
||||
jsonArray.push_back({0, 0, 0});
|
||||
}
|
||||
|
||||
int p = 1;
|
||||
int p = 0;
|
||||
if (item.second == "谷") p = 1;
|
||||
else if (item.second == "平") p = 2;
|
||||
else if (item.second == "峰") p = 3;
|
||||
else if (item.second == "尖") p = 4;
|
||||
else p = 0;
|
||||
jsonArray.push_back({h, m, p});
|
||||
char str[5] = {};
|
||||
sprintf(str, "%02d:%02d", h, m);
|
||||
mapT[str] = {h, m, p};
|
||||
}
|
||||
|
||||
njson jsonArray = njson::array();
|
||||
for (auto& item: mapT)
|
||||
{
|
||||
if (jsonArray.size() == 0 && item.first != "00:00")
|
||||
{
|
||||
jsonArray.push_back({0, 0, 0});
|
||||
}
|
||||
jsonArray.push_back(item.second);
|
||||
}
|
||||
json.push_back(jsonArray);
|
||||
}
|
||||
|
||||
@@ -674,12 +674,11 @@ void Station::writeStatistic()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
int pos = npos;
|
||||
if (tOffset > 20) { pos += 1; }
|
||||
mapCacheElectIn[pos] = statData.dayElectIn;
|
||||
mapCacheElectOut[pos] = statData.dayElectOut;
|
||||
mapCacheElectIn[pos] = (pos == 0) ? 0 : statData.dayElectIn;
|
||||
mapCacheElectOut[pos] = (pos == 0) ? 0 : statData.dayElectOut;
|
||||
mapCacheElectCharger[pos] = 0;
|
||||
|
||||
// 预测数据源记录
|
||||
@@ -703,57 +702,61 @@ void Station::writeStatistic()
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Station::predict()
|
||||
{
|
||||
int64_t tNow = Utils::time();
|
||||
|
||||
string dt1 = Utils::dateStr(tNow-86400*7);
|
||||
int days = 7;
|
||||
string dt1 = Utils::dateStr(tNow-86400*days);
|
||||
string dt2 = Utils::dateStr(tNow-86400);
|
||||
|
||||
/// 预测实现方案:
|
||||
// 查询前7天的历史数据,根据历史数据计算今日数据,每10分钟一个数据,一天共144个数据点
|
||||
// 查询前7天的历史数据(不包含今天),根据历史数据计算今日数据,每10分钟一个数据,一天共144个数据点
|
||||
string sql = "SELECT * FROM predict_day pd WHERE pd.station_id='" + std::to_string(stationId)
|
||||
+ "'AND dt>='" + dt1 + "' AND dt<='" + dt2 + "'";
|
||||
+ "' AND dt>='" + dt1 + " AND dt<'" + dt2 + "';";
|
||||
|
||||
vector<Fields> result;
|
||||
DAO::exec(NULL, sql, result);
|
||||
|
||||
// 数据源的条数(1天的数据算作1条)
|
||||
int countStorageIn = 0;
|
||||
int countStorageOut = 0;
|
||||
int countCharge = 0;
|
||||
// 数据源的每个时刻数据点的个数
|
||||
vector<int> countStorageIn(predictStorageIn.size(), 0);
|
||||
vector<int> countStorageOut(predictStorageOut.size(), 0);
|
||||
vector<int> countCharge(predictCharge.size(), 0);
|
||||
|
||||
for (int row=0; row<result.size(); ++row)
|
||||
{
|
||||
// 如果数据全是0,则不参与计算
|
||||
auto& fields = result[row];
|
||||
|
||||
vector<int>* vdptr = NULL;
|
||||
int datatype = fields.get<int>("datatype"); // 1:储能充电,2:储能放电,3:充电桩充电,4:发电
|
||||
if (datatype == 1)
|
||||
{
|
||||
countStorageIn++;
|
||||
vdptr = &predictStorageIn;
|
||||
}
|
||||
else if (datatype == 2)
|
||||
{
|
||||
countStorageOut++;
|
||||
vdptr = &predictStorageOut;
|
||||
}
|
||||
else if (datatype == 3)
|
||||
{
|
||||
countCharge++;
|
||||
vdptr = &predictCharge;
|
||||
}
|
||||
if (datatype == 1) { vdptr = &predictStorageIn; }
|
||||
else if (datatype == 2) { vdptr = &predictStorageOut; }
|
||||
else if (datatype == 3) { vdptr = &predictCharge; }
|
||||
|
||||
if (vdptr)
|
||||
{
|
||||
string& strval = fields.value("value");
|
||||
std::vector<int> vec;
|
||||
JSON::parseArray(strval, vec);
|
||||
|
||||
for (int i = 0; i<vdptr->size() && i<vec.size(); ++i)
|
||||
{
|
||||
(*vdptr)[i] += vec[i];
|
||||
auto& v0 = vec[i];
|
||||
if (v0 > 0)
|
||||
{
|
||||
(*vdptr)[i] += v0;
|
||||
if (datatype == 1) { countStorageIn[i]++; }
|
||||
else if (datatype == 2) { countStorageOut[i]++; }
|
||||
else if (datatype == 3) { countCharge[i]++; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i<predictStorageIn.size(); ++i)
|
||||
{
|
||||
if (countStorageIn[i] > 0) { predictStorageIn[i] = predictStorageIn[i] / countStorageIn[i]; }
|
||||
if (countStorageOut[i] > 0) { predictStorageOut[i] = predictStorageOut[i] / countStorageOut[i]; }
|
||||
if (countCharge[i] > 0) { predictCharge[i] = predictCharge[i] / countCharge[i]; }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -27,13 +27,74 @@ std::string Utils::toHex(const std::string& s)
|
||||
}
|
||||
std::string Utils::fromHex(const std::string& hexstr)
|
||||
{
|
||||
std::vector<uint8_t> v;
|
||||
v.reserve(hexstr.size() / 2);
|
||||
std::vector<uint8_t> result;
|
||||
result.reserve(hexstr.size() / 2);
|
||||
for (std::string::const_iterator it = hexstr.begin(); it != hexstr.end(); it += 2)
|
||||
{
|
||||
v.push_back(static_cast<char>(strtol(std::string(it, it + 2).c_str(), nullptr, 16)));
|
||||
result.push_back(static_cast<char>(strtol(std::string(it, it + 2).c_str(), nullptr, 16)));
|
||||
}
|
||||
return std::string(v.begin(), v.end());
|
||||
return std::string(result.begin(), result.end());
|
||||
}
|
||||
|
||||
#include <iostream>
|
||||
string Utils::fromHexText(string s)
|
||||
{
|
||||
vector<unsigned char> result;
|
||||
string tmp;
|
||||
stringstream ss;
|
||||
int v;
|
||||
for (auto ch : s)
|
||||
{
|
||||
if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F'))
|
||||
{
|
||||
tmp += ch;
|
||||
if (tmp.size() == 2)
|
||||
{
|
||||
ss.clear();
|
||||
ss.str("");
|
||||
ss << hex << tmp;
|
||||
ss >> v;
|
||||
result.emplace_back((unsigned char)v);
|
||||
tmp.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
return string(result.begin(), result.end());
|
||||
}
|
||||
string Utils::toHexText(string s, string d/* = " "*/)
|
||||
{
|
||||
stringstream ss;
|
||||
for (unsigned int i = 0; i < s.size(); ++i)
|
||||
{
|
||||
ss << std::setw(2) << std::setfill('0') << std::hex << std::uppercase << (int)static_cast<unsigned char>(s[i]) << ((i < s.size() - 1) ? d : "");
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
int64_t Utils::hexBinToInt(const string& str, bool swap/*=false*/)
|
||||
{
|
||||
int64_t v = 0;
|
||||
for (size_t i = 0; i < str.size(); i++)
|
||||
{
|
||||
if (swap)
|
||||
{
|
||||
v = v + (str[str.size() - 1 - i] << (str.size() - 1 - i) * 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
v = v + (str[i] << (str.size() - 1 - i) * 8);
|
||||
}
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
int Utils::hexStrToInt(const std::string& str)
|
||||
{
|
||||
stringstream ss;
|
||||
int ret;
|
||||
ss << hex << str.c_str();
|
||||
ss >> ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
string Utils::toStr(int v)
|
||||
@@ -80,57 +141,9 @@ double Utils::toDouble(const std::string& str)
|
||||
ss >> ret;
|
||||
return ret;
|
||||
}
|
||||
int64_t Utils::hexbinToInt(const string& str, bool swap/*=false*/)
|
||||
{
|
||||
int64_t v = 0;
|
||||
for (size_t i = 0; i < str.size(); i++)
|
||||
{
|
||||
if (swap)
|
||||
{
|
||||
v = v + (str[str.size() - 1 - i] << (str.size() - 1 - i) * 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
v = v + (str[i] << (str.size() - 1 - i) * 8);
|
||||
}
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
int Utils::hexstrToInt(const std::string& str)
|
||||
{
|
||||
stringstream ss;
|
||||
int ret;
|
||||
ss << hex << str.c_str();
|
||||
ss >> ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#include <iostream>
|
||||
string Utils::from_hex_text(string s)
|
||||
{
|
||||
vector<unsigned char> result;
|
||||
string tmp;
|
||||
stringstream ss;
|
||||
int v;
|
||||
for (auto ch : s)
|
||||
{
|
||||
if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F'))
|
||||
{
|
||||
tmp += ch;
|
||||
if (tmp.size() == 2)
|
||||
{
|
||||
ss.clear();
|
||||
ss.str("");
|
||||
ss << hex << tmp;
|
||||
ss >> v;
|
||||
result.emplace_back((unsigned char)v);
|
||||
tmp.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
return string(result.begin(), result.end());
|
||||
}
|
||||
|
||||
|
||||
//string Utils::fromHexText1(string s)
|
||||
//{
|
||||
@@ -166,16 +179,7 @@ string Utils::from_hex_text(string s)
|
||||
// return string(result.begin(), result.end());
|
||||
//}
|
||||
|
||||
string Utils::to_hex_text(string s, string d/* = " "*/)
|
||||
{
|
||||
stringstream ss;
|
||||
for (unsigned int i = 0; i < s.size(); ++i)
|
||||
{
|
||||
unsigned char ch = s[i];
|
||||
ss << std::setw(2) << std::setfill('0') << std::hex << std::uppercase << (int)ch << ((i < s.size() - 1) ? d : "");
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
|
||||
void time_point_to_duration()
|
||||
{
|
||||
@@ -418,13 +422,8 @@ int64_t Utils::timeDaySeconds()
|
||||
return tsNow - tsDay;
|
||||
}
|
||||
|
||||
void Utils::sleep_ms(int ms)
|
||||
void Utils::sleepMS(int ms)
|
||||
{
|
||||
// 计算时间间隔:
|
||||
//auto start = chrono::high_resolution_clock::now();
|
||||
//auto end = chrono::high_resolution_clock::now();
|
||||
//chrono::duration<double, std::milli> elapsed = end - start;
|
||||
//int64_t t = elapsed.count();
|
||||
std::this_thread::sleep_for(chrono::milliseconds(ms));
|
||||
}
|
||||
|
||||
|
||||
@@ -8,9 +8,6 @@
|
||||
#include <iomanip>
|
||||
#include <functional>
|
||||
#include <thread>
|
||||
|
||||
//#include "Crypto.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class Utils
|
||||
@@ -19,6 +16,11 @@ public:
|
||||
static std::string toHex(std::vector<unsigned char>& s, int len = 0);
|
||||
static std::string toHex(const std::string& s);
|
||||
static std::string fromHex(const std::string& hexstr);
|
||||
static string fromHexText(string s);
|
||||
static string toHexText(string s, string d = " ");
|
||||
|
||||
static int64_t hexBinToInt(const string& str, bool swap = false);
|
||||
static int hexStrToInt(const string& str);
|
||||
|
||||
static string toStr(int v);
|
||||
static string toStr(float v, int precision = 2);
|
||||
@@ -28,12 +30,6 @@ public:
|
||||
static float toFloat(const string& str);
|
||||
static double toDouble(const string& str);
|
||||
|
||||
static int64_t hexbinToInt(const string& str, bool swap = false);
|
||||
|
||||
static int hexstrToInt(const string& str);
|
||||
|
||||
static string from_hex_text(string s);
|
||||
static string to_hex_text(string s, string d = " ");
|
||||
|
||||
template<typename T>
|
||||
static void append_bytes(vector<unsigned char>& dest, const T& src, int len)
|
||||
@@ -84,7 +80,7 @@ public:
|
||||
static string gbkToUtf8(string s);
|
||||
static string utf8ToGbk(string s);
|
||||
|
||||
static void sleep_ms(int ms);
|
||||
static void sleepMS(int ms);
|
||||
|
||||
static int random(int min, int max);
|
||||
|
||||
@@ -96,8 +92,6 @@ public:
|
||||
class TimeTick
|
||||
{
|
||||
public:
|
||||
int64_t tickMS_ = 0;
|
||||
|
||||
TimeTick(int t=0)
|
||||
{
|
||||
if (t !=0) { tickMS_ = Utils::time(); }
|
||||
@@ -105,19 +99,16 @@ public:
|
||||
|
||||
bool elapse(int64_t second, bool reset = true)
|
||||
{
|
||||
auto tick_now = Utils::time();
|
||||
bool res = tick_now - tickMS_ > second;
|
||||
if (res && reset)
|
||||
{
|
||||
tickMS_ = tick_now;
|
||||
}
|
||||
return res;
|
||||
auto tickNow = Utils::time();
|
||||
bool ret = tickNow - tickMS_ > second;
|
||||
if (ret && reset) { tickMS_ = tickNow; }
|
||||
return ret;
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
tickMS_ = Utils::time();
|
||||
}
|
||||
void reset() { tickMS_ = Utils::time(); }
|
||||
|
||||
public:
|
||||
int64_t tickMS_ = 0;
|
||||
};
|
||||
|
||||
#endif // !!! _Utils_H_
|
||||
|
||||
21
src/main.cpp
21
src/main.cpp
@@ -167,10 +167,27 @@ void OpensslSM2_test()
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
{
|
||||
stringstream ss;
|
||||
float v = 3.123456;
|
||||
float ratio = 0.1;
|
||||
|
||||
ss << "(" << setw(2) << setfill('0') << 1;
|
||||
std::cout << ss.str();
|
||||
std::cout << Utils::toStr(v, 0) << std::endl;
|
||||
std::cout << Utils::toStr(v, 1) << std::endl;
|
||||
|
||||
ratio = 1;
|
||||
if (ratio == 1.0f)
|
||||
{
|
||||
std::cout << Utils::toStr(ratio, 2) << std::endl;
|
||||
}
|
||||
|
||||
std::cout << Utils::toFloat("1") << std::endl;
|
||||
|
||||
//ss << "(" << setw(2) << setfill('0') << 1 << ")";
|
||||
//std::cout << ss.str();
|
||||
|
||||
std::cout << "======================" << std::endl;
|
||||
}
|
||||
|
||||
// 设置控制台输出为 UTF-8 编码
|
||||
SetConsoleOutputCP(CP_UTF8);
|
||||
|
||||
@@ -13,10 +13,9 @@
|
||||
|
||||
MainApp::MainApp()
|
||||
{
|
||||
// 设置背景色
|
||||
QPalette palette(this->palette());
|
||||
|
||||
// 设置背景为黑色
|
||||
palette.setColor(QPalette::Window, QColor(1, 32, 54));
|
||||
palette.setColor(QPalette::Window, QColor(11, 33, 77));
|
||||
this->setAutoFillBackground(true);
|
||||
this->setPalette(palette);
|
||||
this->setStyleSheet("color: white;");
|
||||
@@ -59,6 +58,7 @@ void MainApp::initMenu()
|
||||
ui.labelDT = std::make_shared< QLabel>();
|
||||
ui.labelDT->setAlignment(Qt::AlignCenter);
|
||||
ui.labelDT->setText(Utils::timeStr().c_str());
|
||||
ui.labelDT->setFont(QFont("微软雅黑", 14));
|
||||
ui.layoutMenu->addWidget(ui.labelDT.get(), 0, 0, 1, 1);
|
||||
// 设置列宽和行高
|
||||
ui.layoutMenu->setRowMinimumHeight(0, 40); // 设置第0列的最小宽度为100像素
|
||||
|
||||
@@ -5,7 +5,9 @@ static const std::string QSS_GROUP =
|
||||
"QGroupBox::title { subcontrol-origin: margin; subcontrol-position: top left; left:10px; margin-left: 0px; padding:0 1px; }";
|
||||
|
||||
static const std::string QSS_BTN =
|
||||
"QPushButton {background:rgba(80, 80, 80,80);border-radius:5px;border:1px solid gray;color:white;font:bold 13px;}";
|
||||
"QPushButton {background:rgba(180,180,180,50);border-radius:2px;border:1px solid gray;color:white;}"
|
||||
"QPushButton:hover {background-color:rgb(32,164,128);}"
|
||||
"QPushButton:pressed {border-width:2px 0 0 2px;border-style:inset;}";
|
||||
|
||||
static const std::string QSS_BTN_ACTIVE =
|
||||
"QPushButton {background:rgba(80, 80, 80,80);border-radius:5px;border:1px solid green;color:green;font:bold 15px;}";
|
||||
@@ -29,7 +31,7 @@ static const std::string QSS_BTN_TAB =
|
||||
//"QPushButton:disabled {color:rgb(150,150,150);}";
|
||||
|
||||
static const std::string QSS_LINE =
|
||||
"QLineEdit { background-color: rgb(14, 49, 66); color: #ffffff; border: 1px solid gray; border-radius: 5px; font: bold 13px; }";
|
||||
"QLineEdit { background-color:rgba(180,180,180,36); color:#ffffff; border:1px solid gray; border-radius:3px; font:bold 13px; }"; //14, 49, 66
|
||||
|
||||
static const std::string QSS_TABLE = // 表格整体样式
|
||||
"QTableWidget {"
|
||||
@@ -70,6 +72,13 @@ MyWidget::MyWidget(QWidget* parent) : QWidget(parent)
|
||||
setAutoFillBackground(true);
|
||||
}
|
||||
|
||||
shared_ptr<QPushButton> MyQUI::Button(QWidget* parent, int x, int y, int w, int h, std::string title)
|
||||
{
|
||||
auto btn = std::make_shared<QPushButton>(title.c_str(), parent);
|
||||
btn->setGeometry(x, y, w, h);
|
||||
btn->setStyleSheet(QSS_BTN.c_str());
|
||||
return btn;
|
||||
}
|
||||
|
||||
std::shared_ptr<QGroupBox> MyQUI::GroupBox(QWidget* parent, int x, int y, int w, int h, std::string title)
|
||||
{
|
||||
|
||||
@@ -81,6 +81,8 @@ using MyPairLabelLine = pair<shared_ptr<QLabel>, shared_ptr<QLineEdit>>;
|
||||
class MyQUI
|
||||
{
|
||||
public:
|
||||
static shared_ptr<QPushButton> Button(QWidget* parent, int x, int y, int w, int h, std::string title);
|
||||
|
||||
static shared_ptr<QGroupBox> GroupBox(QWidget* parent, int x, int y, int w, int h, std::string title);
|
||||
|
||||
static MyPairLabelLine PairLine(QWidget* parent, int x, int y, string k, string v, bool readonly=true);
|
||||
|
||||
@@ -64,13 +64,12 @@ QWHome::QWHome(QWidget* parent) : MyWidget(parent)
|
||||
table->setColumnWidth(4, 80);
|
||||
}
|
||||
|
||||
logFilter = MyQUI::PairLine(this, 10, y += 270, "日志过滤: ", "", false);
|
||||
btnLogClean = std::make_shared<QPushButton>("清除", this);
|
||||
btnLogClean->setGeometry(400, y, 80, 26);
|
||||
logFilter = MyQUI::PairLine(this, 10, y += 280, "日志过滤: ", "", false);
|
||||
btnLogClean = MyQUI::Button(this, 400, y-1, 80, 28, "清除");
|
||||
connect(btnLogClean.get(), &QPushButton::clicked, this, [=]() { texteditLog->clear(); });
|
||||
|
||||
texteditLog = std::make_shared<QTextEdit>(this);
|
||||
texteditLog->setGeometry(10, y += 30, 1190, 280);
|
||||
texteditLog->setGeometry(10, y += 35, 1190, 280);
|
||||
texteditLog->setStyleSheet("background-color: transparent; border: 1px solid gray; font-weight: 400;");
|
||||
texteditLog->setReadOnly(true);
|
||||
texteditLog->document()->setMaximumBlockCount(1000);
|
||||
|
||||
Reference in New Issue
Block a user