summaryrefslogtreecommitdiffstats
path: root/src/customtraylabel.cpp
diff options
context:
space:
mode:
authorSlávek Banko <[email protected]>2013-07-05 19:06:59 +0200
committerSlávek Banko <[email protected]>2013-07-05 19:06:59 +0200
commit14286a0eb6ec163c90e3d13c27fea147dbb82481 (patch)
treea5d70bd732b00ec833525dc1d25abc80f2d49144 /src/customtraylabel.cpp
downloadtdedocker-14286a0eb6ec163c90e3d13c27fea147dbb82481.tar.gz
tdedocker-14286a0eb6ec163c90e3d13c27fea147dbb82481.zip
Initial import
Diffstat (limited to 'src/customtraylabel.cpp')
-rw-r--r--src/customtraylabel.cpp360
1 files changed, 360 insertions, 0 deletions
diff --git a/src/customtraylabel.cpp b/src/customtraylabel.cpp
new file mode 100644
index 0000000..aca36e1
--- /dev/null
+++ b/src/customtraylabel.cpp
@@ -0,0 +1,360 @@
+/*
+ * 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 "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(QString(ICONS_PATH) + "/kdocker.png");
+ if (kdocker_png.isNull())
+ kdocker_png.load(qApp->applicationDirPath() + "/icons/kdocker.png");
+ setIcon(kdocker_png);
+ TrayLabelMgr *tlMgr = TrayLabelMgr::instance();
+
+ mOptionsMenu = new QPopupMenu(this);
+ mSessionManagement = new QAction(tr("Dock when session restored"), 0, this);
+ mSessionManagement->setToggleAction(true);
+ connect(mSessionManagement, SIGNAL(toggled(bool)),
+ this, SLOT(enableSessionManagement(bool)));
+ mSessionManagement->addTo(mOptionsMenu);
+
+ mAutoLaunch = new QAction(tr("Launch on startup"), 0, this);
+ mAutoLaunch->setToggleAction(true);
+ connect(mAutoLaunch, SIGNAL(activated()),
+ this, SLOT(slotSetLaunchOnStartup()));
+ mAutoLaunch->addTo(mOptionsMenu);
+
+ mOptionsMenu->insertItem(tr("Set Icon"), this, SLOT(setCustomIcon()));
+
+ mBalloonTimeout = new QAction(tr("Set balloon timeout"), 0, this);
+ connect(mBalloonTimeout, SIGNAL(activated()),
+ this, SLOT(slotSetBalloonTimeout()));
+ mBalloonTimeout->addTo(mOptionsMenu);
+
+ mDockWhenObscured = new QAction(tr("Dock when obscured"), 0, this);
+ mDockWhenObscured->setToggleAction(true);
+ connect(mDockWhenObscured, SIGNAL(toggled(bool)),
+ this, SLOT(setDockWhenObscured(bool)));
+ mDockWhenObscured->addTo(mOptionsMenu);
+
+ mDockWhenMinimized = new QAction(tr("Dock when minimized"), 0, this);
+ mDockWhenMinimized->setToggleAction(true);
+ connect(mDockWhenMinimized, SIGNAL(toggled(bool)),
+ this, SLOT(setDockWhenMinimized(bool)));
+ mDockWhenMinimized->addTo(mOptionsMenu);
+
+ mDockWhenFocusLost = new QAction(tr("Dock when focus lost"), 0, this);
+ mDockWhenFocusLost->setToggleAction(true);
+ connect(mDockWhenFocusLost, SIGNAL(toggled(bool)),
+ this, SLOT(setDockWhenFocusLost(bool)));
+ mDockWhenFocusLost->addTo(mOptionsMenu);
+
+ mSkipTaskbar = new QAction(tr("Skip taskbar"), 0, this);
+ mSkipTaskbar->setToggleAction(true);
+ connect(mSkipTaskbar, SIGNAL(toggled(bool)),
+ this, SLOT(setSkipTaskbar(bool)));
+ mSkipTaskbar->addTo(mOptionsMenu);
+
+ mMainMenu = new QPopupMenu(this);
+ mMainMenu->insertItem(QIconSet(kdocker_png),
+ tr("About KDocker"), tlMgr, SLOT(about()));
+ mMainMenu->insertSeparator();
+ mMainMenu->insertItem(tr("Options"), mOptionsMenu);
+ mMainMenu->insertItem(tr("Dock Another"), tlMgr, SLOT(dockAnother()));
+ mMainMenu->insertItem(tr("Undock All"), tlMgr, SLOT(undockAll()));
+ mMainMenu->insertSeparator();
+
+ mShowId = mMainMenu->insertItem(QString("Show/Hide [untitled]"),
+ this, SLOT(toggleShow()));
+ mMainMenu->insertItem(QString(tr("Undock")), this, SLOT(undock()));
+ mMainMenu->insertItem(QString(tr("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(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, tr("KDocker"),
+ tr("%1 is not a valid icon").arg(icon));
+ }
+
+ setTrayIcon(icon);
+}
+
+// Get balloon timeout from the user
+void CustomTrayLabel::slotSetBalloonTimeout(void)
+{
+ bool ok;
+ int timeout = QInputDialog::getInteger(tr("KDocker"),
+ tr("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;
+ 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, tr("KDocker"),
+ tr("\"%1\" is not a valid executable "
+ "or was not found in your $PATH").arg(app),
+ tr("Select program"), tr("Cancel")) == 1)
+ {
+ 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() ? tr("Show %1") : tr("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);
+ 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",
+ tr("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"));
+}
+