/* * 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 #include #include #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 TDEToggleAction(i18n("Dock when session restored"), 0, this); connect(mSessionManagement, SIGNAL(toggled(bool)), this, SLOT(enableSessionManagement(bool))); mSessionManagement->plug(mOptionsMenu); mOptionsMenu->insertItem(i18n("Set Icon"), this, SLOT(setCustomIcon())); mBalloonTimeout = new TDEAction(i18n("Set balloon timeout"), 0, this); connect(mBalloonTimeout, SIGNAL(activated()), this, SLOT(slotSetBalloonTimeout())); mBalloonTimeout->plug(mOptionsMenu); mDockWhenObscured = new TDEToggleAction(i18n("Dock when obscured"), 0, this); mDockWhenObscured->plug(mOptionsMenu); mDockIfMinimized = new TDEToggleAction(i18n("Dock when minimized"), 0, this); connect(mDockIfMinimized, SIGNAL(toggled(bool)), this, SLOT(setDockWhenMinimized(bool))); mDockIfMinimized->plug(mOptionsMenu); mDockWhenFocusLost = new TDEToggleAction(i18n("Dock when focus lost"), 0, this); mDockWhenFocusLost->plug(mOptionsMenu); mSkipTaskbar = new TDEToggleAction(i18n("Skip taskbar"), 0, this); connect(mSkipTaskbar, SIGNAL(toggled(bool)), this, SLOT(setSkipTaskbar(bool))); mSkipTaskbar->plug(mOptionsMenu); mMainMenu = new TDEPopupMenu(this); mMainMenu->insertItem(i18n("Options"), mOptionsMenu); mMainMenu->insertItem(i18n("Dock Another"), tlMgr, SLOT(dockAnother())); mMainMenu->insertItem(i18n("Undock All"), tlMgr, SLOT(undockAll())); mMainMenu->insertItem(i18n("Quit All"), tlMgr, SLOT(quitAll())); 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); mDockIfMinimized->setChecked(isDockWhenMinimized()); mSkipTaskbar->setChecked(isSkippingTaskbar()); setAcceptDrops(true); // and you thought this function only installs the menu } void CustomTrayLabel::enableSessionManagement(bool sm) { mSessionManagement->setChecked(!appName().isEmpty() && sm); } // Session Management bool CustomTrayLabel::restoreState(TDEConfig *config) { setDockWhenObscured(config->readBoolEntry("DockWhenObscured", false)); TRACE("DWM=%i DWO=%i", isDockWhenMinimized(), mDockWhenObscured->isChecked()); return TQTrayLabel::restoreState(config); } bool CustomTrayLabel::saveState(TDEConfig *config) { if (!mSessionManagement->isChecked()) { return false; } if (!TQTrayLabel::saveState(config)) { return false; } config->writeEntry("DockWhenObscured", mDockWhenObscured->isChecked()); TRACE("WM=%i DWO=%i", isDockWhenMinimized(), mDockWhenObscured->isChecked()); 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; } void CustomTrayLabel::setAppName(const TQString& name) { //FIXME HACK relies on window and application name being the same. 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->isChecked()) { /* * 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->setChecked(false); TQTimer::singleShot(800, mDockWhenObscured, SLOT(toggle())); TRACE("Turning off DWO for some time"); } } void CustomTrayLabel::obscureEvent(void) { TRACE("obscureEvent"); if (mDockWhenObscured->isChecked() && !isWithdrawn()) withdraw(); } void CustomTrayLabel::focusLostEvent() { if (mDockWhenFocusLost->isChecked()) { 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"