/* * 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 #include #include #include #include #include #include #include #include #include #include #include #include "trace.h" #include "customtraylabel.h" #include "traylabelmgr.h" #include "kdocker.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 kdocker_png(TDEGlobal::iconLoader()->loadIcon("kdocker", TDEIcon::NoGroup, TDEIcon::SizeSmall)); setIcon(kdocker_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(kdocker_png), i18n("About KDocker"), 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("KDocker"), 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("KDocker"), 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("KDocker"), 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 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(TQDropEvent *) { TQMessageBox::information(NULL, "KDocker", 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"