class ModelJson(QObjectListModel): def __init__(self, objname, parent=None): QObjectListModel.__init__(self, parent) self.setObjectName(str(objname)) self.m_locale = QLocale("es") #temp, auto changue when login #self.m_proxy = ProxyModelJson() self.m_order = "" self.boolMetadata = False self.m_fields = QJsonArray() #[]#QJsonArray self.m_fieldsPoint = [] #5.2up self.m_maxLimit = 100 self.m_domain = QJsonArray() #[]#QJsonArray self.m_orderTryton = QJsonArray() #[]#QJsonArray self.m_preferences = {} self.m_qjsonnetwork = QJsonNetwork() self.m_fieldsFormatDecimal = [] #QJsonArray self.m_fieldsFormatDateTime = [] #QJsonArray self.m_model_method_search = "" self.m_hasIndexOfId = {} self.m_engine = None #QQmlApplicationEngine() self.autoBusy = True self.boolSynchro = True # add synchronous call (calldirect), best performance! def prepareDeletion(self): if self.boolSynchro == False: self.m_qjsonnetwork.signalResponse.disconnect(self.slotJsonConnect) self.setFields(QJsonArray()) self.clear() @Slot(int, result=int) def indexisOfId(self, mid): #el index del record en el modelo, no en el proxy return self.m_hasIndexOfId.get(mid, -1) @Slot(bool) def activateMetadata(self, meta): self.boolMetadata = meta @Slot("QJsonObject") def setPreferences(self, preferences): self.m_preferences = preferences @Slot(str) def setOrderInternal( self, order ): # only proxy, defaul false, no es necesario con order tryton self.m_order = order if self.m_order != "": self.m_proxy.setSortData("order") self.m_proxy.setSortLocaleAware(True) self.m_proxy.sort(0, Qt.AscendingOrder) self.m_proxy.setSortRole(self.ObjectRole) @Slot(str, QJsonArray, int, QJsonArray, QJsonArray) def setSearch(self, model_method_search, domain, maxlimit, ordertryton, fields): self.m_maxLimit = maxlimit self.m_domain = domain #.toVariantList() self.m_orderTryton = ordertryton #.toVariantList() self.setFields(fields) self.m_model_method_search = model_method_search @Slot(str) def setModelMethod(self, model_method_search): self.m_model_method_search = model_method_search @Slot(QJsonArray) def setDomain(self, domain): self.m_domain = domain @Slot(int) def setMaxLimit(self, maxlimit): self.m_maxLimit = maxlimit @Slot(QJsonArray) def setOrder(self, ordertryton): self.m_orderTryton = ordertryton @Slot(QJsonArray) def setFields(self, fields): # si es [], son todos self.m_fields = fields self.m_fieldsPoint = [] for f in self.m_fields.toVariantList(): if f.find(".") != -1: self.m_fieldsPoint.append(f) @Slot(str) def setLanguage(self, language): self.m_locale = QLocale(language) @Slot() @Slot(QJsonArray) @Slot(QJsonArray, int) def find(self, domain=QJsonArray(), maxlimit=-1): # if domain!=QJsonArray(): self.m_domain = domain #.toVariantList() self.initSearch(maxlimit) @Slot() @Slot(int) def initSearch(self, maxlimit=-1): self.clear() self.m_hasIndexOfId = {} self.nextSearch(maxlimit) def addResult(self, result, update=False): #QJsonArray jsonobj = {} mis = self._count() for res in result: mid = int(res["id"]) mapJsonDoc = res jsonobj = {} order = "" if self.m_order == "" else mapJsonDoc[ self.m_order].strip() metadata = "" jsonobj = mapJsonDoc if self.boolMetadata: doct = QJsonDocument(mapJsonDoc) metadata = doct.toJson( QJsonDocument.Compact).data().decode("utf-8") # if self.m_fields!= QJsonArray(): if len(self.m_fieldsPoint) > 0: fieldsdoc = list(mapJsonDoc) for fp in self.m_fieldsPoint: if fp not in fieldsdoc: lfp = fp.split(".") for li in range(len(lfp) - 1): lfp[li] = lfp[li] + "." temp = jsonobj[lfp[0]] for c in lfp[1:]: if temp != None: temp = temp[c] jsonobj[fp] = temp for vp in self.m_fieldsFormatDecimal: v = vp[0] if jsonobj.__contains__(v): if jsonobj[v] != None: if jsonobj[v].__contains__("decimal"): jsonobj[v + "_format"] = self.m_locale.toString( float(jsonobj[v]["decimal"]), 'f', vp[1]) #add suport else: jsonobj[v + "_format"] = "" else: jsonobj[v + "_format"] = "" for v in self.m_fieldsFormatDateTime: mfield = v[0] mformat = v[1] if jsonobj.__contains__(mfield): mdateTime = QDateTime() if jsonobj[mfield] != None: if jsonobj[mfield].__contains__("__class__"): if jsonobj[mfield]["__class__"] == "date": mdateTime = QDateTime( QDate(jsonobj[mfield]["year"], jsonobj[mfield]["month"], jsonobj[mfield]["day"]), QTime()) if jsonobj[mfield]["__class__"] == "datetime": mdateTime = QDateTime( QDate(jsonobj[mfield]["year"], jsonobj[mfield]["month"], jsonobj[mfield]["day"]), QTime(jsonobj[mfield]["hour"], jsonobj[mfield]["minute"], jsonobj[mfield]["second"])) jsonobj[mfield + "_format"] = mdateTime.toString(mformat) else: jsonobj[mfield + "_format"] = "" else: jsonobj[mfield + "_format"] = "" if update == False: dataJson = DataJson(mid, order, jsonobj, metadata, self) self.append(dataJson) self.m_hasIndexOfId[mid] = mis mis += 1 else: index = self.indexisOfId(mid) if index != -1: self.at(index).setProperty("order", order) self.at(index).setProperty("json", jsonobj) self.at(index).setProperty("metadata", metadata) @Slot() @Slot(int) def nextSearch(self, maxlimit=-1): # metodo asincronico self.openBusy() limit = self.m_maxLimit if maxlimit != -1: limit = maxlimit params = QJsonArray() params.append(self.m_domain) params.append(self._count()) params.append(limit) params.append(self.m_orderTryton) params.append(self.m_fields) params.append(self.m_preferences) if self.boolSynchro: # result = self.m_qjsonnetwork.callDirect("nextSearch"+self.objectName(), self.m_model_method_search+".search_read" ,params) result = self.m_qjsonnetwork.recursiveCall( "nextSearch" + self.objectName(), self.m_model_method_search + ".search_read", params) reValue = result["data"] if reValue.__class__() == {}: if reValue.__contains__("result"): if reValue["result"].__class__() == []: self.addResult(reValue["result"]) self.closeBusy() else: self.m_qjsonnetwork.call( "nextSearch" + self.objectName(), self.m_model_method_search + ".search_read", params) @Slot(QJsonArray) # metodo asincronico def updateRecords(self, ids): #update record with tryton, self.openBusy() params = QJsonArray() params.append(ids) params.append(self.m_fields) params.append(self.m_preferences) if self.boolSynchro: # result = self.m_qjsonnetwork.callDirect("updateRecords"+self.objectName(), self.m_model_method_search+".read" ,params) result = self.m_qjsonnetwork.recursiveCall( "updateRecords" + self.objectName(), self.m_model_method_search + ".read", params) reValue = result["data"] if reValue.__class__() == {}: if reValue.__contains__("result"): if reValue["result"].__class__() == []: self.addResult(reValue["result"], True) self.closeBusy() else: self.m_qjsonnetwork.call("updateRecords" + self.objectName(), self.m_model_method_search + ".read", params) @Slot(int) def removeItem(self, mid): # elimina solo en memory, no afecta a base datos index = self.indexisOfId(mid) if index != -1: self.m_hasIndexOfId.pop(mid) self.removeAt(index) @Slot(QJsonArray) def addFieldFormatDecimal(self, fields): #ModelArticulo.addFieldFormatDecimal(['total_amount']); self.m_fieldsFormatDecimal = [] for v in fields.toVariantList(): if v.__class__() == '': self.m_fieldsFormatDecimal.append([v, 2]) elif v.__class__() == []: if v.__len__() == 2: if v[0].__class__() == '' and v[1].__class__() == 0: self.m_fieldsFormatDecimal.append(v) @Slot(QJsonArray) def addFieldFormatDateTime(self, fields): #ModelArticulo.addFieldFormatDateTime([['invoice_date','dd/MM/yy'],['create_date','dd/MM/yy hh:mm:ss']]); self.m_fieldsFormatDateTime = [] for v in fields.toVariantList(): if v.__class__() == []: if v.__len__() == 2: if v[0].__class__() == '' and v[1].__class__() == '': self.m_fieldsFormatDateTime.append(v) signalResponse = Signal(str, int) signalResponseData = Signal(str, int, "QJsonObject") #QJsonObject = dict @Slot(str, int, dict) # obsoleto mejor usar calldirect! def slotJsonConnect(self, pid, option, data): #cath datos de call, if pid == "nextSearch" + self.objectName(): if option == 2: #result dataObject = data["data"] if dataObject.__contains__("result"): if dataObject["result"].__class__() == []: self.addResult(dataObject["result"]) self.signalResponseData.emit( "nextSearch", option, {}) # ok envio emit de confirmacion else: #print("la data",data) self.signalResponseData.emit( "nextSearch", 5, data) #puede ser un error 403 timeout else: self.signalResponseData.emit("nextSearch", option, data) #dejo cruzar los datos if pid == "updateRecords" + self.objectName(): if option == 2: #result dataObject = data["data"] if dataObject.__contains__("result"): if dataObject["result"].__class__() == []: self.addResult(dataObject["result"], True) self.signalResponseData.emit( "updateRecords", option, {}) # ok envio emit de confirmacion else: #print("la data",data) self.signalResponseData.emit( "updateRecords", 5, data) #puede ser un error 403 timeout else: self.signalResponseData.emit("nextSearch", option, data) #dejo cruzar los datos def setProxy(self, proxp): self.m_proxy = proxp def setJsonConnect(self, jchac): #=None):#(QJsonNetwork *jchac=nullptr); self.m_qjsonnetwork = jchac self.connectSlotJC() def connectSlotJC(self): if self.boolSynchro == False: self.m_qjsonnetwork.signalResponse.connect(self.slotJsonConnect) # self.connect(self.m_qjsonnetwork, SIGNAL(signalResponse(QString,int,QJsonObject)), # self, SLOT(slotJsonConnect(QString,int,QJsonObject))); def setEngine(self, engine): self.m_engine = engine def openBusy(self): if self.autoBusy: if self.m_engine != None: root = self.m_engine.rootObjects()[0] QMetaObject.invokeMethod(root, "openBusy") def closeBusy(self): if self.autoBusy: if self.m_engine != None: root = self.m_engine.rootObjects()[0] QMetaObject.invokeMethod(root, "closeBusy") @Slot(bool) def setAutoBusy(self, busy): self.autoBusy = busy @Slot(bool) def setSynchro(self, syn): self.boolSynchro = syn self.connectSlotJC() def initProxy(self): if self.m_order != "": self.m_proxy.setSortData("order") self.m_proxy.setSortLocaleAware(True) self.m_proxy.sort(0, Qt.AscendingOrder) self.m_proxy.setSortRole(self.ObjectRole) self.m_proxy.setFilterRoles("metadata") self.m_proxy.setFilterRole(self.ObjectRole) self.m_proxy.setDynamicSortFilter(True) self.m_proxy.setSourceModel(self) def isJsonObject(self, mtextdoc): pass
class SliderBar(QWidget): value_changed = Signal(float) def __init__(self, title: str = '', value: float = 0, min_value: float = 0, max_value: float = 100, displayed_value_factor: float = 1, parent: QWidget = None): super().__init__(parent) self._value = value self._min_value = min_value self._max_value = max_value self._displayed_value_factor = displayed_value_factor self._title_label = QLabel(title) self._color = DEFAULT_BAR_COLOR self._locale = QLocale(QLocale.English) self._locale.setNumberOptions(self._locale.numberOptions() | QLocale.RejectGroupSeparator) validator = QDoubleValidator(self._min_value, self._max_value, 2) validator.setNotation(QDoubleValidator.StandardNotation) validator.setLocale(self._locale) self._value_line_edit = SliderValueLineEdit() self._value_line_edit.setValidator(validator) max_label_width = self._value_line_edit.fontMetrics().width( self._value_to_str(self.max_value)) self._value_line_edit.setFixedWidth(6 + max_label_width) self._value_line_edit.editingFinished.connect( self._on_value_line_edit_editing_finished) h_layout = QHBoxLayout(self) h_layout.setContentsMargins(4, 0, 4, 0) # h_layout.setSpacing(0) h_layout.addWidget(self._title_label, 0, Qt.AlignLeft) h_layout.addWidget(self._value_line_edit, 0, Qt.AlignRight) self._update_value_line_edit() @property def title(self) -> str: return self._title_label.text() @title.setter def title(self, value: str): self._title_label.setText(value) @property def value(self) -> float: return self._value @value.setter def value(self, value: float): value = max(min(value, self._max_value), self._min_value) if self._value != value: self._value = value self._update_value_line_edit() self.update() self.value_changed.emit(self._value) @property def min_value(self) -> float: return self._min_value @min_value.setter def min_value(self, value: float): if self._min_value != value: self._min_value = value if self.value < self._min_value: self.value = self._min_value else: self.update() @property def max_value(self) -> float: return self._max_value @max_value.setter def max_value(self, value: float): if self._max_value != value: self._max_value = value if self.value > self._max_value: self.value = self._max_value else: self.update() @property def color(self) -> QColor: return self._color @color.setter def color(self, value: QColor): if self._color != value: self._color = value self.update() @property def font_height(self): return self._title_label.fontMetrics().height() def set_focus(self): self._value_line_edit.setFocus() def increase_value(self, factor: float = 1): self.change_value_by_delta(1 * factor) def decrease_value(self, factor: float = 1): self.change_value_by_delta(-1 * factor) def change_value_by_delta(self, delta: float): self.value += delta self._value_line_edit.selectAll() def paintEvent(self, event: QPaintEvent): super().paintEvent(event) painter = QPainter(self) painter.setPen(Qt.NoPen) painter.setBrush(self.color) painter.drawRect( 0, 0, round((self._value - self._min_value) / (self._max_value - self._min_value) * self.width()), self.height()) def mouseMoveEvent(self, event: QMouseEvent): self._update_value_by_x(event.x()) event.accept() def mousePressEvent(self, event: QMouseEvent): self.set_focus() self._update_value_by_x(event.x()) event.accept() def mouseDoubleClickEvent(self, event: QMouseEvent): self._value_line_edit.selectAll() event.accept() def keyPressEvent(self, event: QKeyEvent): if event.key() == Qt.Key_Up: self.increase_value() elif event.key() == Qt.Key_Down: self.decrease_value() elif event.key() == Qt.Key_PageUp: self.increase_value(10) elif event.key() == Qt.Key_PageDown: self.decrease_value(10) def wheelEvent(self, event: QWheelEvent): value_delta = event.angleDelta().y() / 120 if event.modifiers() & Qt.ControlModifier: value_delta *= 10 self.set_focus() self.increase_value(value_delta) event.accept() def _on_value_line_edit_editing_finished(self): self.value, ok = self._locale.toFloat(self._value_line_edit.text()) def _update_value_by_x(self, x: int): self.value = (self.max_value - self.min_value) * x / self.width() + self.min_value def _update_value_line_edit(self): self._value_line_edit.setText(self._value_to_str(self.value)) def _value_to_str(self, value: float) -> str: return self._locale.toString( float(value * self._displayed_value_factor), 'f', 2)