From 7a8dd9efba0e257cdcccc47c1d8c0cb5885653b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D0=B5=D0=BB=D0=B8=D0=BF=D0=B5=D0=BD=D0=BA=D0=BE=20?= =?UTF-8?q?=D0=98=D0=B2=D0=B0=D0=BD?= Date: Tue, 22 May 2018 13:49:16 +0000 Subject: [PATCH] git-svn-id: svn://db.shs.com.ru/libs@380 a8b55f48-bf90-11e4-a774-851b48703e85 --- cd_utils/CMakeLists.txt | 4 +- cd_utils/cdutils_c.cpp | 55 ++++++ cd_utils/cdutils_c.h | 34 ++++ cd_utils/cdutils_core.cpp | 149 +++++++++++++- cd_utils/cdutils_core.h | 31 ++- cd_utils/cdutils_interface.cpp | 6 +- cd_utils/cdutils_interface.h | 4 +- cd_utils/cdutils_protocol.h | 3 + cd_utils/cdutils_types.cpp | 91 ++++++++- cd_utils/cdutils_types.h | 19 +- cd_utils/cdutils_x.cpp | 39 ++++ cd_utils/cdutils_x.h | 37 ++++ cd_utils/cdutilstest.cpp | 17 +- piqt_utils/piconnedit/piconnedit_main.cpp | 5 +- qad/widgets/qvariantedit.cpp | 22 ++- qad/widgets/qvariantedit.h | 11 +- qcd_utils/pult/cdgraphics.cpp | 143 ++++++++++++++ qcd_utils/pult/cdgraphics.h | 32 +++ qcd_utils/pult/cdgraphics.ui | 77 +++++++- qcd_utils/pult/cdpult.qrc | 1 + qcd_utils/pult/cdpultwindow.cpp | 5 +- qcd_utils/pult/cdpultwindow.ui | 64 ++++-- qcd_utils/pult/cdviewwidget.ui | 13 +- qcd_utils/pult/icons/format-stroke-color.png | Bin 0 -> 24156 bytes qcd_utils/qcd_model.cpp | 198 ++++++++++++++----- qcd_utils/qcd_model.h | 30 ++- qcd_utils/qcd_view.cpp | 90 ++++++++- qcd_utils/qcd_view.h | 9 +- 28 files changed, 1052 insertions(+), 137 deletions(-) create mode 100644 cd_utils/cdutils_c.cpp create mode 100644 cd_utils/cdutils_c.h create mode 100644 cd_utils/cdutils_x.cpp create mode 100644 cd_utils/cdutils_x.h create mode 100644 qcd_utils/pult/icons/format-stroke-color.png diff --git a/cd_utils/CMakeLists.txt b/cd_utils/CMakeLists.txt index 5769d15..1500c1f 100644 --- a/cd_utils/CMakeLists.txt +++ b/cd_utils/CMakeLists.txt @@ -18,8 +18,8 @@ endif() include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${PIP_INCLUDES}) #file(GLOB HDRS_UTILS "*.h") #file(GLOB CPPS_UTILS "*.cpp") -set(CPPS_UTILS "cdutils_core.cpp" "cdutils_types.cpp" "cdutils_parser.cpp" "cdutils_interface.cpp" "cdutils_k.cpp") -set(HDRS_UTILS "cdutils_core.h" "cdutils_types.h" "cdutils_parser.h" "cdutils_interface.h" "cdutils_k.h" "cdutils_protocol.h") +file(GLOB CPPS_UTILS "cdutils_*.cpp") +file(GLOB HDRS_UTILS "cdutils_*.h") if (DEFINED ENV{QNX_HOST}) add_library(${PROJECT_NAME} STATIC ${CPPS_UTILS} ${HDRS_UTILS}) else() diff --git a/cd_utils/cdutils_c.cpp b/cd_utils/cdutils_c.cpp new file mode 100644 index 0000000..3770e43 --- /dev/null +++ b/cd_utils/cdutils_c.cpp @@ -0,0 +1,55 @@ +#include "cdutils_c.h" +#include "cdutils_core.h" + +using namespace CDUtils; + +CInterface C; + + +CInterface::CInterface(): Interface(CDType::cdC) { + CONNECTU(core, C_Sended, this, sended); + CONNECTU(core, C_SendFail, this, sendFailed); + CONNECTU(core, C_Received, this, received); + CONNECTU(core, C_ReceiveFail, this, receiveFailed); +} + + +void CInterface::send() { + core->C_Send(); +} + + +void CInterface::request() { + core->C_Request(); +} + + +void CInterface::sendCommand(const CDType & c) { + core->sendCommand(c); +} + + +void CInterface::connect(const CDType & c, PIObject * o, Handler eh) { + core->registerCHandler(c, o, eh); +} + + +void CInterface::autoConnect(PIObject * o, const PIString & prefix) { + if (!o) return; + PIString cn = o->className(); + if (!PIObject::__meta_data().contains(cn)) return; + PIMap eh_map; + PIObject::__MetaData & md(PIObject::__meta_data()[cn]); + PIMap::const_iterator it; + for (it = md.eh_func.constBegin(); it != md.eh_func.constEnd(); ++it) { + eh_map[it.value().func_name] = (Handler)it.value().addr; + //piCout << "func" << it.value().func_name; + } + PIVector cl = C.root().children(); + piForeachC (CDType * c, cl) { + PIString cp = prefix + c->pathString().join("_"); + if (cp.isEmpty()) continue; + if (!eh_map.contains(cp)) continue; + connect(*c, o, eh_map[cp]); + } +} diff --git a/cd_utils/cdutils_c.h b/cd_utils/cdutils_c.h new file mode 100644 index 0000000..e09b89d --- /dev/null +++ b/cd_utils/cdutils_c.h @@ -0,0 +1,34 @@ +#ifndef CDUTILS_C_H +#define CDUTILS_C_H + +#include "cdutils_interface.h" + + +namespace CDUtils { + + +class CInterface: public Interface +{ + PIOBJECT(CDUtils::CInterface) +public: + CInterface(); + + EVENT(sended) + EVENT(sendFailed) + EVENT(received) + EVENT(receiveFailed) + EVENT1(keepNamesRequest, bool*, cn) + EVENT_HANDLER(void, send); + EVENT_HANDLER(void, request); + + void sendCommand(const CDType & c); + void connect(const CDType & c, PIObject * o, Handler eh); + void autoConnect(PIObject * o, const PIString & prefix = PIStringAscii("c_")); + +}; + +} + +extern CDUtils::CInterface C; + +#endif // CDUTILS_C_H diff --git a/cd_utils/cdutils_core.cpp b/cd_utils/cdutils_core.cpp index 5a2d2ad..f5fcdf5 100644 --- a/cd_utils/cdutils_core.cpp +++ b/cd_utils/cdutils_core.cpp @@ -64,6 +64,7 @@ CDCore::CDCore() { /*PIString s(app_config); connection.configureFromString(&s); connection.start();*/ + need_rebuild_x = x_pult_side = false; k_.cd_type_ = CDType::cdK; x_.cd_type_ = CDType::cdX; c_.cd_type_ = CDType::cdC; @@ -160,27 +161,44 @@ void CDCore::cd_send(CDSection * cd, CDPacketType pt, bool direct) { void CDCore::initApp() { - init(appConfig()); + init(appConfig(), false); } void CDCore::initPult() { - init(pultConfig()); + init(pultConfig(), true); } -void CDCore::init(const PIString & configuration) { +void CDCore::init(const PIString & configuration, bool pult) { PIString c = configuration; //piCoutObj << "init" << c; connection.stop(); connection.removeAllDevices(); connection.configureFromString(&c); connection.start(); + x_pult_side = pult; } -void CDCore::startPing() { - x_timer.start(1.0); +void CDCore::startX(double freq) { + x_timer.start(1000. / piMaxd(freq, 0.01)); +} + + +void CDCore::sendCommand(const CDType & c) { + piCoutObj << "C_sendCommand" << c; + PIByteArray sba = makeHeader(CD_Command, 0); + sba << c.path(); + sendDirect(sba); +} + + +void CDCore::registerCHandler(const CDType & c, PIObject * o, Handler h) { + PIString sp = pathToString(c.path()); + if (sp.isEmpty() || !h) return; + piCout << "register" << sp; + c_handlers[sp] = OHPair(o, h); } @@ -237,6 +255,32 @@ void CDUtils::CDCore::K_DirectChange(PIDeque path, PIString value) { } +void CDCore::X_Send() { + piCoutObj << "X_Send"; + cd_send(&x_, CD_XSend); +} + + +void CDCore::X_Request() { + piCoutObj << "X_Request"; + PIByteArray sba = makeHeader(CD_XQuery, 0); + sendThreaded(sba); +} + + +void CDCore::C_Send() { + piCoutObj << "C_Send"; + cd_send(&c_, CD_CSend); +} + + +void CDCore::C_Request() { + piCoutObj << "C_Request"; + PIByteArray sba = makeHeader(CD_CQuery, 0); + sendThreaded(sba); +} + + void CDCore::sendThread() { if (send_data.size_s() < 4) return; PacketHeader h; @@ -250,17 +294,43 @@ void CDCore::sendThread() { case CD_KQuery: if (!ok) K_ReceiveFail(); break; + case CD_XSend: + if (ok) X_Sended(); + else X_SendFail(); + break; + case CD_XQuery: + if (!ok) X_ReceiveFail(); + break; + case CD_CSend: + if (ok) C_Sended(); + else C_SendFail(); + break; + case CD_CQuery: + if (!ok) C_ReceiveFail(); + break; default: break; } } void CDCore::xTimerTick() { - PacketHeader ph; - ph.type = CD_Ping; - ph.session_id = 0; + x_mutex.lock(); PIByteArray ba; - ba << ph; + if (x_pult_side) { + ba = makeHeader(CD_XRequest, 0); + if (need_rebuild_x) { + x_selected = x_.collectX(); + need_rebuild_x = false; + } + ba << x_selected; + } else { + ba = makeHeader(CD_XValues, 0); + ba << x_selected; + piForeachC (PIDeque & p, x_selected) { + x_[p].writeX(ba); + } + } + x_mutex.unlock(); connection.writeByName("cd", ba); } @@ -323,11 +393,72 @@ void CDCore::procReceivedPacket(PIByteArray & ba) { ba >> p; k_[p.path].setValue(p.value); } break; + case CD_XRequest: { + x_mutex.lock(); + x_selected.clear(); + ba >> x_selected; + x_.setSelectedX(false); + piForeachC (PIDeque & p, x_selected) { + x_[p].x_enabled = true; + } + x_mutex.unlock(); + } break; + case CD_XValues: { + x_mutex.lock(); + x_selected.clear(); + ba >> x_selected; + piForeachC (PIDeque & p, x_selected) { + x_[p].readX(ba); + } + x_mutex.unlock(); + } break; + case CD_CQuery: + C_Send(); + break; + case CD_CSend: { + piCoutObj << "C received"; + PIByteArray c; + ba >> c; + c << uchar(0); + PIString s = PIString::fromUTF8((const char *)c.data()); + PIIOString ios(&s); + cd_read(&c_, &ios); + C_Received(); + } break; + case CD_Command: { + piCoutObj << "C command"; + PIDeque p; + ba >> p; + if (p.isEmpty()) return; + PIString sp = pathToString(p); + OHPair h = c_handlers.value(sp, OHPair(0, 0)); + //piCoutObj << "found" << sp << h.first; + if (h.first && h.second) h.second(h.first); + } break; default: break; } } +PIString CDCore::pathToString(const PIDeque & p) { + PIString ret; + for (int i = 0; i < p.size_s(); ++i) { + if (!ret.isEmpty()) ret += "."; + ret << p[i]; + } + return ret; +} + + +PIDeque CDCore::stringToPath(const PIString & p) { + PIDeque ret; + PIStringList sl = p.split("."); + piForeachC (PIString & s, sl) + ret << s.toInt(); + return ret; +} + + void CDUtils::CDCore::dataReceived(const PIString & from, const PIByteArray & data) { //piCoutObj << "dataReceived" << from << data.size(); PIIODevice * d = connection.deviceByName("cd"); diff --git a/cd_utils/cdutils_core.h b/cd_utils/cdutils_core.h index b59426c..b541af3 100644 --- a/cd_utils/cdutils_core.h +++ b/cd_utils/cdutils_core.h @@ -27,6 +27,7 @@ class CDCore: public PIObject friend class __Core_Initializer__; friend class CDSection; friend class Interface; + friend class XInterface; public: static CDCore * instance(); @@ -39,6 +40,22 @@ public: EVENT_HANDLER(void, K_Request); EVENT_HANDLER2(void, K_DirectChange, PIDeque, path, PIString, value); + EVENT(X_Sended) + EVENT(X_SendFail) + EVENT(X_Received) + EVENT(X_ReceiveFail) + EVENT(X_ChangedGlobal) + EVENT_HANDLER(void, X_Send); + EVENT_HANDLER(void, X_Request); + + EVENT(C_Sended) + EVENT(C_SendFail) + EVENT(C_Received) + EVENT(C_ReceiveFail) + EVENT(C_ChangedGlobal) + EVENT_HANDLER(void, C_Send); + EVENT_HANDLER(void, C_Request); + void cd_write (CDSection * cd, PIIODevice * d); void cd_read (CDSection * cd, PIIODevice * d); void cd_parse (CDSection * cd, PIIODevice * d); @@ -47,13 +64,17 @@ public: void cd_send (CDSection * cd, CDPacketType pt, bool direct = false); void initApp(); void initPult(); - void init(const PIString & configuration); - void startPing(); + void init(const PIString & configuration, bool pult = false); + void startX(double freq = 20.); + void sendCommand(const CDType & c); + void registerCHandler(const CDType & c, PIObject * o, Handler h); bool inProgress() {return sendt.isRunning();} CDSection & k() {return k_;} CDSection * root(CDType::cdT cdt); PIString typeLetter(CDType::cdT cdt); + static PIString pathToString(const PIDeque & p); + static PIDeque stringToPath(const PIString & p); static PIString pultConfig() {return PIString(pult_config);} static PIString appConfig() {return PIString(app_config);} @@ -72,6 +93,8 @@ private: void sendThreaded(PIByteArray & ba); void procReceivedPacket(PIByteArray & ba); + typedef PIPair OHPair; + static const char app_config[], pult_config[]; PIConnection connection; PIDataTransfer datatr; @@ -79,6 +102,10 @@ private: PIThread sendt; PITimer x_timer; CDSection k_, x_, c_; + PIMutex x_mutex; + PIVector > x_selected; + PIMap c_handlers; + bool need_rebuild_x, x_pult_side; }; diff --git a/cd_utils/cdutils_interface.cpp b/cd_utils/cdutils_interface.cpp index 8cec8ad..d836645 100644 --- a/cd_utils/cdutils_interface.cpp +++ b/cd_utils/cdutils_interface.cpp @@ -9,6 +9,7 @@ using namespace CDUtils; Interface::Interface(CDType::cdT type_) { core = CDCore::instance(); s = core->root(type_); + type = type_; //piCoutObj << (void*)this << core; file_ = core->typeLetter(type_) + PIStringAscii(".dat"); file_size = 0; @@ -108,11 +109,6 @@ void Interface::reinitConnection(const PIString &configuration) { } -void Interface::startPing() { - core->startPing(); -} - - void Interface::write(PIIODevice * d) { core->cd_write(s, d); } diff --git a/cd_utils/cdutils_interface.h b/cd_utils/cdutils_interface.h index d837f0c..ded7fc1 100644 --- a/cd_utils/cdutils_interface.h +++ b/cd_utils/cdutils_interface.h @@ -32,11 +32,11 @@ public: int count(bool recursive = true) const; const PIString file() const {return file_;} int fileSize() const {return file_size;} + CDType::cdT cdType() const {return type;} void setFileName(const PIString & _file); bool configure(const PIString & config); void reinitConnection(const PIString & configuration); - void startPing(); void write(PIIODevice * d); void read(PIIODevice * d); void parse(PIIODevice * d); @@ -63,4 +63,4 @@ protected: } -#endif // CDUTILS_K_H +#endif // CDUTILS_INTERFACE_H diff --git a/cd_utils/cdutils_protocol.h b/cd_utils/cdutils_protocol.h index cc27c5b..df9c91b 100644 --- a/cd_utils/cdutils_protocol.h +++ b/cd_utils/cdutils_protocol.h @@ -14,8 +14,11 @@ enum CDPacketType {CD_Ping, CD_XQuery, CD_XSend, + CD_XRequest, CD_XValues, + CD_CQuery, + CD_CSend, CD_Command, }; diff --git a/cd_utils/cdutils_types.cpp b/cd_utils/cdutils_types.cpp index 18f72a2..8eb4c17 100644 --- a/cd_utils/cdutils_types.cpp +++ b/cd_utils/cdutils_types.cpp @@ -14,9 +14,11 @@ CDType::CDType() { index_ = -1; value_d = 0.; value_i = 0; - value_b = calculated = false; + value_b = calculated = x_enabled = false; cd_type_ = cdNull; parent = 0; + avg_size = 1; + mode_ = X_Current; // debug_cnt = cdtype_debug_cnt; // cdtype_debug_cnt++; // piCout << "[CDType]" << "create Null" << debug_cnt; @@ -36,8 +38,10 @@ CDType::CDType(int i, const PIString & n, const PIString & t, const PIString & v value_i = v.toInt(); value_b = v.toBool(); cd_type_ = cd_t; - calculated = false; + calculated = x_enabled = false; parent = 0; + avg_size = 1; + mode_ = X_Current; if (type_ == "e") { enum_values = parseEnumComment(comment_); // piCout << enum_values.size() << enum_values; @@ -51,17 +55,18 @@ CDType::CDType(int i, const PIString & n, const PIString & t, const PIString & v } -CDType &CDType::operator =(double x) { +CDType & CDType::operator =(double x) { value_d = x; + value_i = x; + value_b = x > 0.; if (mode_ == X_All_Avg) { avg_h << x; double val = 0; if (avg_h.size_s() >= avg_size) { - for (int i=0; iroot(cd_type_); + if (!ps) return ret; + for (int i = 0; i < path_.size_s() - 1; ++i) { + ps = &(ps->section(path_[i])); + if (!ps->alias.isEmpty()) ret << ps->alias; + else ret << PIString::fromNumber(path_[i]); + } + if (!name_.isEmpty()) ret << name_; + else ret << PIString::fromNumber(index_); + return ret; +} + + +void CDType::readX(PIByteArray & ba) { + if (ba.size() < 5) return; + uchar t(0); ba >> t; + switch ((XMode)t) { + case X_Current: + ba >> value_d; + value_i = value_d; + value_b = value_d > 0.; + break; + case X_All_Avg: + ba >> history; + break; + default: break; + } +} + + +void CDType::writeX(PIByteArray & ba) { + ba << uchar(mode_); + switch (mode_) { + case X_Current: + ba << value_d; + break; + case X_All_Avg: + ba << history; + break; + default: break; + } +} + + bool CDType::calculate(PIEvaluator * e, PIVector stack) { if (stack.contains(this)) { error_ = "Circular dependencies: "; @@ -436,8 +487,8 @@ void CDSection::read(const void * ep) { break; case CDType::cdX: c = CDType(id, e->getValue("name").value(), PIString(), PIString(), PIString() , e->getValue("name").comment(), cd_type_); - c.setXMode((CDType::XMode)e->getValue("mode").value().toInt()); - c.setAvg((CDType::XMode)e->getValue("avg").value().toInt()); + c.setXMode((CDType::XMode)e->getValue("mode", int(CDType::X_Current)).value().toInt()); + c.setAvg((CDType::XMode)e->getValue("avg", 1).value().toInt()); break; case CDType::cdC: c = CDType(id, e->getValue("name").value(), PIString(), PIString(), PIString() , e->getValue("name").comment(), cd_type_); @@ -601,6 +652,30 @@ void CDSection::calculateRecursive(PIEvaluator * e) { } +void CDSection::setSelectedX(bool yes) { + PIMap::iterator i; + for (i = cd.begin(); i != cd.end(); ++i) + i.value().x_enabled = yes; + PIMap::iterator j; + for (j = s.begin(); j != s.end(); ++j) + j.value().setSelectedX(yes); +} + + +PIVector > CDSection::collectX() const { + PIVector > ret; + PIMap::const_iterator i; + for (i = cd.begin(); i != cd.end(); ++i) { + if (i.value().x_enabled) + ret << i.value().path(); + } + PIMap::const_iterator j; + for (j = s.constBegin(); j != s.constEnd(); ++j) + ret << j.value().collectX(); + return ret; +} + + void CDSection::makePath(PIDeque p) { PIDeque tp; PIMap::iterator i; diff --git a/cd_utils/cdutils_types.h b/cd_utils/cdutils_types.h index 8c7194d..5a84b6c 100644 --- a/cd_utils/cdutils_types.h +++ b/cd_utils/cdutils_types.h @@ -8,8 +8,8 @@ class PIIODevice; class PIEvaluator; class CD_Pult; -class CDKItem; -class CDKItemModel; +class CDItem; +class CDItemModel; namespace CDUtils { @@ -27,6 +27,7 @@ class CDType { friend class CDSection; friend class CDCore; friend class Interface; + friend class XInterface; public: enum cdT {cdNull, cdK, cdX, cdC}; enum XMode {X_Current, X_All_Avg}; @@ -53,10 +54,15 @@ public: void setEnumValues(const PIVariantTypes::Enum & ev) {enum_values = ev;} const PIString & errorString() const {return error_;} PIDeque path() const {return path_;} + PIStringList pathString() const; + void setXMode(XMode mode) {mode_ = mode;} void setAvg(int avg) {avg_size = avg;} XMode xmode() const {return mode_;} int avg() const {return avg_size;} + bool isSelectedX() const {return x_enabled;} + void readX(PIByteArray & ba); + void writeX(PIByteArray & ba); protected: bool calculate(PIEvaluator * e, PIVector stack = PIVector()); @@ -70,7 +76,7 @@ protected: PIDeque path_; double value_d; int value_i; - bool value_b, calculated; + bool value_b, calculated, x_enabled; PIVector history; PIVector avg_h; int avg_size; @@ -81,9 +87,10 @@ protected: class CDSection { friend class CDCore; friend class Interface; + friend class XInterface; friend class ::CD_Pult; - friend class ::CDKItem; - friend class ::CDKItemModel; + friend class ::CDItem; + friend class ::CDItemModel; public: CDSection(CDType::cdT type_ = CDType::cdNull); @@ -125,6 +132,8 @@ protected: bool isSameStructure(CDSection & v); void prepareCalculate(); void calculateRecursive(PIEvaluator * e); + void setSelectedX(bool yes); + PIVector > collectX() const; PIMap cd; mutable PIMap s; diff --git a/cd_utils/cdutils_x.cpp b/cd_utils/cdutils_x.cpp new file mode 100644 index 0000000..546589f --- /dev/null +++ b/cd_utils/cdutils_x.cpp @@ -0,0 +1,39 @@ +#include "cdutils_x.h" +#include "cdutils_core.h" + +using namespace CDUtils; + +XInterface X; + + +XInterface::XInterface(): Interface(CDType::cdX) { + CONNECTU(core, X_Sended, this, sended); + CONNECTU(core, X_SendFail, this, sendFailed); + CONNECTU(core, X_Received, this, received); + CONNECTU(core, X_ReceiveFail, this, receiveFailed); +} + + +void XInterface::send() { + core->X_Send(); +} + + +void XInterface::request() { + core->X_Request(); +} + + +void XInterface::setEnabled(const CDType & x, bool en) { + CDType & t((*s)[x.path()]); + if (t.cd_type() != CDType::cdX) return; + core->x_mutex.lock(); + t.x_enabled = en; + core->need_rebuild_x = true; + core->x_mutex.unlock(); +} + + +void XInterface::start(double freq) { + core->startX(freq); +} diff --git a/cd_utils/cdutils_x.h b/cd_utils/cdutils_x.h new file mode 100644 index 0000000..00b5c10 --- /dev/null +++ b/cd_utils/cdutils_x.h @@ -0,0 +1,37 @@ +#ifndef CDUTILS_X_H +#define CDUTILS_X_H + +#include "cdutils_interface.h" + + +namespace CDUtils { + + +class XInterface: public Interface +{ + PIOBJECT(CDUtils::XInterface) +public: + XInterface(); + + EVENT(sended) + EVENT(sendFailed) + EVENT(received) + EVENT(receiveFailed) + EVENT1(keepNamesRequest, bool*, xn) + EVENT_HANDLER(void, send); + EVENT_HANDLER(void, request); + + void enable(const CDType & x) {setEnabled(x, true);} + void disable(const CDType & x) {setEnabled(x, false);} + void setEnabled(const CDType & x, bool en); + void setDisabled(const CDType & x, bool dis) {setEnabled(x, !dis);} + + void start(double freq = 20.); + +}; + +} + +extern CDUtils::XInterface X; + +#endif // CDUTILS_X_H diff --git a/cd_utils/cdutilstest.cpp b/cd_utils/cdutilstest.cpp index 9ef166b..939424a 100644 --- a/cd_utils/cdutilstest.cpp +++ b/cd_utils/cdutilstest.cpp @@ -1,7 +1,10 @@ #include "cdutils_k.h" +#include "cdutils_x.h" +#include "cdutils_c.h" #include "cdutils_core.h" #include "cdtest.h" #include "pip.h" +#include using namespace CDUtils; @@ -13,6 +16,7 @@ class Core : public PIObject CDCore::instance()->initApp(); // piCout << "testCore"; CONNECTU(&t, tickEvent, this, timerDone); + CONNECTU(&C, received, this, crecv); t.start(1000); } @@ -44,14 +48,21 @@ class Core : public PIObject } void test() { - piCout << "count" << K.count(); + /*piCout << "count" << K.count(); piCout << K[First]; - piCout << K[Second]; + piCout << K[Second];*/ } EVENT_HANDLER(void, ksend) {piCout << "sended k";} - EVENT_HANDLER(void, krecv) {piCout << "received k";} + EVENT_HANDLER(void, crecv) { + piCout << "received c"; + C.connect(C.section(KD::Logs).section(KD::Spec).section(KD::Formats)[KD::Binary], this, HANDLER(cmd)); + C.autoConnect(this); + } EVENT_HANDLER(void, timerDone) {test();} + EVENT_HANDLER(void, cmd) {piCout << "command cmd";} + EVENT_HANDLER(void, c_Pause) {piCout << "command pause";} + EVENT_HANDLER(void, c_Spectrometer_Connection) {piCout << "command spec_conn";} private: PIFile rf; diff --git a/piqt_utils/piconnedit/piconnedit_main.cpp b/piqt_utils/piconnedit/piconnedit_main.cpp index eef79ac..27c6e65 100644 --- a/piqt_utils/piconnedit/piconnedit_main.cpp +++ b/piqt_utils/piconnedit/piconnedit_main.cpp @@ -10,9 +10,6 @@ int main(int argc, char * argv[]) { #if QT_VERSION >= 0x050000 a.setAttribute(Qt::AA_UseHighDpiPixmaps, true); #endif - EvalSpinBox es; - es.show(); - return a.exec(); ConnectionEdit w; if (a.arguments().size() > 1) { QPIConfig cfg(a.arguments()[1]); @@ -31,5 +28,5 @@ int main(int argc, char * argv[]) { } } } - return 0; + return a.exec(); } diff --git a/qad/widgets/qvariantedit.cpp b/qad/widgets/qvariantedit.cpp index f9a8774..14aa6ae 100644 --- a/qad/widgets/qvariantedit.cpp +++ b/qad/widgets/qvariantedit.cpp @@ -104,7 +104,7 @@ PathEdit::PathEdit(QWidget * parent): QWidget(parent), lay(QBoxLayout::LeftToRig is_dir = is_abs = false; filter = tr("All files(*)"); line = new CLineEdit(this); - line->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + //line->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); butt_select = new QPushButton(this); //butt_select->setIconSize(QSize(16, 16)); butt_select->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); @@ -128,6 +128,12 @@ void PathEdit::changeEvent(QEvent * e) { } +void PathEdit::resizeEvent(QResizeEvent *) { + butt_select->setMaximumHeight(line->height()); + +} + + void PathEdit::select() { QString ret; if (is_dir) ret = QFileDialog::getExistingDirectory(this, tr("Select directory"), value()); @@ -143,6 +149,8 @@ void PathEdit::select() { QVariantEdit::QVariantEdit(QWidget * parent): QWidget(parent) { + setLayout(new QBoxLayout(QBoxLayout::TopToBottom)); + layout()->setContentsMargins(0, 0, 0, 0); _empty = 0; _line = 0; _check = 0; @@ -166,7 +174,7 @@ QVariantEdit::~QVariantEdit() { void QVariantEdit::resizeEvent(QResizeEvent * e) { - _resize(); + //_resize(); QWidget::resizeEvent(e); } @@ -310,7 +318,7 @@ void QVariantEdit::_recreate(const QVariant & new_value) { //qDebug() << _cur_edit; if (_cur_edit) { _resize(); - _cur_edit->show(); + //_cur_edit->show(); } _value = new_value; } @@ -405,6 +413,12 @@ void QVariantEdit::_delete() { } +void QVariantEdit::_resize() { + if (!_cur_edit) return; + layout()->addWidget(_cur_edit); +} + + void QVariantEdit::_newPath() { _delete(); _path = new PathEdit(this); @@ -412,7 +426,7 @@ void QVariantEdit::_newPath() { _value = _value.toString(); connect(_path, SIGNAL(valueChanged()), this, SLOT(_changed())); _resize(); - _cur_edit->show(); + //_cur_edit->show(); } diff --git a/qad/widgets/qvariantedit.h b/qad/widgets/qvariantedit.h index d371050..6dbeda3 100644 --- a/qad/widgets/qvariantedit.h +++ b/qad/widgets/qvariantedit.h @@ -60,7 +60,8 @@ public: private: virtual void changeEvent(QEvent * e); - + virtual void resizeEvent(QResizeEvent * ); + QBoxLayout lay; CLineEdit * line; QPushButton * butt_select; @@ -89,14 +90,14 @@ public: ~QVariantEdit(); QVariant value() const; - QSize sizeHint() const {if (_cur_edit) return _cur_edit->sizeHint(); return QWidget::sizeHint();} - QSize minimumSizeHint() const {if (_cur_edit) return _cur_edit->minimumSizeHint(); return QWidget::minimumSizeHint();} + //QSize sizeHint() const {if (_cur_edit) return _cur_edit->sizeHint(); return QWidget::sizeHint();} + //QSize minimumSizeHint() const {if (_cur_edit) return _cur_edit->minimumSizeHint(); return QWidget::minimumSizeHint();} protected: - void resizeEvent(QResizeEvent * ); + virtual void resizeEvent(QResizeEvent * ); void _recreate(const QVariant & new_value); void _delete(); - void _resize() {if (_cur_edit) _cur_edit->resize(size());} + void _resize(); void _newPath(); void _setEnum(const QAD::Enum & v); void _setFile(const QAD::File & v); diff --git a/qcd_utils/pult/cdgraphics.cpp b/qcd_utils/pult/cdgraphics.cpp index f29d94e..aeedc62 100644 --- a/qcd_utils/pult/cdgraphics.cpp +++ b/qcd_utils/pult/cdgraphics.cpp @@ -1,11 +1,60 @@ #include "cdgraphics.h" #include "cdutils_core.h" +#include "cdutils_x.h" #include "qcd_core.h" #include "qcd_model.h" +#include "graphic.h" +#include "piqt.h" +#include +#include +#include +#include +#include +#include +#include + +using namespace CDUtils; + + +GDockWidget::GDockWidget(QString title, QMainWindow * p): QDockWidget(title, p) { + da = p; + menu = new QMenu(this); + QAction * a = new QAction(QIcon(":/icons/document-edit.png"), "Rename ...", this); + connect(a, SIGNAL(triggered(bool)), this, SLOT(rename())); + dactions << a; + a = new QAction(QIcon(":/icons/edit-delete.png"), "Remove", this); + connect(a, SIGNAL(triggered(bool)), this, SIGNAL(removeRequest())); + dactions << a; +} + + +void GDockWidget::contextMenuEvent(QContextMenuEvent * e) { + QMenu * mwm = da->createPopupMenu(); + menu->clear(); + menu->addActions(dactions); + menu->addSeparator(); + menu->addActions(mwm->actions()); + menu->popup(e->globalPos()); + mwm->deleteLater(); +} + + +void GDockWidget::rename() { + QString nn = QInputDialog::getText(this, trUtf8("Rename area"), trUtf8("New area name:"), + QLineEdit::Normal, windowTitle()); + if (nn.isEmpty()) return; + setWindowTitle(nn); +} + + CDGraphics::CDGraphics(QWidget * parent) : QWidget(parent), Ui::CDGraphics() { setupUi(this); + da = new QMainWindow(); + da->setWindowFlags(frame->windowFlags()); + da->setDockNestingEnabled(true); + layoutMain->addWidget(da); } @@ -15,3 +64,97 @@ CDGraphics::~CDGraphics() { void CDGraphics::reset() { } + + +bool CDGraphics::eventFilter(QObject * o, QEvent * e) { + //if (o == graphic->viewport()) { + switch (e->type()) { + case QEvent::DragEnter: { + QDragEnterEvent * de = (QDragEnterEvent*)e; + const QMimeData * mime = de->mimeData(); + //qDebug() << "enter" << mime; + if (!mime) break; + if (mime->text().isEmpty()) break; + de->setDropAction(Qt::CopyAction); + de->accept(); + return true; + } break; + case QEvent::Drop: { + QDropEvent * de = (QDropEvent*)e; + const QMimeData * mime = de->mimeData(); + if (!mime) break; + //qDebug() << "drop" << mime->text(); + if (mime->text().isEmpty()) break; + addXToGraphic(mime->text(), viewportGraphic(o)); + de->accept(); + return true; + } break; + default: break; + } + //} + return QWidget::eventFilter(o, e); +} + + +Graphic * CDGraphics::viewportGraphic(QObject * o) const { + if (!o) return 0; + while (!qobject_cast(o) && o) + o = o->parent(); + return qobject_cast(o); +} + + +void CDGraphics::addGraphic() { + Graphic * g = new Graphic(); + g->setGraphicsCount(0); + g->setBorderInputsVisible(false); + g->setLegendVisible(true); + g->viewport()->setAcceptDrops(true); + g->viewport()->installEventFilter(this); + GDockWidget * dw = new GDockWidget(QString("graphics %1").arg(graphics.size()), da); + connect(dw, SIGNAL(removeRequest()), this, SLOT(removeGraphic())); + dw->setWidget(g); + da->addDockWidget(Qt::RightDockWidgetArea, dw); + docks << dw; + graphics << g; +} + + +void CDGraphics::removeGraphic() { + GDockWidget * d = qobject_cast(sender()); + if (!d) return; + Graphic * g = qobject_cast(d->widget()); + docks.removeAll(d); + graphics.removeAll(g); + g->deleteLater(); + d->deleteLater(); +} + + +void CDGraphics::addXToGraphic(const QString & xp, Graphic * g) { + qDebug() << "addGraphic" << xp << g; + if (xp.isEmpty() || !g) return; + CDType & t(X[CDCore::stringToPath(Q2PIString(xp))]); + int gind = g->graphicsCount(); + g->setGraphicsCount(gind + 1); + g->setGraphicName(PI2QString(t.pathString().join(".")), gind); +} + + +void CDGraphics::on_buttonAdd_clicked() { + addGraphic(); +} + + +void CDGraphics::on_buttonClear_clicked() { + foreach (Graphic * g, graphics) + g->clear(); +} + + +void CDGraphics::on_buttonRemoveAll_clicked() { + qDeleteAll(graphics); + qDeleteAll(docks); + graphics.clear(); + docks.clear(); +} diff --git a/qcd_utils/pult/cdgraphics.h b/qcd_utils/pult/cdgraphics.h index 9b83bf2..f174c8f 100644 --- a/qcd_utils/pult/cdgraphics.h +++ b/qcd_utils/pult/cdgraphics.h @@ -2,8 +2,28 @@ #define CDGRAPHICS_H #include +#include +#include #include "ui_cdgraphics.h" +class QMainWindow; +class Graphic; + + +class GDockWidget: public QDockWidget { + Q_OBJECT +public: + GDockWidget(QString title = QString(), QMainWindow * p = 0); + void contextMenuEvent(QContextMenuEvent * e); + QMenu * menu; + QList dactions; + QMainWindow * da; +private slots: + void rename(); +signals: + void removeRequest(); +}; + class CDGraphics : public QWidget, public Ui::CDGraphics { @@ -15,8 +35,20 @@ public: void reset(); private: + bool eventFilter(QObject * o, QEvent * e); + Graphic * viewportGraphic(QObject * o) const; + void addXToGraphic(const QString & xp, Graphic * g); + void addGraphic(); + + QList graphics; + QList docks; + QMainWindow * da; private slots: + void removeGraphic(); + void on_buttonAdd_clicked(); + void on_buttonClear_clicked(); + void on_buttonRemoveAll_clicked(); signals: diff --git a/qcd_utils/pult/cdgraphics.ui b/qcd_utils/pult/cdgraphics.ui index ec8c364..e5f7336 100644 --- a/qcd_utils/pult/cdgraphics.ui +++ b/qcd_utils/pult/cdgraphics.ui @@ -6,14 +6,85 @@ 0 0 - 689 - 459 + 624 + 411 CD Pult + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + + + + Add new + + + + :/icons/list-add.png:/icons/list-add.png + + + + + + + Clear all + + + + :/icons/edit-clear.png:/icons/edit-clear.png + + + + + + + Remove all + + + + :/icons/edit-delete.png:/icons/edit-delete.png + + + + + + + Qt::Horizontal + + + + 1 + 20 + + + + + + + + - + + + diff --git a/qcd_utils/pult/cdpult.qrc b/qcd_utils/pult/cdpult.qrc index 59858dc..b3dc107 100644 --- a/qcd_utils/pult/cdpult.qrc +++ b/qcd_utils/pult/cdpult.qrc @@ -10,5 +10,6 @@ icons/document-revert.png icons/flame.png icons/view-refresh.png + icons/format-stroke-color.png diff --git a/qcd_utils/pult/cdpultwindow.cpp b/qcd_utils/pult/cdpultwindow.cpp index f909b72..33dfa8a 100644 --- a/qcd_utils/pult/cdpultwindow.cpp +++ b/qcd_utils/pult/cdpultwindow.cpp @@ -17,6 +17,7 @@ CDPultWindow::CDPultWindow(QWidget *parent) : EMainWindow(parent), Ui::CDPultWin CDUtils::CDCore::instance()->initPult(); widgetK->setType(CDUtils::CDType::cdK); widgetX->setType(CDUtils::CDType::cdX); + widgetC->setType(CDUtils::CDType::cdC); editFileK->setValue(QVariant::fromValue(QAD::File("", "*.dat"))); editFileX->setValue(QVariant::fromValue(QAD::File("", "*.dat"))); editFileC->setValue(QVariant::fromValue(QAD::File("", "*.dat"))); @@ -32,6 +33,7 @@ CDPultWindow::CDPultWindow(QWidget *parent) : EMainWindow(parent), Ui::CDPultWin reset(); connect(widgetK, SIGNAL(addToLog(CDViewWidget::LogIcon,QString)), this, SLOT(addToLog(CDViewWidget::LogIcon,QString))); connect(widgetX, SIGNAL(addToLog(CDViewWidget::LogIcon,QString)), this, SLOT(addToLog(CDViewWidget::LogIcon,QString))); + connect(widgetC, SIGNAL(addToLog(CDViewWidget::LogIcon,QString)), this, SLOT(addToLog(CDViewWidget::LogIcon,QString))); if (windowState() == Qt::WindowMinimized) setWindowState(Qt::WindowNoState); } @@ -154,9 +156,10 @@ void CDPultWindow::on_editFileK_valueChanged(const QVariant & p) { void CDPultWindow::on_buttonSessionApply_clicked() { widgetK->setFile(editFileK->value().value().file); widgetX->setFile(editFileX->value().value().file); + widgetC->setFile(editFileC->value().value().file); dockCDKView->setVisible(checkHasK->isChecked()); dockCDXView->setVisible(checkHasX->isChecked()); - //dockCDCView->setVisible(checkHasC->isChecked()); + dockCDCView->setVisible(checkHasC->isChecked()); } diff --git a/qcd_utils/pult/cdpultwindow.ui b/qcd_utils/pult/cdpultwindow.ui index 666d73a..bacf238 100644 --- a/qcd_utils/pult/cdpultwindow.ui +++ b/qcd_utils/pult/cdpultwindow.ui @@ -90,21 +90,6 @@ - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - @@ -311,6 +296,44 @@ + + + + :/icons/legend.png:/icons/legend.png + + + C + + + 1 + + + + + + + + + + + + + :/icons/format-stroke-color.png:/icons/format-stroke-color.png + + + Graphics + + + 8 + + + + + + + + + @@ -418,6 +441,10 @@ + + + + @@ -448,9 +475,16 @@
cdviewwidget.h
1
+ + CDGraphics + QWidget +
cdgraphics.h
+ 1 +
+ diff --git a/qcd_utils/pult/cdviewwidget.ui b/qcd_utils/pult/cdviewwidget.ui index 9d01778..00e18e6 100644 --- a/qcd_utils/pult/cdviewwidget.ui +++ b/qcd_utils/pult/cdviewwidget.ui @@ -58,7 +58,7 @@ Receive
- + :/icons/document-revert.png:/icons/document-revert.png @@ -69,7 +69,7 @@ Update description ... - + :/icons/view-refresh.png:/icons/view-refresh.png @@ -80,7 +80,7 @@ Send - + :/icons/flame.png:/icons/flame.png @@ -97,6 +97,12 @@ QAbstractItemView::AnyKeyPressed|QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed + + true + + + QAbstractItemView::DragOnly + QAbstractItemView::ScrollPerPixel @@ -116,6 +122,7 @@ + diff --git a/qcd_utils/pult/icons/format-stroke-color.png b/qcd_utils/pult/icons/format-stroke-color.png new file mode 100644 index 0000000000000000000000000000000000000000..4c4d29007b7ccf9270085d693fcaec27053ed9b0 GIT binary patch literal 24156 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 MWi6#Dm{rLC0A@5kjsO4v literal 0 HcmV?d00001 diff --git a/qcd_utils/qcd_model.cpp b/qcd_utils/qcd_model.cpp index 5ead0a2..a0e31ab 100644 --- a/qcd_utils/qcd_model.cpp +++ b/qcd_utils/qcd_model.cpp @@ -1,22 +1,23 @@ #include "qcd_model.h" #include "cdutils_interface.h" #include "cdutils_core.h" +#include "cdutils_x.h" #include "piqt.h" #include #include #include +#include #include "qvariantedit.h" #include "qad_types.h" using namespace CDUtils; - // CDKItem -CDItem::CDItem(CDUtils::Interface * i, int index, CDItem::CDItemType type, CDItem *parent) { +CDItem::CDItem(CDUtils::Interface * i, int _index, CDItem::CDItemType type, CDItem *parent) { interface = i; - index_ = index; + index_ = _index; parent_ = parent; type_ = type; } @@ -31,20 +32,25 @@ QVariant CDItem::data(int column, int role) const { if (role == Qt::BackgroundRole) { switch (type_) { case ItemCDType: { - CDType & t = interface->section(buildPath())[index_]; + CDType & t(interface->section(buildPath())[index_]); if (t.errorString().isEmpty()) return QBrush(QColor(255, 250, 230)); else return QBrush(QColor(255, 128, 128)); } case ItemCDSection: return QBrush(QColor(230, 250, 230)); } } - if (role == Qt::CheckStateRole && type_ == ItemCDType && column == 4) { - CDType & t = interface->section(buildPath())[index_]; - if (t.type() == "b") return t.toBool() ? Qt::Checked : Qt::Unchecked; - else QVariant(); + if (role == Qt::CheckStateRole && type_ == ItemCDType) { + CDType & t(interface->section(buildPath())[index_]); + if (column == cValue && t.cd_type() == CDType::cdK) { + if (t.type() == "b") return t.toBool() ? Qt::Checked : Qt::Unchecked; + else QVariant(); + } + if (column == cName_Cmd && t.cd_type() == CDType::cdX) { + return t.isSelectedX() ? Qt::Checked : Qt::Unchecked; + } } if (role == Qt::ToolTipRole && type_ == ItemCDType) { - CDType & t = interface->section(buildPath())[index_]; + CDType & t(interface->section(buildPath())[index_]); return PI2QString(t.errorString()); } if (role != Qt::DisplayRole && role != Qt::EditRole) return QVariant(); @@ -54,12 +60,14 @@ QVariant CDItem::data(int column, int role) const { switch (type_) { case ItemCDType: switch (column) { - case 0: return QString::number(index_); - case 1: return PI2QString(rs[index_].name()); - case 2: return stringType(rs[index_].type()); - case 3: return PI2QString(rs[index_].formula()); - case 4: return value(rs[index_], role); - case 5: return PI2QString(rs[index_].comment()); + case cID: return QString::number(index_); + case cName_Cmd: return PI2QString(rs[index_].name()); + case cType: return stringType(rs[index_].type()); + case cXMode: return QVariant::fromValue(xModeEnum(rs[index_].xmode())); + case cXAvg: return rs[index_].avg(); + case cExpression: return PI2QString(rs[index_].formula()); + case cValue: return value(rs[index_], role); + case cComment: return PI2QString(rs[index_].comment()); default: break; } break; @@ -67,9 +75,9 @@ QVariant CDItem::data(int column, int role) const { s = rs.section(index_); // piCout << rs.name << rs.alias << s.name << s.alias; switch (column) { - case 0: return QString("[") + QString::number(index_) + QString("]"); - case 1: return PI2QString(s.alias); - case 2: return PI2QString(s.name); + case cID: return QString("[") + QString::number(index_) + QString("]"); + case cName_Cmd: return PI2QString(s.alias); + case cType: return PI2QString(s.name); default: break; } break; @@ -92,11 +100,28 @@ QVariant CDItem::value(CDType t, int role) const { } -bool CDItem::setData(int column, const QVariant &value) { - if ((column == 3 || column == 4) && type_ == ItemCDType) { - interface->section(buildPath())[index_].setValue(Q2PIString(value.toString())); - interface->calculate(); - return true; +bool CDItem::setData(int column, const QVariant & value) { + if (type_ == ItemCDType) { + CDType & t(interface->section(buildPath())[index_]); + if ((column == cExpression || column == cValue) && (t.cd_type() == CDType::cdK)) { + interface->section(buildPath())[index_].setValue(Q2PIString(value.toString())); + interface->calculate(); + return true; + } + if (t.cd_type() == CDType::cdX) { + switch (column) { + case cName_Cmd: + X.setEnabled(t, value.toBool()); + return true; + case cXMode: + t.setXMode((CDType::XMode)value.toInt()); + return true; + case cXAvg: + t.setAvg(piMax(value.toInt(), 1)); + return true; + default: break; + } + } } return false; } @@ -136,13 +161,51 @@ QString CDItem::stringType(const PIString & t) const { } +QAD::Enum CDItem::xModeEnum(int v) const { + QAD::Enum ret; + ret << QAD::Enumerator(CDType::X_Current, "Current") + << QAD::Enumerator(CDType::X_All_Avg, "All, Averaging"); + ret.selectValue(v); + return ret; +} + + // CDKDelegate CDDelegate::CDDelegate(QObject *parent) : QStyledItemDelegate(parent) { } -QWidget *CDDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const { +void CDDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const { + CDItem * item = ((CDItemModel*)index.model())->getItem(index); + if (item) { + if (item->itemType() == CDItem::ItemCDType && item->interface->cdType() == CDType::cdC) { + QStyleOptionButton bo; + bo.direction = option.direction; + bo.fontMetrics = option.fontMetrics; + bo.palette = option.palette; + bo.rect = option.rect; + bo.state = option.state;// & ~(QStyle::State_HasFocus | QStyle::State_MouseOver); + bo.text = item->data(1, Qt::DisplayRole).toString(); + QWidget * v = (QWidget*)(painter->device()); + if (v) { + QPoint cp = v->mapFromGlobal(QCursor::pos()); + if (bo.rect.contains(cp, true)) { + //bo.state |= QStyle::State_MouseOver; + if (qApp->mouseButtons().testFlag(Qt::LeftButton)) + bo.state |= QStyle::State_On; + } + } + qApp->style()->drawControl(QStyle::CE_PushButton, &bo, painter); + return; + } + } + QStyledItemDelegate::paint(painter, option, index); + +} + + +QWidget * CDDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const { return new QVariantEdit(parent); } @@ -192,7 +255,7 @@ CDItemModel::~CDItemModel() { QVariant CDItemModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) return QVariant(); - CDItem *item = getItem(index); + CDItem * item = getItem(index); return item->data(index.column(), role); } @@ -200,12 +263,14 @@ QVariant CDItemModel::data(const QModelIndex &index, int role) const { QVariant CDItemModel::headerData(int section, Qt::Orientation orientation, int role) const { if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { switch (section) { - case 0: return trUtf8("Index"); - case 1: return trUtf8("Name"); - case 2: return trUtf8("Type"); - case 3: return trUtf8("Expression"); - case 4: return trUtf8("Value"); - case 5: return trUtf8("Comment"); + case cID: return trUtf8("Index"); + case cName_Cmd: return interface->cdType() == CDType::cdC ? trUtf8("Command") : trUtf8("Name"); + case cType: return trUtf8("Type"); + case cXMode: return trUtf8("Mode"); + case cXAvg: return trUtf8("Averaging"); + case cExpression: return trUtf8("Expression"); + case cValue: return trUtf8("Value"); + case cComment: return trUtf8("Comment"); } } return QVariant(); @@ -213,7 +278,7 @@ QVariant CDItemModel::headerData(int section, Qt::Orientation orientation, int r QModelIndex CDItemModel::index(int row, int column, const QModelIndex &parent) const { - if (parent.isValid() && parent.column() != 0) return QModelIndex(); + if (parent.isValid() && parent.column() != cID) return QModelIndex(); CDItem * p = getItem(parent); CDItem * c = p->childs.value(row, 0); if (c) return createIndex(row, column, c); @@ -226,18 +291,18 @@ QModelIndex CDItemModel::parent(const QModelIndex &index) const { CDItem * c = getItem(index); CDItem * p = c->parent_; if (p == root) return QModelIndex(); - return createIndex(p->parent_->childs.indexOf(p), 0, p); + return createIndex(p->parent_->childs.indexOf(p), cID, p); } int CDItemModel::rowCount(const QModelIndex &parent) const { - CDItem *p = getItem(parent); + CDItem * p = getItem(parent); return p->childs.count(); } int CDItemModel::columnCount(const QModelIndex &parent) const { - return 6; + return cLastColumn; } @@ -246,30 +311,42 @@ Qt::ItemFlags CDItemModel::flags(const QModelIndex & index) const { Qt::ItemFlags f = Qt::ItemIsEnabled | Qt::ItemIsSelectable; CDItem * item = getItem(index); if (!item) return 0; - CDType & t(interface->section(item->buildPath())[item->index_]); - if ((index.column() == 3 || index.column() == 4) && - (item->type_ == CDItem::ItemCDType) && - (t.cd_type() == CDType::cdK)) - f |= Qt::ItemIsEditable; - if (item->type_ == CDItem::ItemCDType && index.column() == 4) { - if (t.type() == "b") { - f |= Qt::ItemIsUserCheckable; -// piCout << "ItemIsUserCheckable"; + if (item->type_ == CDItem::ItemCDType) { + CDType & t(interface->section(item->buildPath())[item->index_]); + if (t.cd_type() == CDType::cdK) { + if (index.column() == cExpression || index.column() == cValue) + f |= Qt::ItemIsEditable; + if (index.column() == cValue && t.type() == "b") + f |= Qt::ItemIsUserCheckable; + } + if (t.cd_type() == CDType::cdX) { + if (index.column() == cXMode || index.column() == cXAvg) + f |= Qt::ItemIsEditable; + if (index.column() == cName_Cmd) + f |= Qt::ItemIsUserCheckable | Qt::ItemIsDragEnabled; } } return f; } -bool CDItemModel::setData(const QModelIndex & index, const QVariant &value, int role) { - if (role == Qt::CheckStateRole && index.column() == 4) { +bool CDItemModel::setData(const QModelIndex & index, const QVariant & value, int role) { + if (role == Qt::CheckStateRole && (index.column() == cName_Cmd || index.column() == cValue)) { CDItem * item = getItem(index); if (item->type_ == CDItem::ItemCDType) { - CDType t = interface->section(item->buildPath())[item->index_]; - if (t.type() == "b") { - bool result = item->setData(index.column(), PI2QString(PIString::fromBool(value.toBool()))); - QModelIndex rin(CDItemModel::index(index.row(), 3, index.parent())); - emit dataChanged(rin, rin); + CDType & t(interface->section(item->buildPath())[item->index_]); + if (index.column() == cValue && (t.cd_type() == CDType::cdK)) { + if (t.type() == "b") { + bool result = item->setData(index.column(), PI2QString(PIString::fromBool(value.toBool()))); + QModelIndex rin(CDItemModel::index(index.row(), cExpression, index.parent())); + emit dataChanged(rin, rin); + return result; + } + } + if (index.column() == cName_Cmd && (t.cd_type() == CDType::cdX)) { + bool result = item->setData(index.column(), value); + //QModelIndex rin(CDItemModel::index(index.row(), 1, index.parent())); + //emit dataChanged(rin, rin); return result; } } @@ -278,7 +355,7 @@ bool CDItemModel::setData(const QModelIndex & index, const QVariant &value, int CDItem * item = getItem(index); bool result = item->setData(index.column(), value); if (result) { - QModelIndex rin(CDItemModel::index(index.row(), 3, index.parent())); + QModelIndex rin(CDItemModel::index(index.row(), cExpression, index.parent())); emit dataChanged(rin, rin); emit dataChanged(index, index); } @@ -286,6 +363,23 @@ bool CDItemModel::setData(const QModelIndex & index, const QVariant &value, int } +QMimeData * CDItemModel::mimeData(const QModelIndexList & indexes) const { + if (indexes.size() == 1) { + QModelIndex index = indexes[0]; + if (index.isValid() && interface->cdType() == CDType::cdX) { + CDItem * item = getItem(index); + if (item) { + CDType & t(interface->section(item->buildPath())[item->index_]); + QMimeData * mime = new QMimeData(); + mime->setText(PI2QString(CDCore::pathToString(t.path()))); + return mime; + } + } + } + return QAbstractItemModel::mimeData(indexes); +} + + void CDItemModel::rebuildModel() { beginResetModel(); internalRebuild(); diff --git a/qcd_utils/qcd_model.h b/qcd_utils/qcd_model.h index 75a3357..29c9204 100644 --- a/qcd_utils/qcd_model.h +++ b/qcd_utils/qcd_model.h @@ -10,6 +10,18 @@ namespace CDUtils { class CDType; class CDSection; class Interface; + + enum Column { + cID , + cName_Cmd , + cType , + cXMode , + cXAvg , + cExpression, + cValue , + cComment , + cLastColumn, + }; } namespace QAD { @@ -23,17 +35,21 @@ class CDItem { friend class CDItemModel; public: enum CDItemType{ItemCDType, ItemCDSection}; - CDItem(CDUtils::Interface * interface, int index, CDItemType type, CDItem * parent); + CDItem(CDUtils::Interface * interface, int _index, CDItemType type, CDItem * parent); ~CDItem(); QVariant data(int column, int role) const; QVariant value(CDUtils::CDType t, int role) const; bool setData(int column, const QVariant & value); - -private: + CDItemType itemType() const {return type_;} PIDeque buildPath() const; - QString stringType(const PIString & t) const; + int index() const {return index_;} CDUtils::Interface * interface; + +private: + QString stringType(const PIString & t) const; + QAD::Enum xModeEnum(int v) const; + CDItem * parent_; int index_; CDItemType type_; @@ -47,16 +63,19 @@ class CDDelegate : public QStyledItemDelegate public: CDDelegate(QObject *parent = 0); + void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const; QWidget * createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const; void setEditorData(QWidget *editor, const QModelIndex &index) const; void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const; QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; + }; class CDItemModel : public QAbstractItemModel { Q_OBJECT + friend class CDView; public: explicit CDItemModel(int type_, QObject *parent = 0); ~CDItemModel(); @@ -69,6 +88,8 @@ public: int columnCount(const QModelIndex &parent = QModelIndex()) const; Qt::ItemFlags flags(const QModelIndex &index) const; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); + QMimeData * mimeData(const QModelIndexList & indexes) const; + CDItem * getItem(const QModelIndex & index) const; void buildItem(CDItem * it, CDUtils::CDSection &r); @@ -78,7 +99,6 @@ public slots: private: void internalRebuild(); - CDItem * getItem(const QModelIndex & index) const; CDUtils::Interface * interface; CDItem * root; diff --git a/qcd_utils/qcd_view.cpp b/qcd_utils/qcd_view.cpp index cdc53a4..daae036 100644 --- a/qcd_utils/qcd_view.cpp +++ b/qcd_utils/qcd_view.cpp @@ -1,6 +1,8 @@ #include +#include #include "cdutils_k.h" #include "cdutils_x.h" +#include "cdutils_c.h" #include "cdutils_core.h" #include "qcd_view.h" #include "qcd_model.h" @@ -10,9 +12,10 @@ using namespace CDUtils; -CDView::CDView(QWidget *parent) : QTreeView(parent) { +CDView::CDView(QWidget * parent) : QTreeView(parent) { type_ = -1; model_ = 0; + connect(this, SIGNAL(clicked(QModelIndex)), this, SLOT(indexClicked(QModelIndex))); connect(this, SIGNAL(_qcd_sendFailed()), this, SLOT(cd_sendFailed()), Qt::QueuedConnection); connect(this, SIGNAL(_qcd_sendSucceed()), this, SLOT(cd_sendSucceed()), Qt::QueuedConnection); connect(this, SIGNAL(_qcd_receiveFailed()), this, SLOT(cd_receiveFailed()), Qt::QueuedConnection); @@ -43,28 +46,76 @@ void CDView::setType(int cdt) { CONNECTU(&X, received, this, pi_cd_receiveSucceed); CONNECTU(&X, receiveFailed, this, pi_cd_receiveFailed); break; + case CDType::cdC: + CONNECTU(&C, sended, this, pi_cd_sendSucceed); + CONNECTU(&C, sendFailed, this, pi_cd_sendFailed); + CONNECTU(&C, received, this, pi_cd_receiveSucceed); + CONNECTU(&C, receiveFailed, this, pi_cd_receiveFailed); + break; default: break; } } +void CDView::mousePressEvent(QMouseEvent * e) { + if (type_ == CDType::cdC) { + QModelIndex i = indexAt(e->pos()); + if (i.isValid() && i.column() == cName_Cmd) + update(i); + } + QTreeView::mousePressEvent(e); +} + + +void CDView::mouseReleaseEvent(QMouseEvent * e) { + if (type_ == CDType::cdC) { + QModelIndex i = indexAt(e->pos()); + if (i.isValid() && i.column() == cName_Cmd) + update(i); + } + QTreeView::mouseReleaseEvent(e); +} + + +void CDView::currentChanged(const QModelIndex & cur, const QModelIndex & prev) { + if (type_ == CDType::cdC) { + if (prev.isValid() && prev.column() == cName_Cmd) + update(prev); + } + QTreeView::currentChanged(cur, prev); +} + + void CDView::refresh() { if (type_ < 0) return; if (!model_) { model_ = new CDItemModel(type_); setModel(model_); - setItemDelegateForColumn(4, new CDDelegate()); + setItemDelegateForColumn(type_ == CDType::cdC ? cName_Cmd : cValue, new CDDelegate()); + if (type_ == CDType::cdX) + setItemDelegateForColumn(cXMode, new CDDelegate()); } model_->rebuildModel(); switch ((CDType::cdT)type_) { + case CDType::cdK: + setColumnHidden(cXMode, true); + setColumnHidden(cXAvg, true); + break; case CDType::cdX: - setColumnHidden(3, true); + setColumnHidden(cExpression, true); + break; + case CDType::cdC: + setColumnHidden(cType, true); + setColumnHidden(cXMode, true); + setColumnHidden(cXAvg, true); + setColumnHidden(cExpression, true); + setColumnHidden(cValue, true); break; default: break; } expandAll(); - for (int i=0; i<6; i++) resizeColumnToContents(i); + for (int i = 0; i < model_->columnCount(); i++) resizeColumnToContents(i); } @@ -72,6 +123,7 @@ void CDView::setFile(const QString & filename) { switch ((CDType::cdT)type_) { case CDType::cdK: K.setFileName(Q2PIString(filename)); break; case CDType::cdX: X.setFileName(Q2PIString(filename)); break; + case CDType::cdC: C.setFileName(Q2PIString(filename)); break; default: break; } } @@ -81,16 +133,16 @@ bool CDView::inProgress() const { switch ((CDType::cdT)type_) { case CDType::cdK: return K.inProgress(); break; case CDType::cdX: return X.inProgress(); break; + case CDType::cdC: return C.inProgress(); break; default: break; } return false; } -void CDView::startPing() { +void CDView::startX(double freq) { switch ((CDType::cdT)type_) { - case CDType::cdK: K.startPing(); break; - case CDType::cdX: X.startPing(); break; + case CDType::cdX: X.start(freq); break; default: break; } } @@ -111,6 +163,7 @@ void CDView::send() { switch ((CDType::cdT)type_) { case CDType::cdK: K.send(); break; case CDType::cdX: X.send(); break; + case CDType::cdC: C.send(); break; default: break; } } @@ -121,6 +174,7 @@ void CDView::receive() { switch ((CDType::cdT)type_) { case CDType::cdK: K.request(); break; case CDType::cdX: X.request(); break; + case CDType::cdC: C.request(); break; default: break; } } @@ -130,6 +184,7 @@ void CDView::save() { switch ((CDType::cdT)type_) { case CDType::cdK: K.writeFile(); break; case CDType::cdX: X.writeFile(); break; + case CDType::cdC: C.writeFile(); break; default: break; } } @@ -145,6 +200,10 @@ void CDView::load() { X.readFile(); X.calculate(); break; + case CDType::cdC: + C.readFile(); + C.calculate(); + break; default: break; } refresh(); @@ -156,6 +215,7 @@ void CDView::clear() { switch ((CDType::cdT)type_) { case CDType::cdK: K.root() = CDSection(); break; case CDType::cdX: X.root() = CDSection(); break; + case CDType::cdC: C.root() = CDSection(); break; default: break; } refresh(); @@ -169,6 +229,7 @@ void CDView::buildFromHeader(const QString & description, int mode) { switch ((CDType::cdT)type_) { case CDType::cdK: K.update(&f, mode); break; case CDType::cdX: X.update(&f, mode); break; + case CDType::cdC: C.update(&f, mode); break; default: break; } refresh(); @@ -179,11 +240,25 @@ void CDView::calculate() { switch ((CDType::cdT)type_) { case CDType::cdK: K.calculate(); break; case CDType::cdX: X.calculate(); break; + case CDType::cdC: C.calculate(); break; default: break; } } +void CDView::indexClicked(const QModelIndex & i) { + if (!model_ || !i.isValid() || type_ != CDType::cdC || i.column() != cName_Cmd) return; + CDItem * item = model_->getItem(i); + if (!item) return; + if (item->itemType() != CDItem::ItemCDType) return; + CDType & t(model_->interface->section(item->buildPath())[item->index()]); + C.sendCommand(t); + emit commandSended(PI2QString(t.pathString().join("."))); + //piCout << t; + qDebug() << PI2QString(t.pathString().join(".")); +} + + void CDView::cd_sendFailed() { busyStatusChanged(false); emit messageStatus("send failed"); @@ -211,4 +286,3 @@ void CDView::cd_receiveSucceed() { emit messageStatus("receive success"); emit receiveSucceed(); } - diff --git a/qcd_utils/qcd_view.h b/qcd_utils/qcd_view.h index 487da91..815f864 100644 --- a/qcd_utils/qcd_view.h +++ b/qcd_utils/qcd_view.h @@ -22,12 +22,17 @@ public: void setType(int cdt); void setFile(const QString & filename); bool inProgress() const; - void startPing(); + void startX(double freq = 20.); CDUtils::CDSection * root(); QString typeLetter() const; CDItemModel * CDModel() {return model_;} +protected: + void mousePressEvent(QMouseEvent * ); + void mouseReleaseEvent(QMouseEvent * ); + void currentChanged(const QModelIndex & cur, const QModelIndex & prev); + public slots: void refresh(); void send(); @@ -39,6 +44,7 @@ public slots: void calculate(); private slots: + void indexClicked(const QModelIndex & i); void cd_sendFailed(); void cd_sendSucceed(); void cd_receiveFailed(); @@ -59,6 +65,7 @@ signals: void receiveFailed(); void receiveSucceed(); void messageStatus(QString msg); + void commandSended(QString msg); void busyStatusChanged(bool busy); void _qcd_sendFailed(); // PRIVATE