You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdedocker/src/customtraylabel.cpp

365 lines
11 KiB

11 years ago
/*
* Copyright (C) 2004 Girish Ramakrishnan All Rights Reserved.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
// $Id: customtraylabel.cpp,v 1.14 2005/06/21 10:04:35 cs19713 Exp $
#include <qsettings.h>
#include <qpopupmenu.h>
#include <qmessagebox.h>
#include <qfiledialog.h>
#include <qinputdialog.h>
#include <qaction.h>
#include <qtimer.h>
#include <qsize.h>
#include <stdlib.h>
#include <kiconloader.h>
#include <kglobal.h>
#include <klocale.h>
11 years ago
#include "trace.h"
#include "customtraylabel.h"
#include "traylabelmgr.h"
#include "kdocker.h"
CustomTrayLabel::CustomTrayLabel(Window w, QWidget* p, const QString& t)
: QTrayLabel(w, p, t), mUndockWhenDead(false)
{
installMenu();
}
CustomTrayLabel::CustomTrayLabel(const QStringList& argv, pid_t pid,
QWidget* parent)
: QTrayLabel(argv, pid, parent), mUndockWhenDead(false)
{
installMenu();
}
/*
* Installs a popup menu on the tray label
*/
void CustomTrayLabel::installMenu()
{
QPixmap kdocker_png(KGlobal::iconLoader()->loadIcon("kdocker", KIcon::NoGroup, KIcon::SizeSmall));
11 years ago
setIcon(kdocker_png);
TrayLabelMgr *tlMgr = TrayLabelMgr::instance();
mOptionsMenu = new QPopupMenu(this);
mSessionManagement = new QAction(i18n("Dock when session restored"), 0, this);
11 years ago
mSessionManagement->setToggleAction(true);
connect(mSessionManagement, SIGNAL(toggled(bool)),
this, SLOT(enableSessionManagement(bool)));
mSessionManagement->addTo(mOptionsMenu);
mAutoLaunch = new QAction(i18n("Launch on startup"), 0, this);
11 years ago
mAutoLaunch->setToggleAction(true);
connect(mAutoLaunch, SIGNAL(activated()),
this, SLOT(slotSetLaunchOnStartup()));
mAutoLaunch->addTo(mOptionsMenu);
mOptionsMenu->insertItem(i18n("Set Icon"), this, SLOT(setCustomIcon()));
11 years ago
mBalloonTimeout = new QAction(i18n("Set balloon timeout"), 0, this);
11 years ago
connect(mBalloonTimeout, SIGNAL(activated()),
this, SLOT(slotSetBalloonTimeout()));
mBalloonTimeout->addTo(mOptionsMenu);
mDockWhenObscured = new QAction(i18n("Dock when obscured"), 0, this);
11 years ago
mDockWhenObscured->setToggleAction(true);
connect(mDockWhenObscured, SIGNAL(toggled(bool)),
this, SLOT(setDockWhenObscured(bool)));
mDockWhenObscured->addTo(mOptionsMenu);
mDockWhenMinimized = new QAction(i18n("Dock when minimized"), 0, this);
11 years ago
mDockWhenMinimized->setToggleAction(true);
connect(mDockWhenMinimized, SIGNAL(toggled(bool)),
this, SLOT(setDockWhenMinimized(bool)));
mDockWhenMinimized->addTo(mOptionsMenu);
mDockWhenFocusLost = new QAction(i18n("Dock when focus lost"), 0, this);
11 years ago
mDockWhenFocusLost->setToggleAction(true);
connect(mDockWhenFocusLost, SIGNAL(toggled(bool)),
this, SLOT(setDockWhenFocusLost(bool)));
mDockWhenFocusLost->addTo(mOptionsMenu);
mSkipTaskbar = new QAction(i18n("Skip taskbar"), 0, this);
11 years ago
mSkipTaskbar->setToggleAction(true);
connect(mSkipTaskbar, SIGNAL(toggled(bool)),
this, SLOT(setSkipTaskbar(bool)));
mSkipTaskbar->addTo(mOptionsMenu);
mMainMenu = new QPopupMenu(this);
mMainMenu->insertItem(QIconSet(kdocker_png),
i18n("About KDocker"), tlMgr, SLOT(about()));
11 years ago
mMainMenu->insertSeparator();
mMainMenu->insertItem(i18n("Options"), mOptionsMenu);
mMainMenu->insertItem(i18n("Dock Another"), tlMgr, SLOT(dockAnother()));
mMainMenu->insertItem(i18n("Undock All"), tlMgr, SLOT(undockAll()));
11 years ago
mMainMenu->insertSeparator();
mShowId = mMainMenu->insertItem(QString("Show/Hide [untitled]"),
this, SLOT(toggleShow()));
mMainMenu->insertItem(QString(i18n("Undock")), this, SLOT(undock()));
mMainMenu->insertItem(QString(i18n("Close")), this, SLOT(close()));
11 years ago
connect(mMainMenu, SIGNAL(aboutToShow()), this, SLOT(updateMenu()));
// Apply defaults here
setLaunchOnStartup(false);
setDockWhenObscured(false);
enableSessionManagement(true);
mDockWhenMinimized->setOn(isDockWhenMinimized());
mSkipTaskbar->setOn(isSkippingTaskbar());
setAcceptDrops(true); // and you thought this function only installs the menu
}
/*
* Session Management
*/
bool CustomTrayLabel::restoreState(QSettings& settings)
{
mAutoLaunch->setOn(settings.readBoolEntry("/LaunchOnStartup"));
setDockWhenObscured(settings.readBoolEntry("/DockWhenObscured"));
TRACE("AutoLaunch=%i DWM=%i DWO=%i", isLaunchOnStartup(),
isDockWhenMinimized(), isDockWhenObscured());
return QTrayLabel::restoreState(settings);
}
bool CustomTrayLabel::saveState(QSettings& settings)
{
if (!mSessionManagement->isOn()) return false;
QTrayLabel::saveState(settings);
settings.writeEntry("/LaunchOnStartup", isLaunchOnStartup());
settings.writeEntry("/DockWhenObscured", isDockWhenObscured());
TRACE("AutoLaunch=%i DWM=%i DWO=%i", isLaunchOnStartup(),
isDockWhenMinimized(), isDockWhenObscured());
return true;
}
static bool which(const char *app)
{
if (access(app, X_OK) == 0) return true;
// Check if the program exist in the $PATH
char *path = strdup(getenv("PATH"));
char prog[300];
if (path == NULL) return false;
TRACE("PATH=%s", path);
char *p = strtok(path, ":");
while (p != NULL)
{
snprintf(prog, sizeof(prog), "%s/%s", p, app);
if (access(prog, X_OK) == 0) break;
p = strtok(NULL, ":");
}
free(path);
TRACE("Located at (%s)", p);
return p != NULL;
}
// Overridden to update our menu
void CustomTrayLabel::setDockWhenMinimized(bool dwm)
{
QTrayLabel::setDockWhenMinimized(dwm);
mDockWhenMinimized->setOn(isDockWhenMinimized());
}
void CustomTrayLabel::setSkipTaskbar(bool skip)
{
QTrayLabel::setSkipTaskbar(skip);
mSkipTaskbar->setOn(isSkippingTaskbar());
}
void CustomTrayLabel::setAppName(const QString& name)
{
QTrayLabel::setAppName(name.lower());
}
/*
* This function is called when QTrayLabel wants to know whether it can
* unsubscribe from root window. This is because it doesnt know if someone
* else is interested in root window events
*/
bool CustomTrayLabel::canUnsubscribeFromRoot(void)
{
return (TrayLabelMgr::instance())->hiddenLabelsCount() == 0;
}
// Get icon from user, load it and if successful load it.
void CustomTrayLabel::setCustomIcon(void)
{
QString icon;
while (true)
{
// Nag the user to give us a valid icon or press cancel
icon = QFileDialog::getOpenFileName();
if (icon.isNull()) return; // user cancelled
if (!QPixmap(icon).isNull()) break;
TRACE("Attempting to set icon to %s", icon.latin1());
QMessageBox::critical(this, i18n("KDocker"),
i18n("%1 is not a valid icon").arg(icon));
11 years ago
}
setTrayIcon(icon);
}
// Get balloon timeout from the user
void CustomTrayLabel::slotSetBalloonTimeout(void)
{
bool ok;
int timeout = QInputDialog::getInteger(i18n("KDocker"),
i18n("Enter balloon timeout (secs). 0 to disable ballooning"),
11 years ago
balloonTimeout()/1000, 0, 60, 1, &ok);
if (!ok) return;
setBalloonTimeout(timeout * 1000);
}
void CustomTrayLabel::setLaunchOnStartup(bool launch)
{
mAutoLaunch->setOn(launch);
slotSetLaunchOnStartup(); // fake an "activated" signal
}
void CustomTrayLabel::slotSetLaunchOnStartup()
{
TRACE("%i", mAutoLaunch->isOn());
if (!mAutoLaunch->isOn()) return;
QString app = appName();
TRACE("Validating %s", app.latin1());
while (true)
{
if (which(app.latin1()))
{
TRACE("Autolaunch enabled to %s", app.latin1());
setAppName(app);
mAutoLaunch->setOn(true);
return;
}
// Request user to provide file name himself
if (QMessageBox::critical(NULL, i18n("KDocker"),
i18n("\"%1\" is not a valid executable "
11 years ago
"or was not found in your $PATH").arg(app),
i18n("Select program"), i18n("Cancel")) == 1)
11 years ago
{
mAutoLaunch->setOn(false);
return; // cancelled
}
app = QFileDialog::getOpenFileName();
if (app.isNull())
{
TRACE("Disabling auto launch");
mAutoLaunch->setOn(false);
return;
}
}
}
// Called when we are just about to display the menu
void CustomTrayLabel::updateMenu(void)
{
QString title = appClass(); // + "(" + appTitle() + ")";
mMainMenu->changeItem(mShowId, QIconSet(*pixmap()),
QString((isWithdrawn() ? i18n("Show %1") : i18n("Hide %1")).arg(title)));
11 years ago
}
void CustomTrayLabel::mapEvent(void)
{
TRACE("mapEvent");
if (mDockWhenObscured->isOn())
{
/*
* We get a obscured event for the time between the map and focus in of
* the window. So we disable it for sometime and reanable.
*/
mDockWhenObscured->setOn(false);
QTimer::singleShot(800, mDockWhenObscured, SLOT(toggle()));
TRACE("Turning off DWO for some time");
}
}
void CustomTrayLabel::obscureEvent(void)
{
TRACE("obscureEvent");
if (mDockWhenObscured->isOn() && !isWithdrawn())
withdraw();
}
void CustomTrayLabel::focusLostEvent()
{
if (mDockWhenFocusLost->isOn()) withdraw();
}
void CustomTrayLabel::mouseReleaseEvent(QMouseEvent * ev)
{
if (ev->button() == Qt::RightButton)
mMainMenu->popup(ev->globalPos());
else
toggleShow();
}
void CustomTrayLabel::destroyEvent(void)
{
mUndockWhenDead = true;
QTrayLabel::destroyEvent();
}
void CustomTrayLabel::processDead(void)
{
/*
* This is a ugly hack but worth every but of ugliness IMO ;).
* Lets say, an instance of xmms, already exists. You type kdocker xmms.
* KDocker launches xmms. xmms cowardly exists seeing its previous instance.
* Wouldnt it be nice now to dock the previous instance of xmms automatically.
* This is more common than you think (think of session restoration)
*/
if (!mUndockWhenDead)
{
scanClients();
if (dockedWindow() != None) return;
}
undock();
}
/*
* Can dock this window iff not docked by another one tray label already
*/
bool CustomTrayLabel::canDockWindow(Window w)
{
TRACE("Checking if 0x%x is already docked", (unsigned) w);
return !(TrayLabelMgr::instance()->isWindowDocked(w));
}
void CustomTrayLabel::dropEvent(QDropEvent *)
{
QMessageBox::information(NULL, "KDocker",
i18n("You cannot drop an item into the tray icon. Drop it on the window\n"
11 years ago
"that is brought in front when you hover the item over the tray icon"));
}
#include "customtraylabel.moc"