TODO en la App Store de Mac, utilizando la arquitectura Pyqt5 ModelView para crear una aplicación Simple TODO

La interfaz ModelView Architecture Qt S MVC para mostrar datos en las vistas

La aplicación en ejecución se muestra a continuación.

TODO 4+

Durante varios años usé esta aplicación en mi iPad, mi iPhone y mi MacBookPro. Si continúa funcionando perfectamente en iOS, parece que no ha seguido completamente la evolución de los macos.
No hay problemas para instalarlo. Pero ya no es posible sincronizar con toodledo en macOS, mientras que sigue siendo posible en iOS: los mismos identificadores no se reconocen.
Por lo tanto, se vuelve innecesario para mí … y la asistencia de Appigo no parece tener prisa por proporcionar una respuesta a mi solicitud. Siempre es desagradable tener en cuenta que el concepto de cliente pierde un poco más de su valor todos los días.

Pisa D

Desde esta actualización, he perdido todas mis listas en el número de 12 y con el que trabajo diariamente de manera profesional. Administro aproximadamente 200 puntos de forma permanente, esta actualización ha puesto en el terreno meses de prueba ! Todas las tareas organizadas en la lista se encontraron agrupadas en una sola lista global. Ciertamente no es este error el que me hará pasar a la versión que dice profesional de este software, de otro modo excelente. Nunca estaré cautivo. Solo me queda esperar la respuesta del soporte contactado esta noche por correo electrónico o luego encontrar la versión anterior de este magnífico software. Realmente espero que sea un beug juvenil de la nueva versión y no una estrategia para forzar la migración a la versión profesional pagada para encontrar funcionalidades ya adquiridas con la versión anterior. Para obtener información, mi sincronización se realiza con Dropbox

Surlepoint, 13/12/2011

El synchro ahora es níquel

Agarré antes de la sincronización que era lenta, caminaba mal, etc. Pero ahora con iCloud, me queda perfectamente.

