1 /*
2  * Copyright (C) 2003 by Scott Monachello <smonach@cox.net>
3  * Copyright (C) 2019  Alexander Potashev <aspotashev@gmail.com>
4  *
5  *   This program is free software; you can redistribute it and/or modify
6  *   it under the terms of the GNU General Public License as published by
7  *   the Free Software Foundation; either version 2 of the License, or
8  *   (at your option) any later version.
9  *
10  *   This program is distributed in the hope that it will be useful,
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *   GNU General Public License for more details.
14  *
15  *   You should have received a copy of the GNU General Public License along
16  *   with this program; if not, write to the
17  *      Free Software Foundation, Inc.
18  *      51 Franklin Street, Fifth Floor
19  *      Boston, MA  02110-1301  USA.
20  *
21  */
22 
23 /*
24  * TrayIcon.
25  *
26  * This implements the functionality of the little icon in the kpanel
27  * tray. Among which are tool tips and the running clock animated icon
28  */
29 
30 #include "tray.h"
31 
32 #include <QApplication>
33 #include <QDesktopWidget>
34 #include <QMenu>
35 #include <QMovie>
36 #include <QToolTip>
37 
38 #include <KLocalizedString>
39 
40 #include "ktt_debug.h"
41 #include "mainwindow.h"
42 #include "model/task.h"
43 #include "timetrackerwidget.h"
44 
TrayIcon(MainWindow * parent)45 TrayIcon::TrayIcon(MainWindow* parent)
46     : KStatusNotifierItem(parent)
47 {
48     Q_INIT_RESOURCE(pics);
49 
50     setObjectName("Ktimetracker Tray");
51 
52     m_animation = new QMovie(":/pics/active-icon.gif", QByteArray("GIF"), this);
53     connect(m_animation, &QMovie::frameChanged, this, &TrayIcon::setActiveIcon);
54     m_animation->jumpToFrame(0);
55 
56     auto* widget = dynamic_cast<TimeTrackerWidget*>(parent->centralWidget());
57     if (widget) {
58         QAction* action = widget->action("configure_ktimetracker");
59         if (action) {
60             contextMenu()->addAction(action);
61         }
62 
63         action = widget->action("stopAll");
64         if (action) {
65             contextMenu()->addAction(action);
66         }
67     }
68 
69     updateToolTip(QList<Task*>());
70 }
71 
startClock()72 void TrayIcon::startClock()
73 {
74     m_animation->start();
75 }
76 
stopClock()77 void TrayIcon::stopClock()
78 {
79     m_animation->stop();
80 }
81 
setActiveIcon(int)82 void TrayIcon::setActiveIcon(int /*unused*/)
83 {
84     setIconByPixmap(QIcon(m_animation->currentPixmap()));
85 }
86 
updateToolTip(const QList<Task * > & activeTasks)87 void TrayIcon::updateToolTip(const QList<Task*> &activeTasks)
88 {
89     if (activeTasks.isEmpty()) {
90         this->setToolTip( "ktimetracker", "ktimetracker", i18n("No active tasks") );
91         return;
92     }
93 
94     QFontMetrics fm(QToolTip::font());
95     const QString continued = i18nc("ellipsis to truncate long list of tasks", ", ...");
96     const int buffer = fm.boundingRect(continued).width();
97     const int desktopWidth = QApplication::desktop()->screenGeometry(associatedWidget()).width();
98     const int maxWidth = desktopWidth - buffer;
99 
100     QString qTip;
101     QString s;
102 
103     // Build the tool tip with all of the names of the active tasks.
104     // If at any time the width of the tool tip is larger than the desktop,
105     // stop building it.
106 
107     for (int i = 0; i < activeTasks.count(); ++i) {
108         Task* task = activeTasks.at(i);
109         if (i > 0) {
110             s += i18nc("separator between task names", ", ") + task->name();
111         } else {
112             s += task->name();
113         }
114 
115         int width = fm.boundingRect(s).width();
116         if (width > maxWidth) {
117             qTip += continued;
118             break;
119         }
120         qTip = s;
121     }
122     this->setToolTip("ktimetracker", "ktimetracker", qTip);
123 }
124