Browse Source

- Based on Qt 4.2

- Brand new trayicon from Qt 4.2
- Updated Changelog
- Updated configure file
adaptive-webui-19844
Christophe Dumez 18 years ago
parent
commit
8b702ef622
  1. 4
      Changelog
  2. 16
      configure
  3. 2
      qbittorrent.qc
  4. 16
      qcm/qt41.qcm
  5. 16
      qcm/qt42.qcm
  6. 36
      src/GUI.cpp
  7. 7
      src/GUI.h
  8. 2
      src/about_imp.h
  9. 3
      src/src.pro
  10. 292
      src/trayicon/trayicon.cpp
  11. 98
      src/trayicon/trayicon.h
  12. 21
      src/trayicon/trayicon.pri
  13. 17
      src/trayicon/trayicon_mac.cpp
  14. 243
      src/trayicon/trayicon_win.cpp
  15. 458
      src/trayicon/trayicon_x11.cpp

4
Changelog

@ -1,3 +1,7 @@ @@ -1,3 +1,7 @@
* Unknown - Christophe Dumez <chris@qbittorrent.org> - v0.8.0
- FEATURE: Based on Qt 4.2
- FEATURE: Brand new trayicon from Qt 4.2
* Mon Oct 16 2006 - Christophe Dumez <chris@qbittorrent.org> - v0.7.1
- I18N: Updated French, Polish, Dutch, Swedish, Slovak translations
- BUGFIX: Fixed Seeds/Leechers display in torrent properties

16
configure vendored