Algunas mejoras posibles: más configuración de visualización.
– Para mostrar solo lo que usa el usuario. Por ejemplo, no uso contextos ni etiquetas (en ningún caso aún no) y me gustaría ya no mostrar estas opciones que “contaminan” mi TODO. Me gustaría tener solo “fecha / prioridad / lista / tipo” para mis notas diarias y hacer clic derecho para las opciones que rara vez uso
– Y por el contrario, me gustaría una pantalla PLSU simple que un menú de caída para elegir la fecha, prioridad, lista, … si solo tengo tres listas, entonces tres botones serían suficientes para mostrar, y podría elegir mi lista Con un clic en lugar de hacer clic en el menú de caída, busque el nombre y haga clic en él. (Lo mismo ocurre con prioridad, especialmente que pasamos de un dibujo muy visual en la lista de TODO a una elección de nombre en las opciones que no es muy natural.

Estos son detalles de ergonomía. Me gusta la simplicidad y la eficiencia de TODO, por lo que me gustaría que pueda ser aún más configurable ser aún más simple.

Aplicación de privacidad

El desarrollador, Appigo, no ha proporcionado detalles sobre sus prácticas privadas y el manejo de datos a Apple. Para obtener más información, consulte la Política de privacidad del desarrollo.

La arquitectura ModelView
La interfaz similar a MVC de QT para mostrar datos en las vistas

A medida que comience a construir aplicaciones más complejas con PYQT5, es probable que se encuentre con los widgets sincronizados con sus datos. Datos almacenados en widgets (E.gramo. Un simple qlistwidget) no está fácilmente disponible para manipular desde Python: los cambios requieren que obtenga un elemento, obtenga los datos y luego lo configure. La solución predeterminada a esto es mantener una representación de datos externo en Python, y luego a las actualizaciones duplicadas tanto a los datos como al widget, o simplemente reescribir el widget de Wihole de los datos. Esto puede volverse feo rápidamente y da como resultado una gran cantidad de calderas solo para jugar los datos.

Afortunadamente, QT tiene una solución para esto: ModelViews. ModelViews es una poderosa alternativa a los widgets de pantalla estándar, que utilizan una interfaz de modelo regular para interactuar con fuentes de datos, desde estructuras de datos simples hasta bases de datos externas. Esto aísla sus datos, permitiendo que se mantenga en cualquier estructura que desee, mientras que la vista se encarga de la presentación y las actualizaciones.

Este tutorial presenta los aspectos clave de la arquitectura ModelView de QT y la utiliza para construir una aplicación simple de escritorio en PYQT5.

Controlador de vista de modelo

Modelo – Ver – Controlador (MVC) es un uso de patrones arquitectónicos para las interfaces de usuario de desarrollo que divide una aplicación en tres piezas interconectadas. Esto separa la representación interna de los datos de cómo se presenta y acepta la información del usuario.

El diseño MVC Pattenn fets tres componentes principales –

  • Modelo Contiene la estructura de datos con la que está trabajando la aplicación.
  • Vista es cualquier representación de información como se muestra al usuario, donde gráfico o tabla. Se permiten múltiples vistas del mismo modelo de datos.
  • Control Acepta la entrada del usuario, transformándola en comandos para el modelo o vista.

Qt aterriza la distinción entre la vista y el controlador se vuelve un poco turbio. QT acepta eventos de entrada del usuario (a través del sistema operativo) y los delega a los widgets (controlador) para manejar. Sin embargo, los widgets también manejan la presentación del estado actual al usuario, colocándolos en la vista. En lugar de agonizar sobre dónde dibujar la línea, en QT-S-speak, la vista y el controlador están fusionados con una “vista de modelo” con arquitectura de modelo/ViewController, por simplicidad, por simplicidad.

Es importante destacar que la distinción entre el datos y Cómo se presenta se conserva.

La vista del modelo

El modelo actúa como la interfaz entre el almacén de datos y el ViewController. El modelo contiene los datos (o una referencia a él) y presenta estos datos a través de una API estandarizada que ve y luego consumen y presente al usuario. Múltiples vistas pueden compartir los mismos datos, presentándolos de maneras completamente diferentes.

Puede usar cualquier “almacén de datos” para su modelo, incluido, por ejemplo, una lista o diccionario estándar de Python, o una base de datos (a través de E.gramo. Sqlalchemy) – Depende de usted.

Las dos partes son esencialmente responsables de –

  1. modelo Almacena los datos, o una referencia a él y devuelve individuos o rangos de registros, y metadatos o mostrar instrucciones.
  2. vista Solicita datos del modelo y muestra lo que se devuelve en el widget.

Hay una discusión profunda de la arquitectura QT en la documentación.

La guía completa para empaquetar aplicaciones GUI de Python con Pyinstaller.

Embalaje de aplicaciones Python con Pyinstaller

[[descuento.Descuento_pc]]]% de descuento para el siguiente [descuento.duración]] [descuento.Descripción]] con el código [descuento.Código promocional]]

Paridad de poder adquisitivo

Los desarrolladores en [[país]] obtienen [[descuento.descuento_pc]]] en todos los libros y cursos con código [descuento.Código promocional]]

Una vista de modelo simple: una lista de tareas

Para demostrar cómo usar ModelViews en la práctica, organizaremos una implementación muy simple de una lista de escritorio. Esto consistirá en un QListView para la lista de elementos, un QlineEdit para ingresar nuevos elementos y un conjunto de botones para agregar, eliminar o marcar los elementos como se hace.

La ui

La ui simple era fea de salida QT Creator y guardada como Mainwindow.ui . Té .El archivo de interfaz de usuario y todas las otras partes se pueden descargar a continuación.

Diseñando una aplicación simple en QT Creator

Diseñando una aplicación simple en QT Creator

La aplicación en ejecución se muestra a continuación.

