summaryrefslogtreecommitdiffstats
path: root/Doc/reference/lexical_analysis.rst
blob: 52a09a895c662248113a616b99c075d93eafa8d3 (plain)
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
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765

.. _lexical:

****************
Lexical analysis
****************

.. index::
   single: lexical analysis
   single: parser
   single: token

A Python program is read by a *parser*.  Input to the parser is a stream of
*tokens*, generated by the *lexical analyzer*.  This chapter describes how the
lexical analyzer breaks a file into tokens.

Python uses the 7-bit ASCII character set for program text.

.. versionadded:: 2.3
   An encoding declaration can be used to indicate that  string literals and
   comments use an encoding different from ASCII.

For compatibility with older versions, Python only warns if it finds 8-bit
characters; those warnings should be corrected by either declaring an explicit
encoding, or using escape sequences if those bytes are binary data, instead of
characters.

The run-time character set depends on the I/O devices connected to the program
but is generally a superset of ASCII.

**Future compatibility note:** It may be tempting to assume that the character
set for 8-bit characters is ISO Latin-1 (an ASCII superset that covers most
western languages that use the Latin alphabet), but it is possible that in the
future Unicode text editors will become common.  These generally use the UTF-8
encoding, which is also an ASCII superset, but with very different use for the
characters with ordinals 128-255.  While there is no consensus on this subject
yet, it is unwise to assume either Latin-1 or UTF-8, even though the current
implementation appears to favor Latin-1.  This applies both to the source
character set and the run-time character set.


.. _line-structure:

Line structure
==============

.. index:: single: line structure

A Python program is divided into a number of *logical lines*.


.. _logical:

Logical lines
-------------

.. index::
   single: logical line
   single: physical line
   single: line joining
   single: NEWLINE token

The end of a logical line is represented by the token NEWLINE.  Statements
cannot cross logical line boundaries except where NEWLINE is allowed by the
syntax (e.g., between statements in compound statements). A logical line is
constructed from one or more *physical lines* by following the explicit or
implicit *line joining* rules.


.. _physical:

Physical lines
--------------

A physical line is a sequence of characters terminated by an end-of-line
sequence.  In source files, any of the standard platform line termination
sequences can be used - the Unix form using ASCII LF (linefeed), the Windows
form using the ASCII sequence CR LF (return followed by linefeed), or the old
Macintosh form using the ASCII CR (return) character.  All of these forms can be
used equally, regardless of platform.

When embedding Python, source code strings should be passed to Python APIs using
the standard C conventions for newline characters (the ``\n`` character,
representing ASCII LF, is the line terminator).


.. _comments:

Comments
--------

.. index::
   single: comment
   single: hash character

A comment starts with a hash character (``#``) that is not part of a string
literal, and ends at the end of the physical line.  A comment signifies the end
of the logical line unless the implicit line joining rules are invoked. Comments
are ignored by the syntax; they are not tokens.


.. _encodings:

Encoding declarations
---------------------

.. index:: source character set, encoding declarations (source file)

If a comment in the first or second line of the Python script matches the
regular expression ``coding[=:]\s*([-\w.]+)``, this comment is processed as an
encoding declaration; the first group of this expression names the encoding of
the source code file. The recommended forms of this expression are ::

   # -*- coding: <encoding-name> -*-

which is recognized also by GNU Emacs, and ::

   # vim:fileencoding=<encoding-name>

which is recognized by Bram Moolenaar's VIM. In addition, if the first bytes of
the file are the UTF-8 byte-order mark (``'\xef\xbb\xbf'``), the declared file
encoding is UTF-8 (this is supported, among others, by Microsoft's
:program:`notepad`).

If an encoding is declared, the encoding name must be recognized by Python. The
encoding is used for all lexical analysis, in particular to find the end of a
string, and to interpret the contents of Unicode literals. String literals are
converted to Unicode for syntactical analysis, then converted back to their
original encoding before interpretation starts. The encoding declaration must
appear on a line of its own.

.. XXX there should be a list of supported encodings.


.. _explicit-joining:

Explicit line joining
---------------------

.. index::
   single: physical line
   single: line joining
   single: line continuation
   single: backslash character

Two or more physical lines may be joined into logical lines using backslash
characters (``\``), as follows: when a physical line ends in a backslash that is
not part of a string literal or comment, it is joined with the following forming
a single logical line, deleting the backslash and the following end-of-line
character.  For example::

   if 1900 < year < 2100 and 1 <= month <= 12 \
      and 1 <= day <= 31 and 0 <= hour < 24 \
      and 0 <= minute < 60 and 0 <= second < 60:   # Looks like a valid date
           return 1

A line ending in a backslash cannot carry a comment.  A backslash does not
continue a comment.  A backslash does not continue a token except for string
literals (i.e., tokens other than string literals cannot be split across
physical lines using a backslash).  A backslash is illegal elsewhere on a line
outside a string literal.


.. _implicit-joining:

Implicit line joining
---------------------

Expressions in parentheses, square brackets or curly braces can be split over
more than one physical line without using backslashes. For example::

   month_names = ['Januari', 'Februari', 'Maart',      # These are the
                  'April',   'Mei',      'Juni',       # Dutch names
                  'Juli',    'Augustus', 'September',  # for the months
                  'Oktober', 'November', 'December']   # of the year

Implicitly continued lines can carry comments.  The indentation of the
continuation lines is not important.  Blank continuation lines are allowed.
There is no NEWLINE token between implicit continuation lines.  Implicitly
continued lines can also occur within triple-quoted strings (see below); in that
case they cannot carry comments.


.. _blank-lines:

Blank lines
-----------

.. index:: single: blank line

A logical line that contains only spaces, tabs, formfeeds and possibly a
comment, is ignored (i.e., no NEWLINE token is generated).  During interactive
input of statements, handling of a blank line may differ depending on the
implementation of the read-eval-print loop.  In the standard implementation, an
entirely blank logical line (i.e. one containing not even whitespace or a
comment) terminates a multi-line statement.


.. _indentation:

Indentation
-----------

.. index::
   single: indentation
   single: whitespace
   single: leading whitespace
   single: space
   single: tab
   single: grouping
   single: statement grouping

Leading whitespace (spaces and tabs) at the beginning of a logical line is used
to compute the indentation level of the line, which in turn is used to determine
the grouping of statements.

First, tabs are replaced (from left to right) by one to eight spaces such that
the total number of characters up to and including the replacement is a multiple
of eight (this is intended to be the same rule as used by Unix).  The total
number of spaces preceding the first non-blank character then determines the
line's indentation.  Indentation cannot be split over multiple physical lines
using backslashes; the whitespace up to the first backslash determines the
indentation.

**Cross-platform compatibility note:** because of the nature of text editors on
non-UNIX platforms, it is unwise to use a mixture of spaces and tabs for the
indentation in a single source file.  It should also be noted that different
platforms may explicitly limit the maximum indentation level.

A formfeed character may be present at the start of the line; it will be ignored
for the indentation calculations above.  Formfeed characters occurring elsewhere
in the leading whitespace have an undefined effect (for instance, they may reset
the space count to zero).

.. index::
   single: INDENT token
   single: DEDENT token

The indentation levels of consecutive lines are used to generate INDENT and
DEDENT tokens, using a stack, as follows.

Before the first line of the file is read, a single zero is pushed on the stack;
this will never be popped off again.  The numbers pushed on the stack will
always be strictly increasing from bottom to top.  At the beginning of each
logical line, the line's indentation level is compared to the top of the stack.
If it is equal, nothing happens. If it is larger, it is pushed on the stack, and
one INDENT token is generated.  If it is smaller, it *must* be one of the
numbers occurring on the stack; all numbers on the stack that are larger are
popped off, and for each number popped off a DEDENT token is generated.  At the
end of the file, a DEDENT token is generated for each number remaining on the
stack that is larger than zero.

Here is an example of a correctly (though confusingly) indented piece of Python
code::

   def perm(l):
           # Compute the list of all permutations of l
       if len(l) <= 1:
                     return [l]
       r = []
       for i in range(len(l)):
                s = l[:i] + l[i+1:]
                p = perm(s)
                for x in p:
                 r.append(l[i:i+1] + x)
       return r

The following example shows various indentation errors::

    def perm(l):                       # error: first line indented
   for i in range(len(l)):             # error: not indented
       s = l[:i] + l[i+1:]
           p = perm(l[:i] + l[i+1:])   # error: unexpected indent
           for x in p:
                   r.append(l[i:i+1] + x)
               return r                # error: inconsistent dedent

(Actually, the first three errors are detected by the parser; only the last
error is found by the lexical analyzer --- the indentation of ``return r`` does
not match a level popped off the stack.)


.. _whitespace:

Whitespace between tokens
-------------------------

Except at the beginning of a logical line or in string literals, the whitespace
characters space, tab and formfeed can be used interchangeably to separate
tokens.  Whitespace is needed between two tokens only if their concatenation
could otherwise be interpreted as a different token (e.g., ab is one token, but
a b is two tokens).


.. _other-tokens:

Other tokens
============

Besides NEWLINE, INDENT and DEDENT, the following categories of tokens exist:
*identifiers*, *keywords*, *literals*, *operators*, and *delimiters*. Whitespace
characters (other than line terminators, discussed earlier) are not tokens, but
serve to delimit tokens. Where ambiguity exists, a token comprises the longest
possible string that forms a legal token, when read from left to right.


.. _identifiers:

Identifiers and keywords
========================

.. index::
   single: identifier
   single: name

Identifiers (also referred to as *names*) are described by the following lexical
definitions:

.. productionlist::
   identifier: (`letter`|"_") (`letter` | `digit` | "_")*
   letter: `lowercase` | `uppercase`
   lowercase: "a"..."z"
   uppercase: "A"..."Z"
   digit: "0"..."9"

Identifiers are unlimited in length.  Case is significant.


.. _keywords:

Keywords
--------

.. index::
   single: keyword
   single: reserved word

The following identifiers are used as reserved words, or *keywords* of the
language, and cannot be used as ordinary identifiers.  They must be spelled
exactly as written here:

.. sourcecode:: text

   and       del       from      not       while
   as        elif      global    or        with
   assert    else      if        pass      yield
   break     except    import    print
   class     exec      in        raise
   continue  finally   is        return
   def       for       lambda    try

.. versionchanged:: 2.4
   :const:`None` became a constant and is now recognized by the compiler as a name
   for the built-in object :const:`None`.  Although it is not a keyword, you cannot
   assign a different object to it.

.. versionchanged:: 2.5
   Using :keyword:`as` and :keyword:`with` as identifiers triggers a warning.  To
   use them as keywords, enable the ``with_statement`` future feature .

.. versionchanged:: 2.6
    :keyword:`as` and :keyword:`with` are full keywords.


.. _id-classes:

Reserved classes of identifiers
-------------------------------

Certain classes of identifiers (besides keywords) have special meanings.  These
classes are identified by the patterns of leading and trailing underscore
characters:

``_*``
   Not imported by ``from module import *``.  The special identifier ``_`` is used
   in the interactive interpreter to store the result of the last evaluation; it is
   stored in the :mod:`__builtin__` module.  When not in interactive mode, ``_``
   has no special meaning and is not defined. See section :ref:`import`.

   .. note::

      The name ``_`` is often used in conjunction with internationalization;
      refer to the documentation for the :mod:`gettext` module for more
      information on this convention.

``__*__``
   System-defined names. These names are defined by the interpreter and its
   implementation (including the standard library).  Current system names are
   discussed in the :ref:`specialnames` section and elsewhere.  More will likely
   be defined in future versions of Python.  *Any* use of ``__*__`` names, in
   any context, that does not follow explicitly documented use, is subject to
   breakage without warning.

``__*``
   Class-private names.  Names in this category, when used within the context of a
   class definition, are re-written to use a mangled form to help avoid name
   clashes between "private" attributes of base and derived classes. See section
   :ref:`atom-identifiers`.


.. _literals:

Literals
========

.. index::
   single: literal
   single: constant

Literals are notations for constant values of some built-in types.


.. _strings:

String literals
---------------

.. index:: single: string literal

String literals are described by the following lexical definitions:

.. index:: single: ASCII@ASCII

.. productionlist::
   stringliteral: [`stringprefix`](`shortstring` | `longstring`)
   stringprefix: "r" | "u" | "ur" | "R" | "U" | "UR" | "Ur" | "uR"
               : | "b" | "B" | "br" | "Br" | "bR" | "BR"
   shortstring: "'" `shortstringitem`* "'" | '"' `shortstringitem`* '"'
   longstring: "'''" `longstringitem`* "'''"
             : | '"""' `longstringitem`* '"""'
   shortstringitem: `shortstringchar` | `escapeseq`
   longstringitem: `longstringchar` | `escapeseq`
   shortstringchar: <any source character except "\" or newline or the quote>
   longstringchar: <any source character except "\">
   escapeseq: "\" <any ASCII character>

One syntactic restriction not indicated by these productions is that whitespace
is not allowed between the :token:`stringprefix` and the rest of the string
literal. The source character set is defined by the encoding declaration; it is
ASCII if no encoding declaration is given in the source file; see section
:ref:`encodings`.

.. index::
   single: triple-quoted string
   single: Unicode Consortium
   single: string; Unicode
   single: raw string

In plain English: String literals can be enclosed in matching single quotes
(``'``) or double quotes (``"``).  They can also be enclosed in matching groups
of three single or double quotes (these are generally referred to as
*triple-quoted strings*).  The backslash (``\``) character is used to escape
characters that otherwise have a special meaning, such as newline, backslash
itself, or the quote character.  String literals may optionally be prefixed with
a letter ``'r'`` or ``'R'``; such strings are called :dfn:`raw strings` and use
different rules for interpreting backslash escape sequences.  A prefix of
``'u'`` or ``'U'`` makes the string a Unicode string.  Unicode strings use the
Unicode character set as defined by the Unicode Consortium and ISO 10646.  Some
additional escape sequences, described below, are available in Unicode strings.
A prefix of ``'b'`` or ``'B'`` is ignored in Python 2; it indicates that the
literal should become a bytes literal in Python 3 (e.g. when code is
automatically converted with 2to3).  A ``'u'`` or ``'b'`` prefix may be followed
by an ``'r'`` prefix.

In triple-quoted strings, unescaped newlines and quotes are allowed (and are
retained), except that three unescaped quotes in a row terminate the string.  (A
"quote" is the character used to open the string, i.e. either ``'`` or ``"``.)

.. index::
   single: physical line
   single: escape sequence
   single: Standard C
   single: C

Unless an ``'r'`` or ``'R'`` prefix is present, escape sequences in strings are
interpreted according to rules similar to those used by Standard C.  The
recognized escape sequences are:

+-----------------+---------------------------------+-------+
| Escape Sequence | Meaning                         | Notes |
+=================+=================================+=======+
| ``\newline``    | Ignored                         |       |
+-----------------+---------------------------------+-------+
| ``\\``          | Backslash (``\``)               |       |
+-----------------+---------------------------------+-------+
| ``\'``          | Single quote (``'``)            |       |
+-----------------+---------------------------------+-------+
| ``\"``          | Double quote (``"``)            |       |
+-----------------+---------------------------------+-------+
| ``\a``          | ASCII Bell (BEL)                |       |
+-----------------+---------------------------------+-------+
| ``\b``          | ASCII Backspace (BS)            |       |
+-----------------+---------------------------------+-------+
| ``\f``          | ASCII Formfeed (FF)             |       |
+-----------------+---------------------------------+-------+
| ``\n``          | ASCII Linefeed (LF)             |       |
+-----------------+---------------------------------+-------+
| ``\N{name}``    | Character named *name* in the   |       |
|                 | Unicode database (Unicode only) |       |
+-----------------+---------------------------------+-------+
| ``\r``          | ASCII Carriage Return (CR)      |       |
+-----------------+---------------------------------+-------+
| ``\t``          | ASCII Horizontal Tab (TAB)      |       |
+-----------------+---------------------------------+-------+
| ``\uxxxx``      | Character with 16-bit hex value | \(1)  |
|                 | *xxxx* (Unicode only)           |       |
+-----------------+---------------------------------+-------+
| ``\Uxxxxxxxx``  | Character with 32-bit hex value | \(2)  |
|                 | *xxxxxxxx* (Unicode only)       |       |
+-----------------+---------------------------------+-------+
| ``\v``          | ASCII Vertical Tab (VT)         |       |
+-----------------+---------------------------------+-------+
| ``\ooo``        | Character with octal value      | (3,5) |
|                 | *ooo*                           |       |
+-----------------+---------------------------------+-------+
| ``\xhh``        | Character with hex value *hh*   | (4,5) |
+-----------------+---------------------------------+-------+

.. index:: single: ASCII@ASCII

Notes:

(1)
   Individual code units which form parts of a surrogate pair can be encoded using
   this escape sequence.

(2)
   Any Unicode character can be encoded this way, but characters outside the Basic
   Multilingual Plane (BMP) will be encoded using a surrogate pair if Python is
   compiled to use 16-bit code units (the default).

(3)
   As in Standard C, up to three octal digits are accepted.

(4)
   Unlike in Standard C, exactly two hex digits are required.

(5)
   In a string literal, hexadecimal and octal escapes denote the byte with the
   given value; it is not necessary that the byte encodes a character in the source
   character set. In a Unicode literal, these escapes denote a Unicode character
   with the given value.

.. index:: single: unrecognized escape sequence

Unlike Standard C, all unrecognized escape sequences are left in the string
unchanged, i.e., *the backslash is left in the string*.  (This behavior is
useful when debugging: if an escape sequence is mistyped, the resulting output
is more easily recognized as broken.)  It is also important to note that the
escape sequences marked as "(Unicode only)" in the table above fall into the
category of unrecognized escapes for non-Unicode string literals.

When an ``'r'`` or ``'R'`` prefix is present, a character following a backslash
is included in the string without change, and *all backslashes are left in the
string*.  For example, the string literal ``r"\n"`` consists of two characters:
a backslash and a lowercase ``'n'``.  String quotes can be escaped with a
backslash, but the backslash remains in the string; for example, ``r"\""`` is a
valid string literal consisting of two characters: a backslash and a double
quote; ``r"\"`` is not a valid string literal (even a raw string cannot end in
an odd number of backslashes).  Specifically, *a raw string cannot end in a
single backslash* (since the backslash would escape the following quote
character).  Note also that a single backslash followed by a newline is
interpreted as those two characters as part of the string, *not* as a line
continuation.

