Ticket #31: basket-tray-screenshot.patch

File basket-tray-screenshot.patch, 13.3 kB (added by amroth, 14 months ago)

Adds a screenshot of the tray with KMess icon to the on window close warning dialog

  • kmess/kmess.cpp

     
    138138  delete notificationContactStatus_; 
    139139  delete notificationNewEmail_; 
    140140  delete nowListeningClient_; 
    141   delete systemTrayWidget_; 
    142141  delete msnNotificationConnection_; 
    143142  CurrentAccount::destroy(); 
    144143 
     
    13051304    kdDebug() << "KMess - Couldn't initialize the KMessView widget." << endl; 
    13061305    return false; 
    13071306  } 
    1308   if ( !initSystemTrayWidget() ) 
    1309   { 
    1310     kdDebug() << "KMess - Couldn't initialize the system tray widget." << endl; 
    1311     return false; 
    1312   } 
    13131307  if ( !initNotifications() ) 
    13141308  { 
    13151309    kdDebug() << "KMess - Couldn't initialize the notifications." << endl; 
     
    17331727} 
    17341728 
    17351729 
    1736 // Initialize the system tray widget 
    1737 bool KMess::initSystemTrayWidget() 
    1738 { 
    1739   bool initialized; 
    17401730 
    1741   // Create the widget 
    1742   systemTrayWidget_ = new SystemTrayWidget( this, "systemtraywidget" ) ; 
    1743   if ( systemTrayWidget_ == 0 ) 
    1744   { 
    1745     kdDebug() << "KMess - Couldn't create system tray widget." << endl; 
    1746     return false; 
    1747   } 
    1748  
    1749   // Initialize the widget 
    1750   initialized = systemTrayWidget_->initialize(); 
    1751   if ( !initialized ) 
    1752   { 
    1753     kdDebug() << "KMess - Couldn't initialize system tray widget." << endl; 
    1754     return false; 
    1755   } 
    1756  
    1757   // Plug some of the menu actions into the system tray widget's menu. 
    1758   connectActionMenu_-> plug( systemTrayWidget_->menu() ); 
    1759   disconnect_->        plug( systemTrayWidget_->menu() ); 
    1760   systemTrayWidget_->  menu()->insertSeparator(); 
    1761   status_->            plug( systemTrayWidget_->menu() ); 
    1762   systemTrayWidget_->  menu()->insertSeparator(); 
    1763   settingsActionMenu_->plug( systemTrayWidget_->menu() ); 
    1764  
    1765   // Make the connections for the system tray widget 
    1766   connect( systemTrayWidget_, SIGNAL( quitSelected() ), 
    1767            this,              SLOT  (     menuQuit() ) ); 
    1768  
    1769   systemTrayWidget_->show(); 
    1770 #ifdef KMESSTEST 
    1771   ASSERT( systemTrayWidget_ != 0 ); 
    1772   ASSERT( systemTrayWidget_->isVisible() ); 
    1773 #endif 
    1774   return true; 
    1775 } 
    1776  
    1777  
    1778  
    17791731// Validate a contact email 
    17801732bool KMess::isValidEmail( QString email ) 
    17811733{ 
  • kmess/kmess.h

     
    4646class KMessTest; 
    4747class KMessView; 
    4848class MsnNotificationConnection; 
    49 class SystemTrayWidget; 
    5049class NowListeningClient; 
    5150 
    5251/** 
     
    107106    bool               initNotifications(); 
    108107    // Initialize the now listening support. 
    109108    bool               initNowListening(); 
    110     // Initialize the system tray widget 
    111     bool               initSystemTrayWidget(); 
    112109    // Validate a contact email 
    113110    bool               isValidEmail( QString email ); 
    114111    // Set the caption 
     
    223220    MsnNotificationConnection *msnNotificationConnection_; 
    224221    // The menu items of the settings menu 
    225222    QDict<AccountAction> settingsMenuItems_; 
    226     // The system tray widget 
    227     SystemTrayWidget  *systemTrayWidget_; 
    228223    // The main view widget 
    229224    KMessView         *view_; 
    230225}; 
  • kmess/systemtraywidget.cpp

     
    1717 
    1818#include "systemtraywidget.h" 
    1919 
     20#include <qdockwindow.h> 
     21#include <qpainter.h> 
    2022#include <qtooltip.h> 
    2123 
    2224#include <kdebug.h> 
    2325#include <klocale.h> 
    2426#include <kpopupmenu.h> 
    2527#include <kiconloader.h> 
     28#include <kmanagerselection.h> 
     29#include <kmessagebox.h> 
    2630 
    2731#include "config.h" 
    2832#include "currentaccount.h" 
     
    3539} 
    3640 
    3741 
     42/** 
     43 * Display an Hide On Close dialog window with a trayicon screenshot 
     44 * 
     45 * This method, taken from the Basket Note Pads project (see the related links below), is used when 
     46 * the user closes the main KMess contact list window. Then a custom dialog window is shown to notify 
     47 * that the app will still run in background. This useful method adds to it a screenshot of the system 
     48 * tray area of the users' desktop, highlighting the application's icons. 
     49 * 
     50 * @see http://basket.kde.org/ - Official site of the Basket Note Pads project 
     51 * @see http://basket.kde.org/systemtray-on-close-info.php - Specific tray dialog page 
     52 */ 
     53void SystemTrayWidget::displayCloseMessage( QString /*fileMenu*/ ) 
     54{ 
     55#if KDE_IS_VERSION( 3, 1, 90 ) 
     56  // Don't do all the computations if they are unneeded: 
     57  if ( ! KMessageBox::shouldBeShownContinue("hideOnCloseInfo") ) 
     58      return; 
     59#endif 
    3860 
     61  // Some values we need: 
     62  QPoint g = mapToGlobal(pos()); 
     63  int desktopWidth  = kapp->desktop()->width(); 
     64  int desktopHeight = kapp->desktop()->height(); 
     65  int tw = width(); 
     66  int th = height(); 
     67 
     68  // We are trying to make a live screenshot of the systray icon to circle it 
     69  //  and show it to the user. If no systray is used or if the icon is not visible, 
     70  //  we should not show that screenshot but only a text! 
     71 
     72  // 1. Determine if the user use a system tray area or not: 
     73  QCString screenstr; 
     74  screenstr.setNum(qt_xscreen()); 
     75  QCString trayatom = "_NET_SYSTEM_TRAY_S" + screenstr; 
     76  bool useSystray = (KSelectionWatcher(trayatom).owner() != 0L); 
     77 
     78  // 2. And then if the icon is visible too (eg. this->show() has been called): 
     79  useSystray = useSystray && isVisible(); 
     80 
     81  // 3. Kicker (or another systray manager) can be visible but masked out of 
     82  //    the screen (ie. on right or on left of it). We check if the icon isn't 
     83  //    out of screen. 
     84  QRect deskRect(0, 0, desktopWidth, desktopHeight); 
     85  if( useSystray && ( ! deskRect.contains( g.x(), g.y() ) ) && ( ! deskRect.contains( g.x() + tw, g.y() + th ) ) ) 
     86  { 
     87    useSystray = false; 
     88  } 
     89 
     90 
     91  QString message = i18n( "Closing the main window will keep KMess running in the" 
     92                          " system tray. Use 'Quit' from the 'File' menu to quit the application." ); 
     93 
     94  // If the system tray is not visible, just show the text message 
     95  if( ! useSystray ) 
     96  { 
     97#ifdef KMESSDEBUG_SYSTEMTRAY 
     98    kdDebug() << "SystemTrayWidget::displayCloseMessage() - Displaying simple dialog with no screenshot." << endl; 
     99#endif 
     100 
     101    KMessageBox::information( kapp->activeWindow(), message, 
     102                              i18n( "Docking in System Tray" ), 
     103                              "hideOnCloseInfo" ); 
     104    return; 
     105  } 
     106 
     107  // We are sure the systray icon is visible: ouf! 
     108 
     109#ifdef KMESSDEBUG_SYSTEMTRAY 
     110    kdDebug() << "SystemTrayWidget::displayCloseMessage() - Displaying dialog with tray icon screenshot: generating image..." << endl; 
     111#endif 
     112 
     113  // Compute size and position of the pixmap to be grabbed: 
     114  int w = desktopWidth / 4; 
     115  int h = desktopHeight / 9; 
     116  int x = g.x() + tw/2 - w/2; // Center the rectange in the systray icon 
     117  int y = g.y() + th/2 - h/2; 
     118  if (x < 0)                 x = 0; // Move the rectangle to stay in the desktop limits 
     119  if (y < 0)                 y = 0; 
     120  if (x + w > desktopWidth)  x = desktopWidth - w; 
     121  if (y + h > desktopHeight) y = desktopHeight - h; 
     122 
     123  // Grab the desktop and draw a circle arround the icon: 
     124  const int CIRCLE_MARGINS = 6; 
     125  const int CIRCLE_WIDTH   = 3; 
     126  const int SHADOW_OFFSET  = 1; 
     127  const int IMAGE_BORDER   = 1; 
     128  int ax = g.x() - x - CIRCLE_MARGINS - 1; 
     129  int ay = g.y() - y - CIRCLE_MARGINS - 1; 
     130  QPixmap shot = QPixmap::grabWindow(qt_xrootwin(), x, y, w, h); 
     131  QPainter painter(&shot); 
     132 
     133  painter.setPen( QPen(KApplication::palette().active().dark(), CIRCLE_WIDTH) ); 
     134  painter.drawArc(ax + SHADOW_OFFSET, ay + SHADOW_OFFSET, 
     135                  tw + 2*CIRCLE_MARGINS, th + 2*CIRCLE_MARGINS, 0, 16*360); 
     136  painter.setPen( QPen(Qt::red, CIRCLE_WIDTH) ); 
     137  painter.drawArc(ax, ay, tw + 2*CIRCLE_MARGINS, th + 2*CIRCLE_MARGINS, 0, 16*360); 
     138 
     139  // Draw the pixmap over the screenshot in case a window hide the icon: 
     140  painter.drawPixmap(g.x(), g.y(), *pixmap()); 
     141  painter.end(); 
     142 
     143  // Then, we add a border arround the image to make it more visible: 
     144  QPixmap finalShot(w + 2*IMAGE_BORDER, h + 2*IMAGE_BORDER); 
     145  finalShot.fill(KApplication::palette().active().foreground()); 
     146 
     147  painter.begin(&finalShot); 
     148  painter.drawPixmap(IMAGE_BORDER, IMAGE_BORDER, shot); 
     149  painter.end(); 
     150 
     151#ifdef KMESSDEBUG_SYSTEMTRAY 
     152  kdDebug() << "SystemTrayWidget::displayCloseMessage() - ...Done, showing the dialog." << endl; 
     153#endif 
     154 
     155  // Associate source to image and show the dialog: 
     156  QMimeSourceFactory::defaultFactory()->setPixmap("systray_shot", finalShot); 
     157 
     158  KMessageBox::information(kapp->activeWindow(), 
     159      "<qt>" + message + "<p><center><img source=\"systray_shot\"></center></p></qt>", 
     160      i18n("Docking in System Tray"), "hideOnCloseInfo"); 
     161 
     162  QMimeSourceFactory::defaultFactory()->setData("systray_shot", 0L); 
     163} 
     164 
     165 
     166 
    39167// The destructor 
    40168SystemTrayWidget::~SystemTrayWidget() 
    41169{ 
  • kmess/systemtraywidget.h

     
    3737 
    3838  public: 
    3939    // The constructor 
    40                      SystemTrayWidget(QWidget *parent=0, const char *name=0); 
     40                     SystemTrayWidget(QWidget *parent=0, const char *name=0); 
    4141    // The destructor 
    42                     ~SystemTrayWidget(); 
     42                    ~SystemTrayWidget(); 
    4343    // Initialize the class 
    4444    bool             initialize(); 
     45    // Display a customized close window with a screenshot of the app's tray icon 
     46    void             displayCloseMessage( QString fileMenu = QString::null ); 
    4547    // Return the context menu 
    4648    KPopupMenu      *menu() const; 
    4749 
  • kmess/kmessinterface.cpp

     
    4141 
    4242#include "kmessdebug.h" 
    4343#include "kmessapplication.h" 
     44#include "systemtraywidget.h" 
    4445 
    4546 
    4647// The constructor 
     
    5758// The destructor 
    5859KMessInterface::~KMessInterface() 
    5960{ 
     61  delete systemTrayWidget_; 
     62 
    6063#ifdef KMESSDEBUG_KMESSINTERFACE 
    6164  kdDebug() << "DESTROYED KMessInterface " << endl; 
    6265#endif 
     
    396399  // Create the menus 
    397400  createMenus(); 
    398401 
     402  if ( ! initSystemTrayWidget() ) 
     403  { 
     404    kdDebug() << "KMess - Couldn't initialize the system tray widget." << endl; 
     405    return false; 
     406  } 
     407 
    399408#ifdef KMESSDEBUG_KMESSINTERFACE 
    400409  kdDebug() << "KMessInterface - initialized" << endl; 
    401410#endif 
     
    403412} 
    404413 
    405414 
     415// Initialize the system tray widget 
     416bool KMessInterface::initSystemTrayWidget() 
     417{ 
     418  bool initialized; 
     419 
     420  // Create the widget 
     421  systemTrayWidget_ = new SystemTrayWidget( this, "systemtraywidget" ) ; 
     422  if ( systemTrayWidget_ == 0 ) 
     423  { 
     424    kdDebug() << "KMessInterface - Couldn't create system tray widget." << endl; 
     425    return false; 
     426  } 
     427 
     428  // Initialize the widget 
     429  initialized = systemTrayWidget_->initialize(); 
     430  if ( !initialized ) 
     431  { 
     432    kdDebug() << "KMessInterface - Couldn't initialize system tray widget." << endl; 
     433    return false; 
     434  } 
     435 
     436  // Plug some of the menu actions into the system tray widget's menu. 
     437  connectActionMenu_-> plug( systemTrayWidget_->menu() ); 
     438  disconnect_->        plug( systemTrayWidget_->menu() ); 
     439  systemTrayWidget_->  menu()->insertSeparator(); 
     440  status_->            plug( systemTrayWidget_->menu() ); 
     441  systemTrayWidget_->  menu()->insertSeparator(); 
     442  settingsActionMenu_->plug( systemTrayWidget_->menu() ); 
     443 
     444  // Make the connections for the system tray widget 
     445  connect( systemTrayWidget_, SIGNAL( quitSelected() ), 
     446           this,              SLOT  (     menuQuit() ) ); 
     447 
     448  systemTrayWidget_->show(); 
     449#ifdef KMESSTEST 
     450  ASSERT( systemTrayWidget_ != 0 ); 
     451  ASSERT( systemTrayWidget_->isVisible() ); 
     452#endif 
     453  return true; 
     454} 
     455 
     456 
    406457// Close has been selected from the menu. 
    407458void KMessInterface::menuClose() 
    408459{ 
     
    470521    applicationClosing(); 
    471522    return true; 
    472523  } 
    473   else 
    474   { 
    475     // Tell that KMess is still visible in the tray 
    476     KMessageBox::information( this, 
    477                               i18n( "Closing the main window will keep KMess running in the " 
    478                                     "system tray. Use 'Quit' from the 'File' menu to quit the application." ), 
    479                               i18n( "Docking in System Tray" ), "hideOnCloseInfo" ); 
    480   } 
    481524 
     525  // Tell that KMess is still visible in the tray 
     526  systemTrayWidget_->displayCloseMessage(); 
     527 
    482528#ifdef KMESSDEBUG_KMESSINTERFACE 
    483529  kdDebug() << "KMessInterface::queryClose: Rejecting quit request, hiding window" << endl; 
    484530#endif 
  • kmess/kmessinterface.h

     
    3434class KPopupMenu; 
    3535class KSelectAction; 
    3636class KToggleAction; 
     37class SystemTrayWidget; 
    3738 
    3839/** 
    3940 * @brief User interface of the KMess class. 
     
    124125    KAction         *showTransferAction_; 
    125126    // The select action for the user's status 
    126127    KSelectAction   *status_; 
     128    // The system tray widget 
     129    SystemTrayWidget *systemTrayWidget_; 
    127130    // The menu for selecting the view mode. 
    128131    KSelectAction   *viewMode_; 
    129132 
     
    138141    void             createMenus(); 
    139142    // Create the "View" menu 
    140143    void             createViewMenu(); 
     144    // Initialize the system tray widget 
     145    bool             initSystemTrayWidget(); 
    141146    // Reject quitting unless the quit menu was pressed 
    142147    bool             queryExit(); 
    143148    // Tell the user that KMess hides in the systray