La todo gui en ejecución (nada funciona todavía)

La todo gui en ejecución (nada funciona todavía)

Los widgets disponibles en la interfaz dimos los ID que se muestran en la tabla a continuación.

objeción Amable Descripción
visión QLISTVIEW La lista de los TDOS actuales
noble Qlineedit La entrada de texto para crear un nuevo elemento de tareas
addButton QpushButton Cree el nuevo TODO, agregándolo a la lista de TODOS
buque de eliminación QpushButton Elimine el TODO seleccionado actual, eliminándolo de la lista TODOS
COMPLETO BUTTON QpushButton Marque la actual TODO seleccionada como lo hizo

Usaremos estos identificadores para conectar la lógica de la aplicación más tarde.

El modelo

Definimos nuestro modelo personalizado subclasificando de la implementación, lo que nos permite centrarnos en las partes exclusivas de nuestro modelo. QT proporciona una serie de bases de modelos diferentes, incluidas listas, árboles y tablas (ideal para hojas de cálculo).

Para este ejemplo, estamos mostrando el resultado a una vista QLISTVIEW . El modelo base coincidente para esto es qabstractListModel . La definición de esquema para nuestro modelo se muestra a continuación.

Clase ToDomodel (Qtcore.QabstractListModel): def __init __ (self, *args, toDos = none, ** kwargs): super (toDomodel, self).__init __ (*args, ** kwargs) yo.TODOS = TODOS o [] DATOS DEF (Self, índice, rol): if rol == Qt.DisplayRole: # Consulte a continuación la estructura de datos. estado, texto = self.TODOS [índice.Fila ()] # Devuelve solo el texto de TODO. Return text def rowCount (self, index): return len (self.Todos) 

Té .La variable TODOS es nuestro almacén de datos y los dos métodos rowCount () y los datos () son métodos del modelo estándar que debemos para un modelo de lista. Pasaremos por estos a su vez abajo.

.Lista de TODOS

El almacén de datos para nuestro modelo es .Todos, una lista simple de Python en la que almacenaremos una tupla de valores en el formato [(bool, str), (bool, str), (bool, str)] donde bool es el por lo tanto estado de una entrada determinada, y STR es el texto del TODO.

Inicializamos a uno mismo.TODO a una lista vacía en el inicio, a menos que se pase una lista a través del argumento de palabras clave TODOS.

ser.Todos = Todos o [] se establecerá.Todos al valor de TODOS proporcionado si es estirado (i.mi. Cualquier otra cosa que no sea una lista vacía, el falso booleano o el valor predeterminado), de lo contrario, se establecerá en la lista vacía [] .

Para crear una usanza de este modelo, podemos simplificar

Modelo = toDomodel () # Crear una lista de tareas de tareas vacías 

O pasar en una lista existente –

TODOS = [(falso, 'un elemento'), (falso, 'otro elemento')] modelo = toDomodel (toDos) 

.Número de filas ()

Té .El método RowCount () es Callade por la vista para obtener el número de filas en los datos actuales. Esto se requiere para que la vista ahora el índice máximo pueda rehacer el almacén de datos (recuento de filas-1). Venta Usamos una lista de Python como nuestro almacén de datos, el valor de retorno para esto es simplemente el len () de la lista.

.Datos ()

Este es el núcleo de su modelo, que maneja las solicitudes de datos desde la vista y devuelve el resultado apropiado. Recibe dos parámetros índice y rol.

El índice es la posición/coordenadas de los datos que solicita la vista, accesible por dos métodos .Fila () y .columna () que da la posición en cada dimensión.

Para nuestro QListView, la columna siempre es 0 y se puede ignorar, pero necesitaría usar esto para datos 2D en una vista de hoja de cálculo.

El rol es una bandera que indica el amable de datos que la vista está solicitando. Esto es porque el .El método de datos () en realidad tiene más responsabilidad que solo los datos principales. También maneja solicitudes de información de estilo, información sobre herramientas, barras de estado, etc. – Basalmente cualquier cosa que pueda ser informada por los datos en sí.

