]> vaikene.ee Git - evaf/blob - src/plugins/SdiWindow/sdiwindow.cpp
c0e3587711afa35e00cbab88a421d4c38b634e47
[evaf] / src / plugins / SdiWindow / sdiwindow.cpp
1 /**
2 * @file SdiWindow/sdiwindow.cpp
3 * @brief SdiWindow module's implementation
4 * @author Enar Vaikene
5 *
6 * Copyright (c) 2011 Enar Vaikene
7 *
8 * This file is part of the eVaf C++ cross-platform application development framework.
9 *
10 * This file can be used under the terms of the GNU General Public License
11 * version 3.0 as published by the Free Software Foundation and appearing in
12 * the file LICENSE included in the packaging of this file. Please review the
13 * the following information to ensure the GNU General Public License version
14 * 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
15 *
16 * Alternatively, this file may be used in accordance with the Commercial License
17 * Agreement provided with the Software.
18 */
19
20 #include "sdiwindow.h"
21 #include "version.h"
22
23 #include <Common/iLogger>
24 #include <Common/iRegistry>
25 #include <Common/iApp>
26 #include <Common/iProp>
27
28 #include <QtGui>
29 #include <QXmlStreamReader>
30
31 namespace eVaf {
32 namespace SdiWindow {
33 namespace Internal {
34 /// iSdiWindow interface instance singleton
35 static iSdiWindow * mSdiWindow = 0;
36 } // namespace eVaf::SdiWindow::Internal
37 } // namespace eVaf::SdiWindow
38 } // namespace eVaf
39
40
41 using namespace eVaf;
42
43 //-------------------------------------------------------------------
44
45 SdiWindow::iSdiWindow * SdiWindow::iSdiWindow::instance()
46 {
47 return SdiWindow::Internal::mSdiWindow;
48 }
49
50
51 //-------------------------------------------------------------------
52
53 SdiWindow::Internal::MainWindow::MainWindow(QWidget * parent, Qt::WindowFlags flags)
54 : QWidget(parent, flags)
55 , mReady(false)
56 , mTimerId(0)
57 {
58 setObjectName(QString("%1-%2").arg(VER_MODULE_NAME_STR).arg(__FUNCTION__));
59
60 // Restore geometry
61 restoreSettings();
62
63 // Apply the size specified in a) properties; or b) on the command line (overwrites stored geometry)
64 setWindowSize();
65
66 // Create the default layout
67 mLayout = new QVBoxLayout;
68 setLayout(mLayout);
69
70 mSdiWindow = this;
71
72 EVAF_INFO("%s created", qPrintable(objectName()));
73 }
74
75 SdiWindow::Internal::MainWindow::~MainWindow()
76 {
77 mSdiWindow = 0;
78
79 // Save geometry
80 saveSettings();
81
82 EVAF_INFO("%s destroyed", qPrintable(objectName()));
83 }
84
85 QString SdiWindow::Internal::MainWindow::getMainPanelName(QString const & args) const
86 {
87 QXmlStreamReader xml(args);
88 while (!xml.atEnd()) {
89 xml.readNext();
90 if (xml.isStartElement() && xml.name() == "attributes") {
91 if (xml.attributes().hasAttribute("mainPanelName"))
92 return xml.attributes().value("mainPanelName").toString();
93 }
94 }
95 return QString();
96 }
97
98 bool SdiWindow::Internal::MainWindow::init(QString const & args)
99 {
100 mMainPanelName = getMainPanelName(args);
101
102 Common::iRegistry::instance()->registerInterface("iSdiWindow", this);
103
104 setWindowTitle(Common::iApp::instance()->name());
105
106 // Start the garbage collector timer
107 mTimerId = startTimer(60 * 1000);
108
109 show();
110
111 mReady = true;
112
113 EVAF_INFO("%s initialized", qPrintable(objectName()));
114
115 return true;
116 }
117
118 void SdiWindow::Internal::MainWindow::done()
119 {
120 mReady = false;
121
122 close();
123
124 if (mTimerId) {
125 killTimer(mTimerId);
126 mTimerId = 0;
127 }
128
129 // Delete all the panels
130 for (int i = mPanels.size() - 1; i >= 0; --i) {
131 QWeakPointer<Gui::Panel> p = mPanels.at(i);
132 if (p)
133 delete p.data();
134 }
135 mPanels.clear();
136 mMinimizedPanels.clear();
137 mPanelNames.clear();
138 mMainPanel.clear();
139 mMainPanelName.clear();
140
141 EVAF_INFO("%s finalized", qPrintable(objectName()));
142 }
143
144 void SdiWindow::Internal::MainWindow::addPanel(QString const & name, Gui::Panel * panel)
145 {
146 mPanels.append(panel);
147 mPanelNames.insert(name, panel);
148
149 // If this is the predefined main panel, add it to this window
150 if (!mMainPanelName.isEmpty()) {
151 if (name == mMainPanelName) {
152 mMainPanel = panel;
153 mLayout->addWidget(panel);
154 }
155 }
156
157 // If the predefined main panel name is not set, use the first panel
158 else {
159 if (!mMainPanel) {
160 mMainPanel = panel;
161 mLayout->addWidget(panel);
162 }
163 }
164 }
165
166 Gui::Panel * SdiWindow::Internal::MainWindow::panel(QString const & name) const
167 {
168 QHash<QString, QWeakPointer<Gui::Panel> >::const_iterator it = mPanelNames.constFind(name);
169 if (it != mPanelNames.constEnd())
170 return it.value().data();
171 return 0;
172 }
173
174 bool SdiWindow::Internal::MainWindow::showPanel(QString const & name)
175 {
176 Gui::Panel * p = panel(name);
177 if (p) {
178 p->show();
179 return true;
180 }
181 return false;
182 }
183
184 void SdiWindow::Internal::MainWindow::saveSettings()
185 {
186 static int ver[4] = {VER_FILE_VERSION};
187 QSettings settings(VER_COMPANY_NAME_STR, Common::iApp::instance()->name());
188 settings.setValue(QString("%1/version/major").arg(objectName()), ver[0]);
189 settings.setValue(QString("%1/version/minor").arg(objectName()), ver[1]);
190 settings.setValue(QString("%1/geometry").arg(objectName()), saveGeometry());
191 }
192
193 void SdiWindow::Internal::MainWindow::restoreSettings()
194 {
195 static int ver[4] = {VER_FILE_VERSION};
196 QSettings settings(VER_COMPANY_NAME_STR, Common::iApp::instance()->name());
197
198 // Ignore saved settings if the version number is not the same
199 // More intelligent checks can be implemented to allow upgrading from previous versions
200 QVariant v = settings.value(QString("%1/version/major").arg(objectName()));
201 if (!v.isValid() || v.toInt() != ver[0])
202 return;
203 v = settings.value(QString("%1/version/minor").arg(objectName()));
204 if (!v.isValid() || v.toInt() != ver[1])
205 return;
206
207 // Restore the geometry
208 restoreGeometry(settings.value(QString("%1/geometry").arg(objectName())).toByteArray());
209 }
210
211 void SdiWindow::Internal::MainWindow::setWindowSize()
212 {
213 // a) Get window size from properties
214 int w = Common::iProp::instance()->getValue("windowWidth", 0).toInt();
215 int h = Common::iProp::instance()->getValue("windowHeight", 0).toInt();
216
217 // b) Use command line arguments
218 QStringList args = QApplication::arguments();
219 for (int i = 1; i < args.size(); ++i) {
220 QStringList arg = args.at(i).simplified().split('=');
221 if (QRegExp("-[-]?w[idth]?").exactMatch(arg.at(0)) && arg.size() > 1) {
222 bool ok;
223 int v = arg.at(1).toInt(&ok);
224 if (ok)
225 w = v;
226 }
227 if (QRegExp("-[-]?h[eight]?").exactMatch(arg.at(0)) && arg.size() > 1) {
228 bool ok;
229 int v = arg.at(1).toInt(&ok);
230 if (ok)
231 h = v;
232 }
233 }
234
235 // Resize the window
236 if (w > 0 || h > 0) {
237 QSize sz = sizeHint();
238 if (w > 0)
239 sz.setWidth(w);
240 if (h > 0)
241 sz.setHeight(h);
242 resize(sz);
243 }
244 }
245
246 void SdiWindow::Internal::MainWindow::closeEvent(QCloseEvent * e)
247 {
248 // Try to close all the managed panels; ignore the event if one of the managed panels refuses to close
249 foreach (QWeakPointer<Gui::Panel> p, mPanels) {
250 if (p) {
251 if (!p.data()->close()) {
252 e->ignore();
253 return;
254 }
255 }
256 }
257
258 QWidget::closeEvent(e);
259 }
260
261 void SdiWindow::Internal::MainWindow::changeEvent(QEvent * e)
262 {
263 if (e->type() == QEvent::WindowStateChange) {
264 QWindowStateChangeEvent * wse = static_cast<QWindowStateChangeEvent *>(e);
265
266 if (windowState() == Qt::WindowNoState && wse->oldState() == Qt::WindowMinimized) {
267
268 // Restore all the managed panels that were previously minimized
269 foreach (QWeakPointer<Gui::Panel> p, mMinimizedPanels) {
270 if (p && p.data()->isVisible())
271 p.data()->showNormal();
272 }
273 mMinimizedPanels.clear();
274 }
275
276 else if (windowState() == Qt::WindowMinimized && wse->oldState() != Qt::WindowMinimized) {
277
278 // Minimize all the managed panels that are not minimized yet
279 mMinimizedPanels.clear();
280 foreach (QWeakPointer<Gui::Panel> p, mPanels) {
281 if (!p)
282 continue;
283
284 if (p.data()->windowState() != Qt::WindowMinimized && p.data()->isVisible()) {
285 mMinimizedPanels.append(p);
286 p.data()->showMinimized();
287 }
288 }
289 }
290 }
291 QWidget::changeEvent(e);
292 }
293
294 void SdiWindow::Internal::MainWindow::timerEvent(QTimerEvent * e)
295 {
296 if (e->timerId() == mTimerId) {
297
298 // Remove panels that are deleted
299 {
300 QList<QWeakPointer<Gui::Panel> >::iterator it = mPanels.begin();
301 while (it != mPanels.end()) {
302 QWeakPointer<Gui::Panel> p = *it;
303 if (!p)
304 it = mPanels.erase(it);
305 else
306 ++it;
307 }
308 }
309
310 // Do the same with panel names
311 {
312 QHash<QString, QWeakPointer<Gui::Panel> >::iterator it = mPanelNames.begin();
313 while (it != mPanelNames.end()) {
314 QWeakPointer<Gui::Panel> p = it.value();
315 if (!p)
316 it = mPanelNames.erase(it);
317 else
318 ++it;
319 }
320 }
321 }
322 else
323 QWidget::timerEvent(e);
324 }
325
326
327 //-------------------------------------------------------------------
328
329 SdiWindow::Internal::SdiWindowPlugin::SdiWindowPlugin()
330 : Plugins::iPlugin()
331 {
332 setObjectName(VER_MODULE_NAME_STR);
333
334 mWindow = new MainWindow;
335
336 EVAF_INFO("%s created", qPrintable(objectName()));
337 }
338
339 SdiWindow::Internal::SdiWindowPlugin::~SdiWindowPlugin()
340 {
341 delete mWindow;
342
343 EVAF_INFO("%s destroyed", qPrintable(objectName()));
344 }
345
346 bool SdiWindow::Internal::SdiWindowPlugin::init(const QString & args)
347 {
348 if (!mWindow->init(args))
349 return false;
350
351 EVAF_INFO("%s initialized", qPrintable(objectName()));
352
353 return true;
354 }
355
356 void SdiWindow::Internal::SdiWindowPlugin::done()
357 {
358 mWindow->done();
359
360 EVAF_INFO("%s finalized", qPrintable(objectName()));
361 }