This commit is contained in:
Gangphon 2023-09-19 11:49:20 +08:00
parent a9b29230e8
commit 07f6adc278
87 changed files with 12869 additions and 15507 deletions

View File

@ -46,11 +46,10 @@ osx {
ICON = res/Logo-raw.png
}
RESOURCES += res.qrc
copydir.files += AClock
copydir.files += borders
copydir.files += translations
copydir.files += $$quote(y50 param)
copydir.files += $$quote(files)
@ -93,6 +92,7 @@ qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
RESOURCES += res.qrc
SOURCES += \
base/changepasswordform.cpp \
@ -103,7 +103,7 @@ SOURCES += \
base/lodateselector.cpp \
base/loqtitlebar.cpp \
base/loqtreewidget.cpp \
base/waitingdlg.cpp \
gutil/qwaitingdlg.cpp \
basedlg.cpp \
basewin.cpp \
cfg.cpp \
@ -117,6 +117,7 @@ SOURCES += \
devicepanel.cpp \
ffplayer.cpp \
globaldefine.cpp \
gutil/cpp.cpp \
gutil/qgui.cpp \
gutil/qjson.cpp \
gutil/qnetwork.cpp \
@ -142,7 +143,6 @@ SOURCES += \
device/ctrlbrightpanel.cpp \
device/ctrlverifyclockpanel.cpp \
device/upgradeapkdialog.cpp \
device/wupgradeapkitem.cpp \
program/copydirthread.cpp \
program/eaclock.cpp \
program/ebase.cpp \
@ -158,14 +158,11 @@ SOURCES += \
program/gentmpthread.cpp \
program/pageeditor.cpp \
program/pagelistitem.cpp \
program/progcreatedlg.cpp \
program/progeditorwin.cpp \
program/progitem.cpp \
program/sendprogramdialog.cpp \
program/sendprogthread.cpp \
program/videosplitthread.cpp \
program/wplanitem.cpp \
program/wplanlist.cpp \
HEADERS += \
base/changepasswordform.h \
@ -175,7 +172,7 @@ HEADERS += \
base/lodateselector.h \
base/loqtitlebar.h \
base/loqtreewidget.h \
base/waitingdlg.h \
gutil/qwaitingdlg.h \
basedlg.h \
basewin.h \
cfg.h \
@ -189,6 +186,7 @@ HEADERS += \
devicepanel.h \
ffplayer.h \
globaldefine.h \
gutil/cpp.h \
gutil/qgui.h \
gutil/qjson.h \
gutil/qnetwork.h \
@ -213,7 +211,6 @@ HEADERS += \
device/ctrlbrightpanel.h \
device/ctrlverifyclockpanel.h \
device/upgradeapkdialog.h \
device/wupgradeapkitem.h \
program/copydirthread.h \
program/eaclock.h \
program/ebase.h \
@ -229,25 +226,17 @@ HEADERS += \
program/gentmpthread.h \
program/pageeditor.h \
program/pagelistitem.h \
program/progcreatedlg.h \
program/progeditorwin.h \
program/progitem.h \
program/sendprogramdialog.h \
program/sendprogthread.h \
program/videosplitthread.h \
program/wplanitem.h \
program/wplanlist.h \
TRANSLATIONS += \
translations/app_zh_CN.ts \
translations/app_zh_TW.ts \
translations/app_ja.ts \
translations/app_en.ts
EXTRA_TRANSLATIONS += \
translations/qt_zh_CN.ts \
translations/qt_zh_TW.ts \
translations/qt_ja.ts \
translations/qt_en.ts
ts/app_zh_CN.ts \
ts/app_zh_TW.ts \
ts/app_en.ts \
ts/app_ja.ts \
ts/app_pt.ts
include(./xlsx/qtxlsx.pri)

File diff suppressed because one or more lines are too long

View File