When an ``'r'`` or ``'R'`` prefix is used in conjunction with a ``'u'`` or
``'U'`` prefix, then the ``\uXXXX`` and ``\UXXXXXXXX`` escape sequences are
processed while  *all other backslashes are left in the string*. For example,
the string literal ``ur"\u0062\n"`` consists of three Unicode characters: 'LATIN
SMALL LETTER B', 'REVERSE SOLIDUS', and 'LATIN SMALL LETTER N'. Backslashes can
be escaped with a preceding backslash; however, both remain in the string.  As a
result, ``\uXXXX`` escape sequences are only recognized when there are an odd
number of backslashes.


.. _string-catenation:

String literal concatenation
----------------------------

Multiple adjacent string literals (delimited by whitespace), possibly using
different quoting conventions, are allowed, and their meaning is the same as
their concatenation.  Thus, ``"hello" 'world'`` is equivalent to
``"helloworld"``.  This feature can be used to reduce the number of backslashes
needed, to split long strings conveniently across long lines, or even to add
comments to parts of strings, for example::

   re.compile("[A-Za-z_]"       # letter or underscore
              "[A-Za-z0-9_]*"   # letter, digit or underscore
             )

Note that this feature is defined at the syntactical level, but implemented at
compile time.  The '+' operator must be used to concatenate string expressions
at run time.  Also note that literal concatenation can use different quoting
styles for each component (even mixing raw strings and triple quoted strings).


.. _numbers:

Numeric literals
----------------

.. index::
   single: number
   single: numeric literal
   single: integer literal
   single: plain integer literal
   single: long integer literal
   single: floating point literal
   single: hexadecimal literal
   single: binary literal
   single: octal literal
   single: decimal literal
   single: imaginary literal
   single: complex; literal

There are four types of numeric literals: plain integers, long integers,
floating point numbers, and imaginary numbers.  There are no complex literals
(complex numbers can be formed by adding a real number and an imaginary number).

Note that numeric literals do not include a sign; a phrase like ``-1`` is
actually an expression composed of the unary operator '``-``' and the literal
``1``.


.. _integers:

Integer and long integer literals
---------------------------------

Integer and long integer literals are described by the following lexical
definitions:

.. productionlist::
   longinteger: `integer` ("l" | "L")
   integer: `decimalinteger` | `octinteger` | `hexinteger` | `bininteger`
   decimalinteger: `nonzerodigit` `digit`* | "0"
   octinteger: "0" ("o" | "O") `octdigit`+ | "0" `octdigit`+
   hexinteger: "0" ("x" | "X") `hexdigit`+
   bininteger: "0" ("b" | "B") `bindigit`+
   nonzerodigit: "1"..."9"
   octdigit: "0"..."7"
   bindigit: "0" | "1"
   hexdigit: `digit` | "a"..."f" | "A"..."F"

Although both lower case ``'l'`` and upper case ``'L'`` are allowed as suffix
for long integers, it is strongly recommended to always use ``'L'``, since the
letter ``'l'`` looks too much like the digit ``'1'``.

