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

313 lines
9.5 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 <tdepopupmenu.h>
#include <tqfiledialog.h>
#include <tqinputdialog.h>
#include <tqtimer.h>
#include <stdlib.h>
#include <khelpmenu.h>
#include <kstdaction.h>
#include <kiconloader.h>
#include <kstdguiitem.h>
#include <tdeaction.h>
#include <tdeconfig.h>
#include <tdeglobal.h>
#include <tdelocale.h>
#include <tdemessagebox.h>
#include "trace.h"
#include "traylabelmgr.h"
#include "customtraylabel.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));
setIcon(tdedocker_png);
TrayLabelMgr *tlMgr = TrayLabelMgr::instance();
mOptionsMenu = new TDEPopupMenu(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);
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(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->insertSeparator();
mMainMenu->insertItem(SmallIcon("help"),KStdGuiItem::help().text(), (new KHelpMenu(this, TDEGlobal::instance()->aboutData()))->menu(), false);
TDEAction *quitAction = KStdAction::quit(this, SLOT(close()), NULL);
quitAction->plug(mMainMenu);
connect(mMainMenu, SIGNAL(aboutToShow()), this, SLOT(updateMenu()));
// Apply defaults here
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(TDEConfig *config)
{
setDockWhenObscured(config->readBoolEntry("DockWhenObscured", false));
TRACE("DWM=%i DWO=%i", isDockWhenMinimized(), isDockWhenObscured());
return TQTrayLabel::restoreState(config);
}
void CustomTrayLabel::saveState(TDEConfig *config)
{
if (!mSessionManagement->isOn()) return;
TQTrayLabel::saveState(config);
config->writeEntry("DockWhenObscured", isDockWhenObscured());
TRACE("WM=%i DWO=%i", isDockWhenMinimized(), isDockWhenObscured());
}
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.local8Bit());
KMessageBox::error(this, i18n("%1 is not a valid icon").arg(icon), i18n("TDEDocker"));
}
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);
}
// 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());
/* contextMenuAboutToShow(contextMenu());
contextMenu()->popup(e->globalPos());
e->accept();
return;*/
}
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 *)
{
KMessageBox::error(NULL, 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"), i18n("TDEDocker"));
}
#include "customtraylabel.moc"