1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
|
(tutorial_financemanager_partone)=
# Finance Manager Tutorial - Part 1
In this tutorial, we will create a finance manager app using QtQuick and PySide6. The app will allow
you to add your expenses and visualize them using a pie charts based on the category of spending.
The application is designed in a way that it is compatible with Desktop and Android platforms.


To download the complete source code for this tutorial, visit
{ref}`example_tutorials_finance_manager_part1`.
## Prerequisites
Before we begin, firstly make sure you have Python 3.9+ and PySide6 installed within you Python
environment. You can install it using pip:
```bash
pip install PySide6
```
## Project Design
The finance manager app is a simple app demonstrating the use of PySide6 to integrate QtQuick with
Python, allowing for a seamless combination of QML for the user interface and Python for the backend
logic. It will have the following components:
1. Expense List: This list will display all the entered expenses, showing the expense name, amount,
category and date. The expenses are organized by their month and year.
2. PieChart: This chart will visualize the expenses based on their categories, giving users a clear
overview of their spending habits.
3. Add Expense: A dialog enabling the user to add new expenses.
The overall project structure will be as follows:
```
finance_manager/
├── main.py
├── financemodel.py
├── Finance/
│ ├── Main.qml
│ ├── FinanceView.qml
│ ├── FinanceDelegate.qml
│ ├── FinancePieChart.qml
│ ├── AddDialog.qml
│ └── qmldir
```
## Let's get started!
### Component Overview
In the first part of this tutorial, we will start by creating the Expense List using some
pre-defined expenses. For this, we will create a new Python file `financemodel.py` that
defines a class **FinanceModel** that will be used to manage the expenses from Python and expose
it to QML.
<details>
<summary class="prominent-summary">financemodel.py</summary>
```{literalinclude} ../../../../../../../../../examples/tutorials/finance_manager/part1/financemodel.py
---
language: python
caption: FinanceModel class definition
linenos: true
---
```
</details>
Here's a brief overview of the `FinanceModel` class, its components and methods:
1. **QML type registration**
- The `FinanceModel` class is registered as a QML type using the {deco}`~PySide6.QtQml.QmlElement`
decorator. This decorator is used to define a Python class as a QML type, allowing it to be used
in QML files.
- The `QML_IMPORT_NAME` variable is used to define the name of the module that will be imported
in QML to access the `FinanceModel` class.
2. **Members**
- **FinanceRole Enum**: Defines custom roles for the model data, such as `ItemNameRole`,
`CategoryRole`, `CostRole`, `DateRole` and `MonthRole`.
- **Finance Dataclass**: Represents an individual expense with the attributes `item_name`,
`category`, `cost`, `date` and `month`.
- **init Method**: Initializes the model with some pre-defined expenses.
- **rowCount Method**: Returns the number of items in the model.
- **data Method**: Returns the data for a given role and index in the model.
- **getCategoryData Method**: Returns a dictionary the total cost for each category in the
model. This method has the `@Slot` decorator to make it accessible from QML.
- **roleNames Method**: Maps role names to their `QByteArray` values.
- **get Method**: A `@Slot` method to get the expense data at a given index.
- **append Method**: A `@Slot` method to append a new expense to the model.
For using as a data model in the `ListView` component in QML, the methods `rowCount`, `data`, and
`roleNames` are required.
Now that we have defined the `FinanceModel` class, let's create the QML components to display the
expenses. First, we create `Finance/Main.qml` file that will be the main QML file for our app.
<details>
<summary class="prominent-summary">Main.qml</summary>
```{literalinclude} ../../../../../../../../../examples/tutorials/finance_manager/part1/Finance/Main.qml
---
language: QML
caption: Main.qml
linenos: true
---
```
</details>
In the `Main.qml` we import the created `Finance` QML module file and the file has the following components:
1. **ApplicationWindow**:
- The main window of the application.
- Sets the theme to `Material.Dark` and accent color to `Material.Gray`.
- Adjusts the window size to the screen dimensions.
- Contains the title "Finance Manager".
2. **ToolBar**:
- A toolbar that is only visible on mobile platforms (Android and iOS). Note that PySide6
supports only Android, but you can use the same code with Qt C++ for iOS.
- Contains a `Label` with the text "Finance Manager".
3. **ColumnLayout**:
- A layout that arranges its children in a column.
- Fills the entire window.
4. **TabBar**:
- Contains two `TabButton` components for switching between **Expense** and **Charts** views.
5. **StackLayout**:
- A layout that stacks its children on top of each other.
- Contains two `Item`components for the "Expenses" and "Charts" views.
6. **FinanceView**:
- A custom component to display the list of expenses.
- Binds to the `finance_model`.
- This component is defined in the `FinanceView.qml` file.
7. **FinancePieChart**:
- A custom component to display a pie chart of expenses by category.
- Updates the chart with data from `finance_model.getCategoryData()` when the component is
completed.
- This component is defined in the `FinancePieChart.qml` file.
8. **FinanceModel**:
- The data model created from Python to store finance data. This is imported by import the
QML module `Finance` in the `Main.qml` file.
9. **AddDialog**:
- A dialog for adding new expense entries.
- Appends new entries to `finance_model` and updates the pie chart.
10. **RoundButton**:
- A circular button to open the `AddDialog.qml`.
- Positioned at the bottom-right corner of the window.
- Contains a "+" symbol and has a highlighted appearance.
Now that we have the basic structure of the main QML file, let's create the `FinanceView.qml` file:
<details>
<summary class="prominent-summary">FinanceView.qml</summary>
```{literalinclude} ../../../../../../../../../examples/tutorials/finance_manager/part1/Finance/FinanceView.qml
---
language: QML
caption: FinanceView.qml
linenos: true
---
```
</details>
`FinanceView.qml` contains the following components:
1. **ListView**:
- The main container for displaying a list of items.
- Fills the entire parent container using `anchors.fill: parent`.
- Uses the `financeModel` property as its data model.
2. **property var financeModel**:
- A property to hold the data model for the list.
- This model is expected to be passed from the parent component. In this case, it is passed from
the `Main.qml` file.
3. **delegate**:
- Defines how each item in the `ListView` should be displayed.
- Uses a custom component `FinanceDelegate` to render each item. This component is defined in the
`FinanceDelegate.qml` file.
- Sets the width of each delegate to match the width of the `ListView`.
4. **model**:
- Binds the `ListView` to the `financeModel` property.
- The `ListView` will display items based on the data in `financeModel`.
5. **section**:
- The section property is used to group the items in the list view based on the month of the
expense.
6. **ScrollBar.vertical**:
- Adds a vertical scrollbar to the `ListView`.
- Ensures that users can scroll through the list if the content exceeds the visible area.
These components together create a scrollable list view for displaying financial data, with each
item rendered using the `FinanceDelegate` component.
Next, let's create the `FinanceDelegate.qml` file:
<details>
<summary class="prominent-summary">FinanceDelegate.qml</summary>
```{literalinclude} ../../../../../../../../../examples/tutorials/finance_manager/part1/Finance/FinanceDelegate.qml
---
language: QML
caption: FinanceDelegate.qml
linenos: true
---
```
</details>
`FinanceDelegate.qml` contains the following components:
1. **ItemDelegate**:
- The root element of the delegate.
- Represents a single item in the `ListView`.
2. **RowLayout**:
- A layout that arranges its children horizontally.
- Contains multiple elements to display different parts of the financial data.
3. **Label (dateLabel)**:
- Displays the date of the expense.
4. **ColumnLayout**:
- A layout that arranges its children vertically.
- Contains labels for the item name and category.
5. **Label (item_name)**:
- Displays the name of the item.
6. **Label (category)**:
- Displays the category of the transaction.
7. **Item**:
- A spacer item to take up the remaining space in the `RowLayout` so that the last label is
aligned to the right.
8. **ColumnLayout (cost section)**:
- A layout that arranges its children vertically.
- Contains labels for the cost description and the actual cost.
9. **Label ("you spent:")**:
- Displays the static text "you spent:"
10. **Label (cost)**:
- Displays the cost of the transaction.
These components together create a detailed and structured visual representation of each financial
transaction in the `ListView`, displaying the date, item name, category, and cost in a readable format.
Then we create the `FinancePieChart.qml` file:
<details>
<summary class="prominent-summary">FinancePieChart.qml</summary>
```{literalinclude} ../../../../../../../../../examples/tutorials/finance_manager/part1/Finance/FinancePieChart.qml
---
language: QML
caption: FinancePieChart.qml
linenos: true
---
```
</details>
`FinancePieChart.qml` contains the following components:
1. **Item**:
- The root element of the QML file.
- Sets the width and height to match the screen dimensions.
2. **GraphsView**:
- A container for displaying charts. This was introduced with
Qt 6.8 with Qt Graphs module.
3. **PieSeries**:
- A series type for creating pie charts. This is also a part of the
Qt Graphs module.
4. **Text**
- A title for the pie chart.
5. **updateChart(data)**:
- A JavaScript function to update the pie chart with new data.
- Clears existing slices in the PieSeries.
- Iterates over the provided data to create new slices.
- Each slice is labeled with the category name and value in euros.
These components together create a responsive pie chart that can be dynamically updated with new
data.
Finally, we create the `AddDialog.qml` file:
<details>
<summary class="prominent-summary">AddDialog.qml</summary>
```{literalinclude} ../../../../../../../../../examples/tutorials/finance_manager/part1/Finance/AddDialog.qml
---
language: QML
caption: AddDialog.qml
linenos: true
---
```
</details>
`AddDialog.qml` contains the following components:
1. **Dialog**:
- Root element for the dialog.: Identifier for the dialog.
- `signal finished(...)`: Custom signal emitted when the dialog is accepted. In this case, it
is emitted when the user adds a new expense.
3. **ColumnLayout**:
- Container for the dialog fields.
4. **TextField**:
- Input fields for the item name, category, cost and date.
5. **Function `createEntry()`**:
- Clears the form fields.
- Sets the dialog title.
- Opens the dialog.
6. **Dialog Properties**:
- `title: qsTr("Add Finance Item")`: Sets the dialog title.
- `standardButtons: Dialog.Ok | Dialog.Cancel`: Adds standard OK and Cancel buttons.
- `Component.onCompleted`: Hides the dialog when the component is first completed.
- `onAccepted`: Calls the `finished` function with the form data when the dialog is accepted.
7. **Function `adjustDialogPosition`**:
- Adjusts the dialog position to move slightly up when the virtual keyboard is shown. This is
only applicable for mobile platforms.
### Main Python file
Now that we have created the main QML file and the necessary components, we can run the application
to see the expense list view in action. Create a new Python file `main.py` and add the following
code:
<details>
<summary class="prominent-summary">main.py</summary>
```{literalinclude} ../../../../../../../../../examples/tutorials/finance_manager/part1/main.py
---
language: python
caption: main.py
linenos: true
---
```
</details>
In the `main.py` file, we create a `QApplication` instance, load the `Main.qml` file. The Python
import statement `from financemodel import FinanceModel` registers the `FinanceModel` class as a QML
type, allowing it to be used in QML files.
### Running the Application
To run the application, execute the `main.py` file using Python:
```bash
python main.py
```
### Deploying the Application
To deploy the application on Desktop, you can use the {ref}`pyside6-deploy` tool. Run the following
command from the project directory:
```bash
pyside6-deploy --name FinanceManager
```
This will create a standalone executable for the application in the project directory.
For deploying to Android, you can use the {ref}`pyside6-android-deploy` tool. Run the following
command from the project directory:
```bash
pyside6-android-deploy --name FinanceManager --wheel-pyside=<path_to_pyside6_wheel>
--wheel-shiboken=<path_to_shiboken_wheel>
```
This will create an APK file that can be installed on an Android device in the project directory.
## Summary
In this part of the tutorial, we have created a basic finance manager app, including the expense
list view categorized by month and year, the pie chart, and the add expense dialog. We have also
defined the `FinanceModel` class in Python to manage the financial data and expose it to QML.
In the next part of the tutorial, we will continue to build on this foundation by moving the
expense data into a database based on the [`sqlalchemy`](https://www.sqlalchemy.org/) Python
package.
|