TODO в магазині App App, використовуючи архітектуру PyQT5 ModelView для створення простого додатка TODO
Інтерфейс ModelView Architecture QT S MVC для відображення даних у переглядах
Contents
- 1 Інтерфейс ModelView Architecture QT S MVC для відображення даних у переглядах
Додаток, що працює, показано нижче.
TODO 4+
Протягом декількох років я використовував цю програму на своєму iPad, моєму iPhone та MacBookPro. Якщо він продовжує працювати ідеально на iOS, здається, що він не повністю дотримувався еволюції MACOS.
Немає проблем з його встановленням. Але більше неможливо синхронізуватися з Toodledo на MacOS, тоді.
Тому для мене це стає непотрібним … і допомога Appigo, здається, не поспішає надати відповідь на моє прохання. Завжди неприємно зазначити, що концепція клієнта втрачає трохи більше своєї цінності щодня.
PISA D
З цього оновлення я втратив усі свої списки за номером 12 і з якими я працюю щодня професійно. Я постійно керую приблизно 200 плямами, це оновлення поставило на землі місяці випробування ! Усі завдання, організовані у списку. Це, звичайно, не ця помилка, яка змусить мене передати версію, яка говорить професіонал цього програмного забезпечення, інакше відмінно. Я ніколи не буду полоненим. Мені залишається лише чекати, коли відповідь підтримки зв’язалася сьогодні ввечері електронною поштою або потім знайде стару версію цього чудового програмного забезпечення. Я дуже сподіваюсь, що це юнацька нова версія, а не стратегія змусити мігрувати до платної версії, щоб знайти функціональні можливості, вже придбані з попередньою версією. Для інформації моя синхронізація виконана за допомогою Dropbox
Surlepoint, 13.12.2011
Синхро зараз нікель
Я схопив перед синхронізацією, яка була повільною, погано ходила тощо. Але зараз з iCloud це мені ідеально підходить.
Деякі можливі вдосконалення: Більше налаштувань дисплея.
– Для відображення лише те, що використовує користувач. Наприклад, я не використовую контексти чи мітки (у будь -якому випадку ще не), і я хотів би більше не відображати ці параметри, які “забруднюють” мій тодо. Я хотів би мати лише “дату / пріоритет / список / тип” для моїх повсякденних нотаток і клацніть правою кнопкою миші для варіантів, якими я рідко використовую
– І навпаки, я хотів би простий дисплей PLSU, ніж меню краплі, щоб вибрати дату, пріоритет, список, … якщо у мене є лише три списки, то три кнопки будуть достатньо для відображення, і я міг би вибрати свій список Одним клацанням замість натискання на меню Drop -Down знайдіть назву та натисніть на нього. (Ditto для пріоритету, особливо, що ми переходимо від дуже візуального малювання до списку Todo до вибору імені у варіантах, що не дуже природно.
Це деталі ергономіки. Мені подобається простота та ефективність TODO, тому я хотів би, щоб це було ще більш налаштовано, щоб бути навіть простішим.
Програма конфіденційності
Розробник, Appigo, не надав деталей про свою приватну практику та обробку даних Apple. Для отримання додаткової інформації див. Політика конфіденційності розвитку.
Архітектура ModelView
Інтерфейс MVC-подібного QT для відображення даних у поданнях
Коли ви почнете будувати більш складні програми з PYQT5, ви, швидше за все, зіткнетеся з віджетами синхронізованою з вашими даними. Дані, що зберігаються у віджетах (e.g. Простий QlistWidget) недоступний для маніпулювання з Python – зміни вимагають отримати елемент, отримати дані, а потім повернути їх назад. Рішення за замовчуванням цього полягає в тому, щоб зберегти зовнішнє подання даних у Python, а потім повторювати оновлення як даних, так і віджет, або просто переписати віджет Wihole з даних. Це може стати потворним швидко, і призводить до багатьох котлів лише для того, щоб придушити дані.
На щастя, QT має рішення для цього – ModelViews. ModelViews – це потужна альтернатива стандартних віджетів дисплея, які використовують звичайний інтерфейс моделі для взаємодії з джерелами даних – від простих структур даних до зовнішніх баз даних. Це ізолює ваші дані, що дозволяє зберігати їх у будь -якій структурі, в той час як погляд піклується про презентацію та оновлення.
Цей підручник представляє ключові аспекти архітектури ModelView QT та використовує її для створення простого робочого столу TODO в PYQT5.
Контролер перегляду моделі
Модель – див. – Контролер (MVC) – це архітектурне використання для інтерфейсів користувача розробки, які розводить програму на три взаємопов’язані частини. Це відокремлює внутрішнє подання даних від того, як подається інформація та приймають від користувача та приймають.
MVC Design Pattenn Fets Три основні компоненти –
- Модель Утримує структуру даних, з якою програма працює.
- Переглянути це будь -яке представлення інформації, як показано користувачеві, де графічне чи таблиця. Дозволено кілька переглядів однієї моделі даних.
- КОНТРОЛЬ Приймає введення від користувача, перетворюючи його на команди на модель або перегляд.
Це Qt приземляється відмінність між View & Controller стає трохи мутним. QT приймає вхідні події від користувача (через ОС) та делегує їх віджежами (контролера) для обробки. Однак віджети також обробляють представлення поточного стану користувачеві, вкладаючи їх прямо в перегляд. Замість того.
Важливо, що відмінність між дані і Як це представлено зберігається.
Перегляд моделі
Модель діє як інтерфейс між магазином даних та ViewController. Модель містить дані (або посилання на неї) та представляє ці дані через стандартизований API, який переглядає, потім споживають та представляють користувачеві. Кілька поглядів можуть поділяти однакові дані, представляючи їх абсолютно різними способами.
Ви можете використовувати будь -який “магазин даних” для своєї моделі, включена, наприклад, стандартний список Python або словник, або база даних (через E.g. SQLALCHEMY) – це право залежить від вас.
Дві частини по суті відповідають за –
- Чай модель Зберігає дані або посилання на нього та повертає індивідуальні або діапазони записів, а також пов’язані з цим метадані або показувати інструкції.
- Чай переглянути Запитає дані з моделі та відображає те, що повертається на віджет.
Існує поглиблене обговорення архітектури QT у документації.
Повний посібник із програм Python GUI Python з Pyinstaller.
[[знижка.Знижка_pc]]]% відключення для наступного [знижка.тривалість]] [знижка.Опис]] за допомогою коду [знижка.COUNON_CODE]]
За паритетом купівельної здатності
Розробники [[Країна]] отримують [[знижка.знижка_pc]] відключення всіх книг та курсів з кодом [знижка.COUNON_CODE]]
Простий перегляд моделі – список TODO
Щоб продемонструвати, як використовувати ModelView на практиці, ми зібрали дуже просту реалізацію списку робочих столів TODO. Це буде складатися з QListView для списку елементів, QllineEdit для введення нових елементів та набору кнопок для додавання, видалення або позначення елементів, як це зроблено.
Інтерфейс
Простий інтерфейс був потворним виїздом QT Creator і врятував як головне нажд.інтерфейс . Чай .Файл користувача та всі інші частини можна завантажити нижче.
Розробка простого додатка TODO у QT Creator
Додаток, що працює, показано нижче.
Біг TODO GUI (ще нічого не працює)
Віджети, доступні в інтерфейсі, ми надали ідентифікатори, показані в таблиці нижче.
обрізка | Вид | Опис |
---|---|---|
todview | Qlistview | Список поточних тодосів |
тододіт | Qlineedit | Текстовий вхід для створення нового елемента Todo |
Адбуттон | Qpushbutton | Створіть новий Todo, додаючи його до списку TODOS |
вибухнути | Qpushbutton | Видаліть поточний обраний Todo, видаляючи його зі списку Todos |
Повна туга | Qpushbutton | Позначте поточний обраний Todo, як це зроблено |
Ми використаємо ці ідентифікатори, щоб пізніше підключити логіку програми.
Модель
Ми визначаємо нашу користувацьку модель шляхом підкласа від впровадження, що дозволяє нам зосередитись на деталях, унікальних для нашої моделі. QT забезпечує ряд різних модельних баз, включаючи списки, дерева та таблиці (ідеально підходить для електронних таблиць).
Для цього прикладу ми відображаємо результат до QListView . Модель відповідності для цього – QabstractListModel . Визначення контуру для нашої моделі показано нижче.
Клас Todomodel (Qtcore.QabstractListModel): def __init __ (self, *args, todos = none, ** kwargs): super (todomodel, self).__init __ (*args, ** kwargs).todos = todos або [] def Data (self, індекс, роль): якщо роль == qt.DisplayRole: # Див. Нижче структуру даних. статус, текст = сам.Todos [індекс.Row ()] # Поверніть лише текст TODO. Повернути текст def rowcount (self, index): return len (self.Todos)
Чай .Змінна Todos – це наш магазин даних, а два методи rowcount () та data () – стандартні методи моделі, які ми повинні для моделі списку. Ми пройдемо через них по черзі.
.Список Todos
Магазин даних для нашої моделі є .Todos, простий список Python, в якому ми будемо зберігати кортець значень у форматі [(bool, str), (bool, str), (bool, str)], де bool є отже стан заданого запису, і STR – це текст TODO.
Ми ініціалізуємо себе.TODO до порожнього списку при запуску, якщо список не передається через аргумент ключового слова Todos.
я.todos = todos або [] встановить себе.todos до наданої вартості todos, якщо воно є тривалий (Я.Е. Що -небудь, крім порожнього списку, булева хибна або жодна значення за замовчуванням), інакше він буде встановлений у порожній список [] .
Щоб створити залежність від цієї моделі, ми можемо просто –
Модель = todomodel () # Створіть порожній список TODO
Або передати в існуючий список –
todos = [(false, 'item'), (false, 'інший елемент')] модель = todomodel (todos)
.RowCount ()
Чай .Метод rowcount () є Callade за переглядом, щоб отримати кількість рядків у поточних даних. Це потрібно для перегляду до теперішнього максимального індексу, який він може переробити магазин даних (кількість рядків-1). Продаж Ми використовуємо список Python як наш магазин даних, поверненням для цього є просто len () списку.
.Дані ()
Це ядро вашої моделі, яка обробляє запити на дані з перегляду та повернути відповідний результат. Він отримує два параметри індекс та роль.
Індекс – це положення/координати даних, про які подання запитується, доступним двома методами .Row () і .congle (), що дають положення в кожному вимірі.
Для нашого Qlistview стовпець завжди 0 і його можна ігнорувати, але вам потрібно буде використовувати це для 2D даних у поданні електронної таблиці.
Роль – це прапор, що вказує вид даних, які подання запитує. Це тому, що .Метод () метод фактично несе більше відповідальності, ніж просто основні дані. Він також обробляє запити на інформацію про стиль, підказки, смуги стану тощо. – Основно все, що могло бути поінформоване самими даними.
Іменування QT.DisplayRole трохи дивно, але це вказує на те, що переглянути запитує нас “Будь ласка, дайте мені дані про відображення”. Є й інші ролі Які дані можуть отримувати для запитів у стилі або запитувати дані у форматі “редагувати готовий”.
Роль | Цінність | Опис |
---|---|---|
QT.Показувати | 0 | Ключові дані, які слід надати у вигляді тексту. (QString) |
QT.Прикраса | 1 | Дані, які слід відображати як прикраса у вигляді ікони. (Qcolor, Qicon або qpixmap) |
QT.Редакційний | 2 | Дані в офіційному наступному для редагування в редакторі. (QString) |
QT.Підказка | 3 | Дані, що відображаються в підказці елемента. (QString) |
QT.Статут | 4 | Дані, що відображаються в панелі стану. (QString) |
QT.Що | 5 | Дані, що відображаються для елемента в “Що це?”Мода. (QString) |
QT.Розмір | 13 | Натяк на розмір для товару, який буде надано для перегляду. (QSize) |
Для повного списку доступних ролі що ви можете отримати, переглянути документацію Qt itmdatarole. Наш список TODO буде використовувати лише QT.DisplayRole та QT.Прикраса .
Основна реалізація
Нижче наведено основну програму заглушки, необхідний для завантаження інтерфейсу та відображення його. Ми додамо наш код моделі та логіку додатків до цієї бази.
Імпорт SYS з PYQT5 Імпорт QTCORE, QTGUI, QtWidgets, UIC від PYQT5.Qtcore імпорт qt_creator_file = "mainwindow.ui "ui_mainwindow, qtbaseclass = uic.Loaduduype (qt_creator_file) клас Todomodel (qtcore.QabstractListModel): def __init __ (self, *args, todos = none, ** kwargs): super (todomodel, self).__init __ (*args, ** kwargs).todos = todos або [] def Data (self, індекс, роль): якщо роль == qt.DisplayRole: статус, текст = сам.Todos [індекс.Row ()] повернути текст def rowcount (self, індекс): повернути len (self.Todos) клас MainWindow (QtWidgets.Qmainwindow, ui_mainwindow): def __init __ (self): qtwidgets.Qumainwindow.__init __ (self) ui_mainwindow.__init __ (Я) Я.Setupui (self) self.Модель = todomodel () self.todview.Setmodel (сам.Модель) APP = QTWIDGETS.QApplication (sys.Argv) Вікно = Вікно MainWindow ().Show () додаток.Exec_ ()
Ми визначаємо наш Todomodel, як і раніше, і ініціалізуємо об’єкт MainWindow. У __init__ для MainWindow ми створюємо екземпляр нашої моделі Todo і встановлюємо цю модель на Todo_view . Збережіть цей файл як TODO.Py і запустіть – з –
python3 todo.темп
Поки ще не багато чого побачити, QListView та наша модель насправді працюють – якщо ви додасте деякі дані за замовчуванням, ви побачите, що вони з’являться у списку.
я.модель = todomodel (todos = [(false, 'мій перший Todo')])))))
Qlistview, що показує жорсткий кодований елемент
Ви можете продовжувати додавати предмети вручну, і вони з’являться в порядку в Qlistview . Далі ми дозволимо додавати ІТМ з програми.
Спочатку створіть новий метод на головному віці з назвою Add . Це наш зворотний дзвінок, який подбає про додавання поточного тексту з введення як нового TODO. Підключіть цей метод до Addbutton.ПРИСТЕМОВАНИЙ СИГНАЛ в кінці блоку __INIT__.
Клас MainWindow (QtWidgets.Qmainwindow, ui_mainwindow): def __init __ (self): qtwidgets.Qumainwindow.__init __ (self) ui_mainwindow.__init __ (Я) Я.Setupui (self) self.Модель = todomodel () self.todview.Setmodel (сам.Модель) # Підключіть кнопку. я.Адбуттон.пресувати.Підключіться (Я.Додати) def add (self): "" Додайте елемент до нашого списку Todo, отримуючи текст із Qllineedit .Todoedit і там очищають. "" "Текст = Я.тододіт.Text () Якщо текст: # не додайте порожніх рядків. # Доступ до списку через модель. я.модель.тодос.Додати ((false, text)) # тригер оновлення. я.модель.Локаз.Emit () # порожні вхід.тододіт.SetText ("")
У блок додавання Помітьте лінію.модель.Локаз.Emit () . Тут ми випромінюємо модельний сигнал .Layoutchanged, щоб повідомити про те, що форма даних було змінено. Це викликає оновлення суб’єкта виду. Якщо ви пропустите цей рядок, Todo все одно буде додано, але QListView не оновлюється.
Якщо лише дані змінюються, але кількість рядків/стовпців не впливають, ви можете використовувати .Замість цього сигнал Datachanged (). Це також визначає змінену область у даних, використовуючи ліворуч та оренду внизу, щоб уникнути переробки всього подання.
Підключення інших дій
Тепер ми можемо підключити решту сигналів кнопки та додати допомогу для продуктивності видаляти і повне операції. Додаємо сигнали кнопки до блоку __init__, як і раніше.
я.Адбуттон.пресувати.Підключіться (Я.Додати) сам.вибухнути.пресувати.Підключіться (Я.Видалити) Я.Повна туга.пресувати.Підключіться (Я.Завершити)
Потім визначте новий метод видалення наступним чином –
Defete (self): indexes = self.todview.selectedDindexes () Якщо індекси: # індекси-це список одного елемента в одному виборі. Індекс = індекси [0] # видаліть елемент і оновити. Del self.модель.Todos [індекс.Row ()] self.модель.Локаз.Emit () # Очистіть вибір (як це не довгий дійсне). я.todview.ClarSelection ()
Ми використовуємо себе.todview.SelectedDindexes, щоб отримати індекси (фактично перелік одного елемента, як ми в режимі одного вибору), а потім .Row () як індекс до нашого списку Todos на нашій моделі. Ми видаляємо індексований елемент за допомогою оператора DEL Python, а потім запускаємо сигнал, що розширився, оскільки форма даних модифікована.
Факло, ми очищаємо активний вибір, оскільки елемент, до якого він пов’язаний, тепер може вийти з меж (якщо ви вибрали останній елемент).
Ви можете спробувати зробити цей Smartter та вибрати останній елемент у списку
Повний метод любить такий –
Def complete (self): індекси = само.todview.SelectRedIndexes () Якщо індекси: індекс = індекси [0] рядок = індекс.Row () статус, текст = сам.модель.Todos [row] self.модель.Todos [рядок] = (правда, текст) # .Datachanged приймає ліворуч і знизу праворуч, які рівні # для одного вибору. я.модель.датах.EMIT (індекс, індекс) # Очистіть вибір (як це не довгий дійсне). я.todview.ClarSelection ()
Це використовує те саме, що і для видалення, але цього разу ми отримуємо предмет із моделі .Список Todos, а потім замініть статус на True .
Ми повинні зробити це отримання та заміну, оскільки наші дані зберігаються як Python Chueples, які неможливо змінити.
Ключові тут різні проти. Стандартні віджетів QT полягає в тому, що ми змінюємо безпосередньо на наші дані, і потрібно просто повідомити QT, що змінює Хаасурд – оновлення стану віджетів здійснюється автоматично.
Використання QT.Прикраса
Якщо ви запускаєте програму зараз, вам слід виявити, що додавання та видалення обох роботи, але під час роботи елементів працює, в поданні немає вказівки. Нам потрібно оновити нашу модель, щоб забезпечити перегляд індикатора для відображення, коли елемент завершено. Оновлена модель показана нижче.
галочка = qtgui.Qimage ('галочка.png ') клас Todomodel (qtcore.QabstractListModel): def __init __ (self, *args, todos = none, ** kwargs): super (todomodel, self).__init __ (*args, ** kwargs).todos = todos або [] def Data (self, індекс, роль): якщо роль == qt.DisplayRole: _, text = self.Todos [індекс.Row ()] повернути текст, якщо роль == qt.Decoryrole: статус, _ =.Todos [індекс.Row ()] якщо статус: повернути галочку def rowcount (self, індекс): повернути len (self.Todos)
Використовували галочку значка галочки.PNG, щоб вказати повні елементи, які ми завантажуємо в об’єкт Qimage на ім’я галочка . У моделі ми провели обробник для QT.DecoryRole, який повертає піктограму галочки для рядків, який статус, є правдивим (для повного).
Піктограма, яку я використовую, взята з фуги, встановленої P.Юсукекаміян
Intostad з ікони i ви також можете повернутися до кольору, e.g. QTGUI.Qcolor (‘зелений’), який буде намальований як суцільний квадрат.
Запускаючи додаток, тепер ви повинні мати можливість відзначити елементи як завершені.
Тодос позначений завершеним
Зберігання даних даних
Наш додаток Todo працює чудово, але він має один фатальний вад, він забуває ваші тодоси, як тільки ви закриєте заявку, думаючи погана ідея.
Рішення полягає у впровадженні деяких виїздів на зберігання даних. Найпростіший підхід – це простий магазин файлів, де ми завантажуємо елементи з файлу JSON або Parkle при запуску та записуємо на зміну.
Для цього ми визначаємо два нові методи на руці . Ці дані завантаження з даних імені файлу json.Json (якщо він існує, ігноруючи помилку, якщо вона цього не зробить).модель.Тодос і напишіть поточне «я».модель.Todos до одного файлу відповідно.
Def навантаження (self): спробуйте: з відкритими ('даними.json ',' r ') як f: self.модель.Todos = json.Завантаження (f) Виняток виняток: Пройдіть Save Save (Self): з відкритими ('даними.json ',' w ') як f: data = json.Сміттєзвалище (я.модель.Todos, f)
Щоб зберегти зміни до даних, необхідних для додавання .Зберегти () обробник до кінця будь -якого методу, який модифікує дані, та .Навантаження () обробник до блоку __init__ після створення моделі.
Заключний код виглядає так –
Імпорт SYS Імпорт JSON з PYQT5 Імпорт QTCORE, QTGUI, QtWidgets, UIC від PYQT5.Qtcore імпорт qt_creator_file = "mainwindow.ui "ui_mainwindow, qtbaseclass = uic.Loaduduseype (qt_creator_file) галочка = qtgui.Qimage ('галочка.png ') клас Todomodel (qtcore.QabstractListModel): def __init __ (self, *args, todos = none, ** kwargs): super (todomodel, self).__init __ (*args, ** kwargs).todos = todos або [] def Data (self, індекс, роль): якщо роль == qt.DisplayRole: _, text = self.Todos [індекс.Row ()] повернути текст, якщо роль == qt.Decoryrole: статус, _ =.Todos [індекс.Row ()] якщо статус: повернути галочку def rowcount (self, індекс): повернути len (self.Todos) клас MainWindow (QtWidgets.Qmainwindow, ui_mainwindow): def __init __ (self): super (mainwindow, self).__В собі.Setupui (self) self.Модель = todomodel () self.Навантаження () Я.todview.Setmodel (сам.Модель) Я.Адбуттон.пресувати.Підключіться (Я.Додати) сам.вибухнути.пресувати.Підключіться (Я.Видалити) Я.Повна туга.пресувати.Підключіться (Я.Повний) def add (self): "" "Додати елемент до нашого списку Todo, отримуючи текст із Qllineedit .Todoedit і там очищають. "" "Текст = Я.тододіт.Text () Якщо текст: # не додайте порожніх рядків. # Доступ до списку через модель. я.модель.тодос.Додати ((false, text)) # тригер оновлення. я.модель.Локаз.Emit () # порожні вхід.тододіт.SetText ("") Я.Зберегти () defete (self): indexes = self.todview.selectedDindexes () Якщо індекси: # індекси-це список одного елемента в одному виборі. Індекс = індекси [0] # видаліть елемент і оновити. Del self.модель.Todos [індекс.Row ()] self.модель.Локаз.Emit () # Очистіть вибір (як це не довгий дійсне). я.todview.ClarSelection () Я.Зберегти () def Complete (self): індекси = самості.todview.SelectRedIndexes () Якщо індекси: індекс = індекси [0] рядок = індекс.Row () статус, текст = сам.модель.Todos [row] self.модель.Todos [рядок] = (правда, текст) # .Datachanged приймає ліворуч і знизу праворуч, які рівні # для одного вибору. я.модель.датах.EMIT (індекс, індекс) # Очистіть вибір (як це не довгий дійсне). я.todview.ClarSelection () Я.Зберегти () def навантаження (self): спробуйте: з відкритими ('даними.db ',' r ') як f: self.модель.Todos = json.Завантаження (f) Виняток виняток: Пройдіть Save Save (Self): з відкритими ('даними.db ',' w ') як f: data = json.Сміттєзвалище (я.модель.todos, f) app = qtwidgets.QApplication (sys.Argv) Вікно = Вікно MainWindow ().Show () додаток.Exec_ ()
Якщо дані у вашій програмі мають потенціал для отримання великих або складніших, ви можете скористатися фактичною базою даних для її зберігання. У цьому випадку модель буде обернути інтерфейс до бази даних та запитати її безпосередньо для відображення даних. Обкладинка L’ll Як це зробити у майбутньому підручнику.
Ще один цікавий приклад QListView див. У цьому прикладі програми медіаплеєра. Він використовує список QT QMediaPlaylist, як датар, із вмістом відображається на QListView .
Про BCR.CX:
BCR.CX – це бразильський запуск технологій, спеціалізований як як у процесах аутсорсингу бізнесу (BPO), так і в аутсорсингу ділового середовища (BEO), в основному орієнтований на генерацію попиту, досвід клієнтів, спілкування, підтримка користувачів та задоволення.
Опис:
Додаток Todo був розроблений як швидкий, безпечний та зручний спосіб для зберігання нотаток агента протягом робочих днів.
Мати можливість створювати та керувати власними завданнями, виходячи з кожного окремого квитка або клієнта.
Створіть стежки та налаштуйте свій робочий процес
Підвищення продуктивності! Використовуючи додаток Todo, ви можете створити індивідуальні робочі процеси для стандартизації повторних процесів. Спробуйте зараз і почніть контролювати свій прогрес, як ваші тодоси та дони.
Ресурси:
- Створіть завдання для кожного квитка
- План прогресу для подальшого виконання
- Створіть стандартизовані робочі процеси для підвищення продуктивності.
- Керуйте своїм списком завдань, щоб не відставати від вашого розпорядку дня.
- Стек і Тодо, і Зендеск Сонячне, щоб отримати повний доступ до функцій програми
- Поліпшити продуктивність шляхом створення або редагування завдань автоматизації та збережіть персоналізовані пресети.