El nombramiento de Qt.DisplayRole es un poco extraño, pero esto indica que el vista nos pregunta “por favor dame datos para visualizar”. Hay otros roles Que los datos pueden recibir para las solicitudes de estilo o la solicitud de datos en formato “listos para la edición”.

Role Valor Descripción
QT.Mostrar 0 Los datos clave se presentarán en forma de texto. (QString)
QT.Decoración 1 Los datos se presentarán como una decoración en forma de un icono. (Qcolor, Qicon o QpixMap)
QT.Editorial 2 Los datos en un seguimiento formal para editar en un editor. (QString)
QT.Titiprol 3 Los datos que se muestran en la información sobre herramientas del elemento. (QString)
QT.Estatustiprol 4 Los datos que se muestran en la barra de estado. (QString)
QT.Cual es thisrole 5 Los datos que se muestran para el elemento en “¿Qué es esto??” moda. (QString)
QT.Sizehintrol 13 El tamaño de la pista para el artículo que se suministrará a las vistas. (QSize)

Para una lista completa de disponibles roles que puede recibir ver la documentación QT itmdatarole. Nuestra lista de TODO solo usará QT.Displayrole y Qt.Decoración .

Implementación básica

A continuación se muestra la aplicación básica de Stub necesaria para cargar la interfaz de usuario y mostrarla. Agregaremos nuestro código de modelo y la lógica de la aplicación a esta base.

Importar SYS de Pyqt5 Import Qtcore, Qtgui, Qtwidgets, UIC de Pyqt5.Qtcore import qt_creator_file = "mainwindow.ui "ui_mainwindow, qtbaseclass = uic.Clase Loaduduype (QT_Creator_File) ToDomodel (QTCore.QabstractListModel): def __init __ (self, *args, toDos = none, ** kwargs): super (toDomodel, self).__init __ (*args, ** kwargs) yo.TODOS = TODOS o [] DATOS DEF (Self, índice, rol): if rol == Qt.Displayrole: status, text = self.TODOS [índice.Fila ()] return text def rowCount (self, index): return len (self.TODOS) Class MainWindow (QTWidgets.Qmainwindow, ui_mainwindow): def __init __ (self): qtwidgets.Qumainwindow.__init __ (self) ui_mainwindow.__init __ (yo) yo.Setupui (yo) yo mismo.Modelo = toDomodel () self.visión.Setmodel (yo.Modelo) aplicación = QtWidgets.QAPLICACIÓN (SYS.Argv) ventana = mainwindow () ventana.Show () aplicación.Exec_ () 

Definimos nuestro ToDomodel como antes e inicializamos el objeto MainWindow. En el __init__ para MainWindow creamos una instancia de nuestro modelo TODO y establecemos este modelo en el TODO_VIEW . Guarde este archivo como TODO.Py y ejecutarlo con –

python3 todo.paso 

Si bien aún no hay mucho que ver, el QListView y nuestro modelo realmente funcionan: si agrega algunos datos predeterminados, verá que aparece en la lista.

ser.modelo = toDomodel (toDos = [(falso, 'mi primer toDo')]))) 

QLISTVIEW que muestra el elemento de TODO codificado

QLISTVIEW que muestra el elemento de TODO codificado

Puede seguir agregando elementos manualmente así y se presentarán en orden en QListView . A continuación, haremos posible agregar ITM desde la aplicación.

Primero cree un nuevo método en MainWindow llamado Add . Esta es nuestra devolución de llamada que se encargará de agregar el texto actual de la entrada como un nuevo TODO. Conecte este método a AddButton.Señal presionada al final del bloque __init__.

