Archive:Development/Tutorials/Session Management (zh CN): Difference between revisions

    From KDE TechBase
    No edit summary
    No edit summary
    Line 1: Line 1:
    {{Template:I18n/Language Navigation Bar|Development/Tutorials/Session Management}}
    {{Template:I18n/Language Navigation Bar|Development/Tutorials/Session Management}}


    ==关于KDE和X11会话管理==
    {{TutorialBrowser|
    从KDE 1.0以来, 遗留的X11R4和ICCCM回话管理协议仍然被支持者。Legacy applications that define the <tt>WM_COMMAND</tt>
     
    series=Basics|
     
    name=Session Management|
     
    pre=[[Development/Tutorials/Creating_Libraries|Creating Libraries]]|
     
    next=|
     
    reading=[http://doc.trolltech.com/4.4/session.html Session Management in the Qt documentation]; [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html KMainWindow]; [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKApplication.html KApplication]
    }}
     
    ==About KDE and X11 session management==
     
    Since KDE 1.0, the legacy X11R4 and ICCCM session management protocols
    are supported. Legacy applications that define the <tt>WM_COMMAND</tt>
    property or support the <tt>WM_SAVE_YOURSELF</tt> protocol will be restarted
    property or support the <tt>WM_SAVE_YOURSELF</tt> protocol will be restarted
    with the specified command.  The window geometries will be restored on a best
    with the specified command.  The window geometries will be restored on a best
    Line 10: Line 25:
    is supported and used. The official documentation of the
    is supported and used. The official documentation of the
    standard can be download from the X Consortium's FTP server  
    standard can be download from the X Consortium's FTP server  
    [http://stuff.mit.edu/afs/sipb/contrib/doc/X11/hardcopy/SM/xsmp.PS.gz ftp.x.org]. Unlike these legacy protocols, the new X11R6
    [http://stuff.mit.edu/afs/sipb/contrib/doc/X11/hardcopy/SM/xsmp.PS.gz ftp.x.org]. Unlike the legacy protocols, the new X11R6
    session management gives a chance to save application
    session management gives a chance to save application
    dependent settings when you log out.  A text
    dependent settings when you log out.  A text
    Line 20: Line 35:
    danger to lose some data, and to cancel the shutdown process if necessary.
    danger to lose some data, and to cancel the shutdown process if necessary.


    ==更多阅读==
    ==Further Reading==


    An introductive overview of session management functionality and
    An introductive overview of session management functionality and
    Line 29: Line 44:
    hide all the ugly details from the programmer. Basically, a
    hide all the ugly details from the programmer. Basically, a
    [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKApplication.html KApplication] manages a
    [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKApplication.html KApplication] manages a
    [http://api.kde.org/4.x-api/kdelibs-apidocs/kdecore/html/classKConfig.html KConfig] configuration object
    [http://api.kde.org/4.x-api/kdelibs-apidocs/kdecore/html/classKConfig.html KConfig] configuration object (available trought
    [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKApplication.html#8f88369c240d6d90a04d29b2761989d9 sessionConfig()]
    [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKApplication.html#8f88369c240d6d90a04d29b2761989d9 KApplication::sessionConfig()])
    for you, that your application can utilize to store session specific data.
    for you, that your application can utilize to store session specific data.


    Line 38: Line 53:
    different user sessions.
    different user sessions.


    ==在应用程序中实现会话管理==
    ==Implementing session management in your application==


    这里只是做一个简单的介绍,详细内容请见具体类文档。
    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 [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html KMainWindow], you have just 2 things to do:
    Implementing session management in KDE is easy. If your main window inherits from [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html KMainWindow], you have just 2 things to do:
    Line 47: Line 63:
    That's all.
    That's all.


    ===实现KMainWindow的几个虚函数===
    ===Reimplement some virtual functions of KMainWindow===
     
    [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html 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, [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html KMainWindow] makes this task easy. You can just re-implement the following functions:
    * [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#4c7a6c395eec0bb245cd9ad6c884f897 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!)
    * [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#c8d0d64ed5b309ba1da410423120d0a6 readProperties()]: To read the additional data again on next login, reimplement this function.


    [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html KMainWindow]会保存它的位置,几何状态以及工具栏,菜单的相对位置。
    Furthermore, the function [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#f8c5708414be62f259114b0453ef8432 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 [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#4c7a6c395eec0bb245cd9ad6c884f897 saveProperties()] is called before or after [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#f8c5708414be62f259114b0453ef8432 queryClose()]!
    * 在用户退出或关闭程序时,提醒用户保存数据(例如: 显示一个忽略变更的对话框,上面有一个“保存”的按钮), 重新编写[http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#f8c5708414be62f259114b0453ef8432 queryClose()]方法。
    * 保存额外信息, 重新实现[http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#4c7a6c395eec0bb245cd9ad6c884f897 saveProperties()]. (对一个文字编辑器来说,这就是已经加载的文件。)注意,用户不应该对这个函数有干扰。就是说,程序中更本就没有什么对话框。
    * 下次登陆时读取一些额外信息,重新实现[http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#c8d0d64ed5b309ba1da410423120d0a6 readProperties()].
    [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html KMainWindow]会自动调用这些方法函数,当然有会话管理器控制。Note that it is not determined if [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#4c7a6c395eec0bb245cd9ad6c884f897 saveProperties()] is called before or after [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#f8c5708414be62f259114b0453ef8432 queryClose()]! 重写之前请仔细阅读相关文档。


    保存应用程序级属性(这些数据只要以此就可以了,不必每次每个都加载),重写[http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#cf811d77a3acdcf2b61f8826429615a7 saveGlobalProperties()] 以及相关的[http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#2d4da4f305f00e8a5c94f5b978334231 readGlobalProperties]。通常,你不需要这些函数方法。
    ''To save your application-wide properties (data that is only needed once per application, and not for each main window instance) reimplement [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#cf811d77a3acdcf2b61f8826429615a7 saveGlobalProperties()] and it's counterpart [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#2d4da4f305f00e8a5c94f5b978334231 readGlobalProperties].  Normally, you don't need these functions.''


    ===在main()函数添加会话管理===
    ===Add session management support to your main() function===


    [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#4c7a6c395eec0bb245cd9ad6c884f897 KMainWindow::saveProperties()] [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#f8c5708414be62f259114b0453ef8432 KMainWindow::queryClose()]是系统自有的,[http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#c8d0d64ed5b309ba1da410423120d0a6 KMainWindow::readProperties()]不是。你的在main()加几行代码来实现会话取回。
    While [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#4c7a6c395eec0bb245cd9ad6c884f897 KMainWindow::saveProperties()] (and also [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#f8c5708414be62f259114b0453ef8432 KMainWindow::queryClose()]) will be called automatically, [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html#c8d0d64ed5b309ba1da410423120d0a6 KMainWindow::readProperties()] will not. You have to add some code to your main() function to implement session restoring.


    Imagine you have an
    Imagine you have an
    Line 66: Line 84:
    [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKXmlGuiWindow.html KXmlGuiWindow], which inherits from
    [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKXmlGuiWindow.html KXmlGuiWindow], which inherits from
    [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html KMainWindow]). In your main() function, you would then create/restore the
    [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/classKMainWindow.html KMainWindow]). In your main() function, you would then create/restore the
    application windows with something like:
    application windows with something like this:


    <code cppqt>
    <code cppqt>
    Line 88: Line 106:
    About 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#".
    About 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
    It is also possible to restore different types of toplevel windows (each
    Line 115: Line 133:
    </code>
    </code>


    现在, [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/kmainwindow_8h.html#88ce427e39f425eefa5a94d746eb2bed kRestoreMainWindows<>()]的方法模版提供最多三个模版参数。
    Currently, the [http://api.kde.org/4.x-api/kdelibs-apidocs/kdeui/html/kmainwindow_8h.html#88ce427e39f425eefa5a94d746eb2bed kRestoreMainWindows<>()] template functions are provided for up to three template arguments.


    ==附录: KDE会话管理架构==
    ==Appendix: Architecture of the KDE session manager==


    KDE的会话管理服务器叫做'''ksmserver''',他是'''kdebase'''的一部分。服务进程与KDE的窗口管理服务进程'''kwin'''进行交互,保存和恢复窗口信息,进行遗留的会话管理。 要启用会话管理, '''ksmserver'''必须X登陆过程的最后一个进程。这个会在'''startkde'''脚本的末尾体现.
    The session management server in KDE is called '''ksmserver''' and it is
    part of the '''kdebase''' package.  The server interacts with the KDE window
    manager '''kwin''' to save and restore the window geometries and to perform
    legacy session management.  To make session management work, '''ksmserver'''
    has to be started as last process of the X login procedure. This happens
    automatically at the end of the '''startkde''' script.




    ''初始作者:'' [mailto:[email protected] Matthias Ettrich]
    ''Initial Author:'' [mailto:[email protected] Matthias Ettrich]


    [[Category:Programming]]
    [[Category:Programming]]
    [[Category:Tutorial]]
    [[Category:Tutorial]]
    [[Category:FAQs]]
    [[Category:FAQs]]

    Revision as of 03:53, 13 September 2009


    Development/Tutorials/Session Management


    Session Management
    Tutorial Series   Basics
    Previous   Creating Libraries
    What's Next  
    Further Reading   Session Management in the Qt documentation; KMainWindow; KApplication

    About KDE and X11 session management

    Since KDE 1.0, the legacy X11R4 and ICCCM session management protocols are supported. 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.

    Further Reading

    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.

    Implementing session management in your application

    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.

    Reimplement some virtual functions of 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.

    Add session management support to your main() function

    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.

    Imagine you have an application with a main window MyWindow inherited from KMainWindow (or from KXmlGuiWindow, which inherits from KMainWindow). In your main() function, you would then create/restore the application windows with something like this:

    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.

    About 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();

    Currently, the kRestoreMainWindows<>() template functions are provided for up to three template arguments.

    Appendix: Architecture of the KDE session manager

    The session management server in KDE is called ksmserver and it is part of the kdebase package. The server interacts with the KDE window manager kwin to save and restore the window geometries and to perform legacy session management. To make session management work, ksmserver has to be started as last process of the X login procedure. This happens automatically at the end of the startkde script.


    Initial Author: Matthias Ettrich