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
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML
><HEAD
><TITLE
>Session Management</TITLE
><META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet Version 1.54"/><LINK
REL="HOME"
TITLE="KDE 2.0 Development"
HREF="index.html"/><LINK
REL="UP"
TITLE="Further KDE Compliance"
HREF="ch07.html"/><LINK
REL="PREVIOUS"
TITLE="Application Configuration Information"
HREF="ch07lev1sec2.html"/><LINK
REL="NEXT"
TITLE="Application Resources"
HREF="ch07lev1sec4.html"/><META
HTTP-EQUIV="Content-Style-Type"
CONTENT="text/css"/><LINK
REL="stylesheet"
HREF="kde-common.css"
TYPE="text/css"/><META
HTTP-EQUIV="Content-Type"
CONTENT="text/html; charset=iso-8859-1"/><META
HTTP-EQUIV="Content-Language"
CONTENT="en"/><LINK
REL="stylesheet"
HREF="kde-localised.css"
TYPE="text/css"
TITLE="KDE-English"/><LINK
REL="stylesheet"
HREF="kde-default.css"
TYPE="text/css"
TITLE="KDE-Default"/></HEAD
><BODY
CLASS="section"
LINK="#336699"
VLINK="#336699"
ALINK="#336699"
BGCOLOR="#FFFFFF"
><DIV
ALIGN="RIGHT"
CLASS="NAVBAR"
><P
><A
HREF="ch07lev1sec2.html"
>Prev</A
> <A
HREF="ch07lev1sec4.html"
>Next</A
> <A
HREF="index.html"
>Table of Contents</A
></P
></DIV
><DIV
CLASS="section"
><TABLE
WIDTH="100%"
CELLPADDING="0"
CELLSPACING="0"
BORDER="0"
ALIGN="CENTER"
><TR
><TD
WIDTH="90%"
><H1
CLASS="section"
><A
NAME="ch07lev1sec3"
>7.3. Session Management</A
></H1
><P
>We touched on session management in <A
HREF="ch02.html"
>Chapter 2 <SPAN
CLASS="QUOTE"
>"A Simple KDE Application."</SPAN
></A
> You created <TT
CLASS="literal"
>KSimpleApp</TT
> and endowed it with the capability to be restarted and maintain its position and size across sessions. (<I
CLASS="emphasis"
>Session</I
> refers to the time between logging in and logging out.) Actually, this functionality was provided by <TT
CLASS="literal"
>KTMainWindow</TT
> from which the class <TT
CLASS="literal"
>KSimpleApp</TT
> was derived.</P
><P
>In general, you'll want to save more information across sessions than just the window position and size. <TT
CLASS="literal"
>KTMainWindow</TT
> offers the virtual methods <TT
CLASS="literal"
>saveProperties()</TT
> and <TT
CLASS="literal"
>readProperties()</TT
> for this purpose. Also, you will want to save the user's data (or at least offer this option) before a session exits. You reimplement the virtual method <TT
CLASS="literal"
>queryClose()</TT
> to do this. Listings 7.11–7.13 show the source code for KSaveAcross, an application that demonstrates these features.</P
><DIV
CLASS="example"
><HR/><A
NAME="ch07list11"
></A
><P
><B
>Example 7.11. ksaveacross.h: Class Declaration for <TT
CLASS="literal"
>KSaveAcross</TT
>, a Widget That Demonstrates Session Management Features of <TT
CLASS="literal"
>KTMainWindow</TT
></B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="programlisting"
> 1
2 1: #ifndef __KSAVEACROSS_H__
3 2: #define __KSAVEACROSS_H__
4 3:
5 4: #include <ktmainwindow.h>
6 5:
7 6: /**
8 7: * KSaveAcross
9 8: * This application saves its data across sessions. Its data is
10 9: * the contents of a QLineEdit.
11 10: **/
12 11: class KSaveAcross : public KTMainWindow
13 12: {
14 13: Q_OBJECT
15 14: public:
16 15: KSaveAcross (const char *name=0);
17 16:
18 17: public slots:
19 18: /**
20 19: * Change the font used by qlineedit.
21 20: **/
22 21: void slotChangeFont();
23 22:
24 23: protected:
25 24: QLineEdit *qlineedit;
26 25:
27 26: /**
28 27: * Ask the user if he/she wants to save the document.
29 28: **/
30 29: bool queryClose();
31 30:
32 31: /**
33 32: * Save the chosen font.
34 33: **/
35 34: void saveProperties (KConfig *kconfig);
36 35: /**
37 36: * Read the chosen font.
38 37: **/
39 38: void readProperties (KConfig *kconfig);
40 39:
41 40: };
42 41:
43 42: #endif</PRE
></TD
></TR
></TABLE
><HR/></DIV
><P
>The content area of the <TT
CLASS="literal"
>KSaveAcross</TT
> widget is a <TT
CLASS="literal"
>QLineEdit</TT
> widget. The menubar offers two choices: change the font used by the <TT
CLASS="literal"
>QLineEdit</TT
> widget or quit the application. The font chosen by the user is saved across sessions.</P
><DIV
CLASS="example"
><HR/><A
NAME="ch07list12"
></A
><P
><B
>Example 7.12. ksaveacross.cpp: Class Definition for <TT
CLASS="literal"
>KSaveAcross</TT
></B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="programlisting"
> 1
2 1: #include <kapp.h>
3 2: #include <kfontdialog.h>
4 3: #include <kstdaction.h>
5 4: #include <kaction.h>
6 5: #include <kmessagebox.h>
7 6: #include <kconfig.h>
8 7:
9 8: #include "ksaveacross.moc"
10 9:
11 10:
12 11: KSaveAcross::KSaveAcross (const char *name)
13 12: {
14 13: KStdAction::quit (kapp, SLOT (closeAllWindows()),
15 14: actionCollection());
16 15:
17 16: new KAction ("Change Font…", 0, this, SLOT(slotChangeFont()),
18 17: actionCollection(), "change_font");
19 18: createGUI();
20 19:
21 20: qlineedit = new QLineEdit (this);
22 21:
23 22: setView (qlineedit);
24 23: }
25 24:
26 25: void
27 26: KSaveAcross::slotChangeFont()
28 27: {
29 28: QFont qfont = qlineedit->font();
30 29:
31 30: if (KFontDialog::getFont (qfont))
32 31: qlineedit->setFont(qfont);
33 32: }
34 33:
35 34: bool
36 35: KSaveAcross::queryClose()
37 36: {
38 37:
39 38:
40 39: const int yes=0, no=1, cancel=2;
41 40: int yesnocancel;
42 41:
43 42: yesnocancel =
44 43: KMessageBox::
45 44: questionYesNo (this, "Save changes to document?", "ksaveacross");
46 45:
47 46: switch (yesnocancel)
48 47: {
49 48: case (yes):
50 49: //You would save the document here and let the application exit.
51 50: return true;
52 51: case (no):
53 52: //Let the application exit without saving the document.
54 53: return true;
55 54: case (cancel):
56 55: //Don't save, but don't let the application exit.
57 56: return false;
58 57: }
59 58: }
60 59:
61 60:
62 61: void
63 62: KSaveAcross::saveProperties (KConfig *kconfig)
64 63: {
65 64: kconfig->writeEntry ("LineEditorFont", qlineedit->font());
66 65: kconfig->sync();
67 66: }
68 67:
69 68: void
70 69: KSaveAcross::readProperties (KConfig *kconfig)
71 70: {
72 71: qlineedit->setFont (kconfig->readFontEntry ("LineEditorFont"));
73 72: }</PRE
></TD
></TR
></TABLE
><HR/></DIV
><P
>The method <TT
CLASS="literal"
>saveProperties()</TT
> (lines 61–66) is called just before the application is terminated by the session manager. If the user quits the application normally, the method is not called. When the session manager restarts the application at the beginning of the next session, the method <TT
CLASS="literal"
>readProperties()</TT
> is called. In these methods, you should save and read in properties that describe the current state of the application but that may not be saved in or specified in the configuration file. A Web browser, for example, might save the URL of the current page in the method <TT
CLASS="literal"
>saveProperties()</TT
>, although it wouldn't want to store this in the configuration file.</P
><P
><TT
CLASS="literal"
>saveProperties()</TT
> and <TT
CLASS="literal"
>readProperties()</TT
> work with <TT
CLASS="literal"
>KConfig</TT
> objects. These <TT
CLASS="literal"
>KConfig</TT
> objects do not operate on the default application configuration file. Instead, they operate on instance-specific configuration files created solely for the purpose of saving this session. The reading and writing methods were described in the previous section. Don't forget to call <TT
CLASS="literal"
>kconfig->sync()</TT
> (line 65) at the end of <TT
CLASS="literal"
>saveProperties()</TT
> to write the information to disk.</P
><P
>Before the application exits, it should ask the user whether he or she wishes to save the current document. If the application does this in the method <TT
CLASS="literal"
>queryClose()</TT
> (a virtual method of the class <TT
CLASS="literal"
>KTMainWindow</TT
>), the question is asked whether the application is closed by the user or by the session manager.</P
><P
>If <TT
CLASS="literal"
>queryClose()</TT
> returns <TT
CLASS="literal"
>3false</TT
>, the application does not exit. The reimplementation of <TT
CLASS="literal"
>queryClose()</TT
> in <TT
CLASS="literal"
>KSaveAcross</TT
> (line 34–58) presents the user with the choices Yes, No, and Cancel as answers to the question, <SPAN
CLASS="QUOTE"
>"Save changes to document?"</SPAN
> If the user answers Yes or No, <TT
CLASS="literal"
>queryClose()</TT
> returns <TT
CLASS="literal"
>true</TT
>, letting the application exit. If the user chooses Cancel, <TT
CLASS="literal"
>queryClose()</TT
> returns <TT
CLASS="literal"
>false</TT
> and the user can continue working.</P
><DIV
CLASS="note"
><TABLE
CLASS="note"
WIDTH="100%"
BORDER="0"
><TR
><TD
WIDTH="25"
ALIGN="CENTER"
VALIGN="TOP"
><IMG
SRC="note.png"
HSPACE="5"
ALT="Note"/></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
><P
>You'll need to create a file called ksaveacrossui.rc and place it in the directory $KDEDIR/share/apps/ksaveacross as explained in <A
HREF="ch05.html"
>Chapter 5, <SPAN
CLASS="QUOTE"
>"KDE User Interface Compliance"</SPAN
></A
>. A usable version of ksaveacrossui.rc is included with the code on this book's Web site.</P
></TD
></TR
></TABLE
></DIV
><P
><A
HREF="ch07lev1sec3.html#ch07list13"
>Listing 7.13</A
> provides the <TT
CLASS="literal"
>main()</TT
> function needed to create and start this application. Notice that I have included the session management code (lines 9–15), which was discussed in <A
HREF="ch02.html"
>Chapter 2</A
>. <A
HREF="ch07lev1sec3.html#ch07fig04"
>Figure 7.4</A
> shows running KSaveAcross.</P
><P
>To create an executable, you'll need the code in <A
HREF="ch07lev1sec3.html#ch07list13"
>Listing 7.13</A
>, and you'll need to place the GUI file, ksaveacrossui.rc (found on this book's web site), in the directory $KDEDIR/share/ kstatusbardemo.</P
><DIV
CLASS="example"
><HR/><A
NAME="ch07list13"
></A
><P
><B
>Example 7.13. main.cpp: A <TT
CLASS="literal"
>main()</TT
> Function Suitable for Testing <TT
CLASS="literal"
>KSaveAcross</TT
></B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="programlisting"
> 1
2 1: #include <kapp.h>
3 2:
4 3: #include "ksaveacross.h"
5 4:
6 5: int
7 6: main (int argc, char *argv[])/
8 7: {
9 8: KApplication kapplication (argc, argv, "ksaveacross");
10 9:
11 10: if (kapplication.isRestored())
12 11: RESTORE(KSaveAcross)
13 12: else
14 13: {
15 14: KSaveAcross *ksaveacross = new KSaveAcross;
16 15: ksaveacross->show();
17 16: }
18 17:
19 18: return kapplication.exec();
20 19: }</PRE
></TD
></TR
></TABLE
><HR/></DIV
><DIV
CLASS="figure"
><HR/><A
NAME="ch07fig04"
></A
><P
><B
>Figure 7.4. KSaveAcross saves its options across sessions and offers to save the user's data before it is closed.</B
></P
><DIV
CLASS="mediaobject"
><P
><IMG
SRC="graphics/07fig04.gif"
></IMG
></P
></DIV
><HR/></DIV
></TD
><TD
WIDTH="10%"
VALIGN="BOTTOM"
ALIGN="CENTER"
><ANNMARK
NAME="ch07lev1sec3"/></TD
></TR
><ANNOTATION
NAME="ch07lev1sec3"
TITLE="Session Management"/></TABLE
></DIV
><DIV
ALIGN="RIGHT"
CLASS="NAVBAR"
><P
><A
HREF="ch07lev1sec2.html"
>Prev</A
> <A
HREF="ch07lev1sec4.html"
>Next</A
> <A
HREF="index.html"
>Table of Contents</A
></P
></DIV
><HR
WIDTH="100%"
SIZE="2"
ALIGN="CENTER"
NOSHADE="NOSHADE"/></BODY
></HTML
>
|