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

366 lines
11 KiB

/*
* 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 <tqsettings.h>
#include <tqpopupmenu.h>
#include <tqmessagebox.h>
#include <tqfiledialog.h>
#include <tqinputdialog.h>
#include <tqaction.h>
#include <tqtimer.h>
#include <tqsize.h>
#include <stdlib.h>
#include <kiconloader.h>
#include <tdeglobal.h>
#include <tdelocale.h>
#include "trace.h"
#include "customtraylabel.h"
#include "traylabelmgr.h"
#include "tdedocker.h"
CustomTrayLabel::CustomTrayLabel(Window w, TQWidget* p, const TQString& t)
: TQTrayLabel(w, p, t), mUndockWhenDead(false)
{
installMenu();
}
CustomTrayLabel::CustomTrayLabel(const TQStringList& argv, pid_t pid,
TQWidget* parent)
: TQTrayLabel(argv, pid, parent), mUndockWhenDead(false)
{
installMenu();
}
/*
* Installs a popup menu on the tray label
*/
void CustomTrayLabel::installMenu()
{
//TQPixmap tdedocker_png(TDEGlobal::iconLoader()->loadIcon("tdedocker", TDEIcon::NoGroup, TDEIcon::SizeSmall));
TQPixmap *tdedocker_png = new TQPixmap("tdedocker");
setIcon(*tdedocker_png);
TrayLabelMgr *tlMgr = TrayLabelMgr::instance();
mOptionsMenu = new TQPopupMenu(this);
mSessionManagement = new TQAction(i18n("Dock when session restored"), 0, this);
mSessionManagement->setToggleAction(true);
connect(mSessionManagement, SIGNAL(toggled(bool)),
this, SLOT(enableSessionManagement(bool)));
mSessionManagement->addTo(mOptionsMenu);
mAutoLaunch = new TQAction(i18n("Launch on startup"), 0, this);
mAutoLaunch->setToggleAction(true);
connect(mAutoLaunch, SIGNAL(activated()),
this, SLOT(slotSetLaunchOnStartup()));
mAutoLaunch->addTo(mOptionsMenu);
mOptionsMenu->insertItem(i18n("Set Icon"), this, SLOT(setCustomIcon()));
mBalloonTimeout = new TQAction(i18n("Set balloon timeout"), 0, this);
connect(mBalloonTimeout, SIGNAL(activated()),
this, SLOT(slotSetBalloonTimeout()));
mBalloonTimeout->addTo(mOptionsMenu);
mDockWhenObscured = new TQAction(i18n("Dock when obscured"), 0, this);
mDockWhenObscured->setToggleAction(true);
connect(mDockWhenObscured, SIGNAL(toggled(bool)),
this, SLOT(setDockWhenObscured(bool)));
mDockWhenObscured->addTo(mOptionsMenu);
mDockWhenMinimized = new TQAction(i18n("Dock when minimized"), 0, this);
mDockWhenMinimized->setToggleAction(true);
connect(mDockWhenMinimized, SIGNAL(toggled(bool)),
this, SLOT(setDockWhenMinimized(bool)));
mDockWhenMinimized->addTo(mOptionsMenu);
mDockWhenFocusLost = new TQAction(i18n("Dock when focus lost"), 0, this);
mDockWhenFocusLost->setToggleAction(true);
connect(mDockWhenFocusLost, SIGNAL(toggled(bool)),
this, SLOT(setDockWhenFocusLost(bool)));
mDockWhenFocusLost->addTo(mOptionsMenu);
mSkipTaskbar = new TQAction(i18n("Skip taskbar"), 0, this);
mSkipTaskbar->setToggleAction(true);
connect(mSkipTaskbar, SIGNAL(toggled(bool)),
this, SLOT(setSkipTaskbar(bool)));
mSkipTaskbar->addTo(mOptionsMenu);
mMainMenu = new TQPopupMenu(this);
mMainMenu->insertItem(TQIconSet(*tdedocker_png),
i18n("About TDEDocker"), tlMgr, SLOT(about()));
mMainMenu->insertSeparator();
mMainMenu->insertItem(i18n("Options"), mOptionsMenu);
mMainMenu->insertItem(i18n("Dock Another"), tlMgr, SLOT(dockAnother()));
mMainMenu->insertItem(i18n("Undock All"), tlMgr, SLOT(undockAll()));
mMainMenu->insertSeparator();
mShowId = mMainMenu->insertItem(TQString("Show/Hide [untitled]"),
this, SLOT(toggleShow()));
mMainMenu->insertItem(TQString(i18n("Undock")), this, SLOT(undock()));
mMainMenu->insertItem(TQString(i18n("Close")), this, SLOT(close()));
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(TQSettings& settings)
{
mAutoLaunch->setOn(settings.readBoolEntry("/LaunchOnStartup"));
setDockWhenObscured(settings.readBoolEntry("/DockWhenObscured"));
TRACE("AutoLaunch=%i DWM=%i DWO=%i", isLaunchOnStartup(),
isDockWhenMinimized(), isDockWhenObscured());
return TQTrayLabel::restoreState(settings);
}
bool CustomTrayLabel::saveState(TQSettings& settings)
{
if (!mSessionManagement->isOn()) return false;
TQTrayLabel::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)
{
TQTrayLabel::setDockWhenMinimized(dwm);
mDockWhenMinimized->setOn(isDockWhenMinimized());
}
void CustomTrayLabel::setSkipTaskbar(bool skip)
{
TQTrayLabel::setSkipTaskbar(skip);
mSkipTaskbar->setOn(isSkippingTaskbar());
}
void CustomTrayLabel::setAppName(const TQString& name)
{
TQTrayLabel::setAppName(name.lower());
}
/*
* This function is called when TQTrayLabel 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)
{
TQString icon;
while (true)
{
// Nag the user to give us a valid icon or press cancel
icon = TQFileDialog::getOpenFileName();
if (icon.isNull()) return; // user cancelled
if (!TQPixmap(icon).isNull()) break;
TRACE("Attempting to set icon to %s", icon.latin1());
TQMessageBox::critical(this, i18n("TDEDocker"),
i18n("%1 is not a valid icon").arg(icon));
}
setTrayIcon(icon);
}
// Get balloon timeout from the user
void CustomTrayLabel::slotSetBalloonTimeout(void)
{
bool ok;
int timeout = TQInputDialog::getInteger(i18n("TDEDocker"),
i18n("Enter balloon timeout (secs). 0 to disable ballooning"),
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;
TQString 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 (TQMessageBox::critical(NULL, i18n("TDEDocker"),
i18n("\"%1\" is not a valid executable "
"or was not found in your $PATH").arg(app),
i18n("Select program"), i18n("Cancel")) == 1)
{
mAutoLaunch->setOn(false);
return; // cancelled
}
app = TQFileDialog::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)
{
TQString title = appClass(); // + "(" + appTitle() + ")";
mMainMenu->changeItem(mShowId, TQIconSet(*pixmap()),
TQString((isWithdrawn() ? i18n("Show %1") : i18n("Hide %1")).arg(title)));
}
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);
TQTimer::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(TQMouseEvent * ev)
{
if (ev->button() == TQt::RightButton)
mMainMenu->popup(ev->globalPos());
else
toggleShow();
}
void CustomTrayLabel::destroyEvent(void)
{
mUndockWhenDead = true;
TQTrayLabel::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 tdedocker xmms.
* TDEDocker 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(TQDropEvent *)
{
TQMessageBox::information(NULL, "TDEDocker",
i18n("You cannot drop an item into the tray icon. Drop it on the window\n"
"that is brought in front when you hover the item over the tray icon"));
}
#include "customtraylabel.moc"