Archive:Development/Tutorials/Session Management (zh CN)

    From KDE TechBase
    Revision as of 08:56, 14 September 2009 by Hualiang.miao (talk | contribs)


    Development/Tutorials/Session Management


    Template:TutorialBrowser (zh CN)

    关于KDE和X11的会话管理

    从KDE 1.0起,遗留的X11R4和ICCCM会话管理协议就被支持着。Legacy applications that define the WM_COMMAND property or support the WM_SAVE_YOURSELF protocol will be restarted with the specified command. The window geometries will be restored on a best effort basis.

    Since KDE 2.0, also the standard X11R6 session management protocol XSMP is supported and used. The official documentation of the standard can be download from the X Consortium's FTP server ftp.x.org. Unlike the legacy protocols, the new X11R6 session management gives a chance to save application dependent settings when you log out. A text editor, for instance, would save the names of the loaded files and would reload them when you log in again. Another major advantage of the new protocol is the support for a clean and safe logout procedure even if the users decides not to restore the session next time. The protocol gives applications the possibility to interact with the user in case they are in danger to lose some data, and to cancel the shutdown process if necessary.

    更多阅读

    An introductive overview of session management functionality and the Qt API for it is available from doc.trolltech.com.

    In KDE, the classes KApplication and KMainWindow hide all the ugly details from the programmer. Basically, a KApplication manages a KConfig configuration object (available trought KApplication::sessionConfig()) for you, that your application can utilize to store session specific data.

    Please read the respective class documentation, especially the one of KMainWindow, for a detailed interface description. With the advanced functionality in KMainWindow, it's really just a matter of a few lines to get even a multi-window application to retains its state between different user sessions.

    在你的应用中实现会话管理

    Here's just a brief overview how things are done. Again, see the respective class documentation for details.

    Implementing session management in KDE is easy. If your main window inherits from KMainWindow, you have just 2 things to do:

    • Reimplement some virtual functions of KMainWindow.
    • Add session management support to your main() function.

    That's all.

    重写KMainWindow的虚函数

    KMainWindow will automatically save its position, geometry and positions of toolbars and menubar on logout - and restore it on the next startup.

    For every other data that your application needs to restore a session, you have to write the code for saving and restoring yourself. However, KMainWindow makes this task easy. You can just re-implement the following functions:

    • saveProperties(): This function is called only when the application is closed by the session manager (and not, when the application is closed by the user). To save the data that you need to restore the session, reimplement this function. (For a text editor for example, that would be the list of loaded files) Note that no user interaction is allowed in this function! (For example, you may not display any dialog!)
    • readProperties(): To read the additional data again on next login, reimplement this function.

    Furthermore, the function queryClose() could be interesting for you. This function is called always before the window is closed, either by the user or indirectly by the session manager. Typically, here you can warn the user that the application or some windows have unsaved data on close or logout (for example: show a dialog with the buttons "Save changes" and "Discard changes"). However, for session management it isn't nice to request a user interaction before closing, so you better avoid this. Note that it is not determined if saveProperties() is called before or after queryClose()!

    To save your application-wide properties (data that is only needed once per application, and not for each main window instance) reimplement saveGlobalProperties() and it's counterpart readGlobalProperties. Normally, you don't need these functions.

    给你的main()函数添加会话管理

    While KMainWindow::saveProperties() (and also KMainWindow::queryClose()) will be called automatically, KMainWindow::readProperties() will not. You have to add some code to your main() function to implement session restoring.

    如果你的应用有一个主窗口,MyWindow,他继承与 KMainWindow (或从 KXmlGuiWindow, 他继承于 KMainWindow)。在你的main()函数内,要加上下列代码来创建/恢复窗口:

    KApplication app; if ( app.isSessionRestored() ) {

     kRestoreMainWindows< MyWindow >();
    

    } else {

     // create default application as usual
     // for example:
     MyWindow * window = new MyWindow();
     // # will be replaced with numbers that are guaranteed
     // to be unique in the application:
     window->setObjectName("MyWindow#");
     window->show();
    

    } return app.exec();

    kRestoreMainWindows<>() will create (on the heap) as many instances of your main windows as have existed in the last session and call KMainWindow::restore() with the correct arguments. Note that also QWidget::show() is called implicitly.

    关于setObjectName("MyWindow#"): For session management and window management to work properly, all main windows in the application should have a different name. If you don't do it, KMainWindow will create a unique name, but it's recommended to explicitly pass a window name that will also describe the type of the window. If there can be several windows of the same type, append '#' (hash) to the name, and KMainWindow will replace it with numbers to make the names unique. For example, for a mail client which has one main window showing the mails and folders, and which can also have one or more windows for composing mails, the name for the folders window should be e.g. "mainwindow" and for the composer windows "composer#".

    With this you can easily restore all toplevel windows of your application.

    It is also possible to restore different types of toplevel windows (each derived from KMainWindow, of course) within one application. Imagine you have three classes of main windows: childMW1, childMW2 and childMW3:

    KApplication app; if ( app.isSessionRestored() ) {

     kRestoreMainWindows< childMW1, childMW2, childMW3 >();
    

    } else {

     // create default application as usual
     // for example:
     childMW1* window1 = new childMW1();
     childMW2* window2 = new childMW2();
     childMW3* window3 = new childMW3();
     // # will be replaced with numbers that are guaranteed
     // to be unique in the application:
     window1->setObjectName("type1mainWindow#");
     window2->setObjectName("type2mainWindow#");
     window3->setObjectName("type3mainWindow#");
     window1->show();
     window2->show();
     window3->show();
    

    } return app.exec();

    当前,kRestoreMainWindows<>() 函数模板提供了至多三个参数。

    附录: KDE会话管理的架构

    在KDE中,会话管理服务器称为KSMServer,它是在KDEBbase包的一部分。 KSMServer服务器与与KDE的窗口管理器KWin相互作用,以保存和还原窗口的几何尺寸和执行旧会话管理。为了使会话管理有效,KSMSserver必须是X登录过程的最后一个进程。这会自动在startkde脚本的末尾执行。

    初始作者: Matthias Ettrich