@ -1,65 +1,40 @@
#include "loqtreewidget.h"
#include <QCheckBox>
#include <QHeaderView>
#include <QGuiApplication>
class CheckableHeader : public QHeaderView {
public:
explicit CheckableHeader(Qt::Orientation orientation, QWidget *isSelAll) : QHeaderView(orientation), fdIsSelAll(isSelAll) {
fdIsSelAll->setParent(this);
}
QWidget *fdIsSelAll;
protected:
void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const override {
QHeaderView::paintSection(painter, rect, logicalIndex);
if(logicalIndex == 0) fdIsSelAll->setGeometry(rect);
}
};
LoQTreeWidget::LoQTreeWidget(QWidget *parent) : QTreeWidget(parent), m_checkState(CheckNone) {
fdIsSelAll = new QCheckBox;
fdIsSelAll->setStyleSheet("QCheckBox{margin-left: 5px;}");
m_header = new CheckableHeader(Qt::Horizontal, fdIsSelAll);
setHeader(m_header);
setProperty("ssType", "topList");
connect(fdIsSelAll, SIGNAL(toggled(bool)), this, SLOT(onCheckAll(bool)));
connect(this, &LoQTreeWidget::itemClicked, this, [this](QTreeWidgetItem *item, int column) {
if(selectionMode()==QAbstractItemView::NoSelection) return;
if(column > 0) item->setCheckState(0, item->checkState(0) == Qt::Unchecked ? Qt::Checked : Qt::Unchecked);
adjustCheckState();
void LoQTreeWidget::addFd() {
fdCheckAll = new QCheckBox(this);
connect(fdCheckAll, &QCheckBox::stateChanged, this, [=](int state) {
if(state==Qt::PartiallyChecked) return;
int cnt = topLevelItemCount();
for(int rr=0; rr<cnt; rr++) if(! topLevelItem(rr)->isHidden()) topLevelItem(rr)->setCheckState(1, (Qt::CheckState) state);
emit selChanged();
});
setFocusPolicy(Qt::NoFocus);
}
void LoQTreeWidget::adjustCheckState() {
bool isAllChecked = true;
auto cellClicked = [=](QTreeWidgetItem *item, int column) {
if(column > 2) return;
if(! fdCheckAll->isVisible()) return;
auto state = item->checkState(1)==Qt::Checked ? Qt::Unchecked : Qt::Checked;
item->setCheckState(1, state);
int cnt = topLevelItemCount();
if(cnt == 0) {
isAllChecked = false;
m_checkState = CheckNone;
} else {
int k = 0;
for(int i=0; i<cnt; i++) if(!this->isRowHidden(i,indexFromItem(topLevelItem(i)->parent()))) {
if(topLevelItem(i)->checkState(0) == Qt::Unchecked) isAllChecked = false;
else k++;
fdCheckAll->blockSignals(true);
for(int rr=0; rr<cnt; rr++) if(! topLevelItem(rr)->isHidden() && topLevelItem(rr)->checkState(1)!=state) {
fdCheckAll->setCheckState(Qt::PartiallyChecked);
goto end;
}
if(k > 1) m_checkState = CheckMulti;
else if(k > 0) m_checkState = CheckOne;
else m_checkState = CheckNone;
}
fdIsSelAll->blockSignals(true);
fdIsSelAll->setChecked(isAllChecked);
fdIsSelAll->blockSignals(false);
emit sigCheckStateChanged(m_checkState);
fdCheckAll->setCheckState(state);
end:fdCheckAll->blockSignals(false);
emit selChanged();
};
connect(this, &QTreeWidget::itemClicked, this, cellClicked);
connect(this, &QTreeWidget::itemEntered, this, [=](QTreeWidgetItem *item, int column) {
if(column > 2) return;
if(! fdCheckAll->isVisible()) return;
if((QGuiApplication::mouseButtons() & Qt::LeftButton) == 0) return;
cellClicked(item, column);
});
}
void LoQTreeWidget::onCheckAll(bool checked) {
int cnt = topLevelItemCount();
for(int i=0; i<cnt; i++) {
if(checked) {
if(this->isRowHidden(i,indexFromItem(topLevelItem(i)->parent()))) topLevelItem(i)->setCheckState(0, Qt::Unchecked);
else topLevelItem(i)->setCheckState(0, Qt::Checked);
}
else topLevelItem(i)->setCheckState(0, Qt::Unchecked);
}
adjustCheckState();
void LoQTreeWidget::updateGeometries() {
QTreeWidget::updateGeometries();
if(fdCheckAll==0) return;
fdCheckAll->move(columnWidth(0)+headerItem()->data(1, MarginRole).toInt()+4, 2);
}

View File

@ -1,34 +1,19 @@
#ifndef LOQTREEWIDGET_H
#define LOQTREEWIDGET_H
#include "gutil/qgui.h"
#include <QCheckBox>
#include <QTreeWidgetItem>
class LoQTreeWidget : public QTreeWidget {
class LoQTreeWidget : public TreeWidget {
Q_OBJECT
public:
enum CheckState {
CheckNone,
CheckOne,
CheckMulti
};
explicit LoQTreeWidget(QWidget *parent = nullptr);
void adjustCheckState();
QModelIndex indexFromItem(const QTreeWidgetItem *item, int column = 0) const {
return QTreeWidget::indexFromItem(item, column);
};
QCheckBox *fdIsSelAll;
using TreeWidget::TreeWidget;
void addFd();
QCheckBox *fdCheckAll = 0;
signals:
void sigCheckStateChanged(int);
public slots:
void onCheckAll(bool checked);
private:
QHeaderView *m_header;
int m_checkState;
void selChanged();
protected:
void updateGeometries() override;
};
#endif // LOQTREEWIDGET_H

View File

@ -34,7 +34,7 @@ void BaseWin::paintEvent(QPaintEvent *e) {
painter.setPen(isActive ? penTitleAct : penTitleUnact);
isMaximized() ? painter.drawText(titlePos.x()-8, titlePos.y()-8, title) : painter.drawText(titlePos, title);
}
if(! icon.isNull()) isMaximized() ? painter.drawPixmap(iconPos.x()-8, iconPos.y()-8, icon) : painter.drawPixmap(iconPos, icon);
if(! icon.isNull()) isMaximized() ? painter.drawPixmap(iconPos.x()-8, iconPos.y()-8, iconPos.width(), iconPos.height(), icon) : painter.drawPixmap(iconPos, icon, QRectF());
}
void BaseWin::mousePressEvent(QMouseEvent *e) {

View File

@ -14,7 +14,7 @@ public:
qreal roundRadius{6.0};
QPointF titlePos{36, 26};
QPixmap icon;
QPointF iconPos{13, 13};
QRectF iconPos{13, 13, 16, 16};
protected:
void paintEvent(QPaintEvent *) override;
void mousePressEvent(QMouseEvent *) override;

View File

@ -1,10 +1,10 @@
Table {selection-background-color: #0ae;}
QListWidget, QTreeWidget, TableWidget {selection-background-color: #4ae;}
QCheckBox::indicator, QTableWidget::indicator, QTreeWidget::indicator {
width: 1.15em; height: 1.15em;
}
QLineEdit,QComboBox,QAbstractSpinBox {
QLineEdit, QComboBox, QAbstractSpinBox {
border: 1px solid #aaa;
border-radius: 3px;
padding: 2px;
@ -70,10 +70,6 @@ QMenu::item:selected {
background-color: #8CD;
}
QListWidget {
selection-background-color: #0ae;
}
LoColorSelector {
border: 1px solid #aaa;
border-radius: 4px;
@ -83,20 +79,6 @@ LoColorSelector {
font-size: 14px;
}
QTreeWidget[ssType="topList"]::item {
border-right: 1px solid #ddd;
border-bottom: 1px solid #ddd;
height: 38px;
}
QTreeWidget[ssType="topList"]>QHeaderView::section {
height: 30px;
}
QTreeWidget[ssType="topList"]::item:hover {
background-color: #ddd;
}
QPushButton[ssType="progManageTool"] {
border-radius: 4px;
background-color: #19c;
@ -115,7 +97,6 @@ QPushButton[ssType="progManageTool"]:disabled {
color: #777;
}
LoQTitleBar QPushButton {
border-radius: 4px;
icon-size: 20px;

View File

@ -8,11 +8,14 @@
#include <QMessageBox>
#include <QMetaEnum>
QString gFileHome;
QString gApkHome;
QList<LedCard> gSelCards;
bool gVideoCompress = true;
bool gVideoTranscoding = true;
bool gTextAntialiasing = false;
bool gWidthSplit = false;
int gSendBatch = 5;
bool gHideDetect = false;
bool gShowLora = false;

View File

@ -40,6 +40,8 @@ struct ST_ANSY_PROGRAM_PACKET {
unsigned char pDataBuffer[20];
};
extern QString gFileHome;
extern QString gApkHome;
class DevicePanel;
extern DevicePanel *gDevicePanel;
extern QList<LedCard> gSelCards;
@ -47,6 +49,7 @@ extern bool gVideoCompress;
extern bool gVideoTranscoding;
extern bool gTextAntialiasing;
extern bool gWidthSplit;
extern int gSendBatch;
extern bool gHideDetect;
extern bool gShowLora;
@ -69,7 +72,6 @@ enum _ENUM_CONTRL_WIDGET {
class DeviceItem;
extern DeviceItem *findItem(QString id);
inline int verCompare(const QString& a, const QString& b) {
auto aparts = a.split(".");
auto bparts = b.split(".");

2
LedOK/gutil/cpp.cpp Normal file
View File

@ -0,0 +1,2 @@
//#include "cpp.h"

View File

@ -1,5 +1,5 @@
#ifndef CU_H
#define CU_H
#ifndef CPP_H
#define CPP_H
#include <chrono>
#include <memory>
@ -21,44 +21,64 @@ inline long long system_micro() {
template <class T>
struct SharedData {
size_t cnt{1};
T data;
uint64_t cnt{1};
};
template <class T>
class SharedPtr {
public:
SharedPtr(SharedData<T> *ptr = 0) : ptr{ptr} {}
SharedPtr(const SharedPtr &other) : ptr{other.ptr} {
if(ptr) ptr->cnt++;
}
~SharedPtr() {
if(ptr==0) return;
if(ptr->cnt > 1) ptr->cnt--;
else delete ptr;
}
bool isNull() {return ptr==0;}
SharedPtr(const SharedPtr &other) : ptr{other.ptr} {
if(ptr) ptr->cnt++;
}
SharedPtr &operator=(const SharedPtr &other) {
this->~SharedPtr();
new (this) SharedPtr(other);
return *this;
}
SharedPtr(SharedPtr &&other) noexcept : ptr(other.ptr) {
other.ptr = 0;
}
SharedPtr &operator=(SharedPtr &&other) noexcept {
auto aaa = ptr;
ptr = other._pri;
other.ptr = aaa;
return *this;
}
T &operator*() {
bool isNull() const noexcept {return ptr==0;}
bool empty() const noexcept {
return ptr ? ptr->data.empty() : true;
}
size_t size() const noexcept {
return ptr ? ptr->data.size() : 0;
}
T &operator*() const {
if(ptr==0) ptr = new SharedData<T>;
return ptr->data;
}
T *operator->() {
T *operator->() const {
if(ptr==0) ptr = new SharedData<T>;
return &ptr->data;
}
const T &operator*() const {
return ptr->data;
bool operator==(const SharedPtr &other) const {
if(ptr==other.ptr) return true;
auto siz = size();
if(siz!=other.size()) return false;
if(siz==0) return true;
return ptr->data==other.ptr->data;
}
const T *operator->() const {
return &ptr->data;
bool operator!=(const SharedPtr &other) const {
return ! (*this==other);
}
SharedData<T> *ptr{0};
mutable SharedData<T> *ptr = 0;
};
@ -71,30 +91,38 @@ public:
using const_iterator = std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types<V>>>;
Vector(std::initializer_list<V> _Ilist) {
this->ptr = new SharedData<std::vector<V>>{_Ilist, 1};
this->ptr = new SharedData<std::vector<V>>{1, _Ilist};
}
bool empty() const noexcept {
return this->ptr ? this->ptr->data.empty() : true;
}
uint64_t size() const noexcept {
return this->ptr ? this->ptr->data.size() : 0;
}
Vector &append(const V &val) {
(**this).push_back(val);
(*this)->push_back(val);
return *this;
}
Vector &append(V&& val) {
(*this)->push_back(_STD move(val));
return *this;
}
Vector &operator<<(const V &val) {
(*this)->push_back(val);
return *this;
}
Vector &operator<<(V&& val) {
(*this)->push_back(_STD move(val));
return *this;
}
V &operator[](const uint64_t pos) noexcept {
return (**this)[pos];
}
const V &operator[](const uint64_t pos) const noexcept {
return this->ptr ? this->ptr->data[pos] : V();
return (**this)[pos];
}
const const_iterator begin() const noexcept {
return this->ptr ? this->ptr->data.begin() : const_iterator();
iterator begin() const noexcept {
return this->ptr ? this->ptr->data.begin() : iterator();
}
const const_iterator end() const noexcept {
return this->ptr ? this->ptr->data.end() : const_iterator();
iterator end() const noexcept {
return this->ptr ? this->ptr->data.end() : iterator();
}
};
@ -103,45 +131,55 @@ struct NodeBase {
NodeBase *next{this};
NodeBase *prev{this};
};
template <class V>
template <class P>
struct _Node : NodeBase {
V value;
P value;
~_Node() {
if(next) delete (_Node<V>*) next;
if(next) delete (_Node<P>*) next;
}
};
template <class V>
template <class P>
class LinkedMapIterator {
public:
LinkedMapIterator(_Node<V> *node) : node(node) {}
bool operator==(const LinkedMapIterator& that) const {
return node == that.node;
LinkedMapIterator(_Node<P> *node) : node(node) {}
bool operator==(const LinkedMapIterator& other) const noexcept {
return node == other.node;
}
bool operator!=(const LinkedMapIterator& that) const {
return node != that.node;
bool operator!=(const LinkedMapIterator& other) const noexcept {
return node != other.node;
}
LinkedMapIterator& operator++() {
node = (_Node<V>*) node->next;
node = (_Node<P>*) node->next;
return *this;
}
LinkedMapIterator& operator--() {
node = (_Node<V>*) node->prev;
node = (_Node<P>*) node->prev;
return *this;
}
V &operator*() const {
const LinkedMapIterator operator++(int) {
auto rtn = *this;
node = (_Node<P>*) node->next;
return rtn;
}
const LinkedMapIterator operator--(int) {
auto rtn = *this;
node = (_Node<P>*) node->prev;
return rtn;
}
P &operator*() const noexcept {
return node->value;
}
V *operator->() const {
P *operator->() const noexcept {
return &node->value;
}
_Node<V> *node{0};
_Node<P> *node{0};
};
template <class K, class V>
struct LinkedMapPri : NodeBase {
size_t cnt = 1;
std::unordered_map<K, _Node<std::pair<K, V>>*> map;
uint64_t cnt{1};
~LinkedMapPri() {
if(prev) prev->next = 0;
if(next) delete (_Node<std::pair<K, V>>*) next;
@ -162,26 +200,64 @@ public:
LinkedMap(std::unordered_map<K, Node*> &&map) : _pri{new LinkedMapPri<K, V>{0, 0, map}} {
_pri->next = _pri->prev = _pri;
}
LinkedMap(const LinkedMap &other) : _pri{other._pri} {
if(_pri) _pri->cnt++;
}
~LinkedMap() {
if(_pri==0) return;
if(_pri->cnt > 1) _pri->cnt--;
else delete _pri;
}
LinkedMap(const LinkedMap &other) : _pri{other._pri} {
if(_pri) _pri->cnt++;
}
LinkedMap &operator=(const LinkedMap &other) {
this->~LinkedMap();
new (this) LinkedMap(other);
return *this;
}
LinkedMap(LinkedMap &&other) noexcept : _pri(other._pri) {
other._pri = 0;
}
LinkedMap &operator=(LinkedMap &&other) noexcept {
auto aaa = _pri;
_pri = other._pri;
other._pri = aaa;
return *this;
}
bool empty() const noexcept {
return _pri==0 || _pri->map.empty();
}
size_t size() const noexcept {
return _pri ? _pri->map.size() : 0;
}
iterator find(const K &k) const {
if(_pri==0) return iterator((Node*) _pri);
auto it = _pri->map.find(k);
if(it==_pri->map.end()) return iterator((Node*) _pri);
return iterator(it->second);
}
const V operator()(const K &k) const {
return (*this)[k];
}
const V operator[](const K &k) const {
if(_pri==0) return V();
auto it = _pri->map.find(k);
if(it==_pri->map.end()) return V();
return it->second->value.second;
}
V &operator[](const K &k) {
if(_pri==0) _pri = new LinkedMapPri<K, V>;
auto pair = _pri->map.emplace(k, nullptr);
if(pair.second) {
auto node = new Node{_pri, _pri->prev, {k, V()}};
_pri->prev->next = node;
_pri->prev = node;
pair.first->second = node;
}
return pair.first->second->value.second;
}
LinkedMap &insert(const K &k, const V &v) {
if(_pri==0) _pri = new LinkedMapPri<K, V>;
auto pair = _pri->map.emplace(k, nullptr);
@ -205,17 +281,32 @@ public:
node->prev = 0;
delete node;
}
inline bool empty() const {
return _pri==0 || _pri->map.empty();
bool operator==(const LinkedMap &other) const {
if(_pri==other._pri) return true;
auto siz = size();
if(siz!=other.size()) return false;
if(siz==0) return true;
auto aaa = begin();
auto bbb = other.begin();
while(aaa!=end()) {
if(aaa->first != bbb->first || aaa->second != bbb->second) return false;
++aaa;
++bbb;
}
return true;
}
bool operator!=(const LinkedMap &other) const {
return ! (*this==other);
}
const_iterator begin() const {
return const_iterator((Node*) (_pri ? _pri->next : 0));
iterator begin() const {
return iterator((Node*) (_pri ? _pri->next : 0));
}
const_iterator end() const {
return const_iterator((Node*) _pri);
iterator end() const {
return iterator((Node*) _pri);
}
LinkedMapPri<K, V> *_pri{0};
LinkedMapPri<K, V> *_pri = 0;
};
#endif // CU_H
#endif // CPP_H

View File

@ -1,2 +0,0 @@
//#include "cu.h"

View File

@ -1,6 +1,30 @@
#ifndef QCORE_H
#define QCORE_H
#include <QThread>
#include <QEventLoop>
#include <QTimer>
#define ToStr QString::number
inline QString toStr(int num, int base=10) {return QString::number(num, base);}
inline QString toStr(uint num, int base=10) {return QString::number(num, base);}
inline QString toStr(long num, int base=10) {return QString::number(num, base);}
inline QString toStr(ulong num, int base=10) {return QString::number(num, base);}
inline QString toStr(qlonglong num, int base=10) {return QString::number(num, base);}
inline QString toStr(qulonglong num, int base=10) {return QString::number(num, base);}
inline QString toStr(double num, char format='g', int precision=6) {return QString::number(num, format, precision);}
inline QString gUrlSuffix(const QString &url, int size, bool withDot = false) {
auto ss = url.lastIndexOf('/')+1;
if(ss==url.size()) return QString();
ss++;
auto ee = url.indexOf('?', ss);
if(ee==-1) ee = url.size();
int end = ee-size-1;
if(end<ss) end = ss;
for(int i=ee-1; i>=end; --i) if(url[i]=='.') return withDot ? url.mid(i, ee-i) : url.mid(i+1, ee-i-1);
return QString();
}
inline QString byteSizeStr(double size) {
const char *units[]{"B", "KB", "MB", "GB", "TB", "PB"};
@ -9,17 +33,13 @@ inline QString byteSizeStr(double size) {
return QString::number(size, 'g', 3)+" "+units[i];
}
inline long long steady_milli() {
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
}
inline long long system_milli() {
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
}
inline long long steady_micro() {
return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
}
inline long long system_micro() {
return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
inline void wait(int msec, QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents) {
QTimer timer;
timer.setSingleShot(true);
QEventLoop loop;
QObject::connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
timer.start(msec);
loop.exec(flags);
}
template <typename Func>

View File

@ -1,44 +1,212 @@
#include "qgui.h"
#include <QPainter>
#include <QResizeEvent>
#include <QProxyStyle>
const int AlignRight = Qt::AlignRight | Qt::AlignVCenter;
const Qt::Alignment AlignRight = Qt::AlignRight | Qt::AlignVCenter;
Table::Table(std::initializer_list<ColAttr> colAttrs, int rows, QWidget *parent) : QTableWidget{rows, (int)colAttrs.size(), parent} {
int i = 0;
for(typename std::initializer_list<ColAttr>::const_iterator it = colAttrs.begin(); it != colAttrs.end(); ++it) {
auto item = horizontalHeaderItem(i);
if(item==0) setHorizontalHeaderItem(i, item = new QTableWidgetItem());
item->setText(it->text);
if(it->width > 0) horizontalHeader()->resizeSection(i, it->width);
if(it->resizeMode != QHeaderView::Interactive) {
if(it->resizeMode==QHeaderView::Stretch && it->width>0) {
item->setData(0x99, it->width > 0 ? it->width : 100);
ColItem TreeWidget::addCol(const QString& field, const QString& text, int width, QHeaderView::ResizeMode resizeMode) {
int i = fdmap.size();
auto item = headerItem();
item->setText(i, text);
item->setData(i, FieldRole, field);
if(width > 0) {
blocked = true;
if(header()->minimumSectionSize() > width) header()->setMinimumSectionSize(width);
header()->resizeSection(i, width);
blocked = false;
}
if(resizeMode != QHeaderView::Interactive) {
if(resizeMode==QHeaderView::Stretch && width > 0) {
item->setData(i, WidthRole, width);
if(noStretch) {
noStretch = false;
} else horizontalHeader()->setSectionResizeMode(i, (QHeaderView::ResizeMode)it->resizeMode);
connect(header(), &QHeaderView::sectionResized, this, &TreeWidget::onSectionResized);
header()->installEventFilter(this);
}
mFieldMap.emplace(it->field, i++);
} else header()->setSectionResizeMode(i, resizeMode);
}
fdmap.emplace(field, i);
if(i==0) hasRowNum = field=="#";
return {item, i};
}
void Table::resizeEvent(QResizeEvent *event) {
QTableWidget::resizeEvent(event);
if(noStretch || event->size().width() == event->oldSize().width()) return;
resizeSec();
bool TreeWidget::eventFilter(QObject *watched, QEvent *event) {
if(watched==header()) {
if(event->type()==QEvent::Resize) {
auto eve = (QResizeEvent *) event;
if(eve->size().width() != eve->oldSize().width()) adjSections(-1, 0);
} else if(isSectionResized && event->type()==QEvent::Leave) {
isSectionResized = false;
auto item = headerItem();
for(int cc=0; cc<columnCount(); cc++) if(item->data(cc, WidthRole).isValid()) item->setData(cc, WidthRole, header()->sectionSize(cc));
}
return true;
}
return QTreeWidget::eventFilter(watched, event);
}
void TreeWidget::rowsInserted(const QModelIndex &parent, int start, int end) {
QTreeWidget::rowsInserted(parent, start, end);
if(parent.internalId()) return;
if(minRowHeight) for(int rr=start; rr<=end; rr++) {
auto item = topLevelItem(rr);
if(item->sizeHint(0).height() < minRowHeight) item->setSizeHint(0, {0, minRowHeight});
}
int align;
for(int cc=0; cc<columnCount(); cc++) if((align = headerItem()->data(cc, AlignRole).toInt())) for(int rr=start; rr<=end; rr++) topLevelItem(rr)->setTextAlignment(cc, (Qt::Alignment)align);
}
void TreeWidget::drawRow(QPainter *painter, const QStyleOptionViewItem &options, const QModelIndex &index) const {
QTreeWidget::drawRow(painter, options, index);
if(hasRowNum) {
QRect rect(columnViewportPosition(0), options.rect.top(), columnWidth(0), options.rect.height());
painter->fillRect(rect, header()->palette().button());
painter->drawText(rect, Qt::AlignCenter, QString::number(index.row()+1));
}
if(hasGrid) {
QBrush color({128, 128, 128, 128});
QRect rec(options.rect.left()-1-horizontalOffset(), options.rect.top(), 1, options.rect.height());
auto last = columnCount() - 1;
if(hasGrid > 1) for(int i=0; i<last; i++) {
rec.translate(columnWidth(header()->logicalIndex(i)), 0);
painter->fillRect(rec, color);
} else {
int ttlwidth = columnWidth(header()->logicalIndex(last));
for(int i=0; i<last; i++) {
auto width = columnWidth(header()->logicalIndex(i));
rec.translate(width, 0);
painter->fillRect(rec, color);
ttlwidth += width;
}
painter->fillRect(options.rect.left(), options.rect.bottom(), ttlwidth, 1, color);
}
}
}
void TreeWidget::onSectionResized(int logicalIndex, int oldSize, int newSize) {
if(blocked || newSize==0 || oldSize==0) return;
if(! headerItem()->data(logicalIndex, WidthRole).isValid()) return;
if(adjSections(logicalIndex, newSize)) isSectionResized = true;
}
bool TreeWidget::adjSections(int index, int size) {
auto item = headerItem();
int remain = header()->width() - size, stretchWidth = 0, width;
for(int cc=0; cc<columnCount(); cc++) if(cc!=index && ! header()->isSectionHidden(cc)) {
width = item->data(cc, WidthRole)|-1;
if(width > -1) {
if(width==0) item->setData(cc, WidthRole, width = header()->sectionSize(cc));
stretchWidth += width;
} else remain -= header()->sectionSize(cc);
}
if(remain<=0 || stretchWidth==0) return false;
auto min = header()->minimumSectionSize();
blocked = true;
for(int cc=0; cc<columnCount(); cc++) if(cc!=index && ! header()->isSectionHidden(cc) && (width = item->data(cc, WidthRole)|-1) > -1) header()->resizeSection(cc, qMax(min, width * remain / stretchWidth));
blocked = false;
return true;
}
void Table::resizeSec() {
auto header = horizontalHeader();
int colCnt = columnCount(), remainWidth = header->width(), stretchWidth = 0, secWidth;
class TreeItemMarginStyle : public QProxyStyle {
public:
using QProxyStyle::QProxyStyle;
TreeItemMarginStyle(QWidget *wgt) : QProxyStyle(wgt->style()), _wgt(wgt) {}
QRect subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const override {
auto res = QProxyStyle::subElementRect(element, option, widget);
auto width = res.width();
if(width && option && option->type==QStyleOption::SO_ViewItem && widget==_wgt) {
if(element==SE_ItemViewItemText) {
auto index = ((QStyleOptionViewItem*)option)->index;
auto add = ((TreeWidget*)widget)->headerItem()->data(index.column(), MarginRole).toInt();
if(add) {
auto align = ((TreeWidget*)widget)->item(index.row())->textAlignment(index.column());
if(align & Qt::AlignRight) res.setWidth(width < add ? 0 : width - add);
else if((align & Qt::AlignHCenter)==0) {
if(((QStyleOptionViewItem*)option)->features & QStyleOptionViewItem::HasCheckIndicator) add += add>>1;
res.setLeft(res.x() + add);
if(width < add) res.setWidth(0);
}
}
} else if(((QStyleOptionViewItem*)option)->features & QStyleOptionViewItem::HasCheckIndicator) {
auto add = ((TreeWidget*)widget)->headerItem()->data(((QStyleOptionViewItem*)option)->index.column(), MarginRole).toInt();
if(add) {
add += add>>1;
res.setLeft(res.x() + add);
if(width < add) res.setWidth(0);
}
}
}
return res;
}
int pixelMetric(QStyle::PixelMetric metric, const QStyleOption *option, const QWidget *widget) const override {
auto res = QProxyStyle::pixelMetric(metric, option, widget);
if(metric==PM_FocusFrameHMargin && option && option->type==QStyleOption::SO_ViewItem && ((QStyleOptionViewItem*)option)->features & QStyleOptionViewItem::HasCheckIndicator && widget==_wgt) res += ((TreeWidget*)widget)->headerItem()->data(((QStyleOptionViewItem*)option)->index.column(), MarginRole).toInt();
return res;
}
QWidget *_wgt = 0;
};
ColItem &ColItem::margin(int margin) {
item->setData(i, MarginRole, margin);
auto tree = (TreeWidget*) item->treeWidget();
if(tree->noMargin) {
tree->noMargin = false;
tree->setStyle(new TreeItemMarginStyle(tree));
}
return *this;
}
TableWidget::TableWidget(std::initializer_list<ColAttr> colAttrs, int rows, QWidget *parent) : QTableWidget{rows, (int)colAttrs.size(), parent} {
int i = 0;
for(auto attr = colAttrs.begin(); attr < colAttrs.end(); ++attr) {
auto item = horizontalHeaderItem(i);
if(item==0) setHorizontalHeaderItem(i, item = new QTableWidgetItem);
item->setText(attr->text);
item->setData(FieldRole, attr->field);
if(attr->width > 0) horizontalHeader()->resizeSection(i, attr->width);
if(attr->resizeMode != QHeaderView::Interactive) {
if(attr->resizeMode==QHeaderView::Stretch && attr->width > 0) {
item->setData(WidthRole, attr->width);
if(noStretch) {
noStretch = false;
connect(horizontalHeader(), &QHeaderView::sectionResized, this, &TableWidget::onSectionResized);
horizontalHeader()->installEventFilter(this);
}
} else horizontalHeader()->setSectionResizeMode(i, attr->resizeMode);
}
fdmap.emplace(attr->field, i++);
}
}
bool TableWidget::eventFilter(QObject *watched, QEvent *event) {
if(watched==horizontalHeader()) {
if(event->type()==QEvent::Resize) {
auto eve = (QResizeEvent *) event;
if(eve->size().width() != eve->oldSize().width()) adjSections(-1, 0);
} else if(isSectionResized && event->type()==QEvent::Leave) {
isSectionResized = false;
QTableWidgetItem *item;
for(int cc=0; cc<colCnt; cc++) if((item = horizontalHeaderItem(cc))) {
if((secWidth = item->data(0x99).toInt()) > 0) stretchWidth += secWidth;
else remainWidth -= header->sectionSize(cc);
for(int cc=0; cc<columnCount(); cc++) if((item = horizontalHeaderItem(cc)) && item->data(WidthRole).isValid()) item->setData(WidthRole, horizontalHeader()->sectionSize(cc));
}
if(remainWidth<=0 || stretchWidth==0) return;
for(int cc=0; cc<colCnt; cc++) if((item = horizontalHeaderItem(cc)) && (secWidth = item->data(0x99).toInt()) > 0) header->resizeSection(cc, secWidth * remainWidth / stretchWidth);
return true;
}
return QTableWidget::eventFilter(watched, event);
}
void Table::updateGeometries() {
QTableWidget::updateGeometries();
emit updGeos();
void TableWidget::onSectionResized(int logicalIndex, int oldSize, int newSize) {
if(blocked || newSize==0 || oldSize==0) return;
if(! horizontalHeaderItem(logicalIndex)->data(WidthRole).isValid()) return;
if(adjSections(logicalIndex, newSize)) isSectionResized = true;
}
bool TableWidget::adjSections(int index, int size) {
QTableWidgetItem *item;
int remain = horizontalHeader()->width() - size, stretchWidth = 0, width;
for(int cc=0; cc<columnCount(); cc++) if(cc!=index && ! horizontalHeader()->isSectionHidden(cc) && (item = horizontalHeaderItem(cc))) {
width = item->data(WidthRole)|-1;
if(width > -1) {
if(width==0) item->setData(WidthRole, width = horizontalHeader()->sectionSize(cc));
stretchWidth += width;
} else remain -= horizontalHeader()->sectionSize(cc);
}
if(remain<=0 || stretchWidth==0) return false;
auto min = horizontalHeader()->minimumSectionSize();
blocked = true;
for(int cc=0; cc<columnCount(); cc++) if(cc!=index && ! horizontalHeader()->isSectionHidden(cc) && (item = horizontalHeaderItem(cc)) && (width = item->data(WidthRole)|-1) > -1) horizontalHeader()->resizeSection(cc, qMax(min, width * remain / stretchWidth));
blocked = false;
return true;
}

View File

@ -2,6 +2,8 @@
#define QGUI_H
#include <QComboBox>
#include <QDialog>
#include <QDialogButtonBox>
#include <QHeaderView>
#include <QLabel>
#include <QListWidget>
@ -9,6 +11,7 @@
#include <QStackedLayout>
#include <QTableWidget>
#include <QTextEdit>
#include <QTreeWidget>
#define MainMust \
#if(QT_VERSION_MAJOR > 5) \
@ -19,8 +22,11 @@
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);\
#endif
extern const Qt::Alignment AlignRight;
extern const int AlignRight;
inline int operator|(const QVariant &value, int def) {
return value.isValid() ? value.toInt() : def;
}
inline QWidget *parentWgt(QObject *obj) {
while(obj && ! obj->isWidgetType()) obj = obj->parent();
@ -34,11 +40,16 @@ inline QWidget *parentWin(QObject *obj) {
return (QWidget*) obj;
}
inline int setCurrentData(QComboBox *combo, const QVariant &data) {
inline int SetCurData(QComboBox *combo, const QVariant &data) {
auto idx = combo->findData(data);
if(idx>-1) combo->setCurrentIndex(idx);
return idx;
}
inline int SetCurText(QComboBox *combo, const QString& text) {
auto idx = combo->findText(text);
if(idx>-1) combo->setCurrentIndex(idx);
return idx;
}
inline void gFont(QWidget *wgt, int size, bool bold = false, bool italic = false) {
auto ft = wgt->font();
ft.setPixelSize(size);
@ -46,7 +57,7 @@ inline void gFont(QWidget *wgt, int size, bool bold = false, bool italic = false
if(italic) ft.setItalic(true);
wgt->setFont(ft);
}
inline void gFont(QWidget *wgt, const QString &family, int size = 0, bool bold = false, bool italic = false) {
inline void gFont(QWidget *wgt, const QString& family, int size = 0, bool bold = false, bool italic = false) {
auto ft = wgt->font();
ft.setFamily(family);
if(size) ft.setPixelSize(size);
@ -54,14 +65,14 @@ inline void gFont(QWidget *wgt, const QString &family, int size = 0, bool bold =
if(italic) ft.setItalic(true);
wgt->setFont(ft);
}
inline QFont qfont(const QString &family, int pixelSize, bool bold = false, bool italic = false) {
inline QFont qfont(const QString& family, int pixelSize, bool bold = false, bool italic = false) {
QFont ft(family);
ft.setPixelSize(pixelSize);
if(bold) ft.setBold(true);
if(italic) ft.setItalic(true);
return ft;
}
inline void gAppendText(QTextEdit *wgt, const QString &text, const QColor &color) {
inline void gAppendText(QTextEdit *wgt, const QString& text, const QColor &color) {
auto c0 = wgt->textColor();
wgt->setTextColor(color);
wgt->append(text);
@ -70,39 +81,55 @@ inline void gAppendText(QTextEdit *wgt, const QString &text, const QColor &color
class VBox : public QBoxLayout {
public:
inline VBox(QWidget *parent=nullptr) : QBoxLayout(TopToBottom, parent) {}
inline VBox(QBoxLayout *parent) : QBoxLayout(TopToBottom) {
VBox(QWidget *parent=nullptr) : QBoxLayout(TopToBottom, parent) {}
VBox(QBoxLayout *parent) : QBoxLayout(TopToBottom) {
parent->addLayout(this);
};
inline VBox(QStackedLayout *stack) : QBoxLayout(TopToBottom, new QWidget) {
VBox(QStackedLayout *stack) : QBoxLayout(TopToBottom, new QWidget) {
stack->addWidget(parentWidget());
setContentsMargins(0,0,0,0);
};
inline VBox(QSplitter *splitter) : QBoxLayout(TopToBottom, new QWidget) {
VBox(QSplitter *splitter) : QBoxLayout(TopToBottom, new QWidget) {
splitter->addWidget(parentWidget());
setContentsMargins(0,0,0,0);
};
inline QLabel *addLabel(const QString &text) {
QLabel *addLabel() {
auto lb = new QLabel;
addWidget(lb);
return lb;
}
QLabel *addLabel(const QString& text) {
auto lb = new QLabel(text);
addWidget(lb);
return lb;
}
QDialogButtonBox *addBtnBox(QDialog *dlg = 0) {
auto btnBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
if(dlg) connect(btnBox, &QDialogButtonBox::rejected, dlg, &QDialog::reject);
addWidget(btnBox);
return btnBox;
}
};
class HBox : public QBoxLayout {
public:
inline HBox(QWidget *parent=nullptr) : QBoxLayout(LeftToRight, parent) {}
inline HBox(QBoxLayout *parent) : QBoxLayout(LeftToRight) {
HBox(QWidget *parent=nullptr) : QBoxLayout(LeftToRight, parent) {}
HBox(QBoxLayout *parent) : QBoxLayout(LeftToRight) {
parent->addLayout(this);
};
inline HBox(QStackedLayout *stack) : QBoxLayout(LeftToRight, new QWidget) {
HBox(QStackedLayout *stack) : QBoxLayout(LeftToRight, new QWidget) {
stack->addWidget(parentWidget());
setContentsMargins(0,0,0,0);
};
inline HBox(QSplitter *splitter) : QBoxLayout(LeftToRight, new QWidget) {
HBox(QSplitter *splitter) : QBoxLayout(LeftToRight, new QWidget) {
splitter->addWidget(parentWidget());
setContentsMargins(0,0,0,0);
};
inline QLabel *addLabel(const QString &text) {
QLabel *addLabel() {
auto lb = new QLabel;
addWidget(lb);
return lb;
}
QLabel *addLabel(const QString& text) {
auto lb = new QLabel(text);
addWidget(lb);
return lb;
@ -111,16 +138,16 @@ public:
class Grid : public QGridLayout {
public:
using QGridLayout::QGridLayout;
inline Grid(QBoxLayout *parent) {
Grid(QBoxLayout *parent) {
parent->addLayout(this);
};
inline Grid(QStackedLayout *stack) : QGridLayout(new QWidget) {
Grid(QStackedLayout *stack) : QGridLayout(new QWidget) {
stack->addWidget(parentWidget());
};
inline Grid(QSplitter *splitter) : QGridLayout(new QWidget) {
Grid(QSplitter *splitter) : QGridLayout(new QWidget) {
splitter->addWidget(parentWidget());
};
inline QLabel *addLabel(const QString &text) {
QLabel *addLabel(const QString& text) {
auto lb = new QLabel(text);
addWidget(lb);
return lb;
@ -132,7 +159,7 @@ public:
using QListWidget::QListWidget;
using QListWidget::addItem;
inline auto addItem(const QString &text, const QVariant &value) {
auto addItem(const QString& text, const QVariant &value) {
auto item = new QListWidgetItem(text);
item->setData(Qt::UserRole, value);
insertItem(count(), item);
@ -141,172 +168,396 @@ public:
};
struct ColAttr {
ColAttr(QString field, QString text, int width=0, QHeaderView::ResizeMode resizeMode = QHeaderView::Interactive) : field(field), text(text), width(width), resizeMode(resizeMode) {}
ColAttr(QString field, QString text, QHeaderView::ResizeMode resizeMode) : field(field), text(text), resizeMode(resizeMode) {}
ColAttr(const QString& field, const QString& text, int width=0, QHeaderView::ResizeMode resizeMode = QHeaderView::Interactive) : field(field), text(text), width(width), resizeMode(resizeMode) {}
ColAttr(const QString& field, const QString& text, QHeaderView::ResizeMode resizeMode) : field(field), text(text), resizeMode(resizeMode) {}
QString field;
QString text;
int width{0};
int width = 0;
QHeaderView::ResizeMode resizeMode;
};
class Table : public QTableWidget {
enum ItemDataRole {
MarginRole = 0xfc,
AlignRole,
FieldRole,
WidthRole
};
struct ColItem {
QTreeWidgetItem *item;
int i;
auto &align(int align) {
item->setData(i, AlignRole, align);
return *this;
}
auto &alignC() {
return align(Qt::AlignCenter);
}
auto &alignR() {
return align(Qt::AlignVCenter | Qt::AlignRight);
}
ColItem &margin(int margin);
};
class TreeWidgetItem;
class TreeWidget : public QTreeWidget {
friend ColItem;
Q_OBJECT
public:
using QTreeWidget::QTreeWidget;
ColItem addCol(const QString& field, const QString& text, int width = 0, QHeaderView::ResizeMode resizeMode = QHeaderView::Interactive);
ColItem addCol(const QString& field, const QString& text, QHeaderView::ResizeMode resizeMode) {
return addCol(field, text, 0, resizeMode);
}
auto setDefs() {
if(! hasRowNum) setIndentation(0);
setAlternatingRowColors(true);
header()->setStretchLastSection(false);
return this;
}
auto setHeaderAlignC() {
auto item = headerItem();
for(int cc=0; cc<columnCount(); ++cc) item->setTextAlignment(cc, Qt::AlignCenter);
}
auto setColFit() {
header()->setSectionResizeMode(QHeaderView::ResizeToContents);
return this;
}
auto setColWidth(int value, QHeaderView::ResizeMode mode = QHeaderView::Interactive) {
header()->setDefaultSectionSize(value);
if(mode!=QHeaderView::Interactive) header()->setSectionResizeMode(mode);
return this;
}
auto setHeaderText(const QString& column, const QString& text) {
headerItem()->setText(fdmap.at(column), text);
return this;
}
using QTreeWidget::showColumn;
void showColumn(const QString& column) {
showColumn(fdmap.at(column));
}
using QTreeWidget::hideColumn;
void hideColumn(const QString& column) {
hideColumn(fdmap.at(column));
}
auto item(int idx) const {
return (TreeWidgetItem*) topLevelItem(idx);
}
auto selectedItem() const {
auto is = selectedItems();
return is.isEmpty() ? 0 : (TreeWidgetItem*) is.at(0);
}
auto curItem() const {
return (TreeWidgetItem*) currentItem();
}
QString field(int column) const {
return headerItem()->data(column, FieldRole).toString();
}
QString sortField() const {
return field(sortColumn());
}
using QTreeWidget::sortItems;
void sortItems(const QString& column, Qt::SortOrder order = Qt::AscendingOrder) {
sortItems(fdmap.at(column), order);
}
std::unordered_map<QString, int> fdmap;
int minRowHeight = 0;
char hasGrid = 1;
bool hasRowNum = false;
int sizeHintForColumn(int column) const override {
return QTreeWidget::sizeHintForColumn(column);
}
signals:
void updGeos();
protected:
bool eventFilter(QObject *watched, QEvent *event) override;
void updateGeometries() override {
QTreeWidget::updateGeometries();
emit updGeos();
}
void rowsInserted(const QModelIndex &parent, int start, int end) override;
void drawRow(QPainter *painter, const QStyleOptionViewItem &options, const QModelIndex &index) const override;
void onSectionResized(int logicalIndex, int oldSize, int newSize);
bool adjSections(int index, int size);
bool noStretch = true;
bool noMargin = true;
bool isSectionResized = false;
bool blocked = false;
};
inline int operator*(const QString& key, QTreeView &table) {
if((size_t)&table==0) return 0;
return ((TreeWidget&)table).fdmap.at(key);
}
inline int operator*(const char *key, QTreeView &table) {
if((size_t)&table==0) return 0;
return ((TreeWidget&)table).fdmap.at(key);
}
class TreeWidgetItem : public QTreeWidgetItem {
public:
using QTreeWidgetItem::QTreeWidgetItem;
using QTreeWidgetItem::checkState;
auto checkState(const QString& column) const {
return checkState(column**treeWidget());
}
using QTreeWidgetItem::setCheckState;
auto setCheckState(const QString& column, Qt::CheckState state) {
setCheckState(column**treeWidget(), state);
return this;
}
using QTreeWidgetItem::text;
auto text(const QString& column) const {
return text(column**treeWidget());
}
using QTreeWidgetItem::setText;
auto setText(const QString& column, const QString& text) {
setText(column**treeWidget(), text);
return this;
}
auto setText(const QString& column, const QString& text, const QVariant &value) {
auto idx = column**treeWidget();
setText(idx, text);
setData(idx, Qt::UserRole, value);
return this;
}
auto setText(const QString& column, const QString& text, int alignment) {
auto idx = column**treeWidget();
setText(idx, text);
setTextAlignment(idx, (Qt::Alignment)alignment);
return this;
}
using QTreeWidgetItem::background;
auto background(const QString& column) const {
return background(column**treeWidget());
}
using QTreeWidgetItem::setBackground;
auto setBackground(const QString& column, const QBrush &brush) {
setBackground(column**treeWidget(), brush);
return this;
}
using QTreeWidgetItem::foreground;
auto foreground(const QString& column) const {
return foreground(column**treeWidget());
}
using QTreeWidgetItem::setForeground;
auto setForeground(const QString& column, const QBrush &brush) {
setForeground(column**treeWidget(), brush);
return this;
}
using QTreeWidgetItem::data;
auto data(int col) const {
return data(col, Qt::UserRole);
}
auto data(const QString& column, int role = Qt::UserRole) const {
return data(column**treeWidget(), role);
}
using QTreeWidgetItem::setData;
auto setData(int col, const QVariant &value) {
setData(col, Qt::UserRole, value);
return this;
}
auto setData(const QString& column, const QVariant &value) {
setData(column**treeWidget(), Qt::UserRole, value);
return this;
}
auto setData(const QString& column, int role, const QVariant &value) {
setData(column**treeWidget(), role, value);
return this;
}
auto cellWidget(int column) {
return treeWidget()->itemWidget(this, column);
}
auto cellWidget(const QString& column) {
return treeWidget()->itemWidget(this, column**treeWidget());
}
void setCellWidget(int column, QWidget *widget) {
treeWidget()->setItemWidget(this, column, widget);
}
void setCellWidget(const QString& column, QWidget *widget) {
treeWidget()->setItemWidget(this, column**treeWidget(), widget);
}
};
class TableWidget : public QTableWidget {
Q_OBJECT
public:
using QTableWidget::QTableWidget;
Table() {}
Table(std::initializer_list<ColAttr> colAttrs, int rows = 0, QWidget *parent = 0);
TableWidget() {}
TableWidget(std::initializer_list<ColAttr> colAttrs, int rows = 0, QWidget *parent = 0);
inline auto setDefs() {
auto setDefs() {
setSelectionBehavior(QTableWidget::SelectRows);
setEditTriggers(QAbstractItemView::NoEditTriggers);
setAlternatingRowColors(true);
return this;
}
inline auto setColStretch() {
auto setColStretch() {
horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
return this;
}
inline auto setRowStretch() {
auto setRowStretch() {
verticalHeader()->setSectionResizeMode(QHeaderView::Stretch);
return this;
}
inline auto setColFit() {
auto setColFit() {
horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
return this;
}
inline auto setRowFit() {
auto setRowFit() {
verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
return this;
}
inline auto setColWidth(int value, QHeaderView::ResizeMode mode = QHeaderView::Interactive) {
auto header = horizontalHeader();
header->setDefaultSectionSize(value);
if(mode!=QHeaderView::Interactive) header->setSectionResizeMode(mode);
auto setColWidth(int value) {
if(horizontalHeader()->minimumSectionSize() > value) horizontalHeader()->setMinimumSectionSize(value);
horizontalHeader()->setDefaultSectionSize(value);
return this;
}
inline auto setRowHeight(int value, QHeaderView::ResizeMode mode = QHeaderView::Interactive) {
auto header = verticalHeader();
header->setDefaultSectionSize(value);
if(mode!=QHeaderView::Interactive) header->setSectionResizeMode(mode);
auto setColResize(QHeaderView::ResizeMode mode) {
horizontalHeader()->setSectionResizeMode(mode);
return this;
}
auto setRowHeight(int value) {
if(verticalHeader()->minimumSectionSize() > value) verticalHeader()->setMinimumSectionSize(value);
verticalHeader()->setDefaultSectionSize(value);
return this;
}
auto setRowResize(QHeaderView::ResizeMode mode) {
verticalHeader()->setSectionResizeMode(mode);
return this;
}
inline auto setHeaderText(int col, QString text) {
auto setHeaderText(int col, const QString& text) {
auto item = horizontalHeaderItem(col);
if(item==0) setHorizontalHeaderItem(col, item = new QTableWidgetItem());
item->setText(text);
return item;
}
inline auto setHeaderText(QString column, QString text) {
auto col = mFieldMap[column];
return setHeaderText(col, text);
auto setHeaderText(const QString& column, const QString& text) {
return setHeaderText(fdmap.at(column), text);
}
inline auto setVHeaderText(int row, QString text) {
auto setVHeaderText(int row, const QString& text) {
auto item = verticalHeaderItem(row);
if(item==0) setVerticalHeaderItem(row, item = new QTableWidgetItem());
item->setText(text);
return item;
}
inline auto appendRow() {
auto appendRow() {
auto value = rowCount();
setRowCount(value + 1);
return value;
}
using QTableWidget::item;
inline auto item(int row, QString column) {
auto col = mFieldMap[column];
return item(row, col);
auto item(int row, const QString& column) {
return item(row, fdmap.at(column));
}
inline auto itemValid(int row, int col) {
auto anitem = item(row, col);
if(anitem==0) setItem(row, col, anitem = new QTableWidgetItem);
return anitem;
auto itemValid(int row, int col) {
auto itm = item(row, col);
if(itm==0) setItem(row, col, itm = new QTableWidgetItem);
return itm;
}
inline auto itemValid(int row, QString column) {
auto col = mFieldMap[column];
return itemValid(row, col);
auto itemValid(int row, const QString& column) {
return itemValid(row, fdmap.at(column));
}
using QTableWidget::setItem;
inline void setItem(int row, QString column, QTableWidgetItem *item) {
auto col = mFieldMap[column];
setItem(row, col, item);
void setItem(int row, const QString& column, QTableWidgetItem *item) {
setItem(row, fdmap.at(column), item);
}
inline auto text(int row, int col) {
auto text(int row, int col) {
auto itm = item(row, col);
if(itm==0) return QString();
return itm->text();
}
inline auto text(int row, QString column) {
auto col = mFieldMap[column];
return text(row, col);
auto text(int row, const QString& column) {
return text(row, fdmap.at(column));
}
inline auto setText(int row, int col, const QString &text) {
auto setText(int row, int col, const QString& text) {
auto itm = item(row, col);
if(itm) itm->setText(text);
else setItem(row, col, itm = new QTableWidgetItem(text));
return itm;
}
inline auto setText(int row, QString column, const QString &text) {
auto col = mFieldMap[column];
return setText(row, col, text);
auto setText(int row, const QString& column, const QString& text) {
return setText(row, fdmap.at(column), text);
}
auto setText(int row, int col, const QString& text, const QVariant &value) {
auto itm = item(row, col);
if(itm) itm->setText(text);
else setItem(row, col, itm = new QTableWidgetItem(text));
itm->setData(Qt::UserRole, value);
return itm;
}
auto setText(int row, const QString& column, const QString& text, const QVariant &value) {
return setText(row, fdmap.at(column), text, value);
}
inline auto data(int row, int col) {
auto data(int row, int col) {
auto itm = item(row, col);
if(itm==0) return QVariant();
return itm->data(Qt::UserRole);
}
inline auto data(int row, QString column) {
auto col = mFieldMap[column];
return data(row, col);
auto data(int row, const QString& column) {
return data(row, fdmap.at(column));
}
inline auto setData(int row, int col, const QVariant &value) {
auto setData(int row, int col, const QVariant &value) {
auto itm = item(row, col);
if(itm==0) setItem(row, col, itm = new QTableWidgetItem);
itm->setData(Qt::UserRole, value);
return itm;
}
inline auto setData(int row, QString column, const QVariant &value) {
auto col = mFieldMap[column];
return setData(row, col, value);
auto setData(int row, const QString& column, const QVariant &value) {
return setData(row, fdmap.at(column), value);
}
using QTableWidget::cellWidget;
inline auto cellWidget(int row, QString column) {
auto col = mFieldMap[column];
return cellWidget(row, col);
auto cellWidget(int row, const QString& column) {
return cellWidget(row, fdmap.at(column));
}
using QTableWidget::setCellWidget;
inline void setCellWidget(int row, QString column, QWidget *widget) {
auto col = mFieldMap[column];
setCellWidget(row, col, widget);
void setCellWidget(int row, const QString& column, QWidget *widget) {
setCellWidget(row, fdmap.at(column), widget);
}
std::map<QString, int> mFieldMap;
using QTableWidget::sortItems;
void sortItems(const QString& column, Qt::SortOrder order) {
sortItems(fdmap.at(column), order);
}
std::unordered_map<QString, int> fdmap;
public Q_SLOTS:
inline void clearRows() {setRowCount(0);}
void clearRows() {setRowCount(0);}
signals:
void updGeos();
protected:
void resizeEvent(QResizeEvent *event) override;
void updateGeometries() override;
void resizeSec();
bool noStretch{true};
};
class ResizeEmitedWgt : public QWidget {
Q_OBJECT
public:
using QWidget::QWidget;
protected:
void resizeEvent(QResizeEvent *) override {emit resized();}
signals:
void resized();
bool eventFilter(QObject *watched, QEvent *event) override;
void updateGeometries() override {
QTableWidget::updateGeometries();
emit updGeos();
};
void onSectionResized(int logicalIndex, int oldSize, int newSize);
bool adjSections(int index, int size);
bool noStretch = true;
bool isSectionResized = false;
bool blocked = false;
};
@ -317,43 +568,43 @@ public:
Wrp(T *obj = nullptr){
this->obj = obj;
};
inline Wrp& operator()(T *obj){
Wrp& operator()(T *obj){
this->obj = obj;
return *this;
}
inline Wrp& operator()(T *obj, QLayout *layout){
Wrp& operator()(T *obj, QLayout *layout){
this->obj = obj;
layout->addWidget(obj);
return *this;
}
inline Wrp& addTo(QLayout *layout){
Wrp& addTo(QLayout *layout){
layout->addWidget(obj);
return *this;
}
inline Wrp& margin(int a){
Wrp& margin(int a){
obj->setMargin(a);
return *this;
}
inline Wrp& font(const QFont &font){
Wrp& font(const QFont &font){
obj->setFont(font);
return *this;
}
inline Wrp& font(int size){
Wrp& font(int size){
auto font = obj->font();
font.setPixelSize(size);
obj->setFont(font);
return *this;
}
inline Wrp& width(int w){
Wrp& width(int w){
obj->setFixedWidth(w);
return *this;
}
inline Wrp& height(int h){
Wrp& height(int h){
obj->setFixedHeight(h);
return *this;
}
inline Wrp& padding(int wAdd, int hAdd, int minW = 32, int minH = 16){
Wrp& padding(int wAdd, int hAdd, int minW = 32, int minH = 16){
wAdd+=8;
hAdd+=8;
QSize size = obj->fontMetrics().size(Qt::TextShowMnemonic, obj->text());
@ -367,11 +618,11 @@ public:
return *this;
}
inline Wrp& alignC(){
Wrp& alignC(){
obj->setAlignment(Qt::AlignCenter);
return *this;
}
inline Wrp& alignR(){
Wrp& alignR(){
obj->setAlignment(Qt::AlignRight);
return *this;
}

View File

@ -1,4 +1,12 @@
#include "qjson.h"
#include "qdebug.h"
QDebug operator<<(QDebug debug, const JValue &val) {
auto old = debug.autoInsertSpaces();
debug.noquote().nospace() << JToBytes(val, "\t");
debug.setAutoInsertSpaces(old);
return debug;
}
inline QChar readOne(QTextStream &in) {
QChar ch;

View File

@ -1,7 +1,7 @@
#ifndef QJSON_H
#define QJSON_H
#include "cu.h"
#include "cpp.h"
#include "QtCore/qhashfunctions.h"
#include <QTextStream>
@ -11,99 +11,154 @@ using JArray = Vector<JValue>;
class JValue {
public:
int data[2]{0};
long long data = 0;
enum Type {
Null, Bool, Int, Long, Double, Obj, Array, Str
Null, Long, Ulong, Double, Bool, Obj, Array, Str
};
Type type{Null};
Type type = Null;
JValue(Type = Null) {}
JValue(bool b) : type(Bool) {data[0] = b;}
JValue(int n) : type(Int) {data[0] = n;}
JValue(qint64 n) : type(Long) {*(qint64*) data = n;}
JValue(double d) : type(Double) {*(double*) data = d;}
JValue(const JObj &o) : type(Obj) {new (data) JObj(o);}
JValue(const JArray &a) : type(Array) {new (data) JArray(a);}
JValue(const QString &s) : type(Str) {*(SharedData<QString>**) data = new SharedData<QString>{s, 1};}
JValue(bool b) : type(Bool) {data = b;}
JValue(int n) : type(Long) {data = n;}
JValue(qint64 n) : type(Long) {data = n;}
JValue(quint64 n) : type(Ulong) {*(quint64*) &data = n;}
JValue(double d) : type(Double) {*(double*) &data = d;}
JValue(const JObj &o) : type(Obj) {new (&data) JObj(o);}
JValue(const JArray &a) : type(Array) {new (&data) JArray(a);}
JValue(JObj &&o) : type(Obj) {new (&data) JObj(std::move(o));}
JValue(JArray &&a) : type(Array) {new (&data) JArray(std::move(a));}
JValue(const QString &s) : type(Str) {*(SharedData<QString>**) &data = new SharedData<QString>{1, s};}
JValue(QString &&s) : type(Str) {*(SharedData<QString>**) &data = new SharedData<QString>{1, std::move(s)};}
JValue(const char *s) : JValue(QString::fromUtf8(s)) {}
JValue(const JValue &other) {
type = other.type;
if(type==Obj) new (data) JObj(*(JObj*) other.data);
else if(type==Array) new (data) JArray(*(JArray*) other.data);
else {
data[0] = other.data[0];
data[1] = other.data[1];
if(type==Str) (*(SharedData<QString>**) data)->cnt++;
}
}
~JValue() {
if(type < Obj) return;
else if(type==Obj) ((JObj*) data)->~JObj();
else if(type==Array) ((JArray*) data)->~JArray();
else if(type==Obj) ((JObj*) &data)->~JObj();
else if(type==Array) ((JArray*) &data)->~JArray();
else if(type==Str) {
auto ptr = *(SharedData<QString>**) data;
auto ptr = *(SharedData<QString>**) &data;
if(ptr->cnt > 1) ptr->cnt--;
else delete ptr;
}
}
JValue(const JValue &other) {
type = other.type;
if(type==Obj) new (&data) JObj(*(JObj*) &other.data);
else if(type==Array) new (&data) JArray(*(JArray*) &other.data);
else {
data = other.data;
if(type==Str) (*(SharedData<QString>**) &data)->cnt++;
}
}
JValue &operator=(const JValue &other) {
this->~JValue();
new (this) JValue(other);
return *this;
}
JValue(JValue &&other) noexcept : data(other.data), type(other.type) {
other.data = 0;
other.type = Null;
}
JValue &operator=(JValue &&other) noexcept {
std::swap(data, other.data);
std::swap(type, other.type);
return *this;
}
bool isNull() const {return type==Null;}
bool isStr() const {return type==Str;}
bool isObj() const {return type==Obj;}
bool isArray() const {return type==Array;}
bool toBool(bool def = false) const {
return type==Null ? def : data[0] || data[1];
return type==Null ? def : data;
}
int toInt(int def = 0) const {
if(type==Bool || type==Int) return data[0];
if(type==Long) return *(qint64*) data;
if(type==Double) return *(double*) data;
return def;
return toLong(def);
}
qint64 toLong(qint64 def = 0) const {
if(type==Bool || type==Int) return data[0];
if(type==Long) return *(qint64*) data;
if(type==Double) return *(double*) data;
if(type==Long || type==Bool) return data;
if(type==Double) return *(double*) &data;
if(type==Ulong) return *(quint64*) &data;
return def;
}
quint64 toULong(quint64 def = 0) const {
if(type==Ulong) return *(quint64*) &data;
if(type==Long || type==Bool) return data;
if(type==Double) return *(double*) &data;
return def;
}
double toDouble(double def = 0) const {
if(type==Bool || type==Int) return data[0];
if(type==Long) return *(qint64*) data;
if(type==Double) return *(double*) data;
if(type==Double) return *(double*) &data;
if(type==Long || type==Bool) return data;
if(type==Ulong) return *(quint64*) &data;
return def;
}
QString toStr(const QString &def = "") const {
if(type==Bool) return data[0] ? "true" : "false";
if(type==Int) return QString::number(data[0]);
if(type==Long) return QString::number(*(qint64*) data);
if(type==Double) return QString::number(*(double*) data);
if(type==Str) return (*(SharedData<QString>**) data)->data;
if(type==Str) return (*(SharedData<QString>**) &data)->data;
if(type==Long) return QString::number(data);
if(type==Double) return QString::number(*(double*) &data);
if(type==Bool) return data ? "true" : "false";
if(type==Ulong) return QString::number(*(quint64*) &data);
return def;
}
QString toString(const QString &def = "") const {
return toStr(def);
}
JObj toObj() const {
if(type==Obj) return *(JObj*) data;
if(type==Obj) return *(JObj*) &data;
return JObj();
}
JArray toArray() const {
if(type==Array) return *(JArray*) data;
if(type==Array) return *(JArray*) &data;
return JArray();
}
const JValue operator[](const QString &key) const {
return type==Obj ? (*(JObj*) data)[key] : JValue();
return type==Obj ? (*(const JObj*) &data)[key] : JValue();
}
const JValue operator[](int i) const {
return type==Array ? (*(JArray*) data)[i] : JValue();
return type==Array ? (*(const JArray*) &data)[i] : JValue();
}
JArray::iterator begin() const noexcept {
return type==Array ? ((const JArray*) &data)->begin() : JArray::iterator();
}
JArray::iterator end() const noexcept {
return type==Array ? ((const JArray*) &data)->end() : JArray::iterator();
}
size_t size() const noexcept {
if(type==Array) return ((const JArray*) &data)->size();
else if(type==Obj) return ((const JObj*) &data)->size();
return 0;
}
bool operator==(const JValue &other) const {
if(type==other.type) {
if(data==other.data) return true;
if(type==Null) return true;
if(type<=Double) return false;
if(type==Bool) return ((bool)data)==(bool)other.data;
if(type==Str) return (*(SharedData<QString>**) &data)->data==(*(SharedData<QString>**) &other.data)->data;
if(type==Obj) return *(JObj*) &data == *(JObj*) &other.data;
if(type==Array) return *(JArray*) &data == *(JArray*) &other.data;
} else {
if(type>Double || other.type>Double || type==Null || other.type==Null) return false;
if(type==Double || other.type==Double) return toDouble()==other.toDouble();
if(type==Long) return data==other.toLong();
else return toLong()==other.data;
}
return false;
}
bool operator!=(const JValue &other) const {
return ! (*this==other);
}
private:
JValue(const void *) = delete; // avoid implicit conversions from char * to bool
};
QDebug operator<<(QDebug debug, const JValue &val);
class JParser {
public:
JParser(QTextStream &in) : in(in) {
@ -160,7 +215,7 @@ public:
#endif
}
void write(const JValue &obj);
void write(const JValue &value);
void writeStr(const QString &str);
void writeMap(const JObj &map);
void writeList(const JArray &objs);
@ -170,21 +225,21 @@ protected:
int cnt{0};
};
inline QString JToStr(const JValue &obj, QString indent = "") {
inline QString JToStr(const JValue &value, QString indent = "") {
QString json;
QTextStream out(&json);
JOut(out, indent).write(obj);
JOut(out, indent).write(value);
return json;
}
inline QByteArray JToBytes(const JValue &obj, QString indent = "") {
inline QByteArray JToBytes(const JValue &value, QString indent = "") {
QByteArray json;
QTextStream out(&json);
JOut(out, indent).write(obj);
JOut(out, indent).write(value);
return json;
}
inline QTextStream::Status JWrite(const JValue &obj, QIODevice *device, QString indent = "") {
inline QTextStream::Status JWrite(const JValue &value, QIODevice *device, QString indent = "") {
QTextStream out(device);
JOut(out, indent).write(obj);
JOut(out, indent).write(value);
return out.status();
}

View File

@ -57,11 +57,13 @@ bool TcpSocket::waitForDisconnected(int msecs) {
return connAndExec(msecs, &loop);
}
bool TcpSocket::waitForBytesWritten(int msecs) {
if(bytesToWrite() == 0) return true;
QEventLoop loop;
connect(this, &QTcpSocket::bytesWritten, &loop, &QEventLoop::quit);
return connAndExec(msecs, &loop);
}
bool TcpSocket::waitForReadyRead(int msecs) {
if(bytesAvailable()) return true;
QEventLoop loop;
connect(this, &QTcpSocket::readyRead, &loop, &QEventLoop::quit);
return connAndExec(msecs, &loop);

View File

@ -1,6 +1,7 @@
#ifndef QNETWORK_H
#define QNETWORK_H
#include "qjson.h"
#include <QNetworkReply>
#include <QJsonDocument>
#include <QEventLoop>
@ -65,6 +66,15 @@ public:
if(mAccess==0) mAccess = netAccess();
return mAccess->post(*this, data);
}
inline QNetworkReply *post(const char *data) {
if(mAccess==0) mAccess = netAccess();
return mAccess->post(*this, data);
}
inline QNetworkReply *post(const JValue &json) {
setRawHeader("Content-Type", "application/json");
return post(JToBytes(json));
}
inline QNetworkReply *post(const QJsonDocument &json) {
setRawHeader("Content-Type", "application/json");
return post(json.toJson(QJsonDocument::Compact));
@ -86,6 +96,7 @@ QString errStr(QNetworkReply *);
QString errStrWithData(QNetworkReply *, QJsonDocument * = 0);
inline int waitFinished(QNetworkReply *reply, bool excludeUser = false) {
if(reply->isFinished()) return 0;
QEventLoop loop;
QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
return excludeUser ? loop.exec(QEventLoop::ExcludeUserInputEvents) : loop.exec();

View File

@ -1,5 +1,5 @@
#include "waitingdlg.h"
#include "gutil/qgui.h"
#include "qwaitingdlg.h"
#include "qgui.h"
#include <QTimerEvent>
#include <QPainter>
#include <QPainterPath>
@ -11,7 +11,7 @@ WaitingDlg::WaitingDlg(QWidget *parent, QString text, QString sucText) : QDialog
auto vBox = new VBox(this);
mIndicator = new WaitingIndicator(this);
mIndicator->setFixedSize(120, 120);
mIndicator->setFixedSize(100, 100);
vBox->addWidget(mIndicator, 0, Qt::AlignCenter);
fdText = new QLabel(text);
@ -61,7 +61,7 @@ void WaitingDlg::success() {
}
if(! isVisible()) show();
if(closeTimerId) killTimer(closeTimerId);
closeTimerId = startTimer(1000);
closeTimerId = startTimer(keepTime);
}

View File

@ -1,5 +1,5 @@
#ifndef WAITINGDLG_H
#define WAITINGDLG_H
#ifndef QWAITINGDLG_H
#define QWAITINGDLG_H
#include <QLabel>
#include <QNetworkReply>
@ -36,6 +36,7 @@ public:
QLabel *fdText;
QString sucText;
WaitingIndicator *mIndicator;
int keepTime = 750;
public slots:
void show();
void showLater();
@ -47,4 +48,4 @@ private:
int closeTimerId{0}, showTimerId{0};
};
#endif // WAITINGDLG_H
#endif // QWAITINGDLG_H

View File

@ -1,6 +1,6 @@
#include "mainwindow.h"
#include <QApplication>
#include <QStyleFactory>
#include <QFile>
#include <QMessageBox>
#include <QSplashScreen>
#include <QStandardPaths>
@ -27,7 +27,6 @@ LONG WINAPI handleException(_EXCEPTION_POINTERS *excep) {
}
#endif
QString gFileHome;
QString css;
int main(int argc, char *argv[]) {
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
@ -36,8 +35,13 @@ int main(int argc, char *argv[]) {
QApplication::setOrganizationName("Shanghai Xixun Electronic Technology Co., Ltd.");
QApplication::setOrganizationDomain("www.ledok.cn");
QApplication::setApplicationName("LedOK Express");
QApplication::setStyle("Fusion");
QApplication a(argc, argv);
QApplication::setStyle(QStyleFactory::create("Fusion"));
QSplashScreen splash(QPixmap(":/res/splash.png"));
splash.show();
splash.showMessage(QObject::tr("Setting up the LedOK Express..."), Qt::AlignRight | Qt::AlignTop, Qt::white);
QFile file(":/css.css");
if(file.exists() && file.open(QFile::ReadOnly)) {
a.setStyleSheet(css = file.readAll());
@ -46,11 +50,17 @@ int main(int argc, char *argv[]) {
QFont font;
font.setFamilies(QStringList{"Arial","PingFang SC","Hiragino Sans GB","STHeiti","Microsoft YaHei","WenQuanYi Micro Hei","sans-serif"});
a.setFont(font);
auto plt = a.palette();
plt.setBrush(QPalette::AlternateBase, plt.brush(QPalette::Active, QPalette::Window));
plt.setBrush(QPalette::Inactive, QPalette::Highlight, plt.brush(QPalette::Active, QPalette::Highlight));
plt.setBrush(QPalette::Inactive, QPalette::HighlightedText, plt.brush(QPalette::Active, QPalette::HighlightedText));
a.setPalette(plt);
QTranslator qtTrans;
if(qtTrans.load(QLocale(), "qt", "_", "translations")) QCoreApplication::installTranslator(&qtTrans);
gFileHome = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
QSplashScreen splash(QPixmap(":/res/splash.png"));
splash.show();
splash.showMessage(QObject::tr("Setting up the LedOK Express..."), Qt::AlignRight | Qt::AlignTop, Qt::white);
#ifdef _MSC_VER
SetUnhandledExceptionFilter(handleException);
#endif

View File

@ -2,13 +2,11 @@
#include "gutil/qgui.h"
#include "cfg.h"
#include "globaldefine.h"
#include "deviceitem.h"
#include "devicepanel.h"
#include "gutil/qnetwork.h"
#include "device/upgradeapkdialog.h"
#include <QColorDialog>
#include <QDesktopServices>
#include <QLabel>
#include <QMenu>
#include <QMessageBox>
#include <QProcess>
@ -18,7 +16,8 @@
#include <QStandardPaths>
#include <QDialogButtonBox>
#include <QToolButton>
#include <QApplication>
#include <QDir>
#include <QCoreApplication>
extern QPoint gPlayPos;
@ -81,16 +80,21 @@ MainWindow::MainWindow(QWidget *parent) : BaseWin(parent) {
actJa->setObjectName("ja");
menuLang->addAction(actJa);
auto actPt = new QAction("Português");
actPt->setCheckable(true);
actPt->setObjectName("pt");
menuLang->addAction(actPt);
langGrp = new QActionGroup(menuLang);
langGrp->addAction(actCN);
langGrp->addAction(actTW);
langGrp->addAction(actEn);
langGrp->addAction(actJa);
langGrp->addAction(actPt);
connect(menuLang, &QMenu::triggered, this, [this](QAction* action) {
auto lanName = action->objectName();
translator.load("app_"+lanName, ":/i18n");
transQt.load("qt_"+lanName, ":/i18n");
qInfo() << "load translators" << lanName << translator.load("app_"+lanName, ":/i18n");
});
QSettings settings;
@ -101,21 +105,20 @@ MainWindow::MainWindow(QWidget *parent) : BaseWin(parent) {
else if(langName.endsWith("TW")) actLan = actTW;
else if(langName.startsWith("en")) actLan = actEn;
else if(langName.startsWith("ja")) actLan = actJa;
else if(langName.startsWith("pt")) actLan = actPt;
}
if(actLan==0) {
langName = QLocale().name();
if(langName.endsWith("TW")) actLan = actTW;
else if(langName.startsWith("en")) actLan = actEn;
else if(langName.startsWith("ja")) actLan = actJa;
else if(langName.startsWith("pt")) actLan = actPt;
else actLan = actCN;
}
actLan->setChecked(true);
auto lanName = actLan->objectName();
translator.load("app_"+lanName, ":/i18n");
transQt.load("qt_"+lanName, ":/i18n");
QApplication::installTranslator(&translator);
QApplication::installTranslator(&transQt);
emit menuLang->triggered(actLan);
QCoreApplication::installTranslator(&translator);
auto geo = settings.value("MainGeo").toRect();
if(geo.width()>=800 && geo.height()>=500 && geo.x()>=-600 && geo.x()<=1280 && geo.y()>=-200 && geo.y()<=800) setGeometry(geo);
@ -127,7 +130,7 @@ MainWindow::MainWindow(QWidget *parent) : BaseWin(parent) {
setWindowTitle("LedOK Express");
icon.load(":/res/Logo.png");
titlePos = QPointF(26, 80);
iconPos = QPointF(38, 20);
iconPos = QRectF(38, 20, 64, 64);
auto plt = palette();
plt.setBrush(QPalette::Window, QColor(0xdddddd));
setPalette(plt);
@ -135,10 +138,10 @@ MainWindow::MainWindow(QWidget *parent) : BaseWin(parent) {
//项目保存的文档路径
QString doc_path = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
if(!doc_path.isEmpty()) {
QDir app_dir = QDir(doc_path + "/" + QApplication::applicationName());
QDir app_dir = QDir(doc_path + "/" + QCoreApplication::applicationName());
if(!app_dir.exists()) {
QDir doc_dir(doc_path);
doc_dir.mkdir(QApplication::applicationName());
doc_dir.mkdir(QCoreApplication::applicationName());
}
}
@ -172,8 +175,7 @@ MainWindow::MainWindow(QWidget *parent) : BaseWin(parent) {
actFirmware = new QAction(tr("firmware manager"));
connect(actFirmware, &QAction::triggered, this, [this] {
UpgradeApkDialog dlg(this);
dlg.exec();
new UpgradeApkDialog(this);
});
menu_setting->addAction(actFirmware);
@ -193,22 +195,30 @@ MainWindow::MainWindow(QWidget *parent) : BaseWin(parent) {
fdTrans->setChecked(gVideoTranscoding);
vBox->addWidget(fdTrans);
auto hbox = new HBox(vBox);
hbox->setContentsMargins(-1, 0, -1, -1);
auto hBox = new HBox(vBox);
hBox->setContentsMargins(-1, 0, -1, -1);
auto fdAnti = new QCheckBox(tr("Text antialiasing"));
fdAnti->setChecked(gTextAntialiasing);
hbox->addWidget(fdAnti, 0, Qt::AlignTop);
hBox->addWidget(fdAnti, 0, Qt::AlignTop);
auto fdAntiTip = new QLabel(tr("TextAntilaTip"));
fdAntiTip->setStyleSheet("QLabel{color: #f00;}");
fdAntiTip->setWordWrap(true);
hbox->addWidget(fdAntiTip, 1);
hBox->addWidget(fdAntiTip, 1);
auto fdWidthSplit = new QCheckBox(tr("Width Split"));
fdWidthSplit->setChecked(gWidthSplit);
vBox->addWidget(fdWidthSplit);
hBox = new HBox(vBox);
hBox->addLabel(tr("Program Send Batch"));
auto fdSendBatch = new QSpinBox;
fdSendBatch->setRange(1, 20);
fdSendBatch->setValue(gSendBatch);
hBox->addWidget(fdSendBatch);
hBox->addStretch();
auto fdHideDetect = new QCheckBox(tr("Hide Detect Button"));
fdHideDetect->setChecked(gHideDetect);
vBox->addWidget(fdHideDetect);
@ -226,6 +236,7 @@ MainWindow::MainWindow(QWidget *parent) : BaseWin(parent) {
settings.setValue("VideoTranscoding", gVideoTranscoding = fdTrans->isChecked());
settings.setValue("TextAntialiasing", gTextAntialiasing = fdAnti->isChecked());
settings.setValue("WidthSplit", gWidthSplit = fdWidthSplit->isChecked());
settings.setValue("SendBatch", gSendBatch = fdSendBatch->value());
settings.setValue("HideDetect", gHideDetect = fdHideDetect->isChecked());
settings.setValue("GuangYingPin", gShowLora = fdShowLora->isChecked());
dlg.accept();
@ -322,7 +333,7 @@ MainWindow::MainWindow(QWidget *parent) : BaseWin(parent) {
auto res = msgBox.exec();
qFile.close();
if(res != QDialog::Accepted) return;
QApplication::quit();
QCoreApplication::quit();
QDesktopServices::openUrl(QUrl::fromLocalFile(filePath));
});
menu_setting->addAction(act_update);
@ -457,24 +468,22 @@ MainWindow::MainWindow(QWidget *parent) : BaseWin(parent) {
}
mDevicePanel->mainPanelIdx = id;
if(id==MainPage_DeviceManager) { //设备信息列表页面
mDevicePanel->mDeviceTable->hideColumn(0);
mDevicePanel->mDeviceTable->fdIsSelAll->hide();
if(mDevicePanel->mDeviceCtrlPanel) {
for(int j=DeviceTable_ScreenSize;j<DeviceTable_End;j++) mDevicePanel->mDeviceTable->showColumn(j);
mDevicePanel->mDeviceTable->setMaximumWidth(0xffffff);
mDevicePanel->mDeviceTable->setSelectionMode(QAbstractItemView::NoSelection);
mDevicePanel->mDeviceCtrlPanel->hide();
mDevicePanel->mDeviceTable->hideColumn("check");
mDevicePanel->mDeviceTable->fdCheckAll->hide();
mDevicePanel->fdCardNumInfo->hide();
if(mDevicePanel->mDeviceCtrlPanel) {
for(int j="screenSize"**mDevicePanel->mDeviceTable; j<mDevicePanel->mDeviceTable->columnCount(); j++) mDevicePanel->mDeviceTable->showColumn(j);
mDevicePanel->mDeviceTable->setMaximumWidth(0xffffff);
mDevicePanel->mDeviceCtrlPanel->hide();
}
} else if(id==MainPage_Setting) { //终端控制页面
mDevicePanel->mDeviceTable->showColumn(0);
mDevicePanel->mDeviceTable->fdIsSelAll->show();
for(int j=DeviceTable_ScreenSize; j<DeviceTable_End; j++) mDevicePanel->mDeviceTable->hideColumn(j);
mDevicePanel->mDeviceTable->showColumn("check");
mDevicePanel->mDeviceTable->fdCheckAll->show();
mDevicePanel->fdCardNumInfo->show();
for(int j="screenSize"**mDevicePanel->mDeviceTable; j<mDevicePanel->mDeviceTable->columnCount(); j++) mDevicePanel->mDeviceTable->hideColumn(j);
if(mDevicePanel->mDeviceCtrlPanel) mDevicePanel->mDeviceCtrlPanel->show();
else mDevicePanel->newCtrl();
mDevicePanel->mDeviceTable->setMaximumWidth(340);
mDevicePanel->mDeviceTable->setSelectionMode(QAbstractItemView::SingleSelection);
mDevicePanel->fdCardNumInfo->show();
}
});
@ -522,12 +531,14 @@ MainWindow::MainWindow(QWidget *parent) : BaseWin(parent) {
hBox->addWidget(fdDetectCard);
hBox->addStretch();
hBox->addWidget(new QLabel("V" APP_VERSION" - " __DATE__));
hBox->addLabel("V" APP_VERSION" - " __DATE__);
gApkHome = settings.value("ApkHome").toString();
gVideoCompress = settings.value("VideoCompress", true).toBool();
gVideoTranscoding = settings.value("VideoTranscoding", true).toBool();
gTextAntialiasing = settings.value("TextAntialiasing", false).toBool();
gWidthSplit = settings.value("WidthSplit", false).toBool();
gSendBatch = settings.value("SendBatch", 5).toInt();
gHideDetect = settings.value("HideDetect", false).toBool();
gShowLora = settings.value("GuangYingPin", false).toBool();
@ -574,7 +585,6 @@ MainWindow::MainWindow(QWidget *parent) : BaseWin(parent) {
QColorDialog::setStandardColor(ci++, QColor(mids[i], lows[i], higs[i]));
}
}
MainWindow::~MainWindow() {
QSettings settings;
auto act = langGrp->checkedAction();
@ -582,20 +592,18 @@ MainWindow::~MainWindow() {
settings.setValue("MainGeo", normalGeometry());
settings.setValue("MainIsMax", isMaximized());
settings.setValue("PlayPos", gPlayPos);
if(! gApkHome.isEmpty()) settings.setValue("ApkHome", gApkHome);
if(mDevicePanel->fdIP) {
auto ipstr = mDevicePanel->fdIP->toPlainText();
if(! ipstr.isEmpty()) settings.setValue("SpecifyIP", ipstr);
else settings.remove("SpecifyIP");
}
if(m_pTimerSendResoreIpOneKey) {
if(m_pTimerSendResoreIpOneKey->isActive()) m_pTimerSendResoreIpOneKey->stop();
delete m_pTimerSendResoreIpOneKey;
}
if(mProgPanel) {
settings.setValue("ProgramListSortColumn", mProgPanel->mProgTree->sortColumn());
settings.setValue("ProgramListSortOrder", mProgPanel->mProgTree->header()->sortIndicatorOrder());
}
}
void MainWindow::changeEvent(QEvent *event) {
BaseWin::changeEvent(event);
if(event->type() == QEvent::LanguageChange) transUi();

View File

@ -21,7 +21,6 @@ protected:
private:
QJsonObject updates;
QTranslator translator;
QTranslator transQt;
LoQTitleBar *m_wTitle;
QActionGroup *langGrp;
QAction *act_lang;
@ -38,7 +37,6 @@ private:
DevicePanel *mDevicePanel{0};
ProgPanel *mProgPanel{0};
mGuangYingPinWidget *m_wGuangYingPinWidget{0};
QTimer *m_pTimerSendResoreIpOneKey{0};
bool hasNewVer{false};
};

File diff suppressed because one or more lines are too long

View File

@ -3,7 +3,6 @@
#include "gutil/qgui.h"
#include "cfg.h"
#include "player/playwin.h"
#include "program/progcreatedlg.h"
#include "program/progeditorwin.h"
#include "program/copydirthread.h"
#include <QApplication>
@ -12,6 +11,7 @@
#include <QStandardPaths>
#include <QProgressBar>
#include <QFileDialog>
#include <QLineEdit>
ProgPanel::ProgPanel(QWidget *parent) : QWidget(parent) {
setAttribute(Qt::WA_DeleteOnClose);
@ -56,7 +56,7 @@ ProgPanel::ProgPanel(QWidget *parent) : QWidget(parent) {
}
auto item = new ProgItem(mProgsDir, dlg.fdName->text(), width, dlg.fdHeight->value(), dlg.fdRemark->toPlainText(), widths, max, mProgTree);
item->save();//保存pro.json
mProgTree->adjustCheckState();
if(mProgTree->fdCheckAll->checkState()==Qt::Checked) mProgTree->fdCheckAll->setCheckState(Qt::PartiallyChecked);
auto editor = new ProgEditorWin(item, this);
editor->show();
});
@ -140,7 +140,7 @@ ProgPanel::ProgPanel(QWidget *parent) : QWidget(parent) {
connect(bnExport, &QPushButton::clicked, this, [=] {
int cnt = mProgTree->topLevelItemCount();
QStringList progNames;
for(int i=0; i<cnt; i++) if(mProgTree->topLevelItem(i)->checkState(0) == Qt::Checked) progNames.append(static_cast<ProgItem*>(mProgTree->topLevelItem(i))->mName);
for(int i=0; i<cnt; i++) if(mProgTree->item(i)->checkState("check") == Qt::Checked) progNames.append(((ProgItem*) mProgTree->topLevelItem(i))->mName);
if(progNames.isEmpty()) return;
ProgPortDlg dlg(this, tr("Export"));
@ -183,8 +183,8 @@ ProgPanel::ProgPanel(QWidget *parent) : QWidget(parent) {
if(PlayWin::self) PlayWin::self->close();
else {
int cnt = mProgTree->topLevelItemCount();
for(int i=0; i<cnt; i++) if(mProgTree->topLevelItem(i)->checkState(0) == Qt::Checked) {
auto item = static_cast<ProgItem*>(mProgTree->topLevelItem(i));
for(int i=0; i<cnt; i++) if(mProgTree->item(i)->checkState("check") == Qt::Checked) {
auto item = (ProgItem*) mProgTree->topLevelItem(i);
QString dir = mProgsDir+"/"+item->mName+"_tmp";
QFile file(dir+"/program");
if(! file.open(QIODevice::ReadOnly | QIODevice::Text)) return;
@ -202,65 +202,45 @@ ProgPanel::ProgPanel(QWidget *parent) : QWidget(parent) {
hBox->addStretch();
auto txtSearch = new QLineEdit(this);
txtSearch->setFixedSize(QSize(240, 36));
QAction *search = new QAction(txtSearch);
auto fdSearch = new QLineEdit;
fdSearch->setFixedWidth(200);
auto search = new QAction;
search->setIcon(QIcon(":/res/program/bnSearch.png"));
txtSearch->addAction(search, QLineEdit::LeadingPosition);
txtSearch->setClearButtonEnabled(true);
txtSearch->setStyleSheet("border: 2px solid #aaaaaa;");
hBox->addWidget(txtSearch);
connect(txtSearch,SIGNAL(textChanged(const QString &)),this,SLOT(FilterProgram(const QString &)));
mProgTree = new LoQTreeWidget();
mProgTree->setIndentation(6);
mProgTree->setSortingEnabled(true);
m_headerItem = new QTreeWidgetItem();
for(int i=1; i<ENUM_PROGRAMLISTHEADERITEM_END; i++) m_headerItem->setTextAlignment(i, Qt::AlignCenter);
m_headerItem->setData(ENUM_PROGRAMLISTHEADERITEM_CHECK, Qt::DisplayRole, "");
m_headerItem->setData(ENUM_PROGRAMLISTHEADERITEM_NAME, Qt::DisplayRole, tr("Name"));
m_headerItem->setData(ENUM_PROGRAMLISTHEADERITEM_RESOLUTION, Qt::DisplayRole, tr("Resolution"));
m_headerItem->setData(ENUM_PROGRAMLISTHEADERITEM_SIZE, Qt::DisplayRole, tr("File Size"));
m_headerItem->setData(ENUM_PROGRAMLISTHEADERITEM_LASTTIME, Qt::DisplayRole, tr("Last Modify"));
m_headerItem->setData(ENUM_PROGRAMLISTHEADERITEM_USB_EXPORT, Qt::DisplayRole, tr("USB Update"));
m_headerItem->setData(ENUM_PROGRAMLISTHEADERITEM_SEND, Qt::DisplayRole, tr("Publish"));
mProgTree->setHeaderItem(m_headerItem);
mProgTree->header()->setSectionResizeMode(ENUM_PROGRAMLISTHEADERITEM_CHECK, QHeaderView::Fixed);
mProgTree->header()->setSectionResizeMode(ENUM_PROGRAMLISTHEADERITEM_NAME, QHeaderView::Stretch);
mProgTree->header()->setSectionResizeMode(ENUM_PROGRAMLISTHEADERITEM_RESOLUTION, QHeaderView::Stretch);
mProgTree->header()->setSectionResizeMode(ENUM_PROGRAMLISTHEADERITEM_SIZE, QHeaderView::Stretch);
mProgTree->header()->setSectionResizeMode(ENUM_PROGRAMLISTHEADERITEM_LASTTIME, QHeaderView::Stretch);
mProgTree->header()->setSectionResizeMode(ENUM_PROGRAMLISTHEADERITEM_USB_EXPORT, QHeaderView::Fixed);
mProgTree->header()->setSectionResizeMode(ENUM_PROGRAMLISTHEADERITEM_SEND, QHeaderView::Fixed);
mProgTree->header()->setStretchLastSection(false);
mProgTree->setColumnWidth(ENUM_PROGRAMLISTHEADERITEM_CHECK, 66);
mProgTree->setColumnWidth(ENUM_PROGRAMLISTHEADERITEM_USB_EXPORT, 100);
mProgTree->setColumnWidth(ENUM_PROGRAMLISTHEADERITEM_SEND, 72);
vBox->addWidget(mProgTree);
connect(mProgTree, &LoQTreeWidget::sigCheckStateChanged, this, [this](int f){
switch(f) {
case LoQTreeWidget::CheckNone:
bnEdit->setEnabled(false);
bnDelete->setEnabled(false);
bnExport->setEnabled(false);
bnSend->setEnabled(false);
break;
case LoQTreeWidget::CheckOne:
bnEdit ->setEnabled(true);
bnDelete->setEnabled(true);
bnExport->setEnabled(true);
bnSend ->setEnabled(true);
break;
case LoQTreeWidget::CheckMulti:
bnEdit ->setEnabled(false);
bnDelete->setEnabled(true);
bnExport->setEnabled(true);
bnSend ->setEnabled(true);
break;
default: break;
fdSearch->addAction(search, QLineEdit::LeadingPosition);
fdSearch->setClearButtonEnabled(true);
fdSearch->setStyleSheet("border: 2px solid #aaa;");
connect(fdSearch, &QLineEdit::textChanged, this, [this](const QString &text) {
auto cnt = mProgTree->topLevelItemCount();
for(int i=0; i<cnt; i++) {
auto item = mProgTree->item(i);
item->setHidden(! (text.isEmpty() || item->text("name").contains(text) || item->text("resolution").contains(text)));
}
});
hBox->addWidget(fdSearch);
auto table = new LoQTreeWidget;
table->addCol("#", "", 20);
table->addCol("check", "", 36).margin(6);
table->addCol("name", "", 300, QHeaderView::Stretch);
table->addCol("resolution", "", 150, QHeaderView::Stretch);
table->addCol("size", "", 100, QHeaderView::Stretch);
table->addCol("lasttime", "", 180);
table->addCol("usb", "", 80);
table->addCol("send", "", 80);
table->setDefs()->setHeaderAlignC();
table->addFd();
table->minRowHeight = 36;
table->setSelectionMode(QAbstractItemView::NoSelection);
table->setSortingEnabled(true);
connect(table, &LoQTreeWidget::selChanged, this, [=] {
auto en = table->fdCheckAll->checkState()!=Qt::Unchecked;
bnEdit->setEnabled(en);
bnDelete->setEnabled(en);
bnExport->setEnabled(en);
bnSend->setEnabled(en);
});
vBox->addWidget(mProgTree = table);
QString doc_path = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
if(!doc_path.isEmpty()) {
@ -289,27 +269,20 @@ ProgPanel::ProgPanel(QWidget *parent) : QWidget(parent) {
if(settings.value("ProgramListSortOrder").toInt()==0) mProgTree->sortByColumn(settings.value("ProgramListSortColumn").toInt(),Qt::SortOrder::AscendingOrder);
else mProgTree->sortByColumn(settings.value("ProgramListSortColumn").toInt(),Qt::SortOrder::DescendingOrder);
// ui->wProgramList->setSortingEnabled( false ); //不使能QT的自动排序
// ui->wProgramList->header()->setSortIndicatorShown( true ); // 设置三角标识符可见
// ui->wProgramList->header()->setSectionsClickable( true ); // 设置标题栏单击响应使能
// connect( ui->wProgramList->header(), SIGNAL( sectionClicked(int) ), this, SLOT( OnClickColumn(int) ) );
transUi();
}
void ProgPanel::OnClickColumn(int iColumn) {
if(iColumn!=ENUM_PROGRAMLISTHEADERITEM_CHECK && iColumn!=ENUM_PROGRAMLISTHEADERITEM_SEND) mProgTree->sortByColumn(iColumn, mProgTree->header()->sortIndicatorOrder());
}
void ProgPanel::changeEvent(QEvent *event) {
QWidget::changeEvent(event);
if(event->type() == QEvent::LanguageChange) transUi();
}
void ProgPanel::transUi() {
m_headerItem->setData(ENUM_PROGRAMLISTHEADERITEM_CHECK, 0, "");
m_headerItem->setData(ENUM_PROGRAMLISTHEADERITEM_NAME, 0, tr("Name"));
m_headerItem->setData(ENUM_PROGRAMLISTHEADERITEM_RESOLUTION, 0, tr("Resolution"));
m_headerItem->setData(ENUM_PROGRAMLISTHEADERITEM_SIZE, 0, tr("File Size"));
m_headerItem->setData(ENUM_PROGRAMLISTHEADERITEM_LASTTIME, 0, tr("Last Modify"));
m_headerItem->setData(ENUM_PROGRAMLISTHEADERITEM_USB_EXPORT, 0, tr("USB Update"));
m_headerItem->setData(ENUM_PROGRAMLISTHEADERITEM_SEND, 0, tr("Publish"));
mProgTree->headerItem()->setText("name"**mProgTree, tr("Name"));
mProgTree->headerItem()->setText("resolution"**mProgTree, tr("Resolution"));
mProgTree->headerItem()->setText("size"**mProgTree, tr("File Size"));
mProgTree->headerItem()->setText("lasttime"**mProgTree, tr("Last Modify"));
mProgTree->headerItem()->setText("usb"**mProgTree, tr("USB Update"));
mProgTree->headerItem()->setText("send"**mProgTree, tr("Publish"));
bnNew->setText(tr("New"));
bnEdit->setText(tr("Edit"));
bnDelete->setText(tr("Delete"));
@ -322,7 +295,7 @@ void ProgPanel::transUi() {
void ProgPanel::onEditClicked(bool){
int cnt = mProgTree->topLevelItemCount();
for(int i=0; i<cnt; i++) {
if(mProgTree->topLevelItem(i)->checkState(0) == Qt::Checked) {
if(mProgTree->item(i)->checkState("check") == Qt::Checked) {
auto item = static_cast<ProgItem*>(mProgTree->topLevelItem(i));
auto editor = new ProgEditorWin(item, this);
editor->show();
@ -348,7 +321,7 @@ void ProgPanel::onCreateNewProgramOnOpenEditProgramWidget(QString name, QSize re
if(checkIfNameRepeated(name)) return;
auto item = new ProgItem(mProgsDir, name, res.width(), res.height(), remarks, splitWidths, max, mProgTree);
item->save();//保存pro.json
mProgTree->adjustCheckState();
if(mProgTree->fdCheckAll->checkState()==Qt::Checked) mProgTree->fdCheckAll->setCheckState(Qt::PartiallyChecked);
auto editor = new ProgEditorWin(item, this);
editor->show();
}
@ -356,65 +329,18 @@ void ProgPanel::onDeleteClicked(bool){
auto res = QMessageBox::information(this, tr("Tip Info"), tr("You will delete the selected solution(s),are you sure?"), QMessageBox::Ok, QMessageBox::Cancel);
if(res == QMessageBox::Ok) {
int cnt = mProgTree->topLevelItemCount();
QList<ProgItem*> list;
for(int i=0; i<cnt; i++) {
if(mProgTree->topLevelItem(i)->checkState(0) == Qt::Checked) {
auto item = static_cast<ProgItem*>(mProgTree->topLevelItem(i));
list.push_back(item);
}
}
while(!list.isEmpty()) {
auto item = list.takeFirst();
for(int i=0; i<cnt; i++) if(mProgTree->item(i)->checkState("check") == Qt::Checked) {
auto item = (ProgItem*) mProgTree->topLevelItem(i--);
item->del();
delete item;
}
mProgTree->adjustCheckState();
mProgTree->fdCheckAll->blockSignals(true);
mProgTree->fdCheckAll->setCheckState(Qt::Unchecked);
mProgTree->fdCheckAll->blockSignals(false);
emit mProgTree->selChanged();
}
}
void ProgPanel::FilterProgram(const QString &strtemp){
if (strtemp.isEmpty()) //显示全部
{
for (int i = 0; i< mProgTree->topLevelItemCount(); ++i)
{
QTreeWidgetItem* topItem = mProgTree->topLevelItem(i);
mProgTree->setRowHidden(i,mProgTree->indexFromItem(topItem->parent()),false);
}
}
else
{
QList<QTreeWidgetItem*> resultList = mProgTree->findItems(strtemp, Qt::MatchContains,ENUM_PROGRAMLISTHEADERITEM_NAME); //搜索结果
if (resultList.size() > 0)
{
for (int i = 0; i< mProgTree->topLevelItemCount(); ++i)
{
QTreeWidgetItem* topItem = mProgTree->topLevelItem(i);
if (resultList.contains(topItem))
mProgTree->setRowHidden(i,mProgTree->indexFromItem(topItem->parent()),false); //显示匹配的结果
else
mProgTree->setRowHidden(i,mProgTree->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果
}
}
else {
QList<QTreeWidgetItem*> resultList1 = mProgTree->findItems(strtemp, Qt::MatchContains,ENUM_PROGRAMLISTHEADERITEM_RESOLUTION); //搜索结果
if (resultList1.size() > 0){
for (int i = 0; i< mProgTree->topLevelItemCount(); ++i){
QTreeWidgetItem* topItem = mProgTree->topLevelItem(i);
if (resultList1.contains(topItem)) mProgTree->setRowHidden(i,mProgTree->indexFromItem(topItem->parent()),false); //显示匹配的结果
else mProgTree->setRowHidden(i,mProgTree->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果
}
}
else {
for (int i = 0; i< mProgTree->topLevelItemCount(); ++i){
QTreeWidgetItem* topItem = mProgTree->topLevelItem(i);
mProgTree->setRowHidden(i,mProgTree->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果
}
}
}
}
}
ProgPortDlg::ProgPortDlg(QWidget *parent, QString title) : QDialog(parent) {
#ifdef Q_OS_WIN
setWindowFlag(Qt::WindowContextHelpButtonHint, 0);

View File

@ -13,7 +13,6 @@ class ProgPanel : public QWidget {
public:
explicit ProgPanel(QWidget *parent = nullptr);
QTreeWidgetItem *m_headerItem{0};
LoQTreeWidget *mProgTree{0};
protected:
void changeEvent(QEvent *) override;
@ -24,17 +23,13 @@ public slots:
void onEditClicked(bool f);
void onDeleteClicked(bool f);
void onCreateNewProgramOnOpenEditProgramWidget(QString name, QSize res, QString remarks, QList<int> &, int);
void FilterProgram(const QString &strtemp);
private slots:
void OnClickColumn(int iColumn);
private:
QString mProgsDir;
QList<ProgItem *> m_pwPorgramItemList;
QPushButton *bnNew = nullptr;
QPushButton *bnEdit = nullptr;
QPushButton *bnDelete = nullptr;
QPushButton *bnNew;
QPushButton *bnEdit;
QPushButton *bnDelete;
QPushButton *bnImport, *bnExport;
QPushButton *bnSend, *btnPlay;
};

View File

@ -1,85 +0,0 @@
#include "progcreatedlg.h"
#include "gutil/qgui.h"
#include "globaldefine.h"
#include <QLabel>
#include <QPushButton>
#include <QDialogButtonBox>
ProgCreateDlg::ProgCreateDlg(QString name, int width, int height, QString remarks, QString widths, QWidget *parent) : QDialog(parent) {
#ifdef Q_OS_WIN
setWindowFlag(Qt::WindowContextHelpButtonHint, 0);
#endif
setWindowTitle(tr("Solution Information"));
auto vBox = new VBox(this);
auto hBox = new HBox(vBox);
auto label = new QLabel(tr("Solution Name"));
label->setMinimumWidth(90);
label->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
hBox->addWidget(label);
hBox->addSpacing(6);
fdName = new QLineEdit;
if(name.isEmpty()) name = QDateTime::currentDateTime().toString("yyyyMMddhhmmsszzz");
else fdName->setDisabled(true);
fdName->setText(name);
hBox->addWidget(fdName);
hBox = new HBox(vBox);
hBox->setSpacing(12);
label = new QLabel(tr("Resolution"));
label->setMinimumWidth(90);
label->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
hBox->addWidget(label);
hBox->addSpacing(6);
auto label_4 = new QLabel(tr("Width"));
hBox->addWidget(label_4);
fdWidth = new QSpinBox;
fdWidth->setMaximum(99999);
fdWidth->setValue(width);
hBox->addWidget(fdWidth);
auto label_5 = new QLabel(tr("Height"));
hBox->addWidget(label_5);
fdHeight = new QSpinBox;
fdHeight->setMaximum(99999);
fdHeight->setValue(height);
hBox->addWidget(fdHeight);
hBox->addStretch();
hBox = new HBox(vBox);
label = new QLabel(tr("Remarks"));
label->setMinimumWidth(90);
label->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
hBox->addWidget(label);
hBox->addSpacing(6);
fdRemark = new QTextEdit(remarks);
fdRemark->setFixedSize(300, 80);
hBox->addWidget(fdRemark);
hBox = new HBox(vBox);
auto lbSplitWidth = new QLabel(tr("每段打折宽度 (用空格分隔)"));
hBox->addWidget(lbSplitWidth);
fdSplitWidths = new QLineEdit(widths);
fdSplitWidths->setPlaceholderText("256 256 256 ...");
hBox->addWidget(fdSplitWidths);
if(! gWidthSplit) {
lbSplitWidth->setVisible(false);
fdSplitWidths->setVisible(false);
}
vBox->addSpacing(6);
auto btnBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(btnBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
connect(btnBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
vBox->addWidget(btnBox);
}

View File

@ -1,20 +0,0 @@
#ifndef PROGCREATEDLG_H
#define PROGCREATEDLG_H
#include <QDialog>
#include <QLineEdit>
#include <QTextEdit>
#include <QSpinBox>
class ProgCreateDlg : public QDialog {
Q_OBJECT
public:
ProgCreateDlg(QString name, int width, int height, QString remarks, QString, QWidget *parent = nullptr);
QLineEdit *fdName;
QSpinBox *fdWidth;
QSpinBox *fdHeight;
QTextEdit *fdRemark;
QLineEdit *fdSplitWidths;
};
#endif // PROGCREATEDLG_H

View File

@ -5,7 +5,7 @@
#include "player/playwin.h"
#include "tools.h"
#include "globaldefine.h"
#include "base/waitingdlg.h"
#include "gutil/qwaitingdlg.h"
#include "program/ebase.h"
#include "program/etext.h"
#include "program/ephoto.h"
@ -19,7 +19,6 @@
#include "program/emultiwin.h"
#include "program/gentmpthread.h"
#include "program/sendprogramdialog.h"
#include "progcreatedlg.h"
#include <QBoxLayout>
#include <QCloseEvent>
#include <QGraphicsDropShadowEffect>
@ -222,7 +221,7 @@ ProgEditorWin::ProgEditorWin(ProgItem *progItem, QWidget *parent) : QWidget(pare
QString value = file.readAll();
file.close();
QJsonParseError jsErr;
QJsonObject prog = QJsonDocument::fromJson(value.toUtf8(), &jsErr).object();
auto prog = QJsonDocument::fromJson(value.toUtf8(), &jsErr).object();
if(jsErr.error) return;
int www = mProgItem->mWidth, hhh = mProgItem->mHeight;
if(mProgItem->mMaxWidth) {
@ -371,9 +370,10 @@ ProgEditorWin::ProgEditorWin(ProgItem *progItem, QWidget *parent) : QWidget(pare
if(listPage->count() > 0) {
auto cur = (PageListItem*) listPage->currentItem();
cur->updateJson();
auto item = new PageListItem(cur->mAttr, cur->mPageDir);
JObj attr;
for(auto &pair : cur->mAttr) attr.insert(pair.first, pair.second);
auto item = new PageListItem(attr, cur->mPageDir);
item->mAttr["name"] = QDateTime::currentDateTime().toString("yyyyMMddhhmmsszzz");
item->mAttr["order"] = listPage->count();
listPage->addItem(item);
listPage->setItemWidget(item, item->itemWgt());
listPage->setCurrentItem(item);
@ -391,12 +391,7 @@ ProgEditorWin::ProgEditorWin(ProgItem *progItem, QWidget *parent) : QWidget(pare
if(res == QMessageBox::Ok) {
delete item;
if(listPage->count() > 0) listPage->setCurrentRow(0);
int cnt = listPage->count();
for(int i=0; i<cnt; i++) {
auto item = (PageListItem*)listPage->item(i);
item->mAttr["order"] = i;
item->fdIdx->setNum(i+1);
}
for(int i=0; i<listPage->count(); i++) ((PageListItem*)listPage->item(i))->fdIdx->setNum(i+1);
}
}
});
@ -412,12 +407,7 @@ ProgEditorWin::ProgEditorWin(ProgItem *progItem, QWidget *parent) : QWidget(pare
listPage->setItemWidget(item, item->itemWgt());
listPage->setCurrentRow(index-1);
}
int cnt = listPage->count();
for(int i=0; i<cnt; i++) {
auto item = (PageListItem*)listPage->item(i);
item->mAttr["order"] = i;
item->fdIdx->setNum(i+1);
}
for(int i=0; i<listPage->count(); i++) ((PageListItem*)listPage->item(i))->fdIdx->setNum(i+1);
}
});
toolBar->addAction(actMoveUp);
@ -432,12 +422,7 @@ ProgEditorWin::ProgEditorWin(ProgItem *progItem, QWidget *parent) : QWidget(pare
listPage->setItemWidget(item, item->itemWgt());
listPage->setCurrentRow(index+1);
}
int cnt = listPage->count();
for(int i=0; i<cnt; i++) {
auto item = (PageListItem*)listPage->item(i);
item->mAttr["order"] = i;
item->fdIdx->setNum(i+1);
}
for(int i=0; i<listPage->count(); i++) ((PageListItem*)listPage->item(i))->fdIdx->setNum(i+1);
}
});
toolBar->addAction(actMoveDown);
@ -516,8 +501,8 @@ ProgEditorWin::ProgEditorWin(ProgItem *progItem, QWidget *parent) : QWidget(pare
QDir progQDir(mProgItem->mProgDir);
if(progQDir.exists()) {
QStringList pageNames = progQDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks);
foreach(QString pageName, pageNames) {
auto pageNames = progQDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks);
for(QString &pageName : pageNames) {
if(pageName.endsWith(PAGEDEL_SUFFIX)) {
QDir(mProgItem->mProgDir + "/" + pageName).removeRecursively();
continue;
@ -525,36 +510,40 @@ ProgEditorWin::ProgEditorWin(ProgItem *progItem, QWidget *parent) : QWidget(pare
QFile pageFile(mProgItem->mProgDir + "/" + pageName + "/page.json");
if(pageFile.exists()) {
pageFile.open(QIODevice::ReadOnly);
mPageJsons.push_back(QJsonDocument::fromJson(pageFile.readAll()).object());
mPageJsons.emplace_back(JFrom(pageFile.readAll()).toObj());
pageFile.close();
} else QDir(mProgItem->mProgDir + "/" + pageName).removeRecursively();
}
}
if(mPageJsons.isEmpty()) onAddPage();
else {
std::sort(mPageJsons.begin(), mPageJsons.end(), [](const QJsonObject &a, const QJsonObject &b) {
std::sort(mPageJsons.begin(), mPageJsons.end(), [](const JObj &a, const JObj &b) {
return a["order"].toInt() < b["order"].toInt();
});
foreach(QJsonObject pageJson, mPageJsons) {
}
if(mPageJsons.empty()) onAddPage();
else for(JObj &pageJson : mPageJsons) {
auto pageDir = mProgItem->mProgDir+"/"+pageJson["name"].toString();
QDir dir(pageDir);
if(! dir.exists() && ! dir.mkdir(pageDir)) continue;
auto item = new PageListItem(pageJson, pageDir);
JObj attr;
for(auto &pair : pageJson) attr.insert(pair.first, pair.second);
auto item = new PageListItem(attr, pageDir);
listPage->addItem(item);
listPage->setItemWidget(item, item->itemWgt());
auto cnt = listPage->count();
if(cnt==5) for(int i=0; i<4; i++) ((PageListItem*)listPage->item(i))->fdIdx->setNum(i+1);
}
}
listPage->setCurrentRow(0);
}
bool ProgEditorWin::isProgChanged() {
if(mPageJsons.size() != listPage->count()) return true;
for(int i=0; i<mPageJsons.count(); i++) {
auto page = static_cast<PageListItem*>(listPage->item(i));
for(int i=0; i<(int)mPageJsons.size(); i++) {
auto page = (PageListItem*) listPage->item(i);
if(page->mAttrWgt==0) continue;
page->updateJson();
if(page->mAttr != mPageJsons[i]) return true;
if(page->mAttr != mPageJsons[i]) {
qDebug()<<page->mAttr;
qDebug()<<mPageJsons[i];
return true;
}
}
return false;
}
@ -585,18 +574,21 @@ bool ProgEditorWin::save() {
QMessageBox::critical(this, tr("Error"), tr("Create Dir failed")+": "+mProgItem->mProgDir);
return 0;
}
QStringList pageNames = progDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks);
foreach(QString pageName, pageNames) {
if(! progDir.rename(pageName, pageName + PAGEDEL_SUFFIX)) {
auto pageNames = progDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks);
for(QString &pageName : pageNames) if(! progDir.rename(pageName, pageName + PAGEDEL_SUFFIX)) {
rtn = 0;
QMessageBox::critical(this, tr("Error"), tr("Rename fail when saving")+" "+pageName);
}
}
//保存每个页面的元素和页面属性到page.json文档
mPageJsons.clear();
for(int i=0; i<cnt; i++) {
auto page = static_cast<PageListItem*>(listPage->item(i));
if(page->saveFiles()) mPageJsons.append(page->mAttr);
auto page = (PageListItem*) listPage->item(i);
page->mAttr["order"] = i;
if(page->saveFiles()) {
JObj json;
for(auto &pair : page->mAttr) json.insert(pair.first, pair.second);
mPageJsons.emplace_back(json);
}
}
pageNames = progDir.entryList(QStringList("*" PAGEDEL_SUFFIX));
foreach(QString pageName, pageNames) {
@ -624,43 +616,102 @@ void ProgEditorWin::onSave() {
mProgItem->onSetProgram();
}
void ProgEditorWin::UdpSendJson(QJsonObject json) {
QUdpSocket *tempUdpSocket= new QUdpSocket(this);
if(!tempUdpSocket->bind(QHostAddress("127.0.0.1"))) {
QMessageBox::critical(this, tr("Warning"), "udp bind failed");
return;
}
QJsonDocument resultJson;
resultJson.setObject(json);
QByteArray byteArray=resultJson.toJson();
QHostAddress localAddress("127.0.0.1");
int iSendLength=tempUdpSocket->writeDatagram(byteArray.data(),byteArray.size(),localAddress,2000);
if(iSendLength != byteArray.size()) {
char *aa=byteArray.data();
tempUdpSocket->writeDatagram(&aa[iSendLength],byteArray.size()-iSendLength,localAddress,2000);
}
delete tempUdpSocket;
}
void ProgEditorWin::onAddPage() {
QDateTime now = QDateTime::currentDateTime();
auto name = now.toString("yyyyMMddhhmmsszzz");
auto pageDir = mProgItem->mProgDir+"/"+name;
QDir dir(pageDir);
if(! dir.exists() && ! dir.mkpath(pageDir)) return;
QJsonObject attr;
JObj attr;
attr["name"] = name;
attr["order"] = listPage->count();
attr["repeat"] = 1;
attr["validDate"] = QJsonObject{
attr["validDate"] = JObj{
{"isValid", false},
{"start", now.date().toString("yyyy-MM-dd")},
{"end", now.addSecs(2678400).date().toString("yyyy-MM-dd")}
};
attr["plans"] = QJsonArray();
auto item = new PageListItem(attr, pageDir);
listPage->addItem(item);
listPage->setItemWidget(item, item->itemWgt());
listPage->setCurrentItem(item);
if(listPage->count()==5) for(int i=0; i<4; i++) ((PageListItem*)listPage->item(i))->fdIdx->setNum(i+1);
}
ProgCreateDlg::ProgCreateDlg(QString name, int width, int height, QString remarks, QString widths, QWidget *parent) : QDialog(parent) {
#ifdef Q_OS_WIN
setWindowFlag(Qt::WindowContextHelpButtonHint, 0);
#endif
setWindowTitle(tr("Solution Information"));
auto vBox = new VBox(this);
auto hBox = new HBox(vBox);
auto label = new QLabel(tr("Solution Name"));
label->setMinimumWidth(90);
label->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
hBox->addWidget(label);
hBox->addSpacing(6);
fdName = new QLineEdit;
if(name.isEmpty()) name = QDateTime::currentDateTime().toString("yyyyMMddhhmmsszzz");
else fdName->setDisabled(true);
fdName->setText(name);
hBox->addWidget(fdName);
hBox = new HBox(vBox);
hBox->setSpacing(12);
label = new QLabel(tr("Resolution"));
label->setMinimumWidth(90);
label->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
hBox->addWidget(label);
hBox->addSpacing(6);
auto label_4 = new QLabel(tr("Width"));
hBox->addWidget(label_4);
fdWidth = new QSpinBox;
fdWidth->setMaximum(99999);
fdWidth->setValue(width);
hBox->addWidget(fdWidth);
auto label_5 = new QLabel(tr("Height"));
hBox->addWidget(label_5);
fdHeight = new QSpinBox;
fdHeight->setMaximum(99999);
fdHeight->setValue(height);
hBox->addWidget(fdHeight);
hBox->addStretch();
hBox = new HBox(vBox);
label = new QLabel(tr("Remarks"));
label->setMinimumWidth(90);
label->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
hBox->addWidget(label);
hBox->addSpacing(6);
fdRemark = new QTextEdit(remarks);
fdRemark->setFixedSize(300, 80);
hBox->addWidget(fdRemark);
hBox = new HBox(vBox);
auto lbSplitWidth = new QLabel(tr("每段打折宽度 (用空格分隔)"));
hBox->addWidget(lbSplitWidth);
fdSplitWidths = new QLineEdit(widths);
fdSplitWidths->setPlaceholderText("256 256 256 ...");
hBox->addWidget(fdSplitWidths);
if(! gWidthSplit) {
lbSplitWidth->setVisible(false);
fdSplitWidths->setVisible(false);
}
vBox->addSpacing(6);
auto btnBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(btnBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
connect(btnBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
vBox->addWidget(btnBox);
}

View File

@ -1,8 +1,11 @@
#ifndef PROGEDITORWIN_H
#define PROGEDITORWIN_H
#include "program/pageeditor.h"
#include <QDialog>
#include <QSpinBox>
#include <QTextEdit>
#include <QListWidget>
#include <QJsonObject>
#include "gutil/qjson.h"
class ProgPanel;
class ProgItem;
@ -18,16 +21,26 @@ protected:
private:
bool isProgChanged();
bool save();
void UdpSendJson(QJsonObject json);
QListWidget *listPage;
PageListItem *mPageItem = nullptr;
PageListItem *mPageItem = 0;
PageEditor *mPageEditor;
QTabWidget *mTabsAttr;
QList<QJsonObject> mPageJsons;
std::vector<JObj> mPageJsons;
ProgItem *mProgItem;
int mNewEleX = 0;
int mNewEleY = 0;
};
class ProgCreateDlg : public QDialog {
Q_OBJECT
public:
ProgCreateDlg(QString name, int width, int height, QString remarks, QString, QWidget *parent = nullptr);
QLineEdit *fdName;
QSpinBox *fdWidth;
QSpinBox *fdHeight;
QTextEdit *fdRemark;
QLineEdit *fdSplitWidths;
};
#endif // PROGEDITORWIN_H

View File

@ -3,25 +3,25 @@
#include "QtWidgets/qlineedit.h"
#include "gutil/qcore.h"
#include "gutil/qgui.h"
#include "base/waitingdlg.h"
#include "progeditorwin.h"
#include "base/waitingdlg.h"
#include "gutil/qwaitingdlg.h"
#include "gutil/qwaitingdlg.h"
#include "gentmpthread.h"
#include <globaldefine.h>
#include "sendprogramdialog.h"
#include "program/progeditorwin.h"
#include <QJsonArray>
#include <QMessageBox>
#include <QStorageInfo>
ProgItem::ProgItem(const QString &progsDir, const QString &name, int w, int h, const QString &remarks, QList<int> &splitWidths, int maxWidth, LoQTreeWidget *tree) : QTreeWidgetItem(UserType),
mName(name), mWidth(w), mHeight(h), mRemark(remarks), mSplitWidths(splitWidths), mMaxWidth(maxWidth), mProgsDir(progsDir), mTree(tree) {
ProgItem::ProgItem(const QString &progsDir, const QString &name, int w, int h, const QString &remarks, QList<int> &splitWidths, int maxWidth, LoQTreeWidget *tree) : TreeWidgetItem(tree),
mName(name), mWidth(w), mHeight(h), mRemark(remarks), mSplitWidths(splitWidths), mMaxWidth(maxWidth), mProgsDir(progsDir) {
m_last = QDateTime::currentDateTime();
mProgDir = progsDir + "/" + mName;
m_orgName = mName;
init();
}
ProgItem::ProgItem(const QString &progsDir, const QJsonObject &json, LoQTreeWidget *tree) : QTreeWidgetItem(UserType), mProgsDir(progsDir), mTree(tree) {
ProgItem::ProgItem(const QString &progsDir, const QJsonObject &json, LoQTreeWidget *tree) : TreeWidgetItem(tree), mProgsDir(progsDir) {
mName = json["name"].toString();
mWidth = json["resolution"]["w"].toInt();
mHeight = json["resolution"]["h"].toInt();
@ -40,41 +40,39 @@ ProgItem::ProgItem(const QString &progsDir, const QJsonObject &json, LoQTreeWidg
}
void ProgItem::init() {
setFlags(flags() & ~Qt::ItemIsUserCheckable);
setCheckState("check", Qt::Unchecked);
auto ft = font(0);
ft.setPixelSize(14);
for(int i=1; i<ENUM_PROGRAMLISTHEADERITEM_USB_EXPORT; i++) setFont(i, ft);
setForeground(ENUM_PROGRAMLISTHEADERITEM_NAME, Qt::transparent);
setText(ENUM_PROGRAMLISTHEADERITEM_NAME, mName);
setData(ENUM_PROGRAMLISTHEADERITEM_RESOLUTION, 0, QString("%1 x %2").arg(mWidth).arg(mHeight));
if(m_fsize<=0) setData(ENUM_PROGRAMLISTHEADERITEM_SIZE, 0, byteSizeStr((qint64)100));
else setData(ENUM_PROGRAMLISTHEADERITEM_SIZE, 0, byteSizeStr(m_fsize));
setData(ENUM_PROGRAMLISTHEADERITEM_LASTTIME, 0, m_last.toString("yyyy-MM-dd hh:mm:ss"));
setTextAlignment(ENUM_PROGRAMLISTHEADERITEM_NAME, Qt::AlignLeft | Qt::AlignVCenter);
for(int i=1; i<ENUM_PROGRAMLISTHEADERITEM_END; i++) setTextAlignment(i, Qt::AlignCenter);
setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
setCheckState(0, Qt::Unchecked);
mTree->insertTopLevelItem(0,this);
for(int i=1; i<treeWidget()->columnCount()-2; i++) {
setFont(i, ft);
setTextAlignment(i, Qt::AlignCenter);
}
setForeground("name"**treeWidget(), Qt::transparent);
setText("name", mName);
setText("resolution", QString("%1 x %2").arg(mWidth).arg(mHeight));
setText("size", m_fsize<=0 ? "100B" : byteSizeStr(m_fsize));
setText("lasttime", m_last.toString("yyyy-MM-dd hh:mm:ss"));
m_bnName = new QPushButton(mName);
m_bnName->setFont(ft);
m_bnName->setCursor(QCursor(Qt::PointingHandCursor));
m_bnName->setStyleSheet(R"delimiter(
QPushButton{border-radius: 4px;}
QPushButton:hover {
background-color: #cccccc;
background-color: #ccc;
text-decoration: underline;
}
)delimiter");
m_bnName->setCursor(QCursor(Qt::PointingHandCursor));
mTree->setItemWidget(this, ENUM_PROGRAMLISTHEADERITEM_NAME, m_bnName);
QObject::connect(m_bnName, &QPushButton::clicked, mTree, [this] {
auto editor = new ProgEditorWin(this, mTree->parentWidget());
QObject::connect(m_bnName, &QPushButton::clicked, treeWidget(), [=] {
auto editor = new ProgEditorWin(this, treeWidget()->parentWidget());
editor->show();
});
m_bnExport = new QPushButton();
m_bnExport->setCursor(QCursor(Qt::PointingHandCursor));
m_bnExport->setStyleSheet(R"rrr(
setCellWidget("name", m_bnName);
auto btnExport = new QPushButton;
btnExport->setCursor(QCursor(Qt::PointingHandCursor));
btnExport->setStyleSheet(R"rrr(
QPushButton {
border-radius: 4px;
image: url(:/res/program/bnExport_u.png);
@ -82,10 +80,8 @@ QPushButton {
QPushButton:pressed{image: url(:/res/program/bnExport_s.png);}
QPushButton:hover{background-color: #cccccc;}
)rrr");
mTree->setItemWidget(this, ENUM_PROGRAMLISTHEADERITEM_USB_EXPORT, m_bnExport);
QObject::connect(m_bnExport, &QPushButton::clicked, mTree, [this] {
QDialog dlg(mTree);
QObject::connect(btnExport, &QPushButton::clicked, treeWidget(), [=] {
QDialog dlg(treeWidget());
dlg.setWindowTitle(QObject::tr("USB Update Program"));
#ifdef Q_OS_WIN
dlg.setWindowFlag(Qt::WindowContextHelpButtonHint, 0);
@ -132,14 +128,20 @@ QPushButton:hover{background-color: #cccccc;}
fdDrives->clear();
auto volumes = QStorageInfo::mountedVolumes();
foreach(auto volume, volumes) fdDrives->addItem(volume.displayName(), volume.rootPath());
foreach(auto volume, volumes) {
auto text = volume.displayName();
auto rootPath = volume.rootPath();
if(text!=rootPath) text += " ("+rootPath+")";
fdDrives->addItem(text, rootPath);
}
dlg.exec();
});
setCellWidget("usb", btnExport);
m_bnSend = new QPushButton();
m_bnSend->setCursor(QCursor(Qt::PointingHandCursor));
m_bnSend->setStyleSheet(R"rrr(
auto btnSend = new QPushButton;
btnSend->setCursor(QCursor(Qt::PointingHandCursor));
btnSend->setStyleSheet(R"rrr(
QPushButton{
border-radius: 4px;
image: url(:/res/program/bnSend_u.png);
@ -147,20 +149,19 @@ QPushButton{
QPushButton:pressed{image: url(:/res/program/bnSend_s.png);}
QPushButton:hover{background-color: #cccccc;}
)rrr");
mTree->setItemWidget(this, ENUM_PROGRAMLISTHEADERITEM_SEND, m_bnSend);
QObject::connect(m_bnSend, &QPushButton::clicked, mTree, [this] {
auto waitingDlg = new WaitingDlg(mTree, QObject::tr("Convertering")+" ...");
QObject::connect(btnSend, &QPushButton::clicked, treeWidget(), [this] {
auto waitingDlg = new WaitingDlg(treeWidget(), QObject::tr("Convertering")+" ...");
auto gen = new GenTmpThread(this, mName, "", "");
QObject::connect(gen, &GenTmpThread::onErr, mTree, [=](QString err) {
QMessageBox::warning(mTree, "GenTmpThread Error", err);
QObject::connect(gen, &GenTmpThread::onErr, treeWidget(), [=](QString err) {
QMessageBox::warning(treeWidget(), "GenTmpThread Error", err);
});
QObject::connect(gen, &QThread::finished, waitingDlg, &WaitingDlg::close);
gen->start();
waitingDlg->exec();
SendProgramDialog dlg(mName, mTree);
SendProgramDialog dlg(mName, treeWidget()->window());
dlg.exec();
});
setCellWidget("send", btnSend);
}
void ProgItem::save() {
@ -177,7 +178,6 @@ void ProgItem::save() {
dRoot = QDir(mProgDir);
if(dRoot.exists()) {
QJsonObject obj;
QJsonObject oSize;
obj["name"] = mName;
obj["resolution"] = QJsonObject{{"w", mWidth}, {"h", mHeight}};
obj["remarks"] = mRemark;
@ -186,10 +186,9 @@ void ProgItem::save() {
obj["splitWidths"] = splitWidths;
obj["file_size"] = m_fsize;
obj["last_edit"] = m_last.toString("yyyy-MM-dd hh:mm:ss");
QJsonDocument json(obj);
QFile f(mProgDir + "/pro.json");
f.open(QIODevice::WriteOnly);
f.write(json.toJson());
f.write(QJsonDocument(obj).toJson());
f.close();
}
}
@ -201,8 +200,8 @@ void ProgItem::del() {
//设置列表项的值
void ProgItem::onSetProgram() {
m_bnName->setText(mName);
setData(ENUM_PROGRAMLISTHEADERITEM_RESOLUTION, 0, QString("%1 x %2").arg(mWidth).arg(mHeight));
setData(ENUM_PROGRAMLISTHEADERITEM_SIZE, 0, byteSizeStr(m_fsize<=0 ? 100 : m_fsize));
setData(ENUM_PROGRAMLISTHEADERITEM_LASTTIME, 0, m_last.toString("yyyy-MM-dd hh:mm:ss"));
setText("resolution", QString("%1 x %2").arg(mWidth).arg(mHeight));
setText("size", byteSizeStr(m_fsize<=0 ? 100 : m_fsize));
setText("lasttime", m_last.toString("yyyy-MM-dd hh:mm:ss"));
save();
}

View File

@ -1,23 +1,19 @@
#ifndef PROGITEM_H
#define PROGITEM_H
#include <QTreeWidget>
#include <QTreeWidgetItem>
#include <QDir>
#include <QDateTime>
#include "base/loqtreewidget.h"
#include <QJsonObject>
#include <QJsonDocument>
#include <QPushButton>
#include <base/loqtreewidget.h>
class ProgPanel;
class ProgItem : public QTreeWidgetItem {
class ProgItem : public TreeWidgetItem {
public:
explicit ProgItem(const QString &progsDir, const QString &name, int w, int h, const QString & remarks, QList<int> &splitWidths, int, LoQTreeWidget *parent);
explicit ProgItem(const QString &progsDir, const QJsonObject &json, LoQTreeWidget *parent);
void save();
void del();
void onSetProgram();
QString mName;
int mWidth;
@ -30,25 +26,9 @@ public:
qint64 m_fsize{0};
QDateTime m_last;
QPushButton *m_bnName;
LoQTreeWidget *mTree;
void onSetProgram();
private:
void init();
QPushButton *m_bnExport;
QPushButton *m_bnSend;
QString m_orgName;
};
enum ENUM_PROGRAMLISTHEADERITEM {
ENUM_PROGRAMLISTHEADERITEM_CHECK=0,
ENUM_PROGRAMLISTHEADERITEM_NAME,
ENUM_PROGRAMLISTHEADERITEM_RESOLUTION,
ENUM_PROGRAMLISTHEADERITEM_SIZE,
ENUM_PROGRAMLISTHEADERITEM_LASTTIME,
ENUM_PROGRAMLISTHEADERITEM_USB_EXPORT,
ENUM_PROGRAMLISTHEADERITEM_SEND,
ENUM_PROGRAMLISTHEADERITEM_END
};
#endif // PROGITEM_H

View File

@ -4,7 +4,7 @@
#include "deviceitem.h"
#include "devicepanel.h"
#include "gutil/qnetwork.h"
#include "base/waitingdlg.h"
#include "gutil/qwaitingdlg.h"
#include <QAction>
#include <QLineEdit>
#include <QHeaderView>
@ -18,176 +18,102 @@ SendProgramDialog::SendProgramDialog(QString progName, QWidget *parent) : QDialo
setWindowFlag(Qt::WindowMaximizeButtonHint);
#endif
setWindowTitle(tr("Publish")+" "+mProgName);
resize(1024, 700);
resize(1024, 720);
auto vBox = new VBox(this);
vBox->setContentsMargins(6,0,6,9);
vBox->setContentsMargins(6,0,6,0);
auto hBox = new HBox(vBox);
label = new QLabel(tr("success info"));
hBox->addWidget(label);
hBox->addSpacing(20);
hBox->addStretch();
auto btnRefresh = new QPushButton(tr("Refresh"));
btnRefresh->setProperty("ssType", "progManageTool");
connect(btnRefresh, &QPushButton::clicked, this, &SendProgramDialog::refresh);
hBox->addWidget(btnRefresh);
auto txtSearch = new QLineEdit;
txtSearch->setFixedWidth(150);
txtSearch->setClearButtonEnabled(true);
txtSearch->setStyleSheet("QLineEdit{border: 2px solid #aaa; padding: 2px;}");
txtSearch->addAction(new QAction(QIcon(":/res/program/bnSearch.png"), QString()), QLineEdit::LeadingPosition);
connect(txtSearch, &QLineEdit::textEdited, this, [=](const QString &text) {
auto cnt = table->rowCount();
for(int rr=0; rr<cnt; rr++) table->setRowHidden(rr, !(text.isEmpty() || table->text(rr, "id").contains(text) || table->text(rr, "ip").contains(text) || table->text(rr, "alias").contains(text) || table->text(rr, "size").contains(text)));
});
hBox->addWidget(txtSearch);
table = new Table{
{"id", "ID", 130},
{"online", tr("Online"), 40},
{"ip", "IP", 100},
{"size", tr("Screen Size"), 80},
{"alias", tr("Alias"), 120},
{"encrypt", tr("Security"), 40},
{"progress", tr("Progress"), 120},
{"remarks", tr("Remarks"), QHeaderView::Stretch}
};
table->setDefs();
auto colId = table->mFieldMap["id"];
table->sortItems(colId);
table->setSelectionMode(Table::NoSelection);
table->setStyle(new ViewItemStyle);
vBox->addWidget(table);
fdCheckAll = new QCheckBox(table);
connect(fdCheckAll, &QCheckBox::stateChanged, this, [=](int state) {
if(state==Qt::PartiallyChecked) return;
int cnt = table->rowCount();
for(int rr=0; rr<cnt; rr++) if(! table->isRowHidden(rr)) table->itemValid(rr, colId)->setCheckState((Qt::CheckState) state);
});
connect(table, &Table::updGeos, this, [=] {
fdCheckAll->move(table->verticalHeader()->size().width() + 8, 2);
});
auto cellClicked = [=](int row, int column) {
if(column!=colId) return;
auto item = table->itemValid(row, colId);
auto state = item->checkState()==Qt::Checked ? Qt::Unchecked : Qt::Checked;
item->setCheckState(state);
int cnt = table->rowCount();
fdCheckAll->blockSignals(true);
for(int rr=0; rr<cnt; rr++) if(! table->isRowHidden(rr) && table->itemValid(rr, colId)->checkState()!=state) {
fdCheckAll->setCheckState(Qt::PartiallyChecked);
goto end;
}
fdCheckAll->setCheckState(state);
end:fdCheckAll->blockSignals(false);
};
connect(table, &Table::cellClicked, table, cellClicked);
connect(table, &Table::cellEntered, table, [=](int row, int column) {
if(column!=colId) return;
if((QApplication::mouseButtons() & Qt::LeftButton) == 0) return;
cellClicked(row, column);
});
auto btnBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
btnBox->button(QDialogButtonBox::Ok)->setText(tr("Publish"));
connect(btnBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
connect(btnBox, &QDialogButtonBox::accepted, this, [=] {
auto btnPublish = new QPushButton(tr("Publish"));
connect(btnPublish, &QPushButton::clicked, this, [=] {
if(mWaitCnt > 0) return;
int cnt = table->rowCount();
int sentCnt{0};
for(int rr=0; rr<cnt; rr++) if(! table->isRowHidden(rr)) {
auto fdId = table->itemValid(rr, colId);
if(fdId->checkState()!=Qt::Checked) continue;
if(fdId->data(isSending).toBool()) continue;
auto btnUnlock = (QPushButton*) table->cellWidget(rr, "encrypt");
auto fdRemarks = table->itemValid(rr, "remarks");
if(btnUnlock && btnUnlock->property("isLocked").toBool()) {
fdRemarks->setText(tr("This screen is encrypted"));
fdRemarks->setForeground(Qt::red);
int cnt = table->topLevelItemCount();
int sentCnt = 0;
SendProgramItem *item;
auto remarks = "remarks"**table;
for(int rr=0; rr<cnt; rr++) if(! (item = (SendProgramItem*) table->topLevelItem(rr))->isHidden() && item->checkState("id") == Qt::Checked && ! item->isSending) {
if(item->btnUnlock && item->isLocked) {
item->setResult(tr("This screen is encrypted"), Qt::red);
continue;
}
auto fdProgress = (QProgressBar*) table->cellWidget(rr, "progress");
fdProgress->setValue(0);
if(sentCnt>=5) {
fdRemarks->setText(" "+tr("Waiting")+" ...");
fdRemarks->setForeground(Qt::black);
item->fdProgress->setValue(0);
if(sentCnt>=gSendBatch) {
item->setText(remarks, " "+tr("Waiting")+" ...");
item->setForeground(remarks, Qt::black);
mWaitCnt++;
continue;
}
fdId->setData(isSending, true);
fdRemarks->setText("");
auto sendProg = new SendProgThread(programsDir()+"/"+mProgName+"_tmp", table->text(rr, "ip"), 3333);
connect(sendProg, &SendProgThread::emErr, fdProgress, [=](QString strTip) {
fdId->setData(isSending, false);
item->isSending = true;
item->setText(remarks, "");
auto sendProg = new SendProgThread(programsDir()+"/"+mProgName+"_tmp", item->text("ip"), 3333);
connect(sendProg, &SendProgThread::emErr, item->fdProgress, [=](QString strTip) {
item->isSending = false;
if(strTip=="OK") {
fdId->setCheckState(Qt::Unchecked);
fdRemarks->setText("OK");
fdRemarks->setForeground(Qt::darkGreen);
item->setCheckState("id", Qt::Unchecked);
item->setText(remarks, "OK");
item->setForeground(remarks, Qt::darkGreen);
} else {
fdRemarks->setText(strTip);
fdRemarks->setForeground(Qt::red);
item->setText(remarks, strTip);
item->setForeground(remarks, Qt::red);
}
sendNext();
});
connect(sendProg, &SendProgThread::emProgress, fdProgress, &QProgressBar::setValue);
connect(sendProg, &SendProgThread::emProgress, item->fdProgress, &QProgressBar::setValue);
connect(this, &SendProgramDialog::stopAllThd, sendProg, &SendProgThread::stop);
sendProg->start();
sentCnt++;
}
});
vBox->addWidget(btnBox);
hBox->addWidget(btnPublish);
refresh();
hBox->addStretch();
auto timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &SendProgramDialog::refresh);
timer->start(60000);
}
void SendProgramDialog::addRow(LedCard card) {
int cnt = table->rowCount();
for(int rr=0; rr<cnt; rr++) if(table->text(rr, "id") == card.id) {
updRow(rr, card);
return;
}
table->setSortingEnabled(false);
table->setRowCount(cnt+1);
auto item = table->setText(cnt, "id", card.id);
item->setCheckState(Qt::Unchecked);
auto btnRefresh = new QPushButton(tr("Refresh"));
connect(btnRefresh, &QPushButton::clicked, this, [=] {
int cnt = gDevicePanel->mDeviceTable->topLevelItemCount();
for(int i=0; i<cnt; i++) {
auto card = ((DeviceItem*)gDevicePanel->mDeviceTable->topLevelItem(i))->mCard;
int cnt = table->topLevelItemCount();
SendProgramItem *item;
for(int rr=0; rr<cnt; rr++) if((item = (SendProgramItem*) table->topLevelItem(rr))->text("id") == card.id) goto end;
item = new SendProgramItem(table);
item->setFlags(item->flags() & ~Qt::ItemIsUserCheckable);
auto fdOnline = new QLabel;
fdOnline->setAlignment(Qt::AlignCenter);
table->setCellWidget(cnt, "online", fdOnline);
auto fdProgress = new QProgressBar;
fdProgress->setAlignment(Qt::AlignCenter);
fdProgress->setStyleSheet("QProgressBar {margin-top: 6px; margin-bottom: 6px;}");
table->setCellWidget(cnt, "progress", fdProgress);
updRow(cnt, card);
table->setSortingEnabled(true);
}
void SendProgramDialog::updRow(int row, LedCard card) {
table->setText(row, "alias", card.alias);
table->setText(row, "ip", card.ip);
table->setText(row, "size", QString("%1 x %2").arg(card.mWidth).arg(card.mHeight))->setTextAlignment(Qt::AlignCenter);
((QLabel*) table->cellWidget(row, "online"))->setPixmap(QPixmap(card.isOnline ? ":/res/O_Online.png" : ":/res/O_Offline.png"));
if(! card.hasPassword) table->setCellWidget(row, "encrypt", 0);
else {
auto btnUnlock = (QPushButton*) table->cellWidget(row, "encrypt");
if(btnUnlock==0) {
btnUnlock = new QPushButton;
btnUnlock->setMaximumHeight(40);
btnUnlock->setProperty("isLocked", card.isLocked);
table->setCellWidget(row, "encrypt", btnUnlock);
connect(btnUnlock, &QPushButton::clicked, btnUnlock, [=] {
if(! btnUnlock->property("isLocked").toBool()) return;
item->setCheckState("id", Qt::Unchecked);
item->setText("id", card.id);
{
item->fdOnline = new QLabel;
item->fdOnline->setScaledContents(true);
item->fdOnline->setFixedSize(24, 24);
auto wgt = new QWidget;
auto hhh = new HBox(wgt);
hhh->setContentsMargins(0,0,0,0);
hhh->addWidget(item->fdOnline);
item->setCellWidget("online", wgt);
}
item->fdProgress = new QProgressBar;
item->fdProgress->setAlignment(Qt::AlignCenter);
item->fdProgress->setStyleSheet("QProgressBar {margin-top: 6px; margin-bottom: 6px;}");
item->setCellWidget("progress", item->fdProgress);
end:
item->setText("ip", card.ip);
item->setText("alias", card.alias);
item->setText("size", QString("%1 x %2").arg(card.mWidth).arg(card.mHeight));
item->fdOnline->setPixmap({card.isOnline ? ":/res/online.png" : ":/res/offline.png"});
if(! card.hasPassword) {
item->isLocked = false;
item->setCellWidget("encrypt", item->btnUnlock = 0);
} else {
item->isLocked = card.isLocked;
if(item->btnUnlock==0) {
item->btnUnlock = new QPushButton;
item->btnUnlock->setMaximumHeight(36);
item->setCellWidget("encrypt", item->btnUnlock);
connect(item->btnUnlock, &QPushButton::clicked, item->btnUnlock, [=] {
if(! item->isLocked) return;
bool ok;
auto pwd = QInputDialog::getText(this, tr("Input password"), tr("Input password"), QLineEdit::Password, QString(), &ok);
if(! ok) return;
@ -197,11 +123,11 @@ void SendProgramDialog::updRow(int row, LedCard card) {
json.insert("pwd", pwd);
auto waitingDlg = new WaitingDlg(this, tr("VerifyPassword")+" ...");
waitingDlg->show();
auto reply = NetReq("http://"+card.ip+":2016/settings").timeout(60000).post(json);
auto reply = NetReq("http://"+card.ip+":2016/settings").timeout(30000).post(json);
waitingDlg->connAbort(reply);
connect(reply, &QNetworkReply::finished, btnUnlock, [=] {
connect(reply, &QNetworkReply::finished, item->btnUnlock, [=] {
QJsonDocument json;
QString err = checkReplyForJson(reply, &json);
auto err = checkReplyForJson(reply, &json);
if(! err.isEmpty()) {
waitingDlg->close();
QMessageBox::critical(this, QObject::tr("Error"), err);
@ -213,8 +139,8 @@ void SendProgramDialog::updRow(int row, LedCard card) {
return;
}
waitingDlg->success();
btnUnlock->setProperty("isLocked", false);
btnUnlock->setIcon(QIcon(":/res/UnLock.png"));
item->isLocked = false;
item->btnUnlock->setIcon(QIcon(":/res/UnLock.png"));
auto item = findItem(card.id);
if(item) {
item->mCard.isLocked = false;
@ -223,8 +149,48 @@ void SendProgramDialog::updRow(int row, LedCard card) {
});
});
}
btnUnlock->setIcon(QIcon(card.isLocked ? ":/res/Lock.png" : ":/res/UnLock.png")); //已验证显示绿色 没验证蓝色
item->btnUnlock->setIcon(QIcon(card.isLocked ? ":/res/Lock.png" : ":/res/UnLock.png")); //已验证显示绿色 没验证蓝色
}
}
label->setText(tr("All")+": "+QString::number(cnt));
});
hBox->addWidget(btnRefresh);
auto txtSearch = new QLineEdit;
txtSearch->setFixedWidth(150);
txtSearch->setClearButtonEnabled(true);
txtSearch->setStyleSheet("QLineEdit{border: 2px solid #aaa; padding: 2px;}");
txtSearch->addAction(new QAction(QIcon(":/res/program/bnSearch.png"), QString()), QLineEdit::LeadingPosition);
connect(txtSearch, &QLineEdit::textEdited, this, [=](const QString &text) {
auto cnt = table->topLevelItemCount();
for(int rr=0; rr<cnt; rr++) {
auto item = table->item(rr);
item->setHidden(! (text.isEmpty() || item->text("id").contains(text) || item->text("ip").contains(text) || item->text("alias").contains(text) || item->text("size").contains(text)));
}
});
hBox->addWidget(txtSearch);
table = new LoQTreeWidget;
table->addCol("#", "", 20);
table->addCol("id", "ID", 130).margin(4);
table->addCol("online", tr("Online"), 40);
table->addCol("ip", "IP", 100);
table->addCol("size", tr("Screen Size"), 80).alignC(),
table->addCol("alias", tr("Alias"), 120);
table->addCol("encrypt", tr("Security"), 40);
table->addCol("progress", tr("Progress"), 120);
table->addCol("remarks", tr("Remarks"), QHeaderView::Stretch);
table->setDefs()->setHeaderAlignC();
table->addFd();
table->setSelectionMode(QAbstractItemView::NoSelection);
table->setSortingEnabled(true);
vBox->addWidget(table);
auto sortField = gDevicePanel->mDeviceTable->sortField();
if(sortField=="id" || sortField=="ip" || sortField=="alias") table->sortItems(sortField, gDevicePanel->mDeviceTable->header()->sortIndicatorOrder());
else table->sortItems("id");
emit btnRefresh->clicked();
}
void SendProgramDialog::closeEvent(QCloseEvent *) {
@ -232,42 +198,30 @@ void SendProgramDialog::closeEvent(QCloseEvent *) {
}
void SendProgramDialog::sendNext() {
if(mWaitCnt <= 0) return;
int cnt = table->rowCount();
for(int rr=0; rr<cnt; rr++) if(! table->isRowHidden(rr)) {
auto fdId = table->itemValid(rr, "id");
if(fdId->checkState()!=Qt::Checked) continue;
if(fdId->data(isSending).toBool()) continue;
auto btnUnlock = (QPushButton*) table->cellWidget(rr, "encrypt");
if(btnUnlock && btnUnlock->property("isLocked").toBool()) continue;
auto fdRemarks = table->itemValid(rr, "remarks");
if(! fdRemarks->text().startsWith(" ")) continue;
fdRemarks->setText("");
auto fdProgress = (QProgressBar*) table->cellWidget(rr, "progress");
fdProgress->setValue(0);
fdId->setData(isSending, true);
int cnt = table->topLevelItemCount();
SendProgramItem *item;
auto remarks = "remarks"**table;
for(int rr=0; rr<cnt; rr++) if(! (item = (SendProgramItem*) table->item(rr))->isHidden() && item->checkState("id") == Qt::Checked && ! item->isSending && ! item->isLocked && item->text(remarks).startsWith(" ")) {
item->setText(remarks, "");
item->fdProgress->setValue(0);
item->isSending = true;
mWaitCnt--;
auto sendProg = new SendProgThread(programsDir()+"/"+mProgName+"_tmp", table->text(rr, "ip"), 3333);
connect(sendProg, &SendProgThread::emErr, fdProgress, [=](QString strTip) {
fdId->setData(isSending, false);
auto sendProg = new SendProgThread(programsDir()+"/"+mProgName+"_tmp", item->text("ip"), 3333);
connect(sendProg, &SendProgThread::emErr, item->fdProgress, [=](QString strTip) {
item->isSending = false;
if(strTip=="OK") {
fdId->setCheckState(Qt::Unchecked);
fdRemarks->setText("OK");
fdRemarks->setForeground(Qt::darkGreen);
item->setCheckState("id", Qt::Unchecked);
item->setText(remarks, "OK");
item->setForeground(remarks, Qt::darkGreen);
} else {
fdRemarks->setText(strTip);
fdRemarks->setForeground(Qt::red);
item->setText(remarks, strTip);
item->setForeground(remarks, Qt::red);
}
sendNext();
});
connect(sendProg, &SendProgThread::emProgress, fdProgress, &QProgressBar::setValue);
connect(sendProg, &SendProgThread::emProgress, item->fdProgress, &QProgressBar::setValue);
connect(this, &SendProgramDialog::stopAllThd, sendProg, &SendProgThread::stop);
sendProg->start();
return;
}
}
void SendProgramDialog::refresh() {
int cnt = gDevicePanel->mDeviceTable->topLevelItemCount();
for(int rr=0; rr<cnt; rr++) addRow(((DeviceItem*)gDevicePanel->mDeviceTable->topLevelItem(rr))->mCard);
label->setText(tr("All")+": "+QString::number(cnt));
}

View File

@ -1,51 +1,44 @@
#ifndef SENDPROGRAMDIALOG_H
#define SENDPROGRAMDIALOG_H
#include "globaldefine.h"
#include "gutil/qgui.h"
#include "base/loqtreewidget.h"
#include <QDialog>
#include <QCheckBox>
#include <QProxyStyle>
#include <QApplication>
#include <QProgressBar>
class SendProgramDialog : public QDialog {
Q_OBJECT
public:
explicit SendProgramDialog(QString, QWidget *parent = nullptr);
explicit SendProgramDialog(QString, QWidget *parent);
signals:
void stopAllThd();
protected slots:
void refresh();
protected:
void closeEvent(QCloseEvent *event) override;
void sendNext();
void addRow(LedCard);
void updRow(int, LedCard);
Table *table;
QCheckBox *fdCheckAll;
LoQTreeWidget *table;
int mWaitCnt{0};
QLabel *label;
QString mProgName;
QString m_strUrl;
enum {isSending = Qt::UserRole};
};
class ViewItemStyle : public QProxyStyle {
class SendProgramItem : public TreeWidgetItem {
public:
ViewItemStyle() : QProxyStyle(QApplication::style()) {}
QRect subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const override {
auto res = QProxyStyle::subElementRect(element, option, widget);
if(option && option->type==QStyleOption::SO_ViewItem && ((QStyleOptionViewItem*)option)->features & QStyleOptionViewItem::HasCheckIndicator && ((QStyleOptionViewItem*)option)->index.internalId()==0) res.setLeft(res.x() + 6);
return res;
}
int pixelMetric(QStyle::PixelMetric metric, const QStyleOption *option, const QWidget *widget) const override {
auto res = QProxyStyle::pixelMetric(metric, option, widget);
if(metric==PM_FocusFrameHMargin && option && option->type==QStyleOption::SO_ViewItem && ((QStyleOptionViewItem*)option)->features & QStyleOptionViewItem::HasCheckIndicator) res += 4;
return res;
using TreeWidgetItem::TreeWidgetItem;
void setResult(QString tip, QColor color) {
auto remarks = "remarks"**treeWidget();
setText(remarks, tip);
setToolTip(remarks, tip);
setForeground(remarks, color);
}
bool isSending = false;
bool isLocked = true;
QLabel *fdOnline;
QProgressBar *fdProgress;
QPushButton *btnUnlock = 0;
};
#endif // SENDPROGRAMDIALOG_H

View File

@ -1,125 +0,0 @@
#include "wplanitem.h"
#include "gutil/qgui.h"
#include <QJsonArray>
wPlanItem::wPlanItem(QListWidgetItem *item, const QJsonObject *json) : m_item(item) {
setAttribute(Qt::WA_DeleteOnClose);
auto vBox = new VBox(this);
vBox->setContentsMargins(6, 6, 0, 6);
auto hBox = new HBox(vBox);
fdIdx = new QLabel("1");
hBox->addWidget(fdIdx);
tStart = new QTimeEdit;
tStart->setDisplayFormat("HH:mm");
hBox->addWidget(tStart);
tEnd = new QTimeEdit;
tEnd->setDisplayFormat("HH:mm");
tEnd->setTime(QTime(23, 59, 59));
hBox->addWidget(tEnd);
bnDel = new QPushButton;
hBox->addWidget(bnDel);
hBox = new HBox(vBox);
sMon = new QPushButton(tr("M"));
sMon ->setCheckable(true);
sMon ->setProperty("ssName", "weeklySelector");
hBox->addWidget(sMon);
hBox->addStretch();
sTues = new QPushButton(tr("Tu"));
sTues->setCheckable(true);
sTues->setProperty("ssName", "weeklySelector");
hBox->addWidget(sTues);
hBox->addStretch();
sWed = new QPushButton(tr("W"));
sWed ->setCheckable(true);
sWed ->setProperty("ssName", "weeklySelector");
hBox->addWidget(sWed);
hBox->addStretch();
sThur = new QPushButton(tr("Th"));
sThur->setCheckable(true);
sThur->setProperty("ssName", "weeklySelector");
hBox->addWidget(sThur);
hBox->addStretch();
sFri = new QPushButton(tr("F"));
sFri ->setCheckable(true);
sFri ->setProperty("ssName", "weeklySelector");
hBox->addWidget(sFri);
hBox->addStretch();
sSat = new QPushButton(tr("Sa"));
sSat ->setCheckable(true);
sSat ->setProperty("ssName", "weeklySelector");
hBox->addWidget(sSat);
hBox->addStretch();
sSun = new QPushButton(tr("Su"));
sSun ->setCheckable(true);
sSun ->setProperty("ssName", "weeklySelector");
hBox->addWidget(sSun);
if(json==0) {
sMon ->setChecked(true);
sTues->setChecked(true);
sWed ->setChecked(true);
sThur->setChecked(true);
sFri ->setChecked(true);
sSat ->setChecked(true);
sSun ->setChecked(true);
} else {
tStart->setTime(QTime::fromString(json->value("start").toString(), "hh:mm"));
tEnd->setTime(QTime::fromString(json->value("end").toString(), "hh:mm"));
auto oWeekly = json->value("weekly").toArray();
sMon ->setChecked(oWeekly.contains(1));
sTues->setChecked(oWeekly.contains(2));
sWed ->setChecked(oWeekly.contains(3));
sThur->setChecked(oWeekly.contains(4));
sFri ->setChecked(oWeekly.contains(5));
sSat ->setChecked(oWeekly.contains(6));
sSun ->setChecked(oWeekly.contains(7));
}
connect(tStart, SIGNAL(timeChanged(const QTime&)), this, SLOT(onItemChanged()));
connect(tEnd, SIGNAL(timeChanged(const QTime&)), this, SLOT(onItemChanged()));
connect(sMon, SIGNAL(toggled(bool)), this, SLOT(onItemChanged()));
connect(sTues, SIGNAL(toggled(bool)), this, SLOT(onItemChanged()));
connect(sWed, SIGNAL(toggled(bool)), this, SLOT(onItemChanged()));
connect(sThur, SIGNAL(toggled(bool)), this, SLOT(onItemChanged()));
connect(sFri, SIGNAL(toggled(bool)), this, SLOT(onItemChanged()));
connect(sSat, SIGNAL(toggled(bool)), this, SLOT(onItemChanged()));
connect(sSun, SIGNAL(toggled(bool)), this, SLOT(onItemChanged()));
connect(bnDel, SIGNAL(clicked(bool)), this, SLOT(onDelete(bool)));
}
void wPlanItem::onItemChanged(){
emit sigItemChanged(m_item);
}
void wPlanItem::onDelete(bool){
emit sigDelete(m_item);
}
QJsonObject wPlanItem::planJson() const {
QJsonObject oRoot;
QJsonArray oWeekly;
if(sMon ->isChecked()) oWeekly.append(QJsonValue(1));
if(sTues->isChecked()) oWeekly.append(QJsonValue(2));
if(sWed ->isChecked()) oWeekly.append(QJsonValue(3));
if(sThur->isChecked()) oWeekly.append(QJsonValue(4));
if(sFri ->isChecked()) oWeekly.append(QJsonValue(5));
if(sSat ->isChecked()) oWeekly.append(QJsonValue(6));
if(sSun ->isChecked()) oWeekly.append(QJsonValue(7));
oRoot["start"] = tStart->time().toString("hh:mm");
oRoot["end"] = tEnd->time().toString("hh:mm");
oRoot["weekly"] = oWeekly;
return oRoot;
}

View File

@ -1,41 +0,0 @@
#ifndef WPLANITEM_H
#define WPLANITEM_H
#include <QPushButton>
#include <QListWidgetItem>
#include <QLabel>
#include <QTimeEdit>
#include <QJsonObject>
class wPlanItem : public QWidget {
Q_OBJECT
public:
explicit wPlanItem(QListWidgetItem *item, const QJsonObject * = 0);
QJsonObject planJson() const;
QLabel *fdIdx;
signals:
void sigItemChanged(QListWidgetItem *);
void sigDelete(QListWidgetItem *);
protected slots:
void onItemChanged();
void onDelete(bool);
private:
QListWidgetItem *m_item;
QTimeEdit *tStart;
QTimeEdit *tEnd;
QPushButton *bnDel;
QPushButton *sMon;
QPushButton *sTues;
QPushButton *sWed;
QPushButton *sThur;
QPushButton *sFri;
QPushButton *sSat;
QPushButton *sSun;
};
#endif // WPLANITEM_H

View File

@ -1,66 +0,0 @@
#include "wplanlist.h"
#include "wplanitem.h"
#include <QJsonArray>
wPlanList::wPlanList(QWidget *parent) : QListWidget(parent) {
setAttribute(Qt::WA_DeleteOnClose);
setFrameShape(QListWidget::NoFrame);
}
void wPlanList::adjustItemNum() {
int n = count();
for(int i=0; i<n; i++) static_cast<wPlanItem*>(itemWidget(item(i)))->fdIdx->setNum(i+1);
}
QJsonArray wPlanList::plansJson() {
QJsonArray oRoot;
int n = count();
for(int i=0; i<n; i++) {
wPlanItem *w = static_cast<wPlanItem*>(itemWidget(item(i)));
oRoot.append(w->planJson());
}
return oRoot;
}
//添加时间计划表
void wPlanList::onAddPlan()
{
QListWidgetItem *item = new QListWidgetItem();
item->setFlags(item->flags() & ~Qt::ItemIsSelectable);
wPlanItem *widget = new wPlanItem(item);
addItem(item);
setItemWidget(item, widget);
setCurrentItem(item);
connect(widget, SIGNAL(sigItemChanged(QListWidgetItem*)), this, SIGNAL(itemChanged(QListWidgetItem*)));
connect(widget, SIGNAL(sigDelete(QListWidgetItem*)), this, SLOT(onDeletePlan(QListWidgetItem*)));
adjustItemNum();
emit itemChanged(item);
}
void wPlanList::onRestorePlan(const QJsonArray &jRoot)
{
clear();
int n = jRoot.count();
for(int i=0; i<n; i++) {
QListWidgetItem *item = new QListWidgetItem();
item->setFlags(item->flags() & ~Qt::ItemIsSelectable);
auto json = jRoot.at(i).toObject();
wPlanItem *widget = new wPlanItem(item, &json);
addItem(item);
setItemWidget(item, widget);
setCurrentItem(item);
connect(widget, SIGNAL(sigItemChanged(QListWidgetItem*)), this, SIGNAL(itemChanged(QListWidgetItem*)));
connect(widget, SIGNAL(sigDelete(QListWidgetItem*)), this, SLOT(onDeletePlan(QListWidgetItem*)));
}
adjustItemNum();
}
void wPlanList::onDeletePlan(QListWidgetItem *item)
{
int index = row(item);
if(index >= 0) {
removeItemWidget(item);
delete item;
emit itemChanged(nullptr);
}
adjustItemNum();
}

View File

@ -1,24 +0,0 @@
#ifndef WPLANLIST_H
#define WPLANLIST_H
#include <QListWidget>
#include <QListWidgetItem>
class wPlanList : public QListWidget {
Q_OBJECT
public:
explicit wPlanList(QWidget *parent = nullptr);
QJsonArray plansJson();
protected:
void adjustItemNum();
signals:
public slots:
void onAddPlan();
void onRestorePlan(const QJsonArray &jRoot);
void onDeletePlan(QListWidgetItem *item);
};
#endif // WPLANLIST_H

View File

@ -17,10 +17,10 @@
<file>res/DeviceNum_All.png</file>
<file>res/FlashArrow.png</file>
<file>res/Lock.png</file>
<file>res/O_Offline.png</file>
<file>res/O_Online.png</file>
<file>res/offline.png</file>
<file>res/online.png</file>
<file>res/UnLock.png</file>
<file>res/bnDetail.png</file>
<file>res/info.png</file>
<file>res/deviceReadbackPic.png</file>
<file>res/DeviceManager_s.png</file>
<file>res/DeviceManager_u.png</file>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 292 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 316 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

BIN
LedOK/res/info.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
LedOK/res/offline.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 652 B

BIN
LedOK/res/online.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 656 B

View File

@ -58,7 +58,7 @@ void Tools::mergeFormat(QTextEdit *textEdit, const QTextCharFormat &fmt) {
if(! cursor.hasSelection()) cursor.select(QTextCursor::WordUnderCursor);
cursor.mergeCharFormat(fmt);
}
void Tools::saveImg(const QString& dir, const QFontMetrics& metric, const QFont& font, const QColor& color, QJsonObject& imgs, const QString& str, const QString& name) {
void Tools::saveImg(const QString& dir, const QFontMetrics& metric, const QFont& font, const QColor& color, JObj& imgs, const QString& str, const QString& name) {
if(str.isEmpty()) return;
QImage img(metric.horizontalAdvance(str), metric.lineSpacing(), QImage::Format_ARGB32);
img.fill(Qt::transparent);
@ -83,8 +83,8 @@ void Tools::saveImg(const QString& dir, const QFontMetrics& metric, const QFont&
file.close();
imgs.insert(name, md5);
}
void Tools::saveImg2(const QString& dir, const QFontMetrics& metric, const QFont& font, const QColor& color, QJsonArray& imgs, const QString& str, const QString& name) {
QJsonObject obj{
void Tools::saveImg2(const QString& dir, const QFontMetrics& metric, const QFont& font, const QColor& color, JArray& imgs, const QString& str, const QString& name) {
JObj obj{
{"name", name},
{"mime", "image/png"}
};

View File

@ -2,6 +2,7 @@
#define TOOLS_H
#include "program/progitem.h"
#include "gutil/qjson.h"
#include <QApplication>
#include <QBrush>
#include <QColor>
@ -14,7 +15,6 @@
const QString str0_9[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
extern QTextEdit *gFdResInfo;
extern QString gFileHome;
extern ProgItem *gProgItem;
extern QString css;
@ -31,8 +31,8 @@ public:
static void mergeFormat(QTextEdit *textEdit, const QTextCharFormat &format);
static QString readErrStr(QImageReader::ImageReaderError);
static QString fileMd5(QString);
static void saveImg(const QString&, const QFontMetrics&, const QFont&, const QColor&, QJsonObject&, const QString&, const QString&);
static void saveImg2(const QString&, const QFontMetrics&, const QFont&, const QColor&, QJsonArray&, const QString&, const QString&);
static void saveImg(const QString&, const QFontMetrics&, const QFont&, const QColor&, JObj&, const QString&, const QString&);
static void saveImg2(const QString&, const QFontMetrics&, const QFont&, const QColor&, JArray&, const QString&, const QString&);
static QColor int2Color(int value);
static int color2Int(const QColor& color);
static QBrush getBrush(const QColor& color);

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
LedOK/translations/qt_ar.qm Normal file

Binary file not shown.

BIN
LedOK/translations/qt_bg.qm Normal file

Binary file not shown.

BIN
LedOK/translations/qt_ca.qm Normal file

Binary file not shown.

BIN
LedOK/translations/qt_cs.qm Normal file

Binary file not shown.

BIN
LedOK/translations/qt_da.qm Normal file

Binary file not shown.

BIN
LedOK/translations/qt_de.qm Normal file

Binary file not shown.

BIN
LedOK/translations/qt_en.qm Normal file

Binary file not shown.

View File

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

BIN
LedOK/translations/qt_es.qm Normal file

Binary file not shown.

BIN
LedOK/translations/qt_fi.qm Normal file

Binary file not shown.

BIN
LedOK/translations/qt_fr.qm Normal file

Binary file not shown.

BIN
LedOK/translations/qt_gd.qm Normal file

Binary file not shown.

BIN
LedOK/translations/qt_he.qm Normal file

Binary file not shown.

BIN
LedOK/translations/qt_hu.qm Normal file

Binary file not shown.

BIN
LedOK/translations/qt_it.qm Normal file

Binary file not shown.

BIN
LedOK/translations/qt_ja.qm Normal file

Binary file not shown.

File diff suppressed because it is too large Load Diff

BIN
LedOK/translations/qt_ko.qm Normal file

Binary file not shown.

BIN
LedOK/translations/qt_lv.qm Normal file

Binary file not shown.

BIN
LedOK/translations/qt_pl.qm Normal file

Binary file not shown.

BIN
LedOK/translations/qt_pt.qm Normal file

Binary file not shown.

BIN
LedOK/translations/qt_ru.qm Normal file

Binary file not shown.

BIN
LedOK/translations/qt_sk.qm Normal file

Binary file not shown.

BIN
LedOK/translations/qt_tr.qm Normal file

Binary file not shown.

BIN
LedOK/translations/qt_uk.qm Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

6107
LedOK/ts/app_pt.ts Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff