Results 1 to 9 of 9

Thread: QtSingleApplication

  1. #1
    Join Date
    Feb 2006
    Posts
    22
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default QtSingleApplication

    (Qt user for 6 months, but this makes me realize I am still a newbie ...
    Thank you in advance for your assistance.)

    Environment:
    Qt 4.1.0
    Windows 2000 SP4
    Microsoft VC 6.0

    What is desired:
    I am using the QtSingleApplication class to guarantee only one instance of an application
    is running.

    When a second instance is started, I want the original instance to become the application
    of focus and the second instance to terminate.

    What is observed:
    The second instance terminates; however, the original instance does not gain
    the input focus. The original instance's taskbar button usually flashes, but its
    main window remains hidden behind other windows.

    vRaiseWindowForThisInst() is being called because the window title is changed.

    I have attempted to strip down the source files to the essentials ...

    File main.h:
    Qt Code:
    1. extern QtSingleApplication * pApp;
    To copy to clipboard, switch view to plain text mode 

    File main.cpp:
    Qt Code:
    1. QtSingleApplication * pApp;
    2.  
    3. int main( int argc, char * argv [] )
    4. {
    5. pApp = new QtSingleApplication( "UniqueName", argc, argv );
    6. if ( pApp->sendMessage( "RUNNING?" ) ) {
    7. return 0;
    8. }
    9. pApp->initialize();
    10.  
    11. pMain = new clMain();
    12.  
    13. return pApp->exec();
    14. }
    To copy to clipboard, switch view to plain text mode 

    File clMain.h:
    Qt Code:
    1. class clMain : public QMainWindow
    2. {
    3. Q_OBJECT
    4.  
    5. public:
    6. clMain( QWidget * parent = 0 );
    7. virtual ~clMain( void );
    8.  
    9. private:
    10. void vRaiseWindowForThisInst( void );
    11. void customEvent( QEvent * event );
    12.  
    13. private slots:
    14. void vMessageReceivedFromOtherInst( const QString & msg );
    15. };
    To copy to clipboard, switch view to plain text mode 

    File clMain.cpp:
    Qt Code:
    1. clMain::clMain( QWidget * parent )
    2. : QMainWindow( parent )
    3. {
    4. QPushButton * pExitAllButton = new QPushButton( "Exit All" );
    5. setCentralWidget( pExitAllButton );
    6.  
    7. connect( pExitAllButton, SIGNAL( clicked() ),
    8. this, SLOT( vExitAllPressed() ) );
    9.  
    10. connect( pApp, SIGNAL( messageReceived( const QString & ) ),
    11. this, SLOT( vMessageReceivedFromOtherInst( const QString & ) ) );
    12.  
    13. setWindowTitle( "Original Title" );
    14. show();
    15. }
    16.  
    17. clMain::~clMain( void )
    18. {
    19. ;
    20. }
    21.  
    22. void clMain::vRaiseWindowForThisInst( void )
    23. {
    24. setWindowTitle( "CHANGED TITLE" );
    25.  
    26. //setFocus( Qt::OtherFocusReason );
    27. //show();
    28. raise();
    29. }
    30.  
    31. enum QEvent::Type {
    32. Event_Main_Raise = QEvent::User + 1
    33. };
    34.  
    35. void clMain::customEvent( QEvent * event )
    36. {
    37. switch ( event->type() ) {
    38. default :
    39. QMainWindow::customEvent( event );
    40. break;
    41.  
    42. case Event_Main_Raise :
    43. vRaiseWindowForThisInst();
    44. break;
    45. }
    46. }
    47.  
    48. void clMain::vMessageReceivedFromOtherInst( const QString & msg )
    49. {
    50. QApplication::postEvent( this, new QEvent( Event_Main_Raise ) );
    51. }
    52.  
    53. void clMain::vExitAllPressed( void )
    54. {
    55. close();
    56. }
    To copy to clipboard, switch view to plain text mode 

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Thanks
    28
    Thanked 975 Times in 912 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QtSingleApplication

    Did you try to invoke the QWidget::activateWindow() method (together with raise())?

  3. #3
    Join Date
    Feb 2006
    Posts
    22
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QtSingleApplication

    Yes, I see I failed to copy&paste all the things I tried. Here they are:
    activateWindow();
    setFocus( Qt::OtherFocusReason );
    show();
    setWindowState( Qt::WindowActive );
    update();
    repaint();
    setVisible( true );
    raise();

    As you can see, I was getting frustrated/desperate/confused ...

  4. #4
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Thanks
    28
    Thanked 975 Times in 912 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QtSingleApplication

    According to the docs, you should call QWidget::setActiveWindow() (or rather QApplication::setActiveWindow() as it should be written):
    void QtSingleApplication::activateMainWidget () [virtual slot]
    Calls QWidget::setActiveWindow() on this application's mainWidget(). This function does nothing if no main widget has been set.
    This slot is typically connected to the messageReceived() signal.
    See also messageReceived().
    So such combo:
    Qt Code:
    1. show();
    2. raise();
    3. activateWindow();
    To copy to clipboard, switch view to plain text mode 
    should be enough. Maybe somebody else knows the answer, but you can always try the OS specific functions as the last resort.

  5. #5
    Join Date
    Feb 2006
    Posts
    22
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QtSingleApplication

    Thank you for your help, jacek, and thank you for redirecting me back to the doc. I had placed the doc aside a while back after many failed attempts and was just trying things by brute force and trial/error.

    I need to go back and re-think this from the beginning. The doc mentions setMainWidget() and its relation to activateMainWidget(). Since setMainWidget() was abandoned from Qt3 to Qt4 (I am using Qt4) I was trying to do the equivalent with QMainWindow, setCentralWidget(), and such.

    If/When I figure this out, I will post the solution.

    Other input/thoughts/suggestions still welcome ...

  6. #6
    Join Date
    Feb 2006
    Posts
    22
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default QtSingleApplication with Qt4

    (Admin: Originally posted in Newbie forum, but now believe beyond that. If this violates forum policy, please pull this thread. However, this post does contain more complete information and code.)

    Qt 4.1.0 / Ms VC 6.0 / Windows 2000 SP4.

    What: Using QtSingleApplication class to guarantee single instance of application.
    Desired: When second instance starts, it should terminate and the original instance should become the application of focus.
    Observed: When the second instance starts, it terminates; however, the original instance is not brought forward as the application of focus.

    The QtSingleApplication doc states that activateMainWidget() ...
    Calls QWidget::setActiveWindow() on this application's mainWidget(). This function does nothing if no main widget has been set.
    The example in the doc also shows setMainWidget() being invoked by main().

    Questions:
    1) Since setMainWidget() was removed from Qt3 to Qt4, is QMainWindow::setCentralWidget() not functionally equivalent? If it is not, what is?
    2) Since this Solution was only tested using Qt 4.1.1 and I am using 4.1.0, is this a version issue? (I did not see anything in the changelog for 4.1.1 that would indicate this.) (I cannot go to 4.1.1 at this time.)

    File main.h
    Qt Code:
    1. #ifndef _main_h_
    2. #define _main_h_
    3.  
    4. #include <QtSingleApplication>
    5.  
    6. extern QtSingleApplication * pApp;
    7.  
    8. #endif //_main_h_
    To copy to clipboard, switch view to plain text mode 

    File main.cpp
    Qt Code:
    1. #include "main.h"
    2.  
    3. #include "clMain.h"
    4.  
    5. QtSingleApplication * pApp;
    6.  
    7. int main( int argc, char * argv [] )
    8. {
    9. pApp = new QtSingleApplication( "UniqueName", argc, argv );
    10. if ( pApp->sendMessage( "RUNNING?" ) ) {
    11. return 0;
    12. }
    13. pApp->initialize();
    14.  
    15. pMain = new clMain();
    16.  
    17. return pApp->exec();
    18. }
    To copy to clipboard, switch view to plain text mode 

    File CustomEvent.h
    Qt Code:
    1. #ifndef _customevent_h_
    2. #define _customevent_h_
    3.  
    4. #include <QEvent>
    5.  
    6. enum QEvent::Type {
    7. Event_Main_Raise = QEvent::User + 1
    8. };
    9.  
    10. #endif //_customevent_h_
    To copy to clipboard, switch view to plain text mode 

    File clMain.h
    Qt Code:
    1. #ifndef _clMain_h_
    2. #define _clMain_h_
    3.  
    4. #include <QMainWindow>
    5. #include <QWidget>
    6. #include <QPushButton>
    7.  
    8. class clMain : public QMainWindow
    9. {
    10. Q_OBJECT
    11.  
    12. public:
    13.  
    14. clMain( QWidget * parent = 0 );
    15. virtual ~clMain( void );
    16.  
    17. private:
    18.  
    19. QPushButton * pExitAllButton;
    20. QWidget * pMainWidget;
    21.  
    22. void vRaiseWindowForThisInst( void );
    23.  
    24. void customEvent( QEvent * event );
    25.  
    26. private slots:
    27.  
    28. void vMessageReceivedFromOtherInst( void );
    29.  
    30. void vExitAllClicked( void );
    31. };
    32.  
    33. extern clMain * pMain;
    34.  
    35. #endif //_clMain_h_
    To copy to clipboard, switch view to plain text mode 

    File clMain.cpp
    ( NOTE to all the #define options:
    Used to select one of many attempts.
    Set ONLY ONE non-zero at a time.
    See connect() attempts in clMain().
    See various method attempts in vRaiseWindowForThisInst(). )
    Qt Code:
    1. // != 0 -> use activateMainWidget() directly
    2. // == 0 -> use indirect method (following ...)
    3. #define _dir_activateMainWidget 0
    4.  
    5. // indirectly ...
    6.  
    7. // != 0 -> use activateMainWidget()
    8. #define _indir_activateMainWidget 0
    9.  
    10. // indirectly on this ...
    11.  
    12. // != 0 -> use show(); raise(); activateWindow()
    13. #define _indir_this_show_raise_activateWindow 0
    14. // != 0 -> use show(); raise(); activateWindow(); setFocus()
    15. #define _indir_this_show_raise_activateWindow_setFocus 0
    16. // != 0 -> use setWindowState(); show(); raise(); activateWindow()
    17. #define _indir_this_setWindowState_show_raise_activateWindow 0
    18. // != 0 -> use setWindowState(); show(); raise(); activateWindow(); setFocus()
    19. #define _indir_this_setWindowState_show_raise_activateWindow_setFocus 1
    20.  
    21. // indirectly on pMainWidget widget ...
    22.  
    23. // != 0 -> use show(); raise(); activateWindow()
    24. #define _indir_MainWidget_show_raise_activateWindow 0
    25. // != 0 -> use show(); raise(); activateWindow(); setFocus()
    26. #define _indir_MainWidget_show_raise_activateWindow_setFocus 0
    27. // != 0 -> use setWindowState(); show(); raise(); activateWindow()
    28. #define _indir_MainWidget_setWindowState_show_raise_activateWindow 0
    29. // != 0 -> use setWindowState(); show(); raise(); activateWindow(); setFocus()
    30. #define _indir_MainWidget_setWindowState_show_raise_activateWindow_setFocus 0
    31.  
    32. // indirectly on pExitAllButton button ...
    33.  
    34. // != 0 -> use show(); raise(); activateWindow()
    35. #define _indir_ExitAllButton_show_raise_activateWindow 0
    36. // != 0 -> use show(); raise(); activateWindow(); setFocus()
    37. #define _indir_ExitAllButton_show_raise_activateWindow_setFocus 0
    38.  
    39. #include "clMain.h"
    40.  
    41. #include "Main.h"
    42. #include "CustomEvent.h"
    43. #include <QGridLayout>
    44.  
    45. clMain * pMain = 0;
    46.  
    47. clMain::clMain( QWidget * parent )
    48. : QMainWindow( parent )
    49. {
    50. pExitAllButton = new QPushButton( "Exit All" );
    51.  
    52. QGridLayout * pLayout = new QGridLayout;
    53. pLayout->addWidget( pExitAllButton, 0, 0, 1, 1 );
    54.  
    55. pMainWidget = new QWidget();
    56. pMainWidget->setLayout( pLayout );
    57.  
    58. setCentralWidget( pMainWidget );
    59.  
    60. connect( pExitAllButton, SIGNAL( clicked() ),
    61. this, SLOT( vExitAllClicked() ) );
    62.  
    63. #if _dir_activateMainWidget
    64. connect( pApp, SIGNAL( messageReceived( const QString & ) ),
    65. pApp, SLOT( activateMainWidget() ) );
    66. #else //_USE_activateMainWidget
    67. connect( pApp, SIGNAL( messageReceived( const QString & ) ),
    68. this, SLOT( vMessageReceivedFromOtherInst() ) );
    69. #endif //_USE_activateMainWidget
    70.  
    71. setWindowTitle( "Original Title" );
    72. show();
    73. }
    74.  
    75. clMain::~clMain( void )
    76. {
    77. ;
    78. }
    79.  
    80. void clMain::vRaiseWindowForThisInst( void )
    81. {
    82. // indirectly ...
    83.  
    84. #if _indir_activateMainWidget
    85. setWindowTitle( "** CHANGED #1 **" );
    86.  
    87. pApp->activateMainWidget();
    88. #endif
    89.  
    90. // indirectly on this ...
    91.  
    92. #if _indir_this_show_raise_activateWindow
    93. setWindowTitle( "** CHANGED #2a **" );
    94.  
    95. show();
    96. raise();
    97. activateWindow();
    98. #endif
    99.  
    100. #if _indir_this_show_raise_activateWindow_setFocus
    101. setWindowTitle( "** CHANGED #3a **" );
    102.  
    103. show();
    104. raise();
    105. activateWindow();
    106.  
    107. setFocus( Qt::OtherFocusReason );
    108. #endif
    109.  
    110. #if _indir_this_setWindowState_show_raise_activateWindow
    111. setWindowTitle( "** CHANGED #4a **" );
    112.  
    113. setWindowState( ( windowState() & ~ Qt::WindowMinimized ) | Qt::WindowActive );
    114.  
    115. show();
    116. raise();
    117. activateWindow();
    118. #endif
    119.  
    120. #if _indir_this_setWindowState_show_raise_activateWindow_setFocus
    121. setWindowTitle( "** CHANGED #5a **" );
    122.  
    123. setWindowState( ( windowState() & ~ Qt::WindowMinimized ) | Qt::WindowActive );
    124.  
    125. show();
    126. raise();
    127. activateWindow();
    128.  
    129. setFocus( Qt::OtherFocusReason );
    130. #endif
    131.  
    132. // indirectly on pMainWidget widget ...
    133.  
    134. #if _indir_MainWidget_show_raise_activateWindow
    135. setWindowTitle( "** CHANGED #2b **" );
    136.  
    137. pMainWidget->show();
    138. pMainWidget->raise();
    139. pMainWidget->activateWindow();
    140. #endif
    141.  
    142. #if _indir_MainWidget_show_raise_activateWindow_setFocus
    143. setWindowTitle( "** CHANGED #3b **" );
    144.  
    145. pMainWidget->show();
    146. pMainWidget->raise();
    147. pMainWidget->activateWindow();
    148.  
    149. pMainWidget->setFocus( Qt::OtherFocusReason );
    150. #endif
    151.  
    152. #if _indir_MainWidget_setWindowState_show_raise_activateWindow
    153. setWindowTitle( "** CHANGED #4b **" );
    154.  
    155. pMainWidget->setWindowState(
    156. ( pMainWidget->windowState() & ~ Qt::WindowMinimized ) | Qt::WindowActive );
    157.  
    158. pMainWidget->show();
    159. pMainWidget->raise();
    160. pMainWidget->activateWindow();
    161. #endif
    162.  
    163. #if _indir_MainWidget_setWindowState_show_raise_activateWindow_setFocus
    164. setWindowTitle( "** CHANGED #5b **" );
    165.  
    166. pMainWidget->setWindowState(
    167. ( pMainWidget->windowState() & ~ Qt::WindowMinimized ) | Qt::WindowActive );
    168.  
    169. pMainWidget->show();
    170. pMainWidget->raise();
    171. pMainWidget->activateWindow();
    172.  
    173. pMainWidget->setFocus( Qt::OtherFocusReason );
    174. #endif
    175.  
    176. // indirectly on pExitAllButton button ...
    177.  
    178. #if _indir_ExitAllButton_show_raise_activateWindow
    179. setWindowTitle( "** CHANGED #2c **" );
    180.  
    181. pExitAllButton->show();
    182. pExitAllButton->raise();
    183. pExitAllButton->activateWindow();
    184. #endif
    185.  
    186. #if _indir_ExitAllButton_show_raise_activateWindow_setFocus
    187. setWindowTitle( "** CHANGED #3c **" );
    188.  
    189. pExitAllButton->show();
    190. pExitAllButton->raise();
    191. pExitAllButton->activateWindow();
    192.  
    193. pExitAllButton->setFocus( Qt::OtherFocusReason );
    194. #endif
    195. }
    196.  
    197. void clMain::customEvent( QEvent * event )
    198. {
    199. switch ( event->type() ) {
    200. default :
    201. QMainWindow::customEvent( event );
    202. break;
    203.  
    204. case Event_Main_Raise :
    205. vRaiseWindowForThisInst();
    206. break;
    207. }
    208. }
    209.  
    210. void clMain::vMessageReceivedFromOtherInst( void )
    211. {
    212. QApplication::postEvent( this, new QEvent( Event_Main_Raise ) );
    213. }
    214.  
    215. void clMain::vExitAllClicked( void )
    216. {
    217. close();
    218. }
    To copy to clipboard, switch view to plain text mode 

  7. #7
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Thanks
    28
    Thanked 975 Times in 912 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QtSingleApplication with Qt4

    Quote Originally Posted by mule
    Originally posted in Newbie forum, but now believe beyond that. If this violates forum policy, please pull this thread. However, this post does contain more complete information and code.
    Next time, please, just ask to move the thread instead of starting a new one.

    Quote Originally Posted by mule
    1) Since setMainWidget() was removed from Qt3 to Qt4, is QMainWindow::setCentralWidget() not functionally equivalent?
    No, QMainWindow::setCentralWidget() just sets the central widget for the main window (i.e. the widget that fills the area between toolbars and statusbar).

    Quote Originally Posted by mule
    Since this Solution was only tested using Qt 4.1.1 and I am using 4.1.0, is this a version issue?
    It looks like the solution itself works. This might be a problem with Qt itself (a bug or limitation).

  8. #8
    Join Date
    Jan 2006
    Location
    Mountain View, CA
    Posts
    279
    Thanked 42 Times in 37 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QtSingleApplication

    Quote Originally Posted by mule
    What is observed:
    The second instance terminates; however, the original instance does not gain
    the input focus. The original instance's taskbar button usually flashes, but its
    main window remains hidden behind other windows.
    There's no bug in your code. It's a restriction of Windows 2000 onwards, see here:

    http://msdn.microsoft.com/library/de...oundwindow.asp
    Save yourself some pain. Learn C++ before learning Qt.

  9. #9
    Join Date
    Feb 2006
    Posts
    22
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QtSingleApplication

    That's it! Thank you, Chicken Blood Machine. I will design a different approach.
    (Anybody know of any hair-restoring products?)

Similar Threads

  1. Replies: 10
    Last Post: 11th June 2007, 10:18
  2. QtSingleApplication and Qr 4.2.1
    By Lele in forum Qt Programming
    Replies: 1
    Last Post: 23rd October 2006, 11:41

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.