Clase MainWindow (QtWidgets.Qmainwindow, ui_mainwindow): def __init __ (self): qtwidgets.Qumainwindow.__init __ (self) ui_mainwindow.__init __ (yo) yo.Setupui (yo) yo mismo.Modelo = toDomodel () self.visión.Setmodel (yo.Modelo) # Conecte el botón. ser.addButton.prensa.Conectar (yo.ADD) Def ADD (Self): "" Agregue un elemento a nuestra lista de TODO, obteniendo el texto del QlineEdit .TODOEDIT Y ALLÍ ALUCHOS. "" "Text = Self.noble.Text () Si Text: # no agregue cadenas vacías. # Acceda a la lista a través del modelo. ser.modelo.diádico.Append ((false, texto)) # activar actuar. ser.modelo.LayoutChanged.Emit () # vacío la entrada self.noble.SetText ("") 

En el bloque de adiciones, aviso de la línea.modelo.LayoutChanged.Emit () . Aquí emitemos una señal de modelo .LayoutChanged para hacerle saber la vista que el forma de los datos han sido alterados. Esto desencadena una actualización de la entidad de la vista. Si omite esta línea, el TODO aún se agregará, pero el QListView no se actualizará.

Si solo se alteran los datos, pero el número de filas/columnas no se ve afectadas, puede usar el .Señal datachanged () en su lugar. Esto también define una región alterada en los datos utilizando un alquiler de la parte superior izquierda y la parte inferior derecha para evitar volver a dibujar la vista completa de la vista completa.

Conectando las otras acciones

Ahora podemos conectar el resto de las señales del botón y agregar ayuda para el rendimiento borrar y completo operaciones. Agregamos las señales del botón al bloque __init__ como antes.

 ser.addButton.prensa.Conectar (yo.Añadir) Self.buque de eliminación.prensa.Conectar (yo.Eliminar) yo mismo.COMPLETO BUTTON.prensa.Conectar (yo.Completo) 

Luego defina un nuevo método de eliminación de la siguiente manera –

 Def Delete (self): indexes = self.visión.selectedDindexes () If indexes: # indexes es una lista de un solo elemento en un solo selecto. Index = indexes [0] # Eliminar el elemento y actualizar. Del Self.modelo.TODOS [índice.Fila ()] yo.modelo.LayoutChanged.Emit () # borre la selección (ya que no es válido). ser.visión.Clarselection () 

Usamos yo.visión.SelectedDindexes para obtener los índices (en realidad una lista de un solo elemento, ya que en modo de selección única) y luego el .Fila () como índice en nuestra lista de TODO en nuestro modelo. Eliminamos el elemento indexado utilizando el operador Del de Python, y luego activamos una señal de diseño de diseño porque la forma de los datos ha sido modificada.

Finalmente, eliminamos la selección activa ya que el elemento con el que se relaciona ahora puede salir de los límites (si ha seleccionado el último elemento).

Puede intentar hacer esto más inteligente y seleccionar el último elemento en la lista en su lugar

Al método completo le gusta como este –

 Def Complete (self): indexes = self.visión.selectredindexes () if indexes: index = indexes [0] fila = índice.Status de fila (), text = self.modelo.Todos [fila] yo.modelo.Todos [fila] = (verdadero, texto) # .Datachanged toma la parte superior izquierda y la parte inferior derecha, que son # # para una sola selección. ser.modelo.datachanged.Emit (índice, índice) # Borrar la selección (ya que no es válido). ser.visión.Clarselection () 

Esto usa la misma indexación que para Eliminar, pero esta vez obtenemos el elemento del modelo .Lista de TODOS y luego reemplace el estado con verdadero .

Tenemos que hacer esta recuperación y reemplazo, ya que nuestros datos se almacenan como tuplas de Python que no se pueden modificar.

La clave diferente aquí vs. Los widgets de QT estándar es que hacemos cambios directamente a nuestros datos, y debemos notificar simplificando a QT que cambia HAASURD: la actualización del estado del widget se maneja automáticamente.

Usando QT.Decoración

