modernize: Reformat ALL the source... again!
[quassel.git] / src / uisupport / graphicalui.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005-2018 by the Quassel Project                        *
3  *   devel@quassel-irc.org                                                 *
4  *                                                                         *
5  *   This contains code from KStatusNotifierItem, part of the KDE libs     *
6  *   Copyright (C) 2009 Marco Martin <notmart@gmail.com>                   *
7  *                                                                         *
8  *   This program is free software; you can redistribute it and/or modify  *
9  *   it under the terms of the GNU General Public License as published by  *
10  *   the Free Software Foundation; either version 2 of the License, or     *
11  *   (at your option) version 3.                                           *
12  *                                                                         *
13  *   This program is distributed in the hope that it will be useful,       *
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
16  *   GNU General Public License for more details.                          *
17  *                                                                         *
18  *   You should have received a copy of the GNU General Public License     *
19  *   along with this program; if not, write to the                         *
20  *   Free Software Foundation, Inc.,                                       *
21  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
22  ***************************************************************************/
23
24 #include "graphicalui.h"
25
26 #include "actioncollection.h"
27 #include "contextmenuactionprovider.h"
28 #include "toolbaractionprovider.h"
29 #include "uisettings.h"
30
31 #ifdef Q_WS_X11
32 #    include <QX11Info>
33 #endif
34
35 QWidget* GraphicalUi::_mainWidget = nullptr;
36 QHash<QString, ActionCollection*> GraphicalUi::_actionCollections;
37 ContextMenuActionProvider* GraphicalUi::_contextMenuActionProvider = nullptr;
38 ToolBarActionProvider* GraphicalUi::_toolBarActionProvider = nullptr;
39 UiStyle* GraphicalUi::_uiStyle = nullptr;
40
41 GraphicalUi::GraphicalUi(QObject* parent)
42     : AbstractUi(parent)
43     , Singleton<GraphicalUi>(this)
44 {
45     Q_INIT_RESOURCE(pics);
46     Q_INIT_RESOURCE(hicolor_icons);
47 #ifdef EMBED_DATA
48     Q_INIT_RESOURCE(icons);
49     Q_INIT_RESOURCE(iconthemes);
50 #endif
51
52 #ifdef Q_OS_WIN
53     _dwTickCount = 0;
54 #endif
55 #ifdef Q_OS_MAC
56     GetFrontProcess(&_procNum);
57 #endif
58 }
59
60 void GraphicalUi::init()
61 {
62 #ifdef Q_OS_WIN
63     mainWidget()->installEventFilter(this);
64 #endif
65 }
66
67 ActionCollection* GraphicalUi::actionCollection(const QString& category, const QString& translatedCategory)
68 {
69     if (_actionCollections.contains(category))
70         return _actionCollections.value(category);
71     auto* coll = new ActionCollection(_mainWidget);
72
73     if (!translatedCategory.isEmpty())
74         coll->setProperty("Category", translatedCategory);
75     else
76         coll->setProperty("Category", category);
77
78     if (_mainWidget)
79         coll->addAssociatedWidget(_mainWidget);
80     _actionCollections.insert(category, coll);
81     return coll;
82 }
83
84 QHash<QString, ActionCollection*> GraphicalUi::actionCollections()
85 {
86     return _actionCollections;
87 }
88
89 void GraphicalUi::loadShortcuts()
90 {
91     foreach (ActionCollection* coll, actionCollections())
92         coll->readSettings();
93 }
94
95 void GraphicalUi::saveShortcuts()
96 {
97     ShortcutSettings s;
98     s.clear();
99     foreach (ActionCollection* coll, actionCollections())
100         coll->writeSettings();
101 }
102
103 void GraphicalUi::setMainWidget(QWidget* widget)
104 {
105     _mainWidget = widget;
106 }
107
108 void GraphicalUi::setContextMenuActionProvider(ContextMenuActionProvider* provider)
109 {
110     _contextMenuActionProvider = provider;
111 }
112
113 void GraphicalUi::setToolBarActionProvider(ToolBarActionProvider* provider)
114 {
115     _toolBarActionProvider = provider;
116 }
117
118 void GraphicalUi::setUiStyle(UiStyle* style)
119 {
120     _uiStyle = style;
121 }
122
123 void GraphicalUi::disconnectedFromCore()
124 {
125     _contextMenuActionProvider->disconnectedFromCore();
126     _toolBarActionProvider->disconnectedFromCore();
127     AbstractUi::disconnectedFromCore();
128 }
129
130 bool GraphicalUi::eventFilter(QObject* obj, QEvent* event)
131 {
132 #ifdef Q_OS_WIN
133     if (obj == mainWidget() && event->type() == QEvent::ActivationChange) {
134         _dwTickCount = GetTickCount();
135     }
136 #endif
137     return AbstractUi::eventFilter(obj, event);
138 }
139
140 // NOTE: Window activation stuff seems to work just fine in Plasma 5 without requiring X11 hacks.
141 // TODO: Evaluate cleaning all this up once we can get rid of Qt4/KDE4
142
143 // Code taken from KStatusNotifierItem for handling minimize/restore
144
145 bool GraphicalUi::checkMainWidgetVisibility(bool perform)
146 {
147 #ifdef Q_OS_WIN
148     // the problem is that we lose focus when the systray icon is activated
149     // and we don't know the former active window
150     // therefore we watch for activation event and use our stopwatch :)
151     if (GetTickCount() - _dwTickCount < 300) {
152         // we were active in the last 300ms -> hide it
153         if (perform)
154             minimizeRestore(false);
155         return false;
156     }
157     else {
158         if (perform)
159             minimizeRestore(true);
160         return true;
161     }
162
163 #else
164
165     if (!mainWidget()->isVisible() || mainWidget()->isMinimized() || !mainWidget()->isActiveWindow()) {
166         if (perform)
167             minimizeRestore(true);
168         return true;
169     }
170     else {
171         if (perform)
172             minimizeRestore(false);
173         return false;
174     }
175
176 #endif
177
178     return true;
179 }
180
181 bool GraphicalUi::isMainWidgetVisible()
182 {
183     return !instance()->checkMainWidgetVisibility(false);
184 }
185
186 void GraphicalUi::minimizeRestore(bool show)
187 {
188     if (show)
189         activateMainWidget();
190     else
191         hideMainWidget();
192 }
193
194 void GraphicalUi::activateMainWidget()
195 {
196 #ifdef Q_WS_X11
197     // Bypass focus stealing prevention
198     QX11Info::setAppUserTime(QX11Info::appTime());
199 #endif
200
201     if (mainWidget()->windowState() & Qt::WindowMinimized) {
202         // restore
203         mainWidget()->setWindowState((mainWidget()->windowState() & ~Qt::WindowMinimized) | Qt::WindowActive);
204     }
205
206     // this does not actually work on all platforms... and causes more evil than good
207     // mainWidget()->move(mainWidget()->frameGeometry().topLeft()); // avoid placement policies
208 #ifdef Q_OS_MAC
209     SetFrontProcess(&instance()->_procNum);
210 #else
211     mainWidget()->show();
212     mainWidget()->raise();
213     mainWidget()->activateWindow();
214 #endif
215 }
216
217 void GraphicalUi::hideMainWidget()
218 {
219     if (instance()->isHidingMainWidgetAllowed())
220 #ifdef Q_OS_MAC
221         ShowHideProcess(&instance()->_procNum, false);
222 #else
223         mainWidget()->hide();
224 #endif
225 }
226
227 void GraphicalUi::toggleMainWidget()
228 {
229     instance()->checkMainWidgetVisibility(true);
230 }