@ -229,21 +229,21 @@ fi @@ -229,21 +229,21 @@ fi
gen_files() {
cat >$1/modules.cpp <<EOT
#line 1 "qt41.qcm"
#line 1 "qt42.qcm"
/*
-----BEGIN QCMOD-----
name: Qt >= 4.1
name: Qt >= 4.2
-----END QCMOD-----
*/
class qc_qt41 : public ConfObj
class qc_qt42 : public ConfObj
{
public:
qc_qt41(Conf *c) : ConfObj(c) {}
QString name() const { return "Qt >= 4.1"; }
QString shortname() const { return "qt41"; }
qc_qt42(Conf *c) : ConfObj(c) {}
QString name() const { return "Qt >= 4.2"; }
QString shortname() const { return "qt42"; }
bool exec()
{
return(QT_VERSION >= 0x040100);
return(QT_VERSION >= 0x040200);
}
};
#line 1 "libtorrent.qcm"
@ -362,7 +362,7 @@ public: @@ -362,7 +362,7 @@ public:
EOT
cat >$1/modules_new.cpp <<EOT
o = new qc_qt41(conf);
o = new qc_qt42(conf);
o->required = true;
o->disabled = false;
o = new qc_libtorrent(conf);

2
qbittorrent.qc

@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
<name>qbittorrent</name>
<profile>qbittorrent.pro</profile>
<moddir>qcm</moddir>
<dep type='qt41'>
<dep type='qt42'>
<required/>
</dep>
<dep type='libtorrent'>

16
qcm/qt41.qcm

@ -1,16 +0,0 @@ @@ -1,16 +0,0 @@
/*
-----BEGIN QCMOD-----
name: Qt >= 4.1
-----END QCMOD-----
*/
class qc_qt41 : public ConfObj
{
public:
qc_qt41(Conf *c) : ConfObj(c) {}
QString name() const { return "Qt >= 4.1"; }
QString shortname() const { return "qt41"; }
bool exec()
{
return(QT_VERSION >= 0x040100);
}
};

16
qcm/qt42.qcm

@ -0,0 +1,16 @@ @@ -0,0 +1,16 @@
/*
-----BEGIN QCMOD-----
name: Qt >= 4.2
-----END QCMOD-----
*/
class qc_qt42 : public ConfObj
{
public:
qc_qt42(Conf *c) : ConfObj(c) {}
QString name() const { return "Qt >= 4.2"; }
QString shortname() const { return "qt42"; }
bool exec()
{
return(QT_VERSION >= 0x040200);
}
};

36
src/GUI.cpp

@ -42,7 +42,6 @@ @@ -42,7 +42,6 @@
#include "misc.h"
#include "createtorrent_imp.h"
#include "properties_imp.h"
#include "trayicon/trayicon.h"
#include "DLListDelegate.h"
#include "SearchListDelegate.h"
#include "downloadThread.h"
@ -153,16 +152,13 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent){ @@ -153,16 +152,13 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent){
connect(actionPreview_file, SIGNAL(triggered()), this, SLOT(previewFileSelection()));
connect(infoBar, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayInfoBarMenu(const QPoint&)));
// Create tray icon
myTrayIcon = new TrayIcon(this);
myTrayIcon = new QSystemTrayIcon(QIcon(":/Icons/qbittorrent22.png"), this);
// Start download list refresher
refresher = new QTimer(this);
connect(refresher, SIGNAL(timeout()), this, SLOT(updateDlList()));
refresher->start(2000);
// Center window
centerWindow();
// Add tray icon and customize it
myTrayIcon->setWMDock(false);
myTrayIcon->setIcon(QPixmap::QPixmap(":/Icons/qbittorrent22.png"));
// Tray icon Menu
myTrayIconMenu = new QMenu(this);
myTrayIconMenu->addAction(actionOpen);
@ -172,9 +168,9 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent){ @@ -172,9 +168,9 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent){
myTrayIconMenu->addAction(actionPause_All);
myTrayIconMenu->addSeparator();
myTrayIconMenu->addAction(actionExit);
myTrayIcon->setPopup(myTrayIconMenu);
myTrayIcon->setContextMenu(myTrayIconMenu);
// End of Icon Menu
connect(myTrayIcon, SIGNAL(clicked(const QPoint &, int)), this, SLOT(toggleVisibility()));
connect(myTrayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(toggleVisibility(QSystemTrayIcon::ActivationReason)));
myTrayIcon->show();
// Use a tcp server to allow only one instance of qBittorrent
tcpServer = new QTcpServer(this);
@ -680,20 +676,22 @@ void GUI::sortSearchListString(int index, Qt::SortOrder sortOrder){ @@ -680,20 +676,22 @@ void GUI::sortSearchListString(int index, Qt::SortOrder sortOrder){
}
// Toggle Main window visibility
void GUI::toggleVisibility(){
if(isHidden()){
show();
if(isMinimized()){
if(isMaximized()){
showMaximized();
}else{
showNormal();
void GUI::toggleVisibility(QSystemTrayIcon::ActivationReason e){
if(e == QSystemTrayIcon::Trigger || e == QSystemTrayIcon::DoubleClick){
if(isHidden()){
show();
if(isMinimized()){
if(isMaximized()){
showMaximized();
}else{
showNormal();
}
}
raise();
activateWindow();
}else{
hide();
}
raise();
activateWindow();
}else{
hide();
}
}

7
src/GUI.h

@ -27,6 +27,8 @@ @@ -27,6 +27,8 @@
#include <QProcess>
#include <QTcpServer>
#include <QTcpSocket>
#include <QCloseEvent>
#include <QSystemTrayIcon>
#include <libtorrent/entry.hpp>
#include <libtorrent/bencode.hpp>
@ -45,7 +47,6 @@ @@ -45,7 +47,6 @@
class createtorrent;
class QTimer;
class TrayIcon;
class DLListDelegate;
class SearchListDelegate;
class downloadThread;
@ -74,7 +75,7 @@ class GUI : public QMainWindow, private Ui::MainWindow{ @@ -74,7 +75,7 @@ class GUI : public QMainWindow, private Ui::MainWindow{
options_imp *options;
createtorrent *createWindow;
QTimer *refresher;
TrayIcon *myTrayIcon;
QSystemTrayIcon *myTrayIcon;
QMenu *myTrayIconMenu;
about *aboutdlg;
QStandardItemModel *DLListModel;
@ -102,7 +103,7 @@ class GUI : public QMainWindow, private Ui::MainWindow{ @@ -102,7 +103,7 @@ class GUI : public QMainWindow, private Ui::MainWindow{
void dropEvent(QDropEvent *event);
void dragEnterEvent(QDragEnterEvent *event);
void centerWindow();
void toggleVisibility();
void toggleVisibility(QSystemTrayIcon::ActivationReason e);
void showAbout();
void setInfoBar(const QString& info, const QString& color="black");
void updateDlList();

2
src/about_imp.h

@ -23,7 +23,7 @@ @@ -23,7 +23,7 @@
#define ABOUT_H
#include "ui_about.h"
#define VERSION "v0.7.1svn"
#define VERSION "v0.8.0alpha1"
class about : public QDialog, private Ui::AboutDlg{
Q_OBJECT

3
src/src.pro

@ -38,9 +38,6 @@ contains(DEBUG_MODE, 0){ @@ -38,9 +38,6 @@ contains(DEBUG_MODE, 0){
CONFIG += release
}
# Includes
include($$TRAYICON_CPP/trayicon.pri)
exists(../conf.pri) {
include(../conf.pri)
}

292
src/trayicon/trayicon.cpp

@ -1,292 +0,0 @@ @@ -1,292 +0,0 @@
/*
* trayicon.cpp - system-independent trayicon class (adapted from Qt example)
* Copyright (C) 2003 Justin Karneges
* Qt4 port: Stefan Gehn
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "trayicon.h"
/*!
\class TrayIcon qtrayicon.h
\brief The TrayIcon class implements an entry in the system tray.
*/
/*!
Creates a TrayIcon object. \a parent and \a name are propagated
to the QObject constructor. The icon is initially invisible.
\sa show
*/
TrayIcon::TrayIcon( QObject *parent)
: QObject(parent), pop(0), d(0)
{
v_isWMDock = FALSE;
}
/*!
Creates a TrayIcon object displaying \a icon and \a tooltip, and opening
\a popup when clicked with the right mousebutton. \a parent and \a name are
propagated to the QObject constructor. The icon is initially invisible.
\sa show
*/
TrayIcon::TrayIcon( const QPixmap &icon, const QString &tooltip, QMenu *popup, QObject *parent )
: QObject(parent), pop(popup), pm(icon), tip(tooltip), d(0)
{
v_isWMDock = FALSE;
if ( !pm.width() || !pm.height() )
pm = QPixmap( 16, 16 );
}
/*!
Removes the icon from the system tray and frees all allocated resources.
*/
TrayIcon::~TrayIcon()
{
sysRemove();
}
/*!
Informs the trayicon that the notification owner has probably been changed;
and that it should attempt to register or re-register.
*/
void TrayIcon::newTrayOwner()
{
// detach ourself from any existing notification area.
hide();
// show ourself on the new notification area
show();
}
/*!
Sets the context menu to \a popup. The context menu will pop up when the
user clicks the system tray entry with the right mouse button.
*/
void TrayIcon::setPopup( QMenu* popup )
{
pop = popup;
}
/*!
Returns the current popup menu.
\sa setPopup
*/
QMenu* TrayIcon::popup() const
{
return pop;
}
/*!
\property TrayIcon::icon
\brief the system tray icon.
*/
void TrayIcon::setIcon( const QPixmap &icon )
{
//if(!popup()) {
// tip = "";
//}
pm = icon;
sysUpdateIcon();
}
QPixmap TrayIcon::icon() const
{
return pm;
}
/*!
\property TrayIcon::toolTip
\brief the tooltip for the system tray entry
On some systems, the tooltip's length is limited and will be truncated as necessary.
*/
void TrayIcon::setToolTip( const QString &tooltip )
{
tip = tooltip;
sysUpdateToolTip();
}
QString TrayIcon::toolTip() const
{
return tip;
}
/*!
Shows the icon in the system tray.
\sa hide
*/
void TrayIcon::show()
{
sysInstall();
}
/*!
Hides the system tray entry.
*/
void TrayIcon::hide()
{
sysRemove();
}
/*!
\reimp
*/
bool TrayIcon::event( QEvent *e )
{
switch ( e->type() ) {
case QEvent::MouseMove:
mouseMoveEvent( (QMouseEvent*)e );
break;
case QEvent::MouseButtonPress:
mousePressEvent( (QMouseEvent*)e );
break;
case QEvent::MouseButtonRelease:
mouseReleaseEvent( (QMouseEvent*)e );
break;
case QEvent::MouseButtonDblClick:
mouseDoubleClickEvent( (QMouseEvent*)e );
break;
default:
return QObject::event( e );
}
return TRUE;
}
/*!
This event handler can be reimplemented in a subclass to receive
mouse move events for the system tray entry.
\sa mousePressEvent(), mouseReleaseEvent(), mouseDoubleClickEvent(), QMouseEvent
*/
void TrayIcon::mouseMoveEvent( QMouseEvent *e )
{
e->ignore();
}
/*!
This event handler can be reimplemented in a subclass to receive
mouse press events for the system tray entry.
\sa mouseReleaseEvent(), mouseDoubleClickEvent(),
mouseMoveEvent(), QMouseEvent
*/
void TrayIcon::mousePressEvent( QMouseEvent *e )
{
#ifndef Q_WS_WIN
// This is for X11, menus appear on mouse press
// I'm not sure whether Mac should be here or below.. Somebody check?
switch ( e->button() ) {
case Qt::RightButton:
if ( pop ) {
pop->popup( e->globalPos() );
e->accept();
}
break;
case Qt::LeftButton:
case Qt::MidButton:
emit clicked( e->globalPos(), e->button() );
break;
default:
break;
}
#endif
e->ignore();
}
/*!
This event handler can be reimplemented in a subclass to receive
mouse release events for the system tray entry.
The default implementations opens the context menu when the entry
has been clicked with the right mouse button.
\sa setPopup(), mousePressEvent(), mouseDoubleClickEvent(),
mouseMoveEvent(), QMouseEvent
*/
void TrayIcon::mouseReleaseEvent( QMouseEvent *e )
{
#ifdef Q_WS_WIN
// This is for Windows, where menus appear on mouse release
switch ( e->button() ) {
case Qt::RightButton:
if ( pop ) {
// Necessary to make keyboard focus
// and menu closing work on Windows.
pop->activateWindow();
pop->popup( e->globalPos() );
pop->activateWindow();
e->accept();
}
break;
case Qt::LeftButton:
case Qt::MidButton:
emit clicked( e->globalPos(), e->button() );
break;
default:
break;
}
#endif
e->ignore();
}
/*!
This event handler can be reimplemented in a subclass to receive
mouse double click events for the system tray entry.
Note that the system tray entry gets a mousePressEvent() and a
mouseReleaseEvent() before the mouseDoubleClickEvent().
\sa mousePressEvent(), mouseReleaseEvent(),
mouseMoveEvent(), QMouseEvent
*/
void TrayIcon::mouseDoubleClickEvent( QMouseEvent *e )
{
if ( e->button() == Qt::LeftButton )
emit doubleClicked( e->globalPos() );
e->accept();
}
/*!
\fn void TrayIcon::clicked( const QPoint &p )
This signal is emitted when the user clicks the system tray icon
with the left mouse button, with \a p being the global mouse position
at that moment.
*/
/*!
\fn void TrayIcon::doubleClicked( const QPoint &p )
This signal is emitted when the user double clicks the system tray
icon with the left mouse button, with \a p being the global mouse position
at that moment.
*/
void TrayIcon::gotCloseEvent()
{
closed();
}

98
src/trayicon/trayicon.h

@ -1,98 +0,0 @@ @@ -1,98 +0,0 @@
/*
* trayicon.h - system-independent trayicon class (adapted from Qt example)
* Copyright (C) 2003 Justin Karneges
* Qt4 port: Stefan Gehn
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef CS_TRAYICON_H
#define CS_TRAYICON_H
#include <QObject>
#include <QImage>
#include <QMenu>
#include <QEvent>
#include <QMouseEvent>
class QPopupMenu;
class TrayIcon : public QObject
{
Q_OBJECT
Q_PROPERTY( QString toolTip READ toolTip WRITE setToolTip )
Q_PROPERTY( QPixmap icon READ icon WRITE setIcon )
public:
TrayIcon( QObject *parent = 0 );
TrayIcon( const QPixmap &, const QString &, QMenu *popup = 0, QObject *parent = 0);
~TrayIcon();
// use WindowMaker dock mode. ignored on non-X11 platforms
void setWMDock(bool use) { v_isWMDock = use; }
bool isWMDock() { return v_isWMDock; }
// Set a popup menu to handle RMB
void setPopup( QMenu * );
QMenu* popup() const;
QPixmap icon() const;
QString toolTip() const;
void gotCloseEvent();
public slots:
void setIcon( const QPixmap &icon );
void setToolTip( const QString &tip );
void show();
void hide();
void newTrayOwner();
signals:
void clicked( const QPoint&, int);
void doubleClicked( const QPoint& );
void closed();
protected:
bool event( QEvent * );
virtual void mouseMoveEvent( QMouseEvent *e );
virtual void mousePressEvent( QMouseEvent *e );
virtual void mouseReleaseEvent( QMouseEvent *e );
virtual void mouseDoubleClickEvent( QMouseEvent *e );
private:
QMenu *pop;
QPixmap pm;
QString tip;
bool v_isWMDock;
// system-dependant part
public:
class TrayIconPrivate;
private:
TrayIconPrivate *d;
void sysInstall();
void sysRemove();
void sysUpdateIcon();
void sysUpdateToolTip();
friend class TrayIconPrivate;
};
#endif // CS_TRAYICON_H

21
src/trayicon/trayicon.pri

@ -1,21 +0,0 @@ @@ -1,21 +0,0 @@
HEADERS += $$TRAYICON_CPP/trayicon.h
SOURCES += $$TRAYICON_CPP/trayicon.cpp
QT += xml
unix:!mac {
SOURCES += $$TRAYICON_CPP/trayicon_x11.cpp
}
win32: {
SOURCES += $$TRAYICON_CPP/trayicon_win.cpp
win32-g++: {
# Probably MinGW
LIBS += libgdi32 libuser32 libshell32
}
else {
# Assume msvc compiler
LIBS += Gdi32.lib User32.lib shell32.lib
}
}
mac: {
SOURCES += $$TRAYICON_CPP/trayicon_mac.cpp
}

17
src/trayicon/trayicon_mac.cpp

@ -1,17 +0,0 @@ @@ -1,17 +0,0 @@
#include "trayicon.h"
void TrayIcon::sysInstall()
{
}
void TrayIcon::sysRemove()
{
}
void TrayIcon::sysUpdateIcon()
{
}
void TrayIcon::sysUpdateToolTip()
{
}

243
src/trayicon/trayicon_win.cpp

@ -1,243 +0,0 @@ @@ -1,243 +0,0 @@
/*
* trayicon_win.cpp - Windows trayicon, adapted from Qt example
* Copyright (C) 2003 Justin Karneges
* Qt4 port: Stefan Gehn
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "trayicon.h"
#include <qwidget.h>
#include <qapplication.h>
#include <qimage.h>
#include <qpixmap.h>
#include <qpainter.h>
#include <qbitmap.h>
#include <qcursor.h>
#include <qlibrary.h>
#include <qt_windows.h>
static uint WM_TASKBARCREATED = 0;
#define WM_NOTIFYICON (WM_APP+101)
typedef BOOL (WINAPI *PtrShell_NotifyIcon)(DWORD,PNOTIFYICONDATA);
static PtrShell_NotifyIcon ptrShell_NotifyIcon = 0;
static void resolveLibs()
{
QLibrary lib("shell32");
//lib.setAutoUnload( FALSE );
static bool triedResolve = FALSE;
if ( !ptrShell_NotifyIcon && !triedResolve )
{
triedResolve = TRUE;
ptrShell_NotifyIcon = (PtrShell_NotifyIcon) lib.resolve( "Shell_NotifyIconW" );
}
}
class TrayIcon::TrayIconPrivate : public QWidget
{
public:
HICON hIcon;
TrayIcon *iconObject;
TrayIconPrivate( TrayIcon *object ) : QWidget( 0 ),
hIcon( 0 ), iconObject( object )
{
if ( !WM_TASKBARCREATED )
WM_TASKBARCREATED = RegisterWindowMessage( TEXT("TaskbarCreated") );
}
~TrayIconPrivate()
{
if ( hIcon )
{
DestroyIcon( hIcon );
hIcon = 0;
}
}
// the unavoidable A/W versions. Don't forget to keep them in sync!
bool trayMessageA( DWORD msg )
{
NOTIFYICONDATAA tnd;
ZeroMemory( &tnd, sizeof(NOTIFYICONDATAA) );
tnd.cbSize = sizeof(NOTIFYICONDATAA);
tnd.hWnd = winId();
tnd.uID = 1;
if ( msg != NIM_DELETE )
{
tnd.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP;
tnd.uCallbackMessage = WM_NOTIFYICON;
tnd.hIcon = hIcon;
if ( !iconObject->toolTip().isNull() )
{
// Tip is limited to 63 + NULL; lstrcpyn appends a NULL terminator.
QString tip = iconObject->toolTip().left( 63 ) + QChar();
lstrcpynA(tnd.szTip, (const char*)tip.toLocal8Bit(), qMin( tip.length()+1, 64 ) );
}
}
return Shell_NotifyIconA(msg, &tnd);
} // trayMessageA
#ifdef UNICODE
bool trayMessageW( DWORD msg )
{
resolveLibs();
if ( ! (ptrShell_NotifyIcon && QSysInfo::WindowsVersion & QSysInfo::WV_NT_based) )
return trayMessageA( msg );
NOTIFYICONDATAW tnd;
ZeroMemory( &tnd, sizeof(NOTIFYICONDATAW) );
tnd.cbSize = sizeof(NOTIFYICONDATAW);
tnd.hWnd = winId();
tnd.uID = 1;
if ( msg != NIM_DELETE )
{
tnd.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP;
tnd.uCallbackMessage = WM_NOTIFYICON;
tnd.hIcon = hIcon;
if ( !iconObject->toolTip().isNull() )
{
// Tip is limited to 63 + NULL; lstrcpyn appends a NULL terminator.
QString tip = iconObject->toolTip().left( 63 ) + QChar();
lstrcpynW(tnd.szTip, (TCHAR*)tip.unicode(), qMin( tip.length()+1, 64 ) );
}
}
return ptrShell_NotifyIcon(msg, &tnd);
} // trayMessageW
#endif
bool trayMessage( DWORD msg )
{
QT_WA(return trayMessageW(msg);, return trayMessageA(msg);)
}
bool iconDrawItem(LPDRAWITEMSTRUCT lpdi)
{
if (!hIcon)
return FALSE;
DrawIconEx(lpdi->hDC, lpdi->rcItem.left, lpdi->rcItem.top, hIcon, 0, 0, 0, NULL, DI_NORMAL );
return TRUE;
}
bool winEvent( MSG * m, long * result )
{
switch(m->message)
{
case WM_DRAWITEM:
return iconDrawItem( (LPDRAWITEMSTRUCT)m->lParam );
case WM_NOTIFYICON:
{
QMouseEvent *e = 0;
QPoint gpos = QCursor::pos();
switch (m->lParam) {
case WM_MOUSEMOVE: e = new QMouseEvent( QEvent::MouseMove, mapFromGlobal( gpos ), gpos, Qt::NoButton, Qt::NoButton, QApplication::keyboardModifiers() ); break;
case WM_LBUTTONDOWN: e = new QMouseEvent( QEvent::MouseButtonPress, mapFromGlobal( gpos ), gpos, Qt::LeftButton, Qt::LeftButton, QApplication::keyboardModifiers() ); break;
case WM_LBUTTONUP: e = new QMouseEvent( QEvent::MouseButtonRelease, mapFromGlobal( gpos ), gpos, Qt::LeftButton, Qt::LeftButton, QApplication::keyboardModifiers() ); break;
case WM_LBUTTONDBLCLK: e = new QMouseEvent( QEvent::MouseButtonDblClick, mapFromGlobal( gpos ), gpos, Qt::LeftButton, Qt::LeftButton, QApplication::keyboardModifiers() ); break;
case WM_RBUTTONDOWN: e = new QMouseEvent( QEvent::MouseButtonPress, mapFromGlobal( gpos ), gpos, Qt::RightButton, Qt::RightButton, QApplication::keyboardModifiers() ); break;
case WM_RBUTTONUP: e = new QMouseEvent( QEvent::MouseButtonRelease, mapFromGlobal( gpos ), gpos, Qt::RightButton, Qt::RightButton, QApplication::keyboardModifiers() ); break;
case WM_RBUTTONDBLCLK: e = new QMouseEvent( QEvent::MouseButtonDblClick, mapFromGlobal( gpos ), gpos, Qt::RightButton, Qt::RightButton, QApplication::keyboardModifiers() ); break;
case WM_MBUTTONDOWN: e = new QMouseEvent( QEvent::MouseButtonPress, mapFromGlobal( gpos ), gpos, Qt::MidButton, Qt::MidButton, QApplication::keyboardModifiers() ); break;
case WM_MBUTTONUP: e = new QMouseEvent( QEvent::MouseButtonRelease, mapFromGlobal( gpos ), gpos, Qt::MidButton, Qt::MidButton, QApplication::keyboardModifiers() ); break;
case WM_MBUTTONDBLCLK: e = new QMouseEvent( QEvent::MouseButtonDblClick, mapFromGlobal( gpos ), gpos, Qt::MidButton, Qt::MidButton, QApplication::keyboardModifiers() ); break;
case WM_CONTEXTMENU: e = new QMouseEvent( QEvent::MouseButtonRelease, mapFromGlobal( gpos ), gpos, Qt::RightButton, Qt::RightButton, QApplication::keyboardModifiers() ); break;
}
if ( e )
{
bool res = QApplication::sendEvent( iconObject, e );
delete e;
return res;
}
}
break;
default:
if ( m->message == WM_TASKBARCREATED )
trayMessage( NIM_ADD );
}
return QWidget::winEvent( m, result );
} // winEvent
}; // class TrayIcon::TrayIconPrivate
static HICON createIcon( const QPixmap &pm )
{
ICONINFO iconInfo;
iconInfo.fIcon = true;
iconInfo.hbmMask = pm.createMaskFromColor(Qt::black).toWinHBITMAP();
iconInfo.hbmColor = pm.toWinHBITMAP(QPixmap::PremultipliedAlpha);
HICON icon = CreateIconIndirect( &iconInfo );
DeleteObject(iconInfo.hbmMask);
iconInfo.hbmMask = 0;
DeleteObject(iconInfo.hbmColor);
iconInfo.hbmColor = 0;
return icon;
}
void TrayIcon::sysInstall()
{
if ( !d )
{
d = new TrayIconPrivate( this );
d->hIcon = createIcon( pm );
d->trayMessage( NIM_ADD );
}
}
void TrayIcon::sysRemove()
{
if ( d )
{
d->trayMessage( NIM_DELETE );
delete d;
d = 0;
}
}
void TrayIcon::sysUpdateIcon()
{
if ( d )
{
if ( d->hIcon )
{
DestroyIcon( d->hIcon );
d->hIcon = 0;
}
d->hIcon = createIcon( pm );
d->trayMessage( NIM_MODIFY );
}
}
void TrayIcon::sysUpdateToolTip()
{
if ( d )
d->trayMessage( NIM_MODIFY );
}

458
src/trayicon/trayicon_x11.cpp

@ -1,458 +0,0 @@ @@ -1,458 +0,0 @@
/*
* trayicon_x11.cpp - X11 trayicon (for use with KDE and GNOME)
* Copyright (C) 2003 Justin Karneges
* GNOME2 Notification Area support: Tomasz Sterna
* Qt4 port: Stefan Gehn
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "trayicon.h"
#include <QApplication>
#include <QDesktopWidget>
#include <QPixmap>
#include <QBitmap>
#include <QToolTip>
#include <QPainter>
#include <QX11Info>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
//----------------------------------------------------------------------------
// common stuff
//----------------------------------------------------------------------------
// for Gnome2 Notification Area
static XErrorHandler old_handler = 0;
static int dock_xerror = 0;
extern "C" int dock_xerrhandler(Display* dpy, XErrorEvent* err)
{
dock_xerror = err->error_code;
return old_handler(dpy, err);
}
static void trap_errors()
{
dock_xerror = 0;
old_handler = XSetErrorHandler(dock_xerrhandler);
}
static bool untrap_errors()
{
XSetErrorHandler(old_handler);
return (dock_xerror == 0);
}
static bool send_message(
Display* dpy, /* display */
Window w, /* sender (tray icon window) */
long message, /* message opcode */
long data1, /* message data 1 */
long data2, /* message data 2 */
long data3 /* message data 3 */
)
{
XEvent ev;
memset(&ev, 0, sizeof(ev));
ev.xclient.type = ClientMessage;
ev.xclient.window = w;
ev.xclient.message_type = XInternAtom(dpy, "_NET_SYSTEM_TRAY_OPCODE", False);
ev.xclient.format = 32;
ev.xclient.data.l[0] = CurrentTime;
ev.xclient.data.l[1] = message;
ev.xclient.data.l[2] = data1;
ev.xclient.data.l[3] = data2;
ev.xclient.data.l[4] = data3;
trap_errors();
XSendEvent(dpy, w, False, NoEventMask, &ev);
XSync(dpy, False);
return untrap_errors();
}
#define SYSTEM_TRAY_REQUEST_DOCK 0
//#define SYSTEM_TRAY_BEGIN_MESSAGE 1
//#define SYSTEM_TRAY_CANCEL_MESSAGE 2
//----------------------------------------------------------------------------
// TrayIcon::TrayIconPrivate
//----------------------------------------------------------------------------
class TrayIcon::TrayIconPrivate : public QWidget
{
public:
TrayIconPrivate(TrayIcon *object, int size);
~TrayIconPrivate() { }
virtual void initWM(WId icon);
virtual void setPixmap(const QPixmap &pm);
virtual void paintEvent(QPaintEvent *);
virtual void enterEvent(QEvent *);
virtual void mouseMoveEvent(QMouseEvent *e);
virtual void mousePressEvent(QMouseEvent *e);
virtual void mouseReleaseEvent(QMouseEvent *e);
virtual void mouseDoubleClickEvent(QMouseEvent *e);
virtual void closeEvent(QCloseEvent *e);
void updateMask();
private:
TrayIcon *iconObject;
QPixmap pix;
int size;
};
TrayIcon::TrayIconPrivate::TrayIconPrivate(TrayIcon *object, int _size)
: QWidget(0/*, Qt::WRepaintNoErase*/)
{
setObjectName(QCoreApplication::instance()->applicationName() + "dock");
iconObject = object;
size = _size;
setFocusPolicy(Qt::NoFocus);
// setBackgroundMode(Qt::X11ParentRelative);
setAttribute(Qt::WA_NoSystemBackground);
setBackgroundRole(QPalette::NoRole);
// This resize will not work as expected,
// we will get resized inside the tray later on.
resize(size, size);
setMinimumSize(size, size);
setMaximumSize(size, size);
}
// This base stuff is required by both FreeDesktop specification and WindowMaker
void TrayIcon::TrayIconPrivate::initWM(WId icon)
{
Display *dsp = QX11Info::display();
WId leader = winId();
char *resName = objectName().toLocal8Bit().data();
char *resClass = QCoreApplication::instance()->applicationName().toLocal8Bit().data();
// set the class hint
XClassHint classhint;
classhint.res_name = resName;
classhint.res_class = resClass;
XSetClassHint(dsp, leader, &classhint);
// set the Window Manager hints
XWMHints *hints;
hints = XGetWMHints(dsp, leader); // init hints
hints->flags = WindowGroupHint | IconWindowHint | StateHint;
hints->window_group = leader;
hints->initial_state = WithdrawnState;
hints->icon_window = icon; // in WM, this should be winId() of separate widget
hints->icon_x = 0;
hints->icon_y = 0;
XSetWMHints(dsp, leader, hints); // set the window hints for WM to use.
XFree(hints);
}
void TrayIcon::TrayIconPrivate::setPixmap(const QPixmap &pm)
{
QBitmap mask( QWidget::size() );
if( pm.size() != QWidget::size() ) {
// let's make a new mask
mask.fill(Qt::color0);
QPainter maskPainter(&mask);
// draw the old mask in the center
maskPainter.drawPixmap((width() - pm.width() ) / 2,
(height() - pm.height()) / 2, pm.mask());
QPixmap newPix(QWidget::size());
QPainter pixPainter( &newPix );
// draw the old pixmap in the center
pixPainter.drawPixmap((width() - pm.width())/2,
(height() - pm.height())/2, pm);
newPix.setMask(mask);
pix = newPix;
} else {
pix = pm;
mask = pm.mask();
}
setMask(mask);
setWindowIcon(pix);
repaint();
}
void TrayIcon::TrayIconPrivate::updateMask()
{
if (!pix.isNull())
{
QBitmap mask(width(), height());
mask.clear();
QPainter mp(&mask);
mp.drawPixmap((width() - pix.width())/2, (height() - pix.height())/2, pix.mask());
mp.end();
setMask(mask);
}
}
void TrayIcon::TrayIconPrivate::paintEvent(QPaintEvent *)
{
QPainter p(this);
// p.drawPixmap((width() - pix.width())/2, (height() - pix.height())/2, pix);
p.drawPixmap(0, 0, pix);
}
void TrayIcon::TrayIconPrivate::enterEvent(QEvent *e)
{
// Taken from KSystemTray..
/*#if QT_VERSION < 0x030200
if ( !qApp->focusWidget() )
{*/
XEvent ev;
memset(&ev, 0, sizeof(ev));
ev.xfocus.display = QX11Info::display();
ev.xfocus.type = FocusIn;
ev.xfocus.window = winId();
ev.xfocus.mode = NotifyNormal;
ev.xfocus.detail = NotifyAncestor;
// unsigned long oldTime = QX11Info::appTime();
// QX11Info::setAppTime(1);
qApp->x11ProcessEvent( &ev );
// QX11Info::setAppTime(oldTime);
/*}
#endif*/
QWidget::enterEvent(e);
}
void TrayIcon::TrayIconPrivate::mouseMoveEvent(QMouseEvent *e)
{
QApplication::sendEvent(iconObject, e);
}
void TrayIcon::TrayIconPrivate::mousePressEvent(QMouseEvent *e)
{
QApplication::sendEvent(iconObject, e);
}
void TrayIcon::TrayIconPrivate::mouseReleaseEvent(QMouseEvent *e)
{
QApplication::sendEvent(iconObject, e);
}
void TrayIcon::TrayIconPrivate::mouseDoubleClickEvent(QMouseEvent *e)
{
QApplication::sendEvent(iconObject, e);
}
void TrayIcon::TrayIconPrivate::closeEvent(QCloseEvent *e)
{
iconObject->gotCloseEvent();
e->accept();
}
//----------------------------------------------------------------------------
// TrayIconFreeDesktop
//----------------------------------------------------------------------------
class TrayIconFreeDesktop : public TrayIcon::TrayIconPrivate
{
public:
TrayIconFreeDesktop(TrayIcon *object, const QPixmap &pm);
protected:
virtual bool x11Event(XEvent*);
};
TrayIconFreeDesktop::TrayIconFreeDesktop(TrayIcon *object, const QPixmap &pm)
: TrayIconPrivate(object, 22)
{
initWM( winId() );
// initialize NetWM
Display *dsp = QX11Info::display();
// dock the widget (adapted from SIM-ICQ)
Screen *screen = XDefaultScreenOfDisplay(dsp); // get the screen
int screen_id = XScreenNumberOfScreen(screen); // and it's number
// tell X that we want to see ClientMessage and Deleted events, which
// are picked up by QApplication::x11EventFilter
Window root_window = QApplication::desktop()->winId();
XWindowAttributes attr;
XGetWindowAttributes(dsp, root_window, &attr);
XSelectInput(dsp, root_window, attr.your_event_mask | StructureNotifyMask);
char buf[32];
snprintf(buf, sizeof(buf), "_NET_SYSTEM_TRAY_S%d", screen_id);
Atom selection_atom = XInternAtom(dsp, buf, false);
XGrabServer(dsp);
Window manager_window = XGetSelectionOwner(dsp, selection_atom);
if ( manager_window != None )
XSelectInput(dsp, manager_window, StructureNotifyMask);
XUngrabServer(dsp);
XFlush(dsp);
if ( manager_window != None )
{
send_message(dsp, manager_window, SYSTEM_TRAY_REQUEST_DOCK, winId(), 0, 0);
}
else
{
object->hide();
return;
}
// some KDE mumbo-jumbo... why is it there? anybody?
Atom kwm_dockwindow_atom = XInternAtom(dsp, "KWM_DOCKWINDOW", false);
Atom kde_net_system_tray_window_for_atom = XInternAtom(dsp, "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", false);
long data = 0;
XChangeProperty(dsp, winId(), kwm_dockwindow_atom, kwm_dockwindow_atom, 32, PropModeReplace, (uchar*)&data, 1);
XChangeProperty(dsp, winId(), kde_net_system_tray_window_for_atom, XA_WINDOW, 32, PropModeReplace, (uchar*)&data, 1);
setPixmap(pm);
}
bool TrayIconFreeDesktop::x11Event(XEvent *ev)
{
switch(ev->type)
{
case ReparentNotify:
// setUpdatesEnabled(false);
show();
// updateMask();
// setUpdatesEnabled(true);
}
return false;
}
//----------------------------------------------------------------------------
// TrayIconWindowMaker
//----------------------------------------------------------------------------
class TrayIconWharf : public TrayIcon::TrayIconPrivate
{
public:
TrayIconWharf(TrayIcon *object, const QPixmap &pm)
: TrayIconPrivate(object, 44)
{
char *resName = QString(objectName() + "-wharf").toLocal8Bit().data();
char *resClass = QCoreApplication::instance()->applicationName().toLocal8Bit().data();
// set the class hint
XClassHint classhint;
classhint.res_name = resName;
classhint.res_class = resClass;
XSetClassHint(QX11Info::display(), winId(), &classhint);
setPixmap(pm);
}
void setPixmap(const QPixmap &_pm){
QPixmap pm;
QImage i = _pm.toImage();
i = i.scaled(i.width() * 2, i.height() * 2);
pm.fromImage(i);
TrayIconPrivate::setPixmap(pm);
// thanks to Robert Spier for this:
// for some reason the repaint() isn't being honored, or isn't for
// the icon. So force one on the widget behind the icon
// erase();
QPaintEvent pe( rect() );
paintEvent(&pe);
}
};
class TrayIconWindowMaker : public TrayIcon::TrayIconPrivate
{
public:
TrayIconWindowMaker(TrayIcon *object, const QPixmap &pm);
~TrayIconWindowMaker();
void setPixmap(const QPixmap &pm);
private:
TrayIconWharf *wharf;
};
TrayIconWindowMaker::TrayIconWindowMaker(TrayIcon *object, const QPixmap &pm)
: TrayIconPrivate(object, 32)
{
wharf = new TrayIconWharf(object, pm);
initWM( wharf->winId() );
}
TrayIconWindowMaker::~TrayIconWindowMaker()
{
delete wharf;
}
void TrayIconWindowMaker::setPixmap(const QPixmap &pm)
{
wharf->setPixmap(pm);
}
//----------------------------------------------------------------------------
// TrayIcon
//----------------------------------------------------------------------------
void TrayIcon::sysInstall()
{
if ( d )
return;
if ( v_isWMDock )
d = (TrayIconPrivate *)(new TrayIconWindowMaker(this, pm));
else
d = (TrayIconPrivate *)(new TrayIconFreeDesktop(this, pm));
sysUpdateToolTip();
if ( v_isWMDock )
d->show();
}
void TrayIcon::sysRemove()
{
if ( !d )
return;
delete d;
d = 0;
}
void TrayIcon::sysUpdateIcon()
{
if ( !d )
return;
QPixmap pix = pm;
d->setPixmap(pix);
}
void TrayIcon::sysUpdateToolTip()
{
if ( !d )
return;
if ( tip.isEmpty() )
d->setToolTip(QString::null);
else
d->setToolTip(tip);
}
Loading…
Cancel
Save