Si ejecuta la aplicación ahora, debería encontrar que agregar y eliminar ambos trabajos, pero mientras completar elementos funciona, no hay indicios de ello en la vista. Necesitamos actualizar nuestro modelo para proporcionar la vista un indicador para mostrar cuando un elemento está completo. El modelo actualizado se muestra a continuación.

tick = Qtgui.Qimage ('Tick.Clase PNG ') ToDomodel (Qtcore.QabstractListModel): def __init __ (self, *args, toDos = none, ** kwargs): super (toDomodel, self).__init __ (*args, ** kwargs) yo.TODOS = TODOS o [] DATOS DEF (Self, índice, rol): if rol == Qt.Displayrole: _, text = self.TODOS [índice.Fila ()] Texto de retorno si rol == Qt.DecorationRole: estado, _ = self.TODOS [índice.Fila ()] if estado: return tick def rowCount (self, index): return len (self.Todos) 

Estaban usando una garrapata ícono de tick.PNG para indicar elementos completos, que cargamos en un objeto Qimage llamado Tick . En el modelo implementamos un controlador para el QT.DecorationRole que devuelve el icono de tick para filas cuyo estado es verdadero (para completo).

El icono que estoy usando está tomado de la fuga establecida por P.yusukekamiyamane

Intostad de un icono I también puedes volver al color, e.gramo. Qtgui.Qcolor (‘verde’) que se dibujará como cuadrado sólido.

Ejecutando la aplicación ahora debería poder marcar los elementos como completos.

Todos marcados completos

Todos marcados completos

Un almacén de datos Persist

Nuestra aplicación TODO funciona muy bien, pero tiene una falla fatal, olvida sus TODO tan pronto como cierre la aplicación mientras piensa que no tiene nada que hacer cuando lo hace puede contribuir a los sentimientos de Zen a corto plazo, probablemente sea un mala idea.

La solución es implementar alguna salida del almacén de datos Persist. El enfoque más simple es una tienda de archivos simple, donde cargamos elementos de un archivo JSON o Pickle al inicio, y volvemos a escribir sobre el cambio.

Para hacer esto definimos dos nuevos métodos en nuestra mano . Estos cargan datos de los datos del nombre de archivo JSON.Json (si existe, ignorando el error si no lo hace).modelo.Todos y escribir el yo actual.modelo.Todos en el mismo archivo, respectivamente.

 Def load (self): intente: con abre ('datos.json ',' r ') como f: yo.modelo.TODOS = JSON.Carga (f) Excepción Excepción: Pase Def Save (Self): con Open ('Datos.json ',' w ') como f: data = json.Volcado (uno mismo.modelo.Todos, f) 

Para persistir los cambios en los datos, necesitamos agregar el .Handler save () al final de cualquier método que modifique los datos y el .Handler load () al bloque __init__ después de que el modelo haya estado creando.

El código final se ve así –

Importar sys import json de pyqt5 import qtcore, qtgui, qtwidgets, uic de pyqt5.Qtcore import qt_creator_file = "mainwindow.ui "ui_mainwindow, qtbaseclass = uic.LoadUduseype (QT_CREATOR_FILE) Tick = QtGui.Qimage ('Tick.Clase PNG ') ToDomodel (Qtcore.QabstractListModel): def __init __ (self, *args, toDos = none, ** kwargs): super (toDomodel, self).__init __ (*args, ** kwargs) yo.TODOS = TODOS o [] DATOS DEF (Self, índice, rol): if rol == Qt.Displayrole: _, text = self.TODOS [índice.Fila ()] Texto de retorno si rol == Qt.DecorationRole: estado, _ = self.TODOS [índice.Fila ()] if estado: return tick def rowCount (self, index): return len (self.TODOS) Class MainWindow (QTWidgets.Qmainwindow, ui_mainwindow): def __init __ (self): super (mainwindow, yo).__En si mismo.Setupui (yo) yo mismo.Modelo = toDomodel () self.Load () yo.visión.Setmodel (yo.Modelo) yo.addButton.prensa.Conectar (yo.Añadir) Self.buque de eliminación.prensa.Conectar (yo.Eliminar) yo mismo.COMPLETO BUTTON.prensa.Conectar (yo.Complete) Def add (self): "" "Agregue un elemento a nuestra lista de TODO, obteniendo el texto de QlineEdit .TODOEDIT Y ALLÍ ALUCHOS. "" "Text = Self.noble.Text () Si Text: # no agregue cadenas vacías. # Acceda a la lista a través del modelo. ser.modelo.diádico.Append ((false, texto)) # activar actuar. ser.modelo.LayoutChanged.Emit () # vacío la entrada self.noble.Settext ("") self.Save () def eliminar (self): indexes = self.visión.selectedDindexes () If indexes: # indexes es una lista de un solo elemento en un solo selecto. Index = indexes [0] # Eliminar el elemento y actualizar. Del Self.modelo.TODOS [índice.Fila ()] yo.modelo.LayoutChanged.Emit () # borre la selección (ya que no es válido). ser.visión.Clarselection () yo.Save () def complete (self): indexes = self.visión.selectredindexes () if indexes: index = indexes [0] fila = índice.Status de fila (), text = self.modelo.Todos [fila] yo.modelo.Todos [fila] = (verdadero, texto) # .Datachanged toma la parte superior izquierda y la parte inferior derecha, que son # # para una sola selección. ser.modelo.datachanged.Emit (índice, índice) # Borrar la selección (ya que no es válido). ser.visión.Clarselection () yo.Save () Def load (self): intente: con abre ('datos.db ',' r ') como f: yo.modelo.TODOS = JSON.Carga (f) Excepción Excepción: Pase Def Save (Self): con Open ('Datos.db ',' w ') como f: data = json.Volcado (uno mismo.modelo.TODOS, F) APP = QTWidgets.QAPLICACIÓN (SYS.Argv) ventana = mainwindow () ventana.Show () aplicación.Exec_ () 

Si los datos en su aplicación tienen el potencial de ser grandes o más complejos, puede prefabricarse para usar una base de datos real para almacenarlo. En este caso, el modelo envolverá la interfaz a la base de datos y la consultará directamente para que los datos muestren. La cubierta de la vida de cómo hacer esto en un próximo tutorial.

Para otro ejemplo interesante de un QListView, consulte esta aplicación de reproductor multimedia de ejemplo. Utiliza el edificio QT QmediaPlayList como almacén de datos, con la pantalla de contenido en una vista QLISTVIEW .

Acerca de BCR.CX:

Bcr.CX es una startup de tecnología brasileña, especializada tanto en los procesos de subcontratación de negocios (BPO) como en la subcontratación del entorno empresarial (BEO), principalmente centrado en la generación de demanda, experiencia del cliente, comunicación, soporte de usuarios y satisfacción.

Descripción:

La aplicación TODO se desarrolló como una forma rápida, segura y fácil de usar para almacenar las notas del agente durante las jornadas laborales.

Poder crear y administrar sus propias tareas, en función de cada boleto individual o cliente.

Cree senderos y personalice su flujo de trabajo

Mejora de la productividad! Uso de la aplicación TODO puede crear flujos de trabajo personalizados para estandarizar procesos de repetición. Intente ahora y comience a controlar su progreso, como sus TODO y donan.

Recursos:

  1. Crear tareas para cada boleto
  2. Barra de progreso para realizar seguimiento de la entrega
  3. Crear flujos de trabajo estandarizados para mejorar la productividad.
  4. Administre su lista de tareas, para mantenerla al día con su rutina diaria.
  1. Apila tanto a TODO como a Zendesk Sunshine para obtener acceso completo a través de las funciones de la aplicación
  2. Mejorar la productividad creando o editando automatizaciones de tareas y guarde sus preajustes personalizados.