Plain integer literals that are above the largest representable plain integer
(e.g., 2147483647 when using 32-bit arithmetic) are accepted as if they were
long integers instead. [#]_  There is no limit for long integer literals apart
from what can be stored in available memory.

Some examples of plain integer literals (first row) and long integer literals
(second and third rows)::

   7     2147483647                        0177
   3L    79228162514264337593543950336L    0377L   0x100000000L
         79228162514264337593543950336             0xdeadbeef


.. _floating:

Floating point literals
-----------------------

Floating point literals are described by the following lexical definitions:

.. productionlist::
   floatnumber: `pointfloat` | `exponentfloat`
   pointfloat: [`intpart`] `fraction` | `intpart` "."
   exponentfloat: (`intpart` | `pointfloat`) `exponent`
   intpart: `digit`+
   fraction: "." `digit`+
   exponent: ("e" | "E") ["+" | "-"] `digit`+

Note that the integer and exponent parts of floating point numbers can look like
octal integers, but are interpreted using radix 10.  For example, ``077e010`` is
legal, and denotes the same number as ``77e10``. The allowed range of floating
point literals is implementation-dependent. Some examples of floating point
literals::

   3.14    10.    .001    1e100    3.14e-10    0e0

Note that numeric literals do not include a sign; a phrase like ``-1`` is
actually an expression composed of the unary operator ``-`` and the literal
``1``.


.. _imaginary:

Imaginary literals
------------------

Imaginary literals are described by the following lexical definitions:

.. productionlist::
   imagnumber: (`floatnumber` | `intpart`) ("j" | "J")

An imaginary literal yields a complex number with a real part of 0.0.  Complex
numbers are represented as a pair of floating point numbers and have the same
restrictions on their range.  To create a complex number with a nonzero real
part, add a floating point number to it, e.g., ``(3+4j)``.  Some examples of
imaginary literals::

   3.14j   10.j    10j     .001j   1e100j  3.14e-10j


.. _operators:

Operators
=========

.. index:: single: operators

The following tokens are operators::

   +       -       *       **      /       //      %
   <<      >>      &       |       ^       ~
   <       >       <=      >=      ==      !=      <>

The comparison operators ``<>`` and ``!=`` are alternate spellings of the same
operator.  ``!=`` is the preferred spelling; ``<>`` is obsolescent.


.. _delimiters:

Delimiters
==========

.. index:: single: delimiters

The following tokens serve as delimiters in the grammar::

   (       )       [       ]       {       }      @
   ,       :       .       `       =       ;
   +=      -=      *=      /=      //=     %=
   &=      |=      ^=      >>=     <<=     **=

The period can also occur in floating-point and imaginary literals.  A sequence
of three periods has a special meaning as an ellipsis in slices. The second half
of the list, the augmented assignment operators, serve lexically as delimiters,
but also perform an operation.

The following printing ASCII characters have special meaning as part of other
tokens or are otherwise significant to the lexical analyzer::

   '       "       #       \

.. index:: single: ASCII@ASCII

The following printing ASCII characters are not used in Python.  Their
occurrence outside string literals and comments is an unconditional error::

   $       ?

.. rubric:: Footnotes

.. [#] In versions of Python prior to 2.4, octal and hexadecimal literals in the range
   just above the largest representable plain integer but below the largest
   unsigned 32-bit number (on a machine using 32-bit arithmetic), 4294967296, were
   taken as the negative plain integer obtained by subtracting 4294967296 from
   their unsigned value.

t supprimer des adresses}
\o \l{tutorials/addressbook-fr/part5}{Ajout d'une fonction de recherche}
\o \l{tutorials/addressbook-fr/part6}{Sauvegarde et chargement}
- \o \l{tutorials/addressbook-fr/part7}{Fonctionnalits avances}
+ \o \l{tutorials/addressbook-fr/part7}{Fonctionnalités avancées}
\endlist
- La petite application que nous dvelopperons ici ne possde pas tous les lments
+ La petite application que nous développerons ici ne possède pas tous les éléments
des interfaces dernier cri, elle va nous permettre d'utiliser les techniques de base
- utilises dans les applications plus complexes.
+ utilisées dans les applications plus complexes.
- Lorsque vous aurez termin ce tutoriel, nous vous recommandons de poursuivre avec l'exemple
- "\l{mainwindows/application}{Application}", qui prsente une interface simple utilisant
- les menus et barres d'outils, la barre d'tat, etc.
+ Lorsque vous aurez terminé ce tutoriel, nous vous recommandons de poursuivre avec l'exemple
+ "\l{mainwindows/application}{Application}", qui présente une interface simple utilisant
+ les menus et barres d'outils, la barre d'état, etc.
*/
@@ -98,156 +98,156 @@
\example tutorials/addressbook-fr/part1
\title Carnet d'adresses 1 - Conception de l'interface utilisateur
- La premire partie de ce tutoriel traite de la conception d'une interface graphique
+ La première partie de ce tutoriel traite de la conception d'une interface graphique
(GUI) basique, que l'on utilisera pour l'application Carnet d'adresses.
- La premire tape dans la cration d'applications graphiques est la conception de
- l'interface utilisateur. Dans ce chapitre, nous verrons comment crer les labels
- et champs de saisie ncessaires l'implementation d'un carnet d'adresses de base.
- Le rsultat attendu est illustr par la capture d'cran ci-dessous.
+ La première étape dans la création d'applications graphiques est la conception de
+ l'interface utilisateur. Dans ce chapitre, nous verrons comment créer les labels
+ et champs de saisie nécessaires à l'implementation d'un carnet d'adresses de base.
+ Le résultat attendu est illustré par la capture d'écran ci-dessous.
\image addressbook-tutorial-part1-screenshot.png
Nous allons avoir besoin de deux objets QLabel, \c nameLabel et \c addressLabel,
ainsi que deux champs de saisie: un objet QLineEdit, \c nameLine, et un objet
- QTextEdit, \c addressText, afin de permettre l'utilisateur d'entrer le nom d'un
- contact et son adresse. Les widgets utiliss ainsi que leur placement sont visibles ci-dessous.
+ QTextEdit, \c addressText, afin de permettre à l'utilisateur d'entrer le nom d'un
+ contact et son adresse. Les widgets utilisés ainsi que leur placement sont visibles ci-dessous.
\image addressbook-tutorial-part1-labeled-screenshot.png
- Trois fichiers sont ncessaires l'implmentation de ce carnet d'adresses:
+ Trois fichiers sont nécessaires à l'implémentation de ce carnet d'adresses:
\list
- \o \c{addressbook.h} - le fichier de dfinition (header) pour la classe \c AddressBook,
- \o \c{addressbook.cpp} - le fichier source, qui comprend l'implmentation de la classe
+ \o \c{addressbook.h} - le fichier de définition (header) pour la classe \c AddressBook,
+ \o \c{addressbook.cpp} - le fichier source, qui comprend l'implémentation de la classe
\c AddressBook
- \o \c{main.cpp} - le fichier qui contient la mthode \c main() , et
+ \o \c{main.cpp} - le fichier qui contient la méthode \c main() , et
une instance de la classe \c AddressBook.
\endlist
- \section1 Programmation en Qt - hritage
+ \section1 Programmation en Qt - héritage
- Lorsque l'on crit des programmes avec Qt, on a gnralement recours
- l'hritage depuis des objets Qt, afin d'y ajouter des fonctionnalits.
- C'est l'un des concepts fondamentaux de la cration de widgets personnaliss
- ou de collections de widgets. Utiliser l'hritage afin de complter
- ou modifier le comportement d'un widget prsente les avantages suivants:
+ Lorsque l'on écrit des programmes avec Qt, on a généralement recours à
+ l'héritage depuis des objets Qt, afin d'y ajouter des fonctionnalités.
+ C'est l'un des concepts fondamentaux de la création de widgets personnalisés
+ ou de collections de widgets. Utiliser l'héritage afin de compléter
+ ou modifier le comportement d'un widget présente les avantages suivants:
\list
- \o La possibilit d'implmenter des mthodes virtuelles et des mthodes
- virtuelles pures pour obtenir exactement ce que l'on souhaite, avec la possibilit
- d'utiliser l'implmentation de la classe mre si besoin est.
+ \o La possibilité d'implémenter des méthodes virtuelles et des méthodes
+ virtuelles pures pour obtenir exactement ce que l'on souhaite, avec la possibilité
+ d'utiliser l'implémentation de la classe mère si besoin est.
\o Cela permet l'encapsulation partielle de l'interface utilisateur dans une classe,
- afin que les autres parties de l'application n'aient pas se soucier de chacun des
+ afin que les autres parties de l'application n'aient pas à se soucier de chacun des
widgets qui forment l'interface utilisateur.
- \o La classe fille peut tre utilise pour crer de nombreux widgets personnaliss
- dans une mme application ou bibliothque, et le code de la classe fille peut tre
- rutilis dans d'autres projets
+ \o La classe fille peut être utilisée pour créer de nombreux widgets personnalisés
+ dans une même application ou bibliothèque, et le code de la classe fille peut être
+ réutilisé dans d'autres projets
\endlist
Comme Qt ne fournit pas de widget standard pour un carnet d'adresses, nous
- partirons d'une classe de widget Qt standard et y ajouterons des fonctionnalits.
- La classe \c AddressBook cre dans ce tutoriel peut tre rutilise si on a besoin d'un
+ partirons d'une classe de widget Qt standard et y ajouterons des fonctionnalités.
+ La classe \c AddressBook crée dans ce tutoriel peut être réutilisée si on a besoin d'un
widget carnet d'adresses basique.
\section1 La classe AddressBook
Le fichier \l{tutorials/addressbook-fr/part1/addressbook.h}{\c addressbook.h} permet de
- dfinir la classe \c AddressBook.
+ définir la classe \c AddressBook.
- On commence par dfinir \c AddressBook comme une classe fille de QWidget et dclarer
- un constructeur. On utilise galement la macro Q_OBJECT pour indiquer que la classe
- exploite les fonctionnalits de signaux et slots offertes par Qt ainsi que
- l'internationalisation, bien que nous ne les utilisions pas ce stade.
+ On commence par définir \c AddressBook comme une classe fille de QWidget et déclarer
+ un constructeur. On utilise également la macro Q_OBJECT pour indiquer que la classe
+ exploite les fonctionnalités de signaux et slots offertes par Qt ainsi que
+ l'internationalisation, bien que nous ne les utilisions pas à ce stade.
\snippet tutorials/addressbook-fr/part1/addressbook.h class definition
- La classe contient les dclarations de \c nameLine et \c addressText,
- les instances prives de QLineEdit et QTextEdit mentionnes prcdemment.
- Vous verrez, dans les chapitres venir que les informations contenues
- dans \c nameLine et \c addressText sont ncessaires de nombreuses mthodes
+ La classe contient les déclarations de \c nameLine et \c addressText,
+ les instances privées de QLineEdit et QTextEdit mentionnées précédemment.
+ Vous verrez, dans les chapitres à venir que les informations contenues
+ dans \c nameLine et \c addressText sont nécessaires à de nombreuses méthodes
du carnet d'adresses.
- Il n'est pas ncessaire de dclarer les objets QLabel que nous allons utiliser
- puisque nous n'aurons pas besoin d'y faire rfrence aprs leur cration.
- La faon dont Qt gre la parent des objets est traite dans la section suivante.
+ Il n'est pas nécessaire de déclarer les objets QLabel que nous allons utiliser
+ puisque nous n'aurons pas besoin d'y faire référence après leur création.
+ La façon dont Qt gère la parenté des objets est traitée dans la section suivante.
- La macro Q_OBJECT implmente des fonctionnalits parmi les plus avances de Qt.
+ La macro Q_OBJECT implémente des fonctionnalités parmi les plus avancées de Qt.
Pour le moment, il est bon de voir la macro Q_OBJECT comme un raccourci nous
- permettant d'utiliser les mthodes \l{QObject::}{tr()} et \l{QObject::}{connect()}.
+ permettant d'utiliser les méthodes \l{QObject::}{tr()} et \l{QObject::}{connect()}.
- Nous en avons maintenant termin avec le fichier \c addressbook.h et allons
- passer l'implmentation du fichier \c addressbook.cpp.
+ Nous en avons maintenant terminé avec le fichier \c addressbook.h et allons
+ passer à l'implémentation du fichier \c addressbook.cpp.
- \section1 Implmentation de la classe AddressBook
+ \section1 Implémentation de la classe AddressBook
- Le constructeur de la classe \c{AddressBook} prend en paramtre un QWidget, \e parent.
- Par convention, on passe ce paramtre au constructeur de la classe mre.
- Ce concept de parent, o un parent peut avoir un ou plusieurs enfants, est utile
- pour regrouper les Widgets avec Qt. Par exemple, si vous dtruisez le parent,
- tous ses enfants seront dtruits galament.
+ Le constructeur de la classe \c{AddressBook} prend en paramètre un QWidget, \e parent.
+ Par convention, on passe ce paramètre au constructeur de la classe mère.
+ Ce concept de parenté, où un parent peut avoir un ou plusieurs enfants, est utile
+ pour regrouper les Widgets avec Qt. Par exemple, si vous détruisez le parent,
+ tous ses enfants seront détruits égalament.
\snippet tutorials/addressbook/part1/addressbook.cpp constructor and input fields
- l'intrieur de ce constructeur, on dclare et instancie deux objets locaux
- QLabel, \c nameLabel et \c addressLabel, de mme on instancie \c nameLine et
- \c addressText. La mthode \l{QObject::tr()}{tr()} renvoie une version traduite
- de la chane de caractres, si elle existe; dans le cas contraire, elle renvoie
- la chane elle mme. On peut voir cette mthode comme un marqueur \tt{<insrer
- la traduction ici>}, permettant de reprer les objets QString considrer
- pour traduire une application. Vous remarquerez, dans les chapitres venir
- comme dans les \l{Qt Examples}{exemples Qt}, qu'elle est utilise chaque fois
- que l'on utilise une chane susceptible d'tre traduite.
+ à l'intérieur de ce constructeur, on déclare et instancie deux objets locaux
+ QLabel, \c nameLabel et \c addressLabel, de même on instancie \c nameLine et
+ \c addressText. La méthode \l{QObject::tr()}{tr()} renvoie une version traduite
+ de la chaîne de caractères, si elle existe; dans le cas contraire, elle renvoie
+ la chaîne elle même. On peut voir cette méthode comme un marqueur \tt{<insérer
+ la traduction ici>}, permettant de repérer les objets QString à considérer
+ pour traduire une application. Vous remarquerez, dans les chapitres à venir
+ comme dans les \l{Qt Examples}{exemples Qt}, qu'elle est utilisée chaque fois
+ que l'on utilise une chaîne susceptible d'être traduite.
Lorsque l'on programme avec Qt, il est utile de savoir comment fonctionnent les
agencements ou layouts. Qt fournit trois classes principales de layouts pour
- contrler le placement des widgets: QHBoxLayout, QVBoxLayout et QGridLayout.
+ contrôler le placement des widgets: QHBoxLayout, QVBoxLayout et QGridLayout.
\image addressbook-tutorial-part1-labeled-layout.png
- On utilise un QGridLayout pour positionner nos labels et champs de saisie de manire
- structure. QGridLayout divise l'espace disponible en une grille, et place les
- widgets dans les cellules que l'on spcifie par les numros de ligne et de colonne.
- Le diagramme ci-dessus prsente les cellules et la position des widgets, et cette
- organisation est obtenue l'aide du code suivant:
+ On utilise un QGridLayout pour positionner nos labels et champs de saisie de manière
+ structurée. QGridLayout divise l'espace disponible en une grille, et place les
+ widgets dans les cellules que l'on spécifie par les numéros de ligne et de colonne.
+ Le diagramme ci-dessus présente les cellules et la position des widgets, et cette
+ organisation est obtenue à l'aide du code suivant:
\snippet tutorials/addressbook/part1/addressbook.cpp layout
- On remarque que le label \c AddressLabel est positionn en utilisant Qt::AlignTop
- comme argument optionnel. Ceci est destin assurer qu'il ne sera pas centr
- verticalement dans la cellule (1,0). Pour un aperu rapide des layouts de Qt,
+ On remarque que le label \c AddressLabel est positionné en utilisant Qt::AlignTop
+ comme argument optionnel. Ceci est destiné à assurer qu'il ne sera pas centré
+ verticalement dans la cellule (1,0). Pour un aperçu rapide des layouts de Qt,
consultez la section \l{Layout Management}.
- Afin d'installer l'objet layout dans un widget, il faut appeler la mthode
+ Afin d'installer l'objet layout dans un widget, il faut appeler la méthode
\l{QWidget::setLayout()}{setLayout()} du widget en question:
\snippet tutorials/addressbook/part1/addressbook.cpp setting the layout
- Enfin, on initialise le titre du widget "Simple Address Book"
+ Enfin, on initialise le titre du widget à "Simple Address Book"
- \section1 Excution de l'application
+ \section1 Exécution de l'application
- Un fichier spar, \c main.cpp, est utilis pour la mthode \c main(). Dans cette
- fonction, on cre une instance de QApplication, \c app. QApplication se charge de
- des ressources communes l'ensemble de l'application, tel que les polices de
- caractres et le curseur par dfaut, ainsi que de l'excution de la boucle d'vnements.
+ Un fichier séparé, \c main.cpp, est utilisé pour la méthode \c main(). Dans cette
+ fonction, on crée une instance de QApplication, \c app. QApplication se charge de
+ des ressources communes à l'ensemble de l'application, tel que les polices de
+ caractères et le curseur par défaut, ainsi que de l'exécution de la boucle d'évènements.
De ce fait, il y a toujours un objet QApplication dans toute application graphique en Qt.
\snippet tutorials/addressbook/part1/main.cpp main function
On construit un nouveau widget \c AddressBook sur la pile et on invoque
- sa mthode \l{QWidget::show()}{show()} pour l'afficher.
- Cependant, le widget ne sera pas visible tant que la boucle d'vnements
- n'aura pas t lance. On dmarre la boucle d'vnements en appelant la
- mthode \l{QApplication::}{exec()} de l'application; le rsultat renvoy
- par cette mthode est lui mme utilis comme valeur de retour pour la mthode
+ sa méthode \l{QWidget::show()}{show()} pour l'afficher.
+ Cependant, le widget ne sera pas visible tant que la boucle d'évènements
+ n'aura pas été lancée. On démarre la boucle d'évènements en appelant la
+ méthode \l{QApplication::}{exec()} de l'application; le résultat renvoyé
+ par cette méthode est lui même utilisé comme valeur de retour pour la méthode
\c main().
- On comprend maintenant pourquoi \c AddressBook a t cr sur la pile: la fin
+ On comprend maintenant pourquoi \c AddressBook a été créé sur la pile: à la fin
du programme, l'objet sort du scope de la fonction \c main() et tous ses widgets enfants
- sont supprims, assurant ainsi qu'il n'y aura pas de fuites de mmoire.
+ sont supprimés, assurant ainsi qu'il n'y aura pas de fuites de mémoire.
*/
/*!
@@ -258,53 +258,53 @@
\example tutorials/addressbook-fr/part2
\title Carnet d'adresses 2 - Ajouter des adresses
- La prochaine tape pour crer notre carnet d'adresses est d'ajouter un soupon
- d'interactivit.
+ La prochaine étape pour créer notre carnet d'adresses est d'ajouter un soupçon
+ d'interactivité.
\image addressbook-tutorial-part2-add-contact.png
Nous allons fournir un bouton que l'utilisateur peut
- cliquer pour ajouter un nouveau contact. Une structure de donnes est aussi
- ncessaire afin de pouvoir stocker les contacts en mmoire.
+ cliquer pour ajouter un nouveau contact. Une structure de données est aussi
+ nécessaire afin de pouvoir stocker les contacts en mémoire.
- \section1 Dfinition de la classe AddressBook
+ \section1 Définition de la classe AddressBook
Maintenant que nous avons mis en place les labels et les champs de saisie,
- nous ajoutons les boutons pour complter le processus d'ajout d'un contact.
+ nous ajoutons les boutons pour compléter le processus d'ajout d'un contact.
Cela veut dire que notre fichier \c addressbook.h a maintenant trois
objets QPushButton et trois slots publics correspondant.
\snippet tutorials/addressbook/part2/addressbook.h slots
- Un slot est une mthode qui rpond un signal. Nous allons
- voir ce concept en dtail lorsque nous implmenterons la classe \c{AddressBook}.
- Pour une explication dtaille du concept de signal et slot, vous pouvez
- vous rfrer au document \l{Signals and Slots}.
+ Un slot est une méthode qui répond à un signal. Nous allons
+ voir ce concept en détail lorsque nous implémenterons la classe \c{AddressBook}.
+ Pour une explication détaillée du concept de signal et slot, vous pouvez
+ vous référer au document \l{Signals and Slots}.
Les trois objets QPushButton \c addButton, \c submitButton et \c cancelButton
- sont maintenant inclus dans la dclaration des variables prives, avec
- \c nameLine et \c addressText du chapitre prcdent.
+ sont maintenant inclus dans la déclaration des variables privées, avec
+ \c nameLine et \c addressText du chapitre précédent.
\snippet tutorials/addressbook/part2/addressbook.h pushbutton declaration
Nous avons besoin d'un conteneur pour stocker les contacts du carnet
- d'adresses, de faon pouvoir les numrer et les afficher.
- Un objet QMap, \c contacts, est utilis pour a, car il permet de stocker
- des paires cl-valeur: le nom du contact est la \e{cl} et l'adresse du contact
+ d'adresses, de façon à pouvoir les énumérer et les afficher.
+ Un objet QMap, \c contacts, est utilisé pour ça, car il permet de stocker
+ des paires clé-valeur: le nom du contact est la \e{clé} et l'adresse du contact
est la \e{valeur}.
\snippet tutorials/addressbook/part2/addressbook.h remaining private variables
- Nous dclarons aussi deux objects QString privs: \c oldName et \c oldAddress.
- Ces objets sont ncessaires pour conserver le nom et l'adresse du dernier contact
- affich avant que l'utilisateur ne clique sur le bouton "Add". Grce ces variables
+ Nous déclarons aussi deux objects QString privés: \c oldName et \c oldAddress.
+ Ces objets sont nécessaires pour conserver le nom et l'adresse du dernier contact
+ affiché avant que l'utilisateur ne clique sur le bouton "Add". Grâce à ces variables
si l'utilisateur clique sur "Cancel", il est possible de revenir
- l'affichage du dernier contact.
+ à l'affichage du dernier contact.
- \section1 Implmentation de la classe AddressBook
+ \section1 Implémentation de la classe AddressBook
Dans le constructeur de \c AddressBook, \c nameLine et
- \c addressText sont mis en mode lecture seule, de faon autoriser l'affichage
+ \c addressText sont mis en mode lecture seule, de façon à autoriser l'affichage
mais pas la modification du contact courant.
\dots
@@ -317,16 +317,16 @@
\snippet tutorials/addressbook/part2/addressbook.cpp pushbutton declaration
- Le bouton \c addButton est affich en invoquant la mthode \l{QPushButton::show()}
- {show()}, tandis que \c submitButton et \c cancelButton sont cachs en invoquant
- \l{QPushButton::hide()}{hide()}. Ces deux boutons ne seront affichs que lorsque
- l'utilisateur cliquera sur "Add", et ceci est gr par la mthode \c addContact()
- dcrite plus loin.
+ Le bouton \c addButton est affiché en invoquant la méthode \l{QPushButton::show()}
+ {show()}, tandis que \c submitButton et \c cancelButton sont cachés en invoquant
+ \l{QPushButton::hide()}{hide()}. Ces deux boutons ne seront affichés que lorsque
+ l'utilisateur cliquera sur "Add", et ceci est géré par la méthode \c addContact()
+ décrite plus loin.
\snippet tutorials/addressbook/part2/addressbook.cpp connecting signals and slots
Nous connectons le signal \l{QPushButton::clicked()}{clicked()} de chaque bouton
- au slot qui grera l'action.
+ au slot qui gèrera l'action.
L'image ci-dessous illustre ceci:
\image addressbook-tutorial-part2-signals-and-slots.png
@@ -336,77 +336,77 @@
\snippet tutorials/addressbook/part2/addressbook.cpp vertical layout
- La methode \l{QBoxLayout::addStretch()}{addStretch()} est utilise pour
- assurer que les boutons ne sont pas rpartis uniformment, mais regroups
- dans la partie supperieure du widget. La figure ci-dessous montre la diffrence
- si \l{QBoxLayout::addStretch()}{addStretch()} est utilis ou pas.
+ La methode \l{QBoxLayout::addStretch()}{addStretch()} est utilisée pour
+ assurer que les boutons ne sont pas répartis uniformément, mais regroupés
+ dans la partie supperieure du widget. La figure ci-dessous montre la différence
+ si \l{QBoxLayout::addStretch()}{addStretch()} est utilisé ou pas.
\image addressbook-tutorial-part2-stretch-effects.png
- Ensuite nous ajoutons \c buttonLayout1 \c mainLayout, en utilisant
+ Ensuite nous ajoutons \c buttonLayout1 à \c mainLayout, en utilisant
\l{QGridLayout::addLayout()}{addLayout()}. Ceci nous permet d'imbriquer les
mises en page puisque \c buttonLayout1 est maintenant un enfant de \c mainLayout.
\snippet tutorials/addressbook/part2/addressbook.cpp grid layout
- Les coordonnes du layout global ressemblent maintenant a:
+ Les coordonnées du layout global ressemblent maintenant à ça:
\image addressbook-tutorial-part2-labeled-layout.png
- Dans la mthode \c addContact(), nous stockons les dtails du dernier
- contact affich dans \c oldName et \c oldAddress. Ensuite, nous
- vidons ces champs de saisie et nous dsactivons le mode
- lecture seule. Le focus est plac sur \c nameLine et on affiche
+ Dans la méthode \c addContact(), nous stockons les détails du dernier
+ contact affiché dans \c oldName et \c oldAddress. Ensuite, nous
+ vidons ces champs de saisie et nous désactivons le mode
+ lecture seule. Le focus est placé sur \c nameLine et on affiche
\c submitButton et \c cancelButton.
\snippet tutorials/addressbook/part2/addressbook.cpp addContact
- La mthode \c submitContact() peut tre divise en trois parties:
+ La méthode \c submitContact() peut être divisée en trois parties:
\list 1
- \o Nous extrayons les dtails du contact depuis \c nameLine et \c addressText
+ \o Nous extrayons les détails du contact depuis \c nameLine et \c addressText
et les stockons dans des objets QString. Nous les validons pour s'assurer
- que l'utilisateur n'a pas cliqu sur "Add" avec des champs de saisie
- vides; sinon un message est affich avec QMessageBox pour rappeller
- l'utilisateur que les deux champs doivent tre complts.
+ que l'utilisateur n'a pas cliqué sur "Add" avec des champs de saisie
+ vides; sinon un message est affiché avec QMessageBox pour rappeller à
+ l'utilisateur que les deux champs doivent être complétés.
\snippet tutorials/addressbook/part2/addressbook.cpp submitContact part1
- \o Ensuite, nous vrifions si le contact existe dj. Si aucun contacts
- existant n'entre en conflit avec le nouveau, nous l'ajoutons
+ \o Ensuite, nous vérifions si le contact existe déjà. Si aucun contacts
+ existant n'entre en conflit avec le nouveau, nous l'ajoutons à
\c contacts et nous affichons un QMessageBox pour informer l'utilisateur
- que le contact a t ajout.
+ que le contact a été ajouté.
\snippet tutorials/addressbook/part2/addressbook.cpp submitContact part2
- Si le contact existe dj, nous affichons un QMessageBox pour informer
- l'utilisateur du problme.
- Notre objet \c contacts est bas sur des paires cl-valeur forms par
- le nom et l'adresse, nous voulons nous assurer que la \e cl est unique.
+ Si le contact existe déjà, nous affichons un QMessageBox pour informer
+ l'utilisateur du problème.
+ Notre objet \c contacts est basé sur des paires clé-valeur formés par
+ le nom et l'adresse, nous voulons nous assurer que la \e clé est unique.
- \o Une fois que les deux vrifications prcdentes ont t traites,
- nous restaurons les boutons leur tat normal l'aide du code
+ \o Une fois que les deux vérifications précédentes ont été traitées,
+ nous restaurons les boutons à leur état normal à l'aide du code
suivant:
\snippet tutorials/addressbook/part2/addressbook.cpp submitContact part3
\endlist
- La capture d'cran ci-dessous montre l'affichage fournit par un objet
- QMessageBox, utilis ici pour afficher un message d'information
- l'utilisateur:
+ La capture d'écran ci-dessous montre l'affichage fournit par un objet
+ QMessageBox, utilisé ici pour afficher un message d'information
+ à l'utilisateur:
\image addressbook-tutorial-part2-add-successful.png
- La mthode \c cancel() restaure les dtails du dernier contact, active
+ La méthode \c cancel() restaure les détails du dernier contact, active
\c addButton, et cache \c submitButton et \c cancelButton.
\snippet tutorials/addressbook/part2/addressbook.cpp cancel
- L'ide gnrale pour augmenter la flexibilit lors de l'ajout d'un
- contact est de donner la possiblit de cliquer sur "Add"
- ou "Cancel" n'importe quel moment.
- L'organigramme ci-dessous reprend l'ensemble des interactions dvelopes
+ L'idée générale pour augmenter la flexibilité lors de l'ajout d'un
+ contact est de donner la possiblité de cliquer sur "Add"
+ ou "Cancel" à n'importe quel moment.
+ L'organigramme ci-dessous reprend l'ensemble des interactions dévelopées
jusqu'ici:
\image addressbook-tutorial-part2-add-flowchart.png
@@ -418,118 +418,118 @@
\contentspage {Tutoriel "Carnet d'adresses"}{Sommaire}
\nextpage {tutorials/addressbook-fr/part4}{Chapitre 4}
\example tutorials/addressbook-fr/part3
- \title Carnet d'adresses 3 - Navigation entre les lments
+ \title Carnet d'adresses 3 - Navigation entre les éléments
- L'application "Carnet d'adresses" est maintenant moiti termine. Il
+ L'application "Carnet d'adresses" est maintenant à moitié terminée. Il
nous faut maintenant ajouter quelques fonctions pour naviguer entre
- les contacts. Avant de commencer, il faut se dcider sur le type de structure de
- donnes le plus appropri pour stocker les contacts.
+ les contacts. Avant de commencer, il faut se décider sur le type de structure de
+ données le plus approprié pour stocker les contacts.
- Dans le chapitre 2, nous avons utilis un QMap utilisant des paires cl-valeur,
- avec le nom du contact comme \e cl, et l'adresse du contact comme \e valeur.
+ Dans le chapitre 2, nous avons utilisé un QMap utilisant des paires clé-valeur,
+ avec le nom du contact comme \e clé, et l'adresse du contact comme \e valeur.
Cela fonctionnait bien jusqu'ici, mais pour ajouter la navigation entre les
- entres, quelques amliorations sont ncessaires.
+ entrées, quelques améliorations sont nécessaires.
- Nous amliorerons le QMap en le faisant ressembler une structure de donnes
- similaire une liste lie, o tous les lments sont connects, y compris
- le premier et le dernier lment. La figure ci-dessous illustre cette structure
- de donne.
+ Nous améliorerons le QMap en le faisant ressembler à une structure de données
+ similaire à une liste liée, où tous les éléments sont connectés, y compris
+ le premier et le dernier élément. La figure ci-dessous illustre cette structure
+ de donnée.
\image addressbook-tutorial-part3-linkedlist.png
- \section1 Dfinition de la classe AddressBook
+ \section1 Définition de la classe AddressBook
Pour ajouter les fonctions de navigation au carnet d'adresses, nous avons
- besoin de deux slots supplmentaires dans notre classe \c AddressBook:
- \c next() et \c previous(). Ceux-ci sont ajouts au fichier addressbook.h:
+ besoin de deux slots supplémentaires dans notre classe \c AddressBook:
+ \c next() et \c previous(). Ceux-ci sont ajoutés au fichier addressbook.h:
\snippet tutorials/addressbook/part3/addressbook.h navigation functions
Nous avons aussi besoin de deux nouveaux objets QPushButton, nous ajoutons
- donc les variables prives \c nextButton et \c previousButton.
+ donc les variables privées \c nextButton et \c previousButton.
\snippet tutorials/addressbook/part3/addressbook.h navigation pushbuttons
- \section1 Implmentation de la classe AddressBook
+ \section1 Implémentation de la classe AddressBook
- A l'intrieur du constructeur de \c AddressBook, dans \c addressbook.cpp, nous
- instancions \c nextButton et \c previousButton et nous les dsactivons
- par dfaut. Nous faisons ceci car la navigation ne doit tre active
+ A l'intérieur du constructeur de \c AddressBook, dans \c addressbook.cpp, nous
+ instancions \c nextButton et \c previousButton et nous les désactivons
+ par défaut. Nous faisons ceci car la navigation ne doit être activée
que lorsqu'il y a plus d'un contact dans le carnet d'adresses.
\snippet tutorials/addressbook/part3/addressbook.cpp navigation pushbuttons
- Nous connectons alors ces boutons leur slots respectifs:
+ Nous connectons alors ces boutons à leur slots respectifs:
\snippet tutorials/addressbook/part3/addressbook.cpp connecting navigation signals
- L'image ci-dessous montre l'interface utilisateur que nous allons crer.
- Remarquez que cela ressemble de plus en plus l'interface du programme
+ L'image ci-dessous montre l'interface utilisateur que nous allons créer.
+ Remarquez que cela ressemble de plus en plus à l'interface du programme
complet.
\image addressbook-tutorial-part3-screenshot.png
Nous suivons les conventions pour les fonctions \c next() et \c previous()
- en plaant \c nextButton droite et \c previousButton gauche. Pour
+ en plaçant \c nextButton à droite et \c previousButton à gauche. Pour
faire cette mise en page intuitive, nous utilisons un QHBoxLayout pour
- placer les widgets cte cte:
+ placer les widgets côte à côte:
\snippet tutorials/addressbook/part3/addressbook.cpp navigation layout
- L'objet QHBoxLayout, \c buttonLayout2, est ensuite ajout \c mainLayout.
+ L'objet QHBoxLayout, \c buttonLayout2, est ensuite ajouté à \c mainLayout.
\snippet tutorials/addressbook/part3/addressbook.cpp adding navigation layout
- La figure ci-dessous montre les systmes de coordonnes pour les widgets du
+ La figure ci-dessous montre les systèmes de coordonnées pour les widgets du
\c mainLayout.
\image addressbook-tutorial-part3-labeled-layout.png
- Dans notre mthode \c addContact(), nous avons desactiv ces boutons
- pour tre sr que l'utilisateur n'utilise pas la navigation lors de
+ Dans notre méthode \c addContact(), nous avons desactivé ces boutons
+ pour être sûr que l'utilisateur n'utilise pas la navigation lors de
l'ajout d'un contact.
\snippet tutorials/addressbook/part3/addressbook.cpp disabling navigation
- Dans notre mthode \c submitContact(), nous activons les boutons de
+ Dans notre méthode \c submitContact(), nous activons les boutons de
navigation, \c nextButton et \c previousButton, en fonction de la
- taille de \c contacts. Commen mentionn plus tt, la navigation n'est
- active que si il y a plus d'un contact dans le carnet d'adresses.
+ taille de \c contacts. Commen mentionné plus tôt, la navigation n'est
+ activée que si il y a plus d'un contact dans le carnet d'adresses.
Les lignes suivantes montrent comment faire cela:
\snippet tutorials/addressbook/part3/addressbook.cpp enabling navigation
Nous incluons aussi ces lignes de code dans le bouton \c cancel().
- Souvenez vous que nous voulons muler une liste-lie ciruculaire
- l'aide de l'objet QMap, \c contacts. Pour faire cela, nous obtenons un itrateur
- sur \c contact dans la mthode \c next(), et ensuite:
+ Souvenez vous que nous voulons émuler une liste-liée ciruculaire à
+ l'aide de l'objet QMap, \c contacts. Pour faire cela, nous obtenons un itérateur
+ sur \c contact dans la méthode \c next(), et ensuite:
\list
- \o Si l'itrateur n'est pas la fin de \c contacts, nous l'incrmentons
- \o Si l'itrateur est la fin de \c contacts, nous changeons sa position
- jusqu'au dbut de \c contacts. Cela donne l'illusion que notre QMap
+ \o Si l'itérateur n'est pas à la fin de \c contacts, nous l'incrémentons
+ \o Si l'itérateur est à la fin de \c contacts, nous changeons sa position
+ jusqu'au début de \c contacts. Cela donne l'illusion que notre QMap
fonctionne comme une liste circulaire.
\endlist
\snippet tutorials/addressbook/part3/addressbook.cpp next() function
- Une fois que nous avons itr jusqu' l'objet recherch dans \c contacts,
+ Une fois que nous avons itéré jusqu'à l'objet recherché dans \c contacts,
nous affichons son contenu sur \c nameLine et \c addressText.
- De la mme faon, pour la mthode \c previous(), nous obtenons un
- itrateur sur \c contacts et ensuite:
+ De la même façon, pour la méthode \c previous(), nous obtenons un
+ itérateur sur \c contacts et ensuite:
\list
- \o Si l'itrateur est la fin de \c contacts, on rinitialise
+ \o Si l'itérateur est à la fin de \c contacts, on réinitialise
l'affichage et on retourne.
- \o Si l'itrateur est au dbut de \c contacts, on change sa
- position jusqu' la fin
- \o Ensuite, on dcrmente l'itrateur
+ \o Si l'itérateur est au début de \c contacts, on change sa
+ position jusqu'à la fin
+ \o Ensuite, on décrémente l'itérateur
\endlist
\snippet tutorials/addressbook/part3/addressbook.cpp previous() function
- nouveau, nous affichons le contenu de l'objet courant dans \c contacts.
+ à nouveau, nous affichons le contenu de l'objet courant dans \c contacts.
*/
@@ -540,27 +540,27 @@
\contentspage {Tutoriel "Carnet d'adresses"}{Sommaire}
\nextpage {tutorials/addressbook-fr/part5}{Chapitre 5}
\example tutorials/addressbook-fr/part4
- \title Carnet d'Adresses 4 - diter et supprimer des adresses
+ \title Carnet d'Adresses 4 - éditer et supprimer des adresses
- Dans ce chapitre, nous verrons comment modifier les donnes des contacts
+ Dans ce chapitre, nous verrons comment modifier les données des contacts
contenus dans l'application carnet d'adresses.
\image addressbook-tutorial-screenshot.png
Nous avons maintenant un carnet d'adresses qui ne se contente pas de
- lister des contacts de faon ordonne, mais permet galement la
- navigation. Il serait pratique d'inclure des fonctions telles qu'diter et
- supprimer, afin que les dtails associs un contact puissent tre
- modifis lorsque c'est ncessaire. Cependant, cela requiert une lgre
- modification, sous la forme d'numrations. Au chapitre prcdent, nous avions deux
- modes: \c {AddingMode} et \c {NavigationMode}, mais ils n'taient pas
- dfinis en tant qu'numrations. Au lieu de a, on activait et dsactivait les
+ lister des contacts de façon ordonnée, mais permet également la
+ navigation. Il serait pratique d'inclure des fonctions telles qu'éditer et
+ supprimer, afin que les détails associés à un contact puissent être
+ modifiés lorsque c'est nécessaire. Cependant, cela requiert une légère
+ modification, sous la forme d'énumérations. Au chapitre précédent, nous avions deux
+ modes: \c {AddingMode} et \c {NavigationMode}, mais ils n'étaient pas
+ définis en tant qu'énumérations. Au lieu de ça, on activait et désactivait les
boutons correspondants manuellement, au prix de multiples redondances dans
le code.
- Dans ce chapitre, on dfinit l'numration \c Mode avec trois valeurs possibles.
+ Dans ce chapitre, on définit l'énumération \c Mode avec trois valeurs possibles.
\list
\o \c{NavigationMode},
@@ -568,22 +568,22 @@
\o \c{EditingMode}.
\endlist
- \section1 Dfinition de la classe AddressBook
+ \section1 Définition de la classe AddressBook
- Le fichier \c addressbook.h est mis a jour pour contenir l'numration \c Mode :
+ Le fichier \c addressbook.h est mis a jour pour contenir l'énumération \c Mode :
\snippet tutorials/addressbook/part4/addressbook.h Mode enum
- On ajoute galement deux nouveaux slots, \c editContact() et
- \c removeContact(), notre liste de slots publics.
+ On ajoute également deux nouveaux slots, \c editContact() et
+ \c removeContact(), à notre liste de slots publics.
\snippet tutorials/addressbook/part4/addressbook.h edit and remove slots
- Afin de basculer d'un mode l'autre, on introduit la mthode
- \c updateInterface() pour contrller l'activation et la dsactivation de
- tous les objets QPushButton. On ajoute galement deux nouveaux boutons,
- \c editButton et \c removeButton, pour les fonctions d'dition
- et de suppression mentionnes plus haut.
+ Afin de basculer d'un mode à l'autre, on introduit la méthode
+ \c updateInterface() pour contrôller l'activation et la désactivation de
+ tous les objets QPushButton. On ajoute également deux nouveaux boutons,
+ \c editButton et \c removeButton, pour les fonctions d'édition
+ et de suppression mentionnées plus haut.
\snippet tutorials/addressbook/part4/addressbook.h updateInterface() declaration
\dots
@@ -591,97 +591,97 @@
\dots
\snippet tutorials/addressbook/part4/addressbook.h mode declaration
- Enfin, on dclare \c currentMode pour garder une trace du mode
- actuellement utilis.
+ Enfin, on déclare \c currentMode pour garder une trace du mode
+ actuellement utilisé.
- \section1 Implmentation de la classe AddressBook
+ \section1 Implémentation de la classe AddressBook
- Il nous faut maintenant implmenter les fonctionnalits de changement de
+ Il nous faut maintenant implémenter les fonctionnalités de changement de
mode de l'application carnet d'adresses. Les boutons \c editButton et
- \c removeButton sont instancis et dsactivs par dfaut, puisque le
- carnet d'adresses dmarre sans aucun contact en mmoire.
+ \c removeButton sont instanciés et désactivés par défaut, puisque le
+ carnet d'adresses démarre sans aucun contact en mémoire.
\snippet tutorials/addressbook/part4/addressbook.cpp edit and remove buttons
- Ces boutons sont ensuite connects leurs slots respectifs,
- \c editContact() et \c removeContact(), avant d'tre ajouts
+ Ces boutons sont ensuite connectés à leurs slots respectifs,
+ \c editContact() et \c removeContact(), avant d'être ajoutés à
\c buttonLayout1.
\snippet tutorials/addressbook/part4/addressbook.cpp connecting edit and remove
\dots
\snippet tutorials/addressbook/part4/addressbook.cpp adding edit and remove to the layout
- La methode \c editContact() place les anciens dtails du contact dans
+ La methode \c editContact() place les anciens détails du contact dans
\c oldName et \c oldAddress, avant de basculer vers le mode
\c EditingMode. Dans ce mode, les boutons \c submitButton et
- \c cancelButton sont tous deux activs, l'utilisateur peut par consquent
- modifier les dtails du contact et cliquer sur l'un de ces deux boutons
+ \c cancelButton sont tous deux activés, l'utilisateur peut par conséquent
+ modifier les détails du contact et cliquer sur l'un de ces deux boutons
par la suite.
\snippet tutorials/addressbook/part4/addressbook.cpp editContact() function
- La mthode \c submitContact() a t divise en deux avec un bloc
+ La méthode \c submitContact() a été divisée en deux avec un bloc
\c{if-else}. On teste \c currentMode pour voir si le mode courant est
- \c AddingMode. Si c'est le cas, on procde l'ajout.
+ \c AddingMode. Si c'est le cas, on procède à l'ajout.
\snippet tutorials/addressbook/part4/addressbook.cpp submitContact() function beginning
\dots
\snippet tutorials/addressbook/part4/addressbook.cpp submitContact() function part1
Sinon, on s'assure que \c currentMode est en \c EditingMode. Si c'est le
- cas, on compare \c oldName et \c name. Si le nom a chang, on supprime
- l'ancien contact de \c contacts et on insre le contact mis a jour.
+ cas, on compare \c oldName et \c name. Si le nom a changé, on supprime
+ l'ancien contact de \c contacts et on insère le contact mis a jour.
\snippet tutorials/addressbook/part4/addressbook.cpp submitContact() function part2
- Si seule l'adresse a chang (i.e. \c oldAddress n'est pas identique
- \c address), on met jour l'adresse du contact. Enfin on rgle
- \c currentMode \c NavigationMode. C'est une tape importante puisque
- c'est cela qui ractive tous les boutons dsactivs.
+ Si seule l'adresse a changé (i.e. \c oldAddress n'est pas identique à
+ \c address), on met à jour l'adresse du contact. Enfin on règle
+ \c currentMode à \c NavigationMode. C'est une étape importante puisque
+ c'est cela qui réactive tous les boutons désactivés.
- Afin de retirer un contact du carnet d'adresses, on implmente la mthode
- \c removeContact(). Cette mthode vrifie que le contact est prsent dans
+ Afin de retirer un contact du carnet d'adresses, on implémente la méthode
+ \c removeContact(). Cette méthode vérifie que le contact est présent dans
\c contacts.
\snippet tutorials/addressbook/part4/addressbook.cpp removeContact() function
- Si c'est le cas, on affiche une bote de dialogue QMessageBox, demandant
- confirmation de la suppression l'utilisateur. Une fois la confirmation
- effectue, on appelle \c previous(), afin de s'assurer que l'interface
- utilisateur affiche une autre entre, et on supprime le contact en
- utilisant le mthode \l{QMap::remove()}{remove()} de \l{QMap}. Dans un
+ Si c'est le cas, on affiche une boîte de dialogue QMessageBox, demandant
+ confirmation de la suppression à l'utilisateur. Une fois la confirmation
+ effectuée, on appelle \c previous(), afin de s'assurer que l'interface
+ utilisateur affiche une autre entrée, et on supprime le contact en
+ utilisant le méthode \l{QMap::remove()}{remove()} de \l{QMap}. Dans un
souci pratique, on informe l'utilisateur de la suppression par le biais
- d'une autre QMessageBox. Les deux botes de dialogue utilises dans cette
- mthode sont reprsentes ci-dessous.
+ d'une autre QMessageBox. Les deux boîtes de dialogue utilisées dans cette
+ méthode sont représentées ci-dessous.
\image addressbook-tutorial-part4-remove.png
- \section2 Mise jour de l'Interface utilisateur
+ \section2 Mise à jour de l'Interface utilisateur
- On a voqu plus haut la mthode \c updateInterface() comme moyen
- d'activer et de dsactiver les diffrents boutons de l'interface en
- fonction du mode. Cette mthode met jour le mode courant selon
- l'argument \c mode qui lui est pass, en l'assignant \c currentMode,
+ On a évoqué plus haut la méthode \c updateInterface() comme moyen
+ d'activer et de désactiver les différents boutons de l'interface en
+ fonction du mode. Cette méthode met à jour le mode courant selon
+ l'argument \c mode qui lui est passé, en l'assignant à \c currentMode,
avant de tester sa valeur.
- Chacun des boutons est ensuite activ ou dsactiv, en fonction du mode.
+ Chacun des boutons est ensuite activé ou désactivé, en fonction du mode.
Le code source pour les cas \c AddingMode et \c EditingMode est visible
ci-dessous:
\snippet tutorials/addressbook/part4/addressbook.cpp update interface() part 1
Dans le cas de \c NavigationMode, en revanche, des tests conditionnels
- sont passs en paramtre de QPushButton::setEnabled(). Ceci permet de
- s'assurer que les boutons \c editButton et \c removeButton ne sont activs
+ sont passés en paramètre de QPushButton::setEnabled(). Ceci permet de
+ s'assurer que les boutons \c editButton et \c removeButton ne sont activés
que s'il existe au moins un contact dans le carnet d'adresses;
- \c nextButton et \c previousButton ne sont activs que lorsqu'il existe
+ \c nextButton et \c previousButton ne sont activés que lorsqu'il existe
plus d'un contact dans le carnet d'adresses.
\snippet tutorials/addressbook/part4/addressbook.cpp update interface() part 2
- En effectuant les oprations de rglage du mode et de mise jour de
- l'interface utilisateur au sein de la mme mthode, on est l'abri de
- l'ventualit o l'interface utilisateur se "dsynchronise" de l'tat
+ En effectuant les opérations de réglage du mode et de mise à jour de
+ l'interface utilisateur au sein de la même méthode, on est à l'abri de
+ l'éventualité où l'interface utilisateur se "désynchronise" de l'état
interne de l'application.
*/
@@ -694,7 +694,7 @@
\example tutorials/addressbook-fr/part5
\title Carnet d'adresse 5 - Ajout d'une fonction de recherche
- Dans ce chapitre, nous allons voir les possibilits pour rechercher
+ Dans ce chapitre, nous allons voir les possibilités pour rechercher
des contacts dans le carnet d'adresse.
\image addressbook-tutorial-part5-screenshot.png
@@ -703,110 +703,110 @@
il devient difficile de naviguer avec les boutons \e Next et \e Previous.
Dans ce cas, une fonction de recherche serait plus efficace pour rechercher
les contacts.
- La capture d'cran ci-dessus montre le bouton de recherche \e Find et sa position
+ La capture d'écran ci-dessus montre le bouton de recherche \e Find et sa position
dans le paneau de bouton.
Lorsque l'utilisateur clique sur le bouton \e Find, il est courant d'afficher
- une bote de dialogue qui demande l'utilisateur d'entrer un nom de contact.
+ une boîte de dialogue qui demande à l'utilisateur d'entrer un nom de contact.
Qt fournit la classe QDialog, que nous sous-classons dans ce chapitre pour
- implmenter la class \c FindDialog.
+ implémenter la class \c FindDialog.
- \section1 Dfinition de la classe FindDialog
+ \section1 Définition de la classe FindDialog
\image addressbook-tutorial-part5-finddialog.png
- Pour sous-classer QDialog, nous commenons par inclure le header de
- QDialog dans le fichier \c finddialog.h. De plus, nous dclarons les
+ Pour sous-classer QDialog, nous commençons par inclure le header de
+ QDialog dans le fichier \c finddialog.h. De plus, nous déclarons les
classes QLineEdit et QPushButton car nous utilisons ces widgets dans
notre classe dialogue.
Tout comme dans la classe \c AddressBook, la classe \c FindDialog utilise
- la macro Q_OBJECT et son constructeur est dfini de faon accepter
- un QWidget parent, mme si cette bote de dialogue sera affiche dans une
- fentre spare.
+ la macro Q_OBJECT et son constructeur est défini de façon à accepter
+ un QWidget parent, même si cette boîte de dialogue sera affichée dans une
+ fenêtre séparée.
\snippet tutorials/addressbook/part5/finddialog.h FindDialog header
- Nous dfinissons la mthode publique \c getFindText() pour tre utilise
+ Nous définissons la méthode publique \c getFindText() pour être utilisée
par les classes qui instancient \c FindDialog, ce qui leur permet d'obtenir
- le texte entr par l'utilisateur. Un slot public, \c findClicked(), est
- dfini pour prendre en charge le texte lorsque l'utilisateur clique sur
+ le texte entré par l'utilisateur. Un slot public, \c findClicked(), est
+ défini pour prendre en charge le texte lorsque l'utilisateur clique sur
le bouton \gui Find.
- Finalement, nous dfinissons les variables prives \c findButton,
+ Finalement, nous définissons les variables privées \c findButton,
\c lineEdit et \c findText, qui correspondent respectivement au bouton
\gui Find, au champ de texte dans lequel l'utilisateur tape le texte
- rechercher, et une variable interne stockant le texte pour une
- utilisation ultrieure.
+ à rechercher, et à une variable interne stockant le texte pour une
+ utilisation ultérieure.
- \section1 Implmentation de la classe FindDialog
+ \section1 Implémentation de la classe FindDialog
Dans le constructeur de \c FindDialog, nous instancions les objets des
- variables prives \c lineEdit, \c findButton et \c findText. Nous utilisons ensuite
+ variables privées \c lineEdit, \c findButton et \c findText. Nous utilisons ensuite
un QHBoxLayout pour positionner les widgets.
\snippet tutorials/addressbook/part5/finddialog.cpp constructor
- Nous mettons en place la mise en page et le titre de la fentre, et
+ Nous mettons en place la mise en page et le titre de la fenêtre, et
nous connectons les signaux aux slots. Remarquez que le signal
- \l{QPushButton::clicked()}{clicked()} de \c{findButton} est connect
- \c findClicked() et \l{QDialog::accept()}{accept()}. Le slot
+ \l{QPushButton::clicked()}{clicked()} de \c{findButton} est connecté
+ à \c findClicked() et \l{QDialog::accept()}{accept()}. Le slot
\l{QDialog::accept()}{accept()} fourni par le QDialog ferme
- la bote de dialogue et lui donne le code de retour \l{QDialog::}{Accepted}.
- Nous utilisons cette fonction pour aider la mthode \c findContact() de la classe
- \c{AddressBook} savoir si l'objet \c FindDialog a t ferm. Ceci sera
- expliqu plus loin lorsque nous verrons la mthode \c findContact().
+ la boîte de dialogue et lui donne le code de retour \l{QDialog::}{Accepted}.
+ Nous utilisons cette fonction pour aider la méthode \c findContact() de la classe
+ \c{AddressBook} à savoir si l'objet \c FindDialog a été fermé. Ceci sera
+ expliqué plus loin lorsque nous verrons la méthode \c findContact().
\image addressbook-tutorial-part5-signals-and-slots.png
Dans \c findClicked(), nous validons le champ de texte pour nous
- assurer que l'utilisateur n'a pas cliqu sur le bouton \gui Find sans
- avoir entr un nom de contact. Ensuite, nous stockons le texte du champ
- d'entre \c lineEdit dans \c findText. Et finalement nous vidons le
- contenu de \c lineEdit et cachons la bote de dialogue.
+ assurer que l'utilisateur n'a pas cliqué sur le bouton \gui Find sans
+ avoir entré un nom de contact. Ensuite, nous stockons le texte du champ
+ d'entrée \c lineEdit dans \c findText. Et finalement nous vidons le
+ contenu de \c lineEdit et cachons la boîte de dialogue.
\snippet tutorials/addressbook/part5/finddialog.cpp findClicked() function
- La variable \c findText a un accesseur publique associ: \c getFindText().
- tant donn que nous ne modifions \c findText directement que dans le
- constructeur et la mthode \c findClicked(), nous ne crons pas
- de manipulateurs associ \c getFindText().
+ La variable \c findText a un accesseur publique associé: \c getFindText().
+ Étant donné que nous ne modifions \c findText directement que dans le
+ constructeur et la méthode \c findClicked(), nous ne créons pas
+ de manipulateurs associé à \c getFindText().
Puisque \c getFindText() est publique, les classes instanciant et
- utilisant \c FindDialog peuvent toujours accder la chane de
- caractres que l'utilisateur a entr et accept.
+ utilisant \c FindDialog peuvent toujours accéder à la chaîne de
+ caractères que l'utilisateur a entré et accepté.
\snippet tutorials/addressbook/part5/finddialog.cpp getFindText() function
- \section1 Dfinition de la classe AddressBook
+ \section1 Définition de la classe AddressBook
Pour utiliser \c FindDialog depuis la classe \c AddressBook, nous
incluons \c finddialog.h dans le fichier \c addressbook.h.
\snippet tutorials/addressbook/part5/addressbook.h include finddialog's header
- Jusqu'ici, toutes les fonctionnalits du carnet d'adresses ont un
- QPushButton et un slot correspondant. De la mme faon, pour la
- fonctionnalit \gui Find, nous avons \c findButton et \c findContact().
+ Jusqu'ici, toutes les fonctionnalités du carnet d'adresses ont un
+ QPushButton et un slot correspondant. De la même façon, pour la
+ fonctionnalité \gui Find, nous avons \c findButton et \c findContact().
- Le \c findButton est dclar comme une variable prive et la
- mthode \c findContact() est dclare comme un slot public.
+ Le \c findButton est déclaré comme une variable privée et la
+ méthode \c findContact() est déclarée comme un slot public.
\snippet tutorials/addressbook/part5/addressbook.h findContact() declaration
\dots
\snippet tutorials/addressbook/part5/addressbook.h findButton declaration
- Finalement, nous dclarons la variable prive \c dialog que nous allons
- utiliser pour accder une instance de \c FindDialog.
+ Finalement, nous déclarons la variable privée \c dialog que nous allons
+ utiliser pour accéder à une instance de \c FindDialog.
\snippet tutorials/addressbook/part5/addressbook.h FindDialog declaration
- Une fois que nous avons instanci la bote de dialogue, nous voulons l'utiliser
- plus qu'une fois. Utiliser une variable prive nous permet d'y rfrer
- plus d'un endroit dans la classe.
+ Une fois que nous avons instancié la boîte de dialogue, nous voulons l'utiliser
+ plus qu'une fois. Utiliser une variable privée nous permet d'y référer
+ à plus d'un endroit dans la classe.
- \section1 Implmentation de la classe AddressBook
+ \section1 Implémentation de la classe AddressBook
- Dans le constructeur de \c AddressBook, nous instancions nos objets privs,
+ Dans le constructeur de \c AddressBook, nous instancions nos objets privés,
\c findbutton et \c findDialog:
\snippet tutorials/addressbook/part5/addressbook.cpp instantiating findButton
@@ -814,25 +814,25 @@
\snippet tutorials/addressbook/part5/addressbook.cpp instantiating FindDialog
Ensuite, nous connectons le signal \l{QPushButton::clicked()}{clicked()} de
- \c{findButton} \c findContact().
+ \c{findButton} à \c findContact().
\snippet tutorials/addressbook/part5/addressbook.cpp signals and slots for find
- Maintenant, tout ce qui manque est le code de notre mthode \c findContact():
+ Maintenant, tout ce qui manque est le code de notre méthode \c findContact():
\snippet tutorials/addressbook/part5/addressbook.cpp findContact() function
- Nous commenons par afficher l'instance de \c FindDialog, \c dialog.
- L'utilisateur peut alors entrer le nom du contact rechercher. Lorsque
- l'utilisateur clique sur le bouton \c findButton, la bote de dialogue est
- masque et le code de retour devient QDialog::Accepted. Ce code de retour
+ Nous commençons par afficher l'instance de \c FindDialog, \c dialog.
+ L'utilisateur peut alors entrer le nom du contact à rechercher. Lorsque
+ l'utilisateur clique sur le bouton \c findButton, la boîte de dialogue est
+ masquée et le code de retour devient QDialog::Accepted. Ce code de retour
vient remplir la condition du premier if.
Ensuite, nous extrayons le texte que nous utiliserons pour la recherche,
- il s'agit ici de \c contactName obtenu l'aide de la mthode \c getFindText()
+ il s'agit ici de \c contactName obtenu à l'aide de la méthode \c getFindText()
de \c FindDialog. Si le contact existe dans le carnet d'adresse, nous
l'affichons directement. Sinon, nous affichons le QMessageBox suivant pour
- indiquer que la recherche choue.
+ indiquer que la recherche à échouée.
\image addressbook-tutorial-part5-notfound.png
*/
@@ -845,49 +845,49 @@
\example tutorials/addressbook-fr/part6
\title Carnet d'Adresses 6 - Sauvegarde et chargement
- Ce chapitre couvre les fonctionnalits de gestion des fichiers de Qt que
- l'on utilise pour crire les procdures de sauvegarde et chargement pour
+ Ce chapitre couvre les fonctionnalités de gestion des fichiers de Qt que
+ l'on utilise pour écrire les procédures de sauvegarde et chargement pour
l'application carnet d'adresses.
\image addressbook-tutorial-part6-screenshot.png
Bien que la navigation et la recherche de contacts soient des
- fonctionnalits importantes, notre carnet d'adresses ne sera pleinement
+ fonctionnalités importantes, notre carnet d'adresses ne sera pleinement
utilisable qu'une fois que l'on pourra sauvegarder les contacts existants
- et les charger nouveau par la suite.
- Qt fournit de nombreuses classes pour grer les \l{Input/Output and
- Networking}{entres et sorties}, mais nous avons choisi de nous contenter d'une
- combinaison de deux classes simples utiliser ensemble: QFile et QDataStream.
+ et les charger à nouveau par la suite.
+ Qt fournit de nombreuses classes pour gérer les \l{Input/Output and
+ Networking}{entrées et sorties}, mais nous avons choisi de nous contenter d'une
+ combinaison de deux classes simples à utiliser ensemble: QFile et QDataStream.
- Un objet QFile reprsente un fichier sur le disque qui peut tre lu, et
- dans lequel on peut crire. QFile est une classe fille de la classe plus
- gnrique QIODevice, qui peut reprsenter diffrents types de
- priphriques.
+ Un objet QFile représente un fichier sur le disque qui peut être lu, et
+ dans lequel on peut écrire. QFile est une classe fille de la classe plus
+ générique QIODevice, qui peut représenter différents types de
+ périphériques.
- Un objet QDataStream est utilis pour srialiser des donnes binaires
- dans le but de les passer un QIODevice pour les rcuprer dans le
- futur. Pour lire ou crire dans un QIODevice, il suffit d'ouvrir le
- flux, avec le priphrique appropri en paramtre, et d'y lire ou
- crire.
+ Un objet QDataStream est utilisé pour sérialiser des données binaires
+ dans le but de les passer à un QIODevice pour les récupérer dans le
+ futur. Pour lire ou écrire dans un QIODevice, il suffit d'ouvrir le
+ flux, avec le périphérique approprié en paramètre, et d'y lire ou
+ écrire.
- \section1 Dfinition de la classe AddressBook
+ \section1 Définition de la classe AddressBook
- On dclare deux slots publics, \c saveToFile() et \c loadFromFile(),
+ On déclare deux slots publics, \c saveToFile() et \c loadFromFile(),
ainsi que deux objets QPushButton, \c loadButton et \c saveButton.
\snippet tutorials/addressbook/part6/addressbook.h save and load functions declaration
\dots
\snippet tutorials/addressbook/part6/addressbook.h save and load buttons declaration
- \section1 Implmentation de la classe AddressBook
+ \section1 Implémentation de la classe AddressBook
Dans notre constructeur, on instancie \c loadButton et \c saveButton.
- Idalement, l'interface serait plus conviviale avec des boutons
+ Idéalement, l'interface serait plus conviviale avec des boutons
affichant "Load contacts from a file" et "Save contacts to a file". Mais
compte tenu de la dimension des autres boutons, on initialise les labels
- des boutons \gui{Load...} et \gui{Save...}. Heureusement, Qt offre une
- faon simple d'ajouter des info-bulles avec
- \l{QWidget::setToolTip()}{setToolTip()}, et nous l'exploitons de la faon
+ des boutons à \gui{Load...} et \gui{Save...}. Heureusement, Qt offre une
+ façon simple d'ajouter des info-bulles avec
+ \l{QWidget::setToolTip()}{setToolTip()}, et nous l'exploitons de la façon
suivante pour nos boutons:
\snippet tutorials/addressbook/part6/addressbook.cpp tooltip 1
@@ -895,85 +895,85 @@
\snippet tutorials/addressbook/part6/addressbook.cpp tooltip 2
Bien qu'on ne cite pas le code correspondant ici, nous ajoutons ces deux boutons au
- layout de droite, \c button1Layout, comme pour les fonctionnalits prcdentes, et
+ layout de droite, \c button1Layout, comme pour les fonctionnalités précédentes, et
nous connectons leurs signaux
- \l{QPushButton::clicked()}{clicked()} leurs slots respectifs.
+ \l{QPushButton::clicked()}{clicked()} à leurs slots respectifs.
- Pour la sauvegarde, on commence par rcuprer le nom de fichier
+ Pour la sauvegarde, on commence par récupérer le nom de fichier
\c fileName, en utilisant QFileDialog::getSaveFileName(). C'est une
- mthode pratique fournie par QFileDialog, qui ouvre une bote de
- dialogue modale et permet l'utilisateur d'entrer un nom de fichier ou
+ méthode pratique fournie par QFileDialog, qui ouvre une boîte de
+ dialogue modale et permet à l'utilisateur d'entrer un nom de fichier ou
de choisir un fichier \c{.abk} existant. Les fichiers \c{.abk}
- correspondent l'extension choisie pour la sauvegarde des contacts de
+ correspondent à l'extension choisie pour la sauvegarde des contacts de
notre carnet d'adresses.
\snippet tutorials/addressbook/part6/addressbook.cpp saveToFile() function part1
- La bote de dialogue affiche est visible sur la capture d'cran ci-
+ La boîte de dialogue affichée est visible sur la capture d'écran ci-
dessous.
\image addressbook-tutorial-part6-save.png
- Si \c fileName n'est pas vide, on cre un objet QFile, \c file, partir
- de \c fileName. QFile fonctionne avec QDataStream puisqu'il drive de
+ Si \c fileName n'est pas vide, on crée un objet QFile, \c file, à partir
+ de \c fileName. QFile fonctionne avec QDataStream puisqu'il dérive de
QIODevice.
- Ensuite, on essaie d'ouvrir le fichier en criture, ce qui correspond au
- mode \l{QIODevice::}{WriteOnly}. Si cela choue, on en informe
+ Ensuite, on essaie d'ouvrir le fichier en écriture, ce qui correspond au
+ mode \l{QIODevice::}{WriteOnly}. Si cela échoue, on en informe
l'utilisateur avec une QMessageBox.
\snippet tutorials/addressbook/part6/addressbook.cpp saveToFile() function part2
Dans le cas contraire, on instancie un objet QDataStream, \c out, afin
- d'crire dans le fichier ouvert. QDataStream ncessite que la mme
- version de flux soit utilise pour la lecture et l'criture. On s'assure
- que c'est le cas en spcifiant explicitement d'utiliser la
+ d'écrire dans le fichier ouvert. QDataStream nécessite que la même
+ version de flux soit utilisée pour la lecture et l'écriture. On s'assure
+ que c'est le cas en spécifiant explicitement d'utiliser la
\l{QDataStream::Qt_4_5}{version introduite avec Qt 4.5} avant de
- srialiser les donnes vers le fichier \c file.
+ sérialiser les données vers le fichier \c file.
\snippet tutorials/addressbook/part6/addressbook.cpp saveToFile() function part3
- Pour le chargement, on rcupre galement \c fileName en utilisant
- QFileDialog::getOpenFileName(). Cette mthode est l'homologue de
- QFileDialog::getSaveFileName() et affiche galement une bote de
- dialogue modale permettant l'utilisateur d'entrer un nom de fichier ou
+ Pour le chargement, on récupère également \c fileName en utilisant
+ QFileDialog::getOpenFileName(). Cette méthode est l'homologue de
+ QFileDialog::getSaveFileName() et affiche également une boîte de
+ dialogue modale permettant à l'utilisateur d'entrer un nom de fichier ou
de selectionner un fichier \c{.abk} existant, afin de le charger dans le
carnet d'adresses.
\snippet tutorials/addressbook/part6/addressbook.cpp loadFromFile() function part1
- Sous Windows, par exemple, cette mthode affiche une bote de dialogue
- native pour la slection de fichier, comme illustr sur la capture
- d'cran suivante:
+ Sous Windows, par exemple, cette méthode affiche une boîte de dialogue
+ native pour la sélection de fichier, comme illustré sur la capture
+ d'écran suivante:
\image addressbook-tutorial-part6-load.png
Si \c fileName n'est pas vide, on utilise une fois de plus un objet
QFile, \c file, et on tente de l'ouvrir en lecture, avec le mode
- \l{QIODevice::}{ReadOnly}. De mme que prcdemment dans notre
- implmentation de \c saveToFile(), si cette tentative s'avre
+ \l{QIODevice::}{ReadOnly}. De même que précédemment dans notre
+ implémentation de \c saveToFile(), si cette tentative s'avère
infructueuse, on en informe l'utilisateur par le biais d'une
QMessageBox.
\snippet tutorials/addressbook/part6/addressbook.cpp loadFromFile() function part2
Dans le cas contraire, on instancie un objet QDataStream, \c in, en
- spcifiant la version utiliser comme prcdemment, et on lit les
- informations srialises vers la structure de donnes \c contacts. Notez
+ spécifiant la version à utiliser comme précédemment, et on lit les
+ informations sérialisées vers la structure de données \c contacts. Notez
qu'on purge \c contacts avant d'y mettre les informations lues afin de
- simplifier le processus de lecture de fichier. Une faon plus avance de
- procder serait de lire les contacts dans un objet QMap temporaire, et
+ simplifier le processus de lecture de fichier. Une façon plus avancée de
+ procéder serait de lire les contacts dans un objet QMap temporaire, et
de copier uniquement les contacts n'existant pas encore dans
\c contacts.
\snippet tutorials/addressbook/part6/addressbook.cpp loadFromFile() function part3
Pour afficher les contacts lus depuis le fichier, on doit d'abord
- valider les donnes obtenues afin de s'assurer que le fichier lu
- contient effectivement des entres de carnet d'adresses. Si c'est le
+ valider les données obtenues afin de s'assurer que le fichier lu
+ contient effectivement des entrées de carnet d'adresses. Si c'est le
cas, on affiche le premier contact; sinon on informe l'utilisateur du
- problme par une QMessageBox. Enfin, on met jour l'interface afin
- d'activer et de dsactiver les boutons de faon approprie.
+ problème par une QMessageBox. Enfin, on met à jour l'interface afin
+ d'activer et de désactiver les boutons de façon appropriée.
*/
/*!
@@ -981,86 +981,86 @@
\previouspage {tutorials/addressbook-fr/part6}{Chapitre 6}
\contentspage {Tutoriel "Carnet d'adresses"}{Sommaire}
\example tutorials/addressbook-fr/part7
- \title Carnet d'adresse 7 - Fonctionnalits avances
+ \title Carnet d'adresse 7 - Fonctionnalités avancées
- Ce chapitre couvre quelques fonctionnalits additionnelles qui
+ Ce chapitre couvre quelques fonctionnalités additionnelles qui
feront de notre carnet d'adresses une application plus pratique
pour une utilisation quotidienne.
\image addressbook-tutorial-part7-screenshot.png
Bien que notre application carnet d'adresses soit utile en tant que telle,
- il serait pratique de pouvoir changer les contacts avec d'autres applications.
- Le format vCard est un un format de fichier populaire pour changer
- ce type de donnes.
- Dans ce chapitre, nous tendrons notre carnet d'adresses pour permettre
+ il serait pratique de pouvoir échanger les contacts avec d'autres applications.
+ Le format vCard est un un format de fichier populaire pour échanger
+ ce type de données.
+ Dans ce chapitre, nous étendrons notre carnet d'adresses pour permettre
d'exporter des contacts dans des fichiers vCard \c{.vcf}.
- \section1 Dfinition de la classe AddressBook
+ \section1 Définition de la classe AddressBook
Nous ajoutons un objet QPushButton, \c exportButton, et un slot
- public correspondant, \c exportAsVCard(), notre classe \c AddressBook
+ public correspondant, \c exportAsVCard(), à notre classe \c AddressBook
dans le fichier \c addressbook.h.
\snippet tutorials/addressbook/part7/addressbook.h exportAsVCard() declaration
\dots
\snippet tutorials/addressbook/part7/addressbook.h exportButton declaration
- \section1 Implmentation de la classe AddressBook
+ \section1 Implémentation de la classe AddressBook
Dans le constructeur de \c AddressBook, nous connectons le signal
\l{QPushButton::clicked()}{clicked()} de \c{exportButton} au slot
\c exportAsVCard().
- Nous ajoutons aussi ce bouton \c buttonLayout1, le layout responsable
+ Nous ajoutons aussi ce bouton à \c buttonLayout1, le layout responsable
du groupe de boutons sur la droite.
- Dans la mthode \c exportAsVCard(), nous commenons par extraire le
- nom du contact dans \n name. Nous dclarons \c firstname, \c lastName et
+ Dans la méthode \c exportAsVCard(), nous commençons par extraire le
+ nom du contact dans \n name. Nous déclarons \c firstname, \c lastName et
\c nameList.
Ensuite, nous cherchons la position du premier espace blanc de \c name.
- Si il y a un espace, nous sparons le nom du contact en \c firstName et
- \c lastName. Finalement, nous remplaons l'espace par un underscore ("_").
+ Si il y a un espace, nous séparons le nom du contact en \c firstName et
+ \c lastName. Finalement, nous remplaçons l'espace par un underscore ("_").
Si il n'y a pas d'espace, nous supposons que le contact ne comprend que
- le prnom.
+ le prénom.
\snippet tutorials/addressbook/part7/addressbook.cpp export function part1
- Comme pour la mthode \c saveToFile(), nous ouvrons une bote de dialogue
- pour donner la possibilit l'utilisateur de choisir un emplacement pour
- le fichier. Avec le nom de fichier choisi, nous crons une instance de QFile
- pour y crire.
+ Comme pour la méthode \c saveToFile(), nous ouvrons une boîte de dialogue
+ pour donner la possibilité à l'utilisateur de choisir un emplacement pour
+ le fichier. Avec le nom de fichier choisi, nous créons une instance de QFile
+ pour y écrire.
Nous essayons d'ouvrir le fichier en mode \l{QIODevice::}{WriteOnly}. Si
- cela choue, nous affichons un QMessageBox pour informer l'utilisateur
- propos de l'origine du problme et nous quittons la mthode. Sinon, nous passons le
- fichier comme paramtre pour crer un objet QTextStream, \c out. De la mme faon que
- QDataStream, la classe QTextStream fournit les fonctionnalits pour
- lire et crire des fichiers de texte. Grce cel, le fichier \c{.vcf}
- gnr pourra tre ouvert et dit l'aide d'un simple diteur de texte.
+ cela échoue, nous affichons un QMessageBox pour informer l'utilisateur
+ à propos de l'origine du problème et nous quittons la méthode. Sinon, nous passons le
+ fichier comme paramètre pour créer un objet QTextStream, \c out. De la même façon que
+ QDataStream, la classe QTextStream fournit les fonctionnalités pour
+ lire et écrire des fichiers de texte. Grâce à celà, le fichier \c{.vcf}
+ généré pourra être ouvert et édité à l'aide d'un simple éditeur de texte.
\snippet tutorials/addressbook/part7/addressbook.cpp export function part2
- Nous crivons ensuite un fichier vCard avec la balise \c{BEGIN:VCARD},
+ Nous écrivons ensuite un fichier vCard avec la balise \c{BEGIN:VCARD},
suivit par \c{VERSION:2.1}.
- Le nom d'un contact est crit l'aide de la balise \c{N:}. Pour la balise
- \c{FN:}, qui remplit le titre du contact, nous devons vrifier si le contact
- un nom de famille dfini ou non. Si oui, nous utilions les dtails de
- \c nameList pour remplir le champ, dans le cas contraire on crit uniquement le contenu
+ Le nom d'un contact est écrit à l'aide de la balise \c{N:}. Pour la balise
+ \c{FN:}, qui remplit le titre du contact, nous devons vérifier si le contact
+ à un nom de famille défini ou non. Si oui, nous utilions les détails de
+ \c nameList pour remplir le champ, dans le cas contraire on écrit uniquement le contenu
de \c firstName.
\snippet tutorials/addressbook/part7/addressbook.cpp export function part3
- Nous continuons en crivant l'adresse du contact. Les points-virgules
- dans l'adresse sont chapps l'aide de "\\", les retours de ligne sont
- remplacs par des points-virgules, et les vigules sont remplaces par des espaces.
- Finalement nous crivons les balises \c{ADR;HOME:;} suivies par l'adresse
+ Nous continuons en écrivant l'adresse du contact. Les points-virgules
+ dans l'adresse sont échappés à l'aide de "\\", les retours de ligne sont
+ remplacés par des points-virgules, et les vigules sont remplacées par des espaces.
+ Finalement nous écrivons les balises \c{ADR;HOME:;} suivies par l'adresse
et la balise \c{END:VCARD}.
\snippet tutorials/addressbook/part7/addressbook.cpp export function part4
- la fin de la mthode, un QMessageBox est affich pour informer l'utilisateur
- que la vCard a t exporte avec succs.
+ À la fin de la méthode, un QMessageBox est affiché pour informer l'utilisateur
+ que la vCard a été exportée avec succès.
- \e{vCard est une marque dpose de \l{http://www.imc.org}
+ \e{vCard est une marque déposée de \l{http://www.imc.org}
{Internet Mail Consortium}}.
*/
diff --git a/doc/src/zh_CN/getting-started/how-to-learn-qt.qdoc b/doc/src/zh_CN/getting-started/how-to-learn-qt.qdoc
new file mode 100644
index 0000000..1c2f56b
--- /dev/null
+++ b/doc/src/zh_CN/getting-started/how-to-learn-qt.qdoc
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \page how-to-learn-qt.html
+ \title 如何学习 Qt
+ \brief Links to guides and resources for learning Qt.
+ \nextpage 教程
+
+ \section1 Getting Started
+
+ 我们假定您已了解 C++, 并将用于 Qt 开发。有关将 Qt 与其他编程语言一起使用的更多信息,请参见 \l{Qt website}{Qt 网站}。
+
+ 如果你想仅使用 C++ 编程, 不使用任何设计工具而仅使用代码设计用户界面,请观看\l{教程}。这些教程是为您了解 Qt 编程量身定做的,并侧重于编写可用代码,而并非功能简介。
+
+ 如果您想使用设计工具来设计用户界面,则至少要阅读 \l{Qt Designer manual}{Qt 设计者手册}的前几章。
+
+ 现在您已经编写了一些小型可用的应用程序,并对 Qt 编程有更加广泛的了解。您可以直接着手做自己的项目,但我们建议您阅读以下一些关键简介以加深您对 Qt 的了解:\l{Qt Object Model}Qt 对象模型}和\l{Signals and Slots}{信号和槽}。
+
+ \beginfloatleft
+ \inlineimage qtdemo-small.png
+ \endfloat
+
+ \section1 了解概况
+
+ 在这个阶段,我们建议您浏览一下\l{All Overviews and HOWTOs}{简介},然后阅读与您项目相关的章节。您可能还会发现,浏览与您项目类似的\l{Qt Examples}{示例}的源代码也会对您有所帮助。由于 Qt 源代码已面向公众开放,您也可阅读 Qt 源代码。
+
+ 如果您运行\l{Examples and Demos Launcher}{示例和演示启动程序},您就会看到许多正在使用的 Qt widget。
+
+ \l{Qt Widget Gallery} 还按照在不同支持平台上的使用风格提供了精选 Qt widget 简介。
+ \clearfloat
+
+ \section1 Books and Learning Materials
+
+ Qt 附带大量文档,并全文带有超文本交叉引用,可轻松地点击了解自己想知道的内容。您使用最多的文档可能是 \l{index.html}{API 引用}。每个链接都提供了浏览 API 引用的不同方式,您可每个都尝试一下,看哪个更适合自己。您还可以尝试 \l{Qt Assistant},这是随 Qt 附带的工具,可访问全部 Qt API,并提供全文本搜索功能。
+
+ 有大量的书籍是关于 Qt 编程的。有关 Qt 书籍的完整列表。
+ We recommend the official Qt book,
+ \l{http://www.amazon.com/gp/product/0132354160/ref=ase_trolltech/}{C++
+ GUI Programming with Qt 4, Second Edition} (ISBN 0-13-235416-0).
+ 本书从 "Hello Qt" 到高级功能(如多线程、2D 和 3D 图形、网络、内容视图类与 XML),全面详实地说明了 Qt 编程。(第一版基于 Qt 4.1,可\l{http://www.qtrac.eu/C++-GUI-Programming-with-Qt-4-1st-ed.zip}{在线}获得。)
+
+ 包括不同语言的翻译版本,请参见\l{Books about Qt Programming}{有关 Qt 编程的书籍}。
+
+ 另一个有关实例代码和 Qt 功能说明的有用资源就是存档的 \l{Qt Quarterly}{Qt 季讯}文章,季讯是为 Qt 用户提供的新闻时讯。
+
+ 有关特定 Qt 模块和其他指南的文档,请参见\l{All Overviews and HOWTOs}。
+
+ \section1 Further Reading
+
+ Qt has an active and helpful user community who communicate using
+ the \l{Qt Mailing Lists}{qt-interest} mailing list, the \l{Qt Centre}
+ Web site, and a number of other community Web sites and Weblogs.
+ In addition, many Qt developers are active members of the
+ \l{KDE}{KDE community}.
+
+ 祝您好运并且学习愉快!
+*/
diff --git a/doc/src/zh_CN/getting-started/tutorials.qdoc b/doc/src/zh_CN/getting-started/tutorials.qdoc
new file mode 100644
index 0000000..dc371d8
--- /dev/null
+++ b/doc/src/zh_CN/getting-started/tutorials.qdoc
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \page tutorials.html
+ \title 教程
+
+ \contentspage 如何学习 Qt
+
+ \brief Tutorials, guides and overviews to help you learn Qt.
+
+ A collection of tutorials and "walkthrough" guides are provided with Qt to
+ help new users get started with Qt development. These documents cover a
+ range of topics, from basic use of widgets to step-by-step tutorials that
+ show how an application is put together.
+
+ \table
+ \row
+ \o{2,1} \l{Widgets 教程}{\bold Widgets}
+ \o{2,1} \l{地址簿教程}{\bold {地址簿}}
+ \row
+ \o \image widget-examples.png Widgets
+ \o
+ A beginner's guide to getting started with widgets and layouts to create
+ GUI applications.
+
+ \o \image addressbook-tutorial.png 地址簿
+ \o
+ A seven part guide to creating a fully-functioning address book
+ application. This tutorial is also available with
+ \l{Tutoriel "Carnet d'adresses"}{French explanation}.
+
+ \row
+ \o{2,1} \l{A Quick Start to Qt Designer}{\bold{Qt Designer}}
+ \o{2,1} \l{Qt Linguist Manual: Programmers#Tutorials}{\bold {Qt Linguist}}
+ \row
+ \o \image designer-examples.png QtDesigner
+ \o
+ A quick guide through \QD showing the basic steps to create a
+ form with this interactive tool.
+
+ \o \image linguist-examples.png QtLinguist
+ \o
+ A guided tour through the translations process, explaining the
+ tools provided for developers, translators and release managers.
+
+ \row
+ \o{2,1} \l{QTestLib Tutorial}{\bold QTestLib}
+ \o{2,1} \l{qmake Tutorial}{\bold qmake}
+ \row
+ \o{2,1}
+ This tutorial gives a short introduction to how to use some of the
+ features of Qt's unit-testing framework, QTestLib. It is divided into
+ four chapters.
+
+ \o{2,1}
+ This tutorial teaches you how to use \c qmake. We recommend that
+ you read the \l{qmake Manual}{qmake user guide} after completing
+ this tutorial.
+
+ \endtable
+*/
diff --git a/doc/src/zh_CN/tutorials/addressbook.qdoc b/doc/src/zh_CN/tutorials/addressbook.qdoc
new file mode 100644
index 0000000..72349af
--- /dev/null
+++ b/doc/src/zh_CN/tutorials/addressbook.qdoc
@@ -0,0 +1,673 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \page tutorials-addressbook.html
+
+ \startpage {index.html}{Qt Reference Documentation}
+ \contentspage 教程
+ \nextpage {tutorials/addressbook/part1}{第一章}
+
+ \title 地址簿教程
+ \brief 本教程介绍了使用 Qt 跨平台框架的 GUI 编程。
+
+ 本教程介绍了使用 Qt 跨平台框架的 GUI 编程。
+
+ \image addressbook-tutorial-screenshot.png
+
+ \omit
+ It doesn't cover everything; the emphasis is on teaching the programming
+ philosophy of GUI programming, and Qt's features are introduced as needed.
+ Some commonly used features are never used in this tutorial.
+ \endomit
+
+ 在学习过程中,我们将了解部分 Qt 基本技术,如
+
+ \list
+ \o Widget 和布局管理器
+ \o 容器类
+ \o 信号和槽
+ \o 输入和输出设备
+ \endlist
+
+ 如果您完全不了解 Qt,请阅读\l{How to Learn Qt}{如何学习 Qt}(如果您还未阅读)。
+
+ 教程的源代码位于 Qt 的 \c examples/tutorials/addressbook 目录下。
+
+ 教程章节:
+
+ \list 1
+ \o \l{tutorials/addressbook/part1}{设计用户界面}
+ \o \l{tutorials/addressbook/part2}{添加地址}
+ \o \l{tutorials/addressbook/part3}{浏览地址簿条目}
+ \o \l{tutorials/addressbook/part4}{编辑和删除地址}
+ \o \l{tutorials/addressbook/part5}{添加查找功能}
+ \o \l{tutorials/addressbook/part6}{加载和保存}
+ \o \l{tutorials/addressbook/part7}{附加功能}
+ \endlist
+
+ 虽然这个小型应用程序看起来并不象一个成熟的现代 GUI 应用程序,但它使用多种用于更复杂应用程序的基本技术。在您完成学习之后,我们建议您查看一下\l{mainwindows/application}{应用程序}示例,它提供带有菜单、工具栏、状态栏等项目的小型 GUI 应用程序。
+*/
+
+/*!
+ \page tutorials-addressbook-part1.html
+ \contentspage {地址簿教程}{目录}
+ \nextpage {tutorials/addressbook/part2}{第二章}
+ \example tutorials/addressbook/part1
+ \title 地址簿 1 — 设计用户界面
+
+ 本教程的第一部分讲述了用于地址簿应用程序的基本图形用户界面 (GUI) 的设计。
+
+ 创建 GUI 程序的第一步就是设计用户界面。在本章中,我们的目标是设置应用基本地址簿应用程序所需的标签和输入字段。下图为期望输出的屏幕截图。
+
+ \image addressbook-tutorial-part1-screenshot.png
+
+ 我们需要使用两个 QLabel 对象:\c nameLabel 和 \c addressLabel,以及两个输入字段:QLineEdit 对象 \c nameLine 和 QTextEdit
+ 对象 \c addressText,这样用户才能输入联系人的姓名和地址。使用的 widget 及其位置如下图所示。
+
+ \image addressbook-tutorial-part1-labeled-screenshot.png
+
+ 要应用地址簿需使用三个文件:
+
+ \list
+ \o \c{addressbook.h} — AddressBook 类的定义文件,
+ \o \c{addressbook.cpp} — AddressBook 类的执行文件,以及
+ \o \c{main.cpp} — 包含 \c main() 函数并带有 AddressBook 实例的文件。
+ \endlist
+
+ \section1 Qt 编程 — 使用子类
+
+ 在编写 Qt 程序时,我们通常使用 Qt 对象子类来添加功能。这是创建定制 widget 或标准 widget 集合的基本概念之一。使用子类扩展或改变 widget 的操作具有以下优势:
+
+ \list
+ \o 我们可以编写虚函数或纯虚函数应用,以得到我们确切所需的功能,并在需要时再使用基本的类应用。
+ \o 这样我们就可以在类中封装部分用户界面,应用程序的其他部分也就无需了解用户界面中单独使用的 widget。
+ \o 可使用子类在同一应用程序或库中创建多个定制 widget,这样子类的代码可在其他项目重复使用。
+ \endlist
+
+ 由于 Qt 未提供特定的地址簿 widget,我们在标准的 Qt widget 类中使用子类,然后添加功能。我们在本教程中创建的 \c AddressBook 类在需要使用基本地址簿 widget 的情况下可重复使用。
+
+ \section1 定义 AddressBook 类
+
+ \l{tutorials/addressbook/part1/addressbook.h}{\c addressbook.h} 文件用于定义 \c AddressBook 类。
+
+ 我们从定义 \c AddressBook 为 QWidget 子类和声明构造器开始入手。我们还使用 Q_OBJECT 宏表明该类使用国际化功能与 Qt 信号和槽功能,即使在本阶段不会用到所有这些功能。
+
+ \snippet tutorials/addressbook/part1/addressbook.h class definition
+
+ 该类包含了 \c nameLine 和 \c addressText 的声明、上文提到的 QLineEdit 和 QTextEdit 的私有实例。在以后章节中,您会看到储存在 \c nameLine 和 \c addressText 中的数据在地址簿的许多功能中都会用到。
+
+ 我们不必包含要使用的 QLabel 对象的声明,这是因为在创建这些对象后我们不必对其进行引用。在下一部分中,我们会说明 Qt 记录对象所属关系的方式。
+
+ Q_OBJECT 宏本身应用了部分更高级的 Qt 功能。 我们暂时把 Q_OBJECT 宏理解为使用 \l{QObject::}{tr()} 和 \l{QObject::}{connect()} 函数的快捷方式,这种理解对我们的学习更有用。
+
+ 我们现已完成 \c addressbook.h 文件,接下来我们来执行对应的 \c addressbook.cpp 文件。
+
+ \section1 应用 AddressBook 类
+
+ \c AddressBook 的构造器接收 QWidget 参数 \a parent。按惯例,我们将参数传递给基本类的构造器。这种父项可有一个或多个子项的所属概念对 Qt 中的 widget 分组十分有用。例如,如果删除父项,也会删除其所有子项。
+
+ \snippet tutorials/addressbook/part1/addressbook.cpp constructor and input fields
+
+ 在该构造器中,我们声明并通过实例来表示两个局部 QLabel 对象 \c nameLabel 和 \c addressLabel,以及 \c nameLine 和 \c addressText。如果字符串已进行转换,则 \l{QObject::tr()}{tr()} 函数返回已转换的字符串,否则返回字符串本身。我们可以将此函数理解 \c{<insert translation here>} 标识来标记要进行转换 QString 对象。在以后章节和 \l{Qt Examples} 中,您会看到只要使用了可转换的字符串就是使用该函数。
+
+ 使用 Qt 编程时,了解布局是如何起作用的会对您很有帮助。Qt 提供三个主要布局类 QHBoxLayout、QVBoxLayout 和 QGridLayout 来处理 widget 的位置。
+
+ \image addressbook-tutorial-part1-labeled-layout.png
+
+ 我们使用 QGridLayout 以结构化的方式放置标签和输入字段。QGridLayout 将可用空间分为网格,并将 widget 放置在指定了行列号的单元格中。上面的图表显示了布局单元格和 widget 的位置。我们通过以下代码指定这种排列方式:
+
+ \snippet tutorials/addressbook/part1/addressbook.cpp layout
+
+ 请注意,\c addressLabel 是使用作为附加参数的 Qt::AlignTop 来排放位置。这可确保其不会纵向放置在单元格 (1,0) 中央。有关 Qt 布局的基本简介,请参见\l{Layout Management}{布局类}文档。
+
+ 要在 widget 上安装布局对象,必须调用 widget 的 \l{QWidget::setLayout()}{setLayout()} 函数:
+
+ \snippet tutorials/addressbook/part1/addressbook.cpp setting the layout
+
+ 最后,我们将 widget 标题设置为“简单地址簿”。
+
+ \section1 运行应用程序
+
+ \c main() 函数使用单独的文件 \c main.cpp。在该函数中,我们实例化了 QApplication 对象 \c app。QApplication 负责管理多种应用范围的资源(如默认字体和光标),以及运行事件循环。因此,在每个使用 Qt 的 GUI 应用程序中都会有一个 QApplication 对象。
+
+ \snippet tutorials/addressbook/part1/main.cpp main function
+
+ 我们使用 new 关键字在堆中构造一个新的 \c AddressBook widget,然后调用 \l{QWidget::show()}{show()} 函数对其进行显示。不过,该 widget 只有在应用程序事件循环开始时才会显示。我们通过调用应用程序的 \l{QApplication::}{exec()} 函数开始事件循环。该函数返回的结果作为 \c main() 函数的返回值。
+*/
+
+/*!
+ \page tutorials-addressbook-part2.html
+ \previouspage 地址簿 1 — 设计用户界面
+ \contentspage {地址簿教程}{目录}
+ \nextpage {tutorials/addressbook/part3}{第三章}
+ \example tutorials/addressbook/part2
+ \title 地址簿 2 — 添加地址
+
+ 创建基本地址簿应用程序的下一步是添加少许用户互动操作。
+
+ \image addressbook-tutorial-part2-add-contact.png
+
+ 我们将提供一个按钮,用户可点击该按钮来添加新联系人。此外,还需要对数据结构进行限定,以便有序地储存这些联系人。
+
+ \section1 定义 AddressBook 类
+
+ 由于已经设置了标签和输入字段,我们只需添加按钮就可完成添加联系人这一步骤。也就是说,在 \c addressbook.h 文件中已经声明了三个 QPushButton 对象和三个对应的公共槽。
+
+ \snippet tutorials/addressbook/part2/addressbook.h slots
+
+ 槽是对特殊信号进行响应的函数。我们将在应用 \c AddressBook 类时进一步详细说明这一概念。如需有关 Qt 信号和槽概念的简介,请参见\l{Signals and Slots}{信号和槽}文档。
+
+ 三个 QPushButton 对象分别是 \c addButton、\c submitButton 和 \c cancelButton,已与要在上一章中说明的 \c nameLine 和 \c addressText 一同包含在私有变量声明中。
+
+ \snippet tutorials/addressbook/part2/addressbook.h pushbutton declaration
+
+ 我们需要一个容器来储存地址簿联系人,这样才能搜索和显示联系人。QMap 对象 \c contacts 就可实现此功能,因为其带有一个键-值对:联系人姓名作为键,而联系人地址作为\e{值}。
+
+ \snippet tutorials/addressbook/part2/addressbook.h remaining private variables
+
+ 我们还会声明两个私有 QString 对象:\c oldName 和 \c oldAddress。这些对象用来保留在用户点击\gui{添加}时最后显示的联系人姓名和地址。这样,当用户点击\gui{取消}时,我们就可以返回至上一个联系人的详细信息。
+
+ \section1 应用 AddressBook 类
+
+ 在 \c AddressBook 构造器中,我们将 \c nameLine 和 \c addressText 设置为只读,这样就可仅显示而不必编辑现有联系人的详细信息。
+
+ \dots
+ \snippet tutorials/addressbook/part2/addressbook.cpp setting readonly 1
+ \dots
+ \snippet tutorials/addressbook/part2/addressbook.cpp setting readonly 2
+
+ 然后,我们实例化以下按钮:\c addButton、\c submitButton 和 \c cancelButton。
+
+ \snippet tutorials/addressbook/part2/addressbook.cpp pushbutton declaration
+
+ 显示 \c addButton 是通过调用 \l{QPushButton::show()}{show()} 函数实现的,而隐藏 \c submitButton 和 \c cancelButton 则需调用 \l{QPushButton::hide()}{hide()}。这两个按钮仅当用户点击\gui{添加}时才会显示,而此操作是通过在下文中说明的\c addContact() 函数处理的。
+
+ \snippet tutorials/addressbook/part2/addressbook.cpp connecting signals and slots
+
+ 我们将按钮的 \l{QPushButton::clicked()}{clicked()} 信号与其相应的槽关联。下面的图表说明了此过程。
+
+ \image addressbook-tutorial-part2-signals-and-slots.png
+
+ 接下来,我们将按钮整齐的排列在地址簿 widget 的右侧,使用 QVBoxLayout 将其进行纵向排列。
+
+ \snippet tutorials/addressbook/part2/addressbook.cpp vertical layout
+
+ \l{QBoxLayout::addStretch()}{addStretch()} 函数用来确保按钮并不是采用均匀间隔排列的,而是更靠近 widget 的顶部。下图显示了是否使用 \l{QBoxLayout::addStretch()}{addStretch()} 的差别。
+
+ \image addressbook-tutorial-part2-stretch-effects.png
+
+ 然后,我们使用 \l{QGridLayout::addLayout()}{addLayout()} 将 \c buttonLayout1 增加至 \c mainLayout。 这样我们就有了嵌套布局,因为 \c buttonLayout1 现在是 \c mainLayout 的子项。
+
+ \snippet tutorials/addressbook/part2/addressbook.cpp grid layout
+
+ 布局坐标显示如下:
+
+ \image addressbook-tutorial-part2-labeled-layout.png
+
+ 在 \c addContact() 函数中,我们使用 \c oldName 和 \c oldAddress 储存最后显示的联系人详细信息。然后,我们清空这些输入字段并关闭只读模式。输入焦点设置在 \c nameLine,显示 \c submitButton 和 \c cancelButton。
+
+ \snippet tutorials/addressbook/part2/addressbook.cpp addContact
+
+ \c submitContact() 函数可分为三个部分:
+
+ \list 1
+ \o 我们从 \c nameLine 和 \c addressText 提取联系人的详细信息,然后将其储存在 QString 对象中。我们还要验证确保用户没有在输入字段为空时点击\gui{提交},否则,会显示 QMessageBox 提示用户输入姓名和地址。
+
+ \snippet tutorials/addressbook/part2/addressbook.cpp submitContact part1
+
+ \o 我们接着继续检查是否联系人已存在。如果不存在,将联系人添加至 \c contacts,然后显示 QMessageBox 提示用户已添加联系人。
+
+ \snippet tutorials/addressbook/part2/addressbook.cpp submitContact part2
+
+ 如果联系人已存在,还是会显示 QMessageBox 以提示用户,以免添加重复的联系人。由于 \c contacts 对象是基于姓名地址的键-值对,因此要确保键唯一。
+
+ \o 在处理了上述两种情况后,使用以下代码将按钮恢复为正常状态:
+
+ \snippet tutorials/addressbook/part2/addressbook.cpp submitContact part3
+
+ \endlist
+
+ 下面的屏幕截图显示了用于向用户显示提示信息的 QMessageBox 对象。
+
+ \image addressbook-tutorial-part2-add-successful.png
+
+ \c cancel() 函数恢复上次显示的联系人详细信息,并启用 \c addButton,还会隐藏 \c submitButton 和
+ \c cancelButton。
+
+ \snippet tutorials/addressbook/part2/addressbook.cpp cancel
+
+ 添加联系人的总体思想就是提高用户操作的灵活性,可在任何时候点击\gui{提交}或\gui{取消}。下面的流程图详细说明了此概念:
+
+ \image addressbook-tutorial-part2-add-flowchart.png
+*/
+
+/*!
+ \page tutorials-addressbook-part3.html
+ \previouspage 地址簿 2 — 添加地址
+ \contentspage {地址簿教程}{目录}
+ \nextpage {tutorials/addressbook/part4}{第四章}
+ \example tutorials/addressbook/part3
+ \title 地址簿 3 — 浏览地址簿条目
+
+ 构建地址簿应用程序现已进展过半。我们需要增加一些函数,以便浏览联系人。但首先要决定采用何种数据结构方式来储存这些联系人。
+
+ 在第二章中,我们使用了 QMap 键-值对,即联系人姓名作为\e{键},而联系人地址作为\e{值}。这种方式很适合我们的实例。不过,要浏览和显示每个条目,还需要进行一些改进。
+
+ 我们改进 QMap 的方式是,将数据结构替换为类似循环链接的列表,其中所有元素都是相互关联的,包括第一个元素和最后一个元素。下图图解说明了该数据结构。
+
+ \image addressbook-tutorial-part3-linkedlist.png
+
+ \section1 定义 AddressBook 类
+
+ 要给地址簿应用程序增加浏览功能,我们需要为 \c AddressBook 类再增加两个函数:\c next() 和 \c previous()。将这两个函数添加到 \c addressbook.h 文件中:
+
+ \snippet tutorials/addressbook/part3/addressbook.h navigation functions
+
+ 我们还需要使用其他两个 QPushButton 对象,因此将 \c nextButton 和 \c previousButton 声明为私有变量:
+
+ \snippet tutorials/addressbook/part3/addressbook.h navigation pushbuttons
+
+ \section1 应用 AddressBook 类
+
+ 在 \c AddressBook 的 \c addressbook.cpp 构造器中,我们实例化 \c nextButton 和 \c previousButton,并且这两项默认为禁用。这是因为仅当地址簿中有多个联系人时才会启用浏览功能。
+
+ \snippet tutorials/addressbook/part3/addressbook.cpp navigation pushbuttons
+
+ 然后,我们将这两个按钮与其相应的槽关联:
+
+ \snippet tutorials/addressbook/part3/addressbook.cpp connecting navigation signals
+
+ 下图即为预期的图形用户界面。请注意,该用户界面已很接近应用程序最终的样子。
+
+ \image addressbook-tutorial-part3-screenshot.png
+
+ 我们按照 \c next() 和 \c previous() 函数的基本规范,将 \c nextButton 放置在右侧,而 \c previousButton 放置在左侧。为了使布局更加直观,我们使用 QHBoxLayout 将 widget 并排放置:
+
+ \snippet tutorials/addressbook/part3/addressbook.cpp navigation layout
+
+ 然后,将 QHBoxLayout 对象 \c buttonLayout2 增加至 \c mainLayout。
+
+ \snippet tutorials/addressbook/part3/addressbook.cpp adding navigation layout
+
+ 下图显示了 widget 在 \c mainLayout 中的坐标位置。
+
+ \image addressbook-tutorial-part3-labeled-layout.png
+
+ 在 \c addContact() 函数中,我们必须禁用这几个按钮,这样用户就不会在增加联系人时尝试进行浏览。
+
+ \snippet tutorials/addressbook/part3/addressbook.cpp disabling navigation
+
+ 此外,在 \c submitContact() 函数中,我们启用了浏览按钮 \c nextButton 和 \c previousButton,这取决于 \c contacts 的多少。如上文所述,浏览功能仅在地址簿中有多个联系人时才会启用。以下代码行说明了如何实现此功能:
+
+ \snippet tutorials/addressbook/part3/addressbook.cpp enabling navigation
+
+ 我们还在 \c cancel() 函数中加入这几行代码。
+
+ 记得我们曾使用 QMap 对象 \c contacts 模拟了一个循环链接的列表。因此,在 \c next() 函数中,我们获取 \c contacts 的迭代器,然后执行以下操作:
+
+ \list
+ \o 如果迭代器未达到 \c contacts 结尾,就会增加一。
+ \o 如果迭代器已达到 \c contacts 的结尾,就移至 \c contacts 的起始位置。这给人感觉 QMap 就像是一个循环链接的列表。
+ \endlist
+
+ \snippet tutorials/addressbook/part3/addressbook.cpp next() function
+
+ 一旦在 \c contacts 中循环至正确的对象,就会通过 \c nameLine 和 \c addressText 显示对象的内容。
+
+ 同样,在 \c previous() 函数中,我们获取 \c contacts 的迭代器,然后执行以下操作:
+
+ \list
+ \o 如果迭代器达到 \c contacts 的结尾,就清除显示内容,然后返回。
+ \o 如果迭代器在 \c contacts 的起始位置,就将其移至结尾。
+ \o 然后,将迭代器减一。
+ \endlist
+
+ \snippet tutorials/addressbook/part3/addressbook.cpp previous() function
+
+ 接着,重新显示 \c contacts 中当前对象的内容。
+*/
+
+/*!
+ \page tutorials-addressbook-part4.html
+ \previouspage 地址簿 3 — 浏览地址簿条目
+ \contentspage {地址簿教程}{目录}
+ \nextpage {tutorials/addressbook/part5}{第五章}
+ \example tutorials/addressbook/part4
+ \title 地址簿 4 — 编辑和删除地址
+
+ 在本章中,我们将了解如何修改储存在地址簿应用程序中的联系人的内容。
+
+ \image addressbook-tutorial-screenshot.png
+
+ 现有的地址簿不仅可以井井有条地储存联系人,还可进行浏览。再添加上编辑和删除功能,以便在需要时更改联系人的详细信息,这样更易于使用。不过,还需使用 enum 类型进行一些改进。在前几章中,我们使用以下两种模式:\c{AddingMode} 和 \c{NavigationMode}。但是,他们并未定义为 enum。我们是采用手动方式启用和禁用相应的按钮,这就导致有多行重复的代码。
+
+ 在本章中,我们定义带有以下三种不同值的 \c{Mode} enum 类型:
+
+ \list
+ \o \c{NavigationMode}、
+ \o \c{AddingMode} 和
+ \o \c{EditingMode}。
+ \endlist
+
+ \section1 定义 AddressBook 类
+
+ \c addressbook.h 文件已更新为包含 Mode \c enum 类型:
+
+ \snippet tutorials/addressbook/part4/addressbook.h Mode enum
+
+ 我们还要向当前的公有槽列表增加两个新槽:\c editContact() 和 \c removeContact()。
+
+ \snippet tutorials/addressbook/part4/addressbook.h edit and remove slots
+
+ 为了在模式间切换,我们引入了 \c updateInterface() 函数来控制所有 QPushButton 对象的启用和禁用。要实现上文提及的编辑和删除功能,我们还要增加两个新按钮:\c editButton 和 \c removeButton。
+
+ \snippet tutorials/addressbook/part4/addressbook.h updateInterface() declaration
+ \dots
+ \snippet tutorials/addressbook/part4/addressbook.h buttons declaration
+ \dots
+ \snippet tutorials/addressbook/part4/addressbook.h mode declaration
+
+ 最后,我们声明 \c currentMode 来跟踪 enum 的当前模式。
+
+ \section1 应用 AddressBook 类
+
+ 我们现在必须应用地址簿应用程序的模式更改功能。\c editButton 和 \c removeButton 已实例化并默认为禁用,这是因为地址簿启动时在内存中没有联系人。
+
+ \snippet tutorials/addressbook/part4/addressbook.cpp edit and remove buttons
+
+ 这些按钮会与其相应的槽 \c editContact() 和 \c removeContact() 关联,然后我们将其添加至 \c buttonLayout1。
+
+ \snippet tutorials/addressbook/part4/addressbook.cpp connecting edit and remove
+ \dots
+ \snippet tutorials/addressbook/part4/addressbook.cpp adding edit and remove to the layout
+
+ 在将模式切换到 \c EditingMode 之前,\c editContact() 函数使用 \c oldName 和 \c oldAddress 储存联系人旧的详细信息。 在该模式下,\c submitButton 和 \c cancelButton 均已启用,这样用户就可以更改联系人的详细信息并可点击任何一个按钮。
+
+ \snippet tutorials/addressbook/part4/addressbook.cpp editContact() function
+
+ \c submitContact() 函数已被 \c{if-else} 语句分为两部分。我们查看 \c currentMode 是否在 \c AddingMode 模式下。如果是,我们继续添加操作。
+
+ \snippet tutorials/addressbook/part4/addressbook.cpp submitContact() function beginning
+ \dots
+ \snippet tutorials/addressbook/part4/addressbook.cpp submitContact() function part1
+
+ 否则,我们查看 \c currentMode 是否在 \c EditingMode 模式下。如果是,我们比较 \c oldName 和 \c name。如果姓名已更改,我们从 \c contacts 中删除旧的联系人并插入已更新的联系人。
+
+ \snippet tutorials/addressbook/part4/addressbook.cpp submitContact() function part2
+
+ 如果仅更改了地址(例如 \c oldAddress 与 \c address 不同),我们就更新联系人的地址。最后,我们将 \c currentMode 设置为 \c NavigationMode。这一步至关重要,因为它会重新启用所有已禁用的按钮。
+
+ 要从地址簿中删除联系人,我们采用 \c removeContact() 函数。该函数查看 \c contacts 中是否包含该联系人。
+
+ \snippet tutorials/addressbook/part4/addressbook.cpp removeContact() function
+
+ 如果有,我们显示 QMessageBox,确认用户的删除操作。一旦用户确认操作,我们调用 \c previous() 确保用户界面显示其他联系人,然后我们使用 QMap 的 \l{QMap::remove()}{remove()} 函数删除已已确认的联系人。出于好意,我们会显示 QMessageBox 提示用户。在该函数中使用两种信息框显示如下:
+
+ \image addressbook-tutorial-part4-remove.png
+
+ \section2 更新用户界面
+
+ 我们在上文提到 \c updateInterface() 函数,它可根据当前的模式启用和禁用按钮。该函数会根据传递给它的 \c mode 参数更新当前的模式,在校验值之前将参数分配给 \c currentMode。
+
+ 这样,每个按钮就根据当前的模式进行启用或禁用。\c AddingMode 和 \c EditingMode 的代码显示如下:
+
+ \snippet tutorials/addressbook/part4/addressbook.cpp update interface() part 1
+
+ 不过对于 \c NavigationMode,我们在 QPushButton::setEnabled() 函数的参数中加入了条件。这样可确保 \c editButton 和 \c removeButton 在地址簿中至少有一个联系人的情况下启用,而 \c nextButton 和 \c previousButton 仅在地址簿中有多个联系人时才启用。
+
+ \snippet tutorials/addressbook/part4/addressbook.cpp update interface() part 2
+
+ 通过在同一函数中设置模式和更新用户界面,我们可以避免用户界面与应用程序内部状态不同步的可能性。
+*/
+
+/*!
+ \page tutorials-addressbook-part5.html
+ \previouspage 地址簿 4 — 编辑和删除地址
+ \contentspage {地址簿教程}{目录}
+ \nextpage {tutorials/addressbook/part6}{第六章}
+ \example tutorials/addressbook/part5
+ \title 地址簿 5 — 添加查找功能
+
+ 在本章中,我们将了解如何在地址簿应用程序中定位联系人和地址。
+
+ \image addressbook-tutorial-part5-screenshot.png
+
+ 随着我们不断为地址簿应用程序添加联系人,使用下一个和上一个按钮浏览联系人就会变得很繁琐。在这种情况下,使用查找函数查找联系人就会更加有效。上面的屏幕截图显示了查找按钮及其在按钮面板上的位置。
+
+ 当用户点击查找按钮时,有必要显示一个对话框,用户可在其中输入联系人的姓名。Qt 提供了 QDialog(我们会在本章中将其用作子类),可使用 \c FindDialog 类。
+
+ \section1 定义 FindDialog 类
+
+ \image addressbook-tutorial-part5-finddialog.png
+
+ 要使用 QDialog 的子类,我们首先要在 \c finddialog.h 文件中声明 QDialog 的头信息。此外,我们还使用向前 (forward) 声明来声明 QLineEdit 和 QPushButton,这样我们就能在对话框类中使用这些 widget。
+
+ 因为在 \c AddressBook 类中,\c FindDialog 类包含了 Q_OBJECT 宏,并且其构造器已定义为接收父级 QWidget,即使对话框以单独的窗口方式打开。
+
+ \snippet tutorials/addressbook/part5/finddialog.h FindDialog header
+
+ 我们定义了公有函数 \c getFindText(),供实例化 \c FindDialog 的类使用,这样这些类可以获取用户输入的文本。公有槽 \c findClicked() 定义为在用户点击\gui{查找}按钮时处理搜索字符串。
+
+ 最后,我们定义私有变量 \c findButton、\c lineEdit 和 \c findText,分别对应\gui{查找}按钮、用户输入搜索字符串的行编辑框和储存搜索字符串供稍后使用的内部字符串。
+
+ \section1 应用 FindDialog 类
+
+ 在 \c FindDialog 的构造器中,我们设置私有变量 \c lineEdit、\c findButton 和 \c findText。使用 QHBoxLayout 放置 widget。
+
+ \snippet tutorials/addressbook/part5/finddialog.cpp constructor
+
+ 我们设定布局和窗口标题,并将信号与其各自的槽关联。请注意,\c findButton 的 \l{QPushButton::clicked()}{clicked()} 信号已与 \c findClicked() 和 \l{QDialog::accept()}{accept()} 关联。QDialog 提供的 \l{QDialog::accept()}{accept()} 槽会隐藏对话框并将结果代码设置为 \l{QDialog::}{Accepted}。我们使用该函数有助于 \c AddressBook 的 \c findContact() 函数知晓 \c FindDialog 对象关闭的时间。我们在讨论 \c findContact() 函数时将对该函数做进一步说明。
+
+ \image addressbook-tutorial-part5-signals-and-slots.png
+
+ 在 \c findClicked() 中,我们验证 \c lineEdit 以确保用户没有在尚未输入联系人姓名时就点击\gui{查找}按钮。然后,我们将 \c findText 设置为从 \c lineEdit 提取的搜索字符串。之后,我们清空 \c lineEdit 的内容并隐藏对话框。
+
+ \snippet tutorials/addressbook/part5/finddialog.cpp findClicked() function
+
+ \c findText 变量已有公有 getter 函数 \c getFindText() 与其相关联。既然我们仅在构造器和 \c findClicked() 函数中直接设定了 \c findText, 我们就不在创建 \c getFindText() 的同时再创建 setter 函数。由于 \c getFindText() 是公有的,实例化和使用 \c FindDialog 的类可始终读取用户已输入并确认的搜索字符串。
+
+ \snippet tutorials/addressbook/part5/finddialog.cpp getFindText() function
+
+ \section1 定义 AddressBook 类
+
+ 要确保我们可使用 \c AddressBook 类中的 \c FindDialog,我们要在 \c addressbook.h 文件中包含 \c finddialog.h。
+
+ \snippet tutorials/addressbook/part5/addressbook.h include finddialog's header
+
+ 至此,所有地址簿功能都有了 QPushButton 和对应的槽。同样,\gui{Find} 功能有 \c findButton 和 \c findContact()。
+
+ \c findButton 声明为私有变量,而 \c findContact() 函数声明为公有槽。
+
+ \snippet tutorials/addressbook/part5/addressbook.h findContact() declaration
+ \dots
+ \snippet tutorials/addressbook/part5/addressbook.h findButton declaration
+
+ 最后,我们声明私有变量 \c dialog,用于引用 \c FindDialog 的实例。
+
+ \snippet tutorials/addressbook/part5/addressbook.h FindDialog declaration
+
+ 在实例化对话框后,我们可能会对其进行多次使用。使用私有变量可在类中不同位置对其进行多次引用。
+
+ \section1 应用 AddressBook 类
+
+ 在 \c AddressBook 类的构造器中,实例化私有对象 \c findButton 和 \c findDialog:
+
+ \snippet tutorials/addressbook/part5/addressbook.cpp instantiating findButton
+ \dots
+ \snippet tutorials/addressbook/part5/addressbook.cpp instantiating FindDialog
+
+ 接下来,将 \c findButton 的 \l{QPushButton::clicked()}{clicked()} 信号与 \c findContact() 关联。
+
+ \snippet tutorials/addressbook/part5/addressbook.cpp signals and slots for find
+
+ 现在唯一要完成的就是 \c findContact() 函数的编码:
+
+ \snippet tutorials/addressbook/part5/addressbook.cpp findContact() function
+
+ 我们从显示 \c FindDialog 的实例 \c dialog 开始入手。这时用户开始输入联系人姓名进行查找。用户点击对话框的 \c findButton 后,对话框会隐藏,并且结果代码设置为 QDialog::Accepted.这样就确保了 \c if 语句始终为真。
+
+ 然后,我们就开始使用 \c FindDialog 的 \c getFindText() 函数提取搜索字符串,这个字符串也就是本例中的 \c contactName。如果地址簿中有联系人,就立即显示该联系人。否则,显示如下所示的 QMessageBox 表明搜索失败。
+
+ \image addressbook-tutorial-part5-notfound.png
+*/
+
+/*!
+ \page tutorials-addressbook-part6.html
+ \previouspage 地址簿 5 — 添加查找功能
+ \contentspage {地址簿教程}{目录}
+ \nextpage {tutorials/addressbook/part7}{第七章}
+ \example tutorials/addressbook/part6
+ \title 地址簿 6 — 加载和保存
+
+ 本章描述了用于编写地址簿应用程序的加载和保存程序所使用的 Qt 文件处理功能。
+
+ \image addressbook-tutorial-part6-screenshot.png
+
+ 虽然浏览和搜索联系人是非常实用的功能,但只有在可以保存现有联系人并可以在以后加载的前提下地址簿才真正完全可用。Qt 提供大量用于\l{Input/Output and Networking}{输入和输出}的类,但我们只选择两个易于合并使用的类:QFile 和 QDataStream。
+
+ QFile 对象表示磁盘上可读取和写入的文件。QFile 是代表多种不同设备且应用更广的 QIODevice 类的子类。
+
+ QDataStream 对象用于按顺序排列二进制数据,以便储存在 QIODevice 中并供以后检索。读取或写入 QIODevice 就如同打开数据流,然后读取或写入一样简单,只是参数为不同的设备。
+
+
+ \section1 定义 AddressBook 类
+
+ 我们声明两个公有槽 \c saveToFile() 和 \c loadFromFile(),以及两个 QPushButton 对象 \c loadButton 和 \c saveButton。
+
+ \snippet tutorials/addressbook/part6/addressbook.h save and load functions declaration
+ \dots
+ \snippet tutorials/addressbook/part6/addressbook.h save and load buttons declaration
+
+ \section1 应用 AddressBook 类
+
+ 在构造器中,我们实例化 \c loadButton 和 \c saveButton。理想情况下,将按钮标签设置为“从文件加载联系人”和“将联系人保存至文件”会更方便用户使用。不过,由于其他按钮的大小限制,我们将标签设置为\gui{加载...}和\gui{保存...}。幸运的是,Qt 提供了使用 \l{QWidget::setToolTip()}{setToolTip()} 来设置工具提示的简单方式,我们可通过如下方式将其用于按钮:
+
+ \snippet tutorials/addressbook/part6/addressbook.cpp tooltip 1
+ \dots
+ \snippet tutorials/addressbook/part6/addressbook.cpp tooltip 2
+
+ 虽然此处没有显示,但与其他应用的功能一样,我们在右侧的布局面板 \c button1Layout 上添加按钮,然后将按钮的 \l{QPushButton::clicked()}{clicked()} 信号与其相应的槽关联。
+
+ 至于保存功能,我们首先使用 QFileDialog::getSaveFileName() 获取 \c fileName。 这是 QFileDialog 提供的一个便捷功能,可弹出样式文件对话框并允许用户输入文件名或选择现有的 \c{.abk} 文件。\c{.abk} 文件是保存联系人时创建的地址簿扩展名。
+
+ \snippet tutorials/addressbook/part6/addressbook.cpp saveToFile() function part1
+
+ 弹出的文件对话框屏幕截图显示如下:
+
+ \image addressbook-tutorial-part6-save.png
+
+ 如果 \c fileName 不为空,我们就使用 \c fileName 创建 QFile 对象 \c file。 QFile 与 QDataStream 一同使用,这是因为QFile 是 QIODevice。
+
+ 接下来,我们尝试以 \l{QIODevice::}{WriteOnly} 模式打开文件。如果未能打开,会显示 QMessageBox 提示用户。
+
+ \snippet tutorials/addressbook/part6/addressbook.cpp saveToFile() function part2
+
+ 否则,会用实例表示 QDataStream 对象 \c out,以写入打开的文件。QDataStream 要求读写操作需使用相同版本的数据流。在将数据按顺序写入 \c file 之前,将使用的版本设置为\l{QDataStream::Qt_4_5}{采用 Qt 4.5 的版本}就可确保版本相同。
+
+ \snippet tutorials/addressbook/part6/addressbook.cpp saveToFile() function part3
+
+ 至于加载功能,我们也是使用 QFileDialog::getOpenFileName() 获取 \c fileName。该函数与 QFileDialog::getSaveFileName() 相对应,也是弹出样式文件对话框并允许用户输入文件名或选择现有的 \c{.abk} 文件加载到地址簿中。
+
+ \snippet tutorials/addressbook/part6/addressbook.cpp loadFromFile() function part1
+
+ 例如,在 Windows 上,该函数弹出本地文件对话框,如以下屏幕截图所示。
+
+ \image addressbook-tutorial-part6-load.png
+
+ 如果 \c fileName 不为空,还是使用 QFile 对象 \c file,然后尝试在 \l{QIODevice::}{ReadOnly} 模式下打开文件。与 \c saveToFile() 的应用方式类似,如果尝试失败,会显示 QMessageBox 提示用户。
+
+ \snippet tutorials/addressbook/part6/addressbook.cpp loadFromFile() function part2
+
+ 否则,会用实例表示 QDataStream 对象 \c in,按上文所述设置其版本,然后将按顺序排列的数据读入 \c contacts 数据结构。请注意,在将数据读入之前清空 \c contacts 可简化文件读取过程。更高级的方法是将联系人读取至临时 QMap 对象,然后仅复制 \c contacts 中不存在的联系人。
+
+ \snippet tutorials/addressbook/part6/addressbook.cpp loadFromFile() function part3
+
+ 要显示从文件中读取的联系人,必须要先验证获取的数据,以确保读取的文件实际包含地址簿联系人。如果为真,显示第一个联系人,否则显示 QMessageBox 提示出现问题。最后,我们更新界面以相应地启用和禁用按钮。
+*/
+
+/*!
+ \page tutorials-addressbook-part7.html
+ \previouspage 地址簿 6 — 加载和保存
+ \contentspage {地址簿教程}{目录}
+ \example tutorials/addressbook/part7
+ \title 地址簿 7 — 附加功能
+
+ 本章讲述了部分可使地址簿应用程序日常使用更加便捷的附加功能。
+
+ \image addressbook-tutorial-part7-screenshot.png
+
+ 虽然地址簿应用程序其自身功能已经很实用,但是如果可和其他应用程序互换联系人数据就会更加有益。vCard 格式是一种流行的文件格式,就可用于此目的。在本章中,我们会扩展地址簿客户端,可将联系人导出到 vCard \c{.vcf} 文件中。
+
+ \section1 定义 AddressBook 类
+
+ 我们在 \c addressbook.h 文件的 \c AddressBook 类中添加 QPushButton 对象 \c exportButton 以及对应的公有槽 \c exportAsVCard()。
+
+ \snippet tutorials/addressbook/part7/addressbook.h exportAsVCard() declaration
+ \dots
+ \snippet tutorials/addressbook/part7/addressbook.h exportButton declaration
+
+ \section1 应用 AddressBook 类
+
+ 在 \c AddressBook 构造器中,我们将 \c exportButton 的 \l{QPushButton::clicked()}{clicked()} 信号连接至 \c exportAsVCard()。我们还会将该按钮添加至 \c buttonLayout1,它是负责右侧按钮面板的布局类。
+
+ 在 \c exportAsVCard() 函数中,我们从提取 \c name 中联系人姓名开始入手。我们声明 \c firstName、\c lastName 和 \c nameList。接下来,我们查找 \c name 中第一处空白的索引。如果有空白,就将联系人的姓名分隔为 \c firstName 和 lastName。然后,将空白替换为下划线 ("_")。或者,如果没有空白,就认定联系人只有名字。
+
+ \snippet tutorials/addressbook/part7/addressbook.cpp export function part1
+
+ 至于 \c saveToFile() 函数,会打开文件对话框,让用户选择文件的位置。通过选择的文件名称,我们创建要写入的 QFile 实例。
+
+ 我们尝试以 \l{QIODevice::}{WriteOnly} 模式打开文件。如果操作失败,会显示 QMessageBox 提示用户出现问题并返回。否则,将文件作为参数传递给 QTextStream 对象 \c out。与 QDataStream 类似,QTextStream 类提供了读取纯文本和将其写入到文件的功能。因此,所生成的 \c{.vcf} 文件可以在文本编辑器中打开进行编辑。
+
+ \snippet tutorials/addressbook/part7/addressbook.cpp export function part2
+
+ 然后,我们写出依次带有 \c{BEGIN:VCARD} 和 \c{VERSION:2.1} 标记的 vCard 文件。联系人的姓名使用 \c{N:} 标记写入。至于写入 vCard “File as”属性的 FN: 标记,我们必须要查看是否联系人带有姓。如果联系人有姓,就使用 \c nameList 中的详细信息填入该标记。否则,仅写入 \c firstName。
+
+ \snippet tutorials/addressbook/part7/addressbook.cpp export function part3
+
+ 我们继续写入联系人的地址。地址中的分号使用 "\\" 进行转义,新行使用分号进行替换,而逗号使用空白进行替换。最后,我们依次写入 \c{ADR;HOME:;}、\c address 和 \c{END:VCARD} 标记。
+
+ \snippet tutorials/addressbook/part7/addressbook.cpp export function part4
+
+ 最后,会显示 QMessageBox 提示用户已成功导出 vCard。
+
+ \e{vCard 是 \l{http://www.imc.org}{Internet Mail Consortium} 的商标}。
+*/
diff --git a/doc/src/zh_CN/tutorials/widgets-tutorial.qdoc b/doc/src/zh_CN/tutorials/widgets-tutorial.qdoc
new file mode 100644