]> vaikene.ee Git - evaf/blob - src/plugins/SdiWindow/sdiwindow.cpp
eb1a449ab3f84dc6884972f3da38e0a82481da4f
[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 <QtWidgets>
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 {
57 setObjectName(QString("%1-%2").arg(VER_MODULE_NAME_STR).arg(__FUNCTION__));
58
59 // Restore geometry
60 restoreSettings();
61
62 // Apply the size specified in a) properties; or b) on the command line (overwrites stored geometry)
63 setWindowSize();
64
65 // Create the default layout
66 mLayout = new QVBoxLayout;
67 setLayout(mLayout);
68
69 mSdiWindow = this;
70
71 EVAF_INFO("%s created", qPrintable(objectName()));
72 }
73
74 SdiWindow::Internal::MainWindow::~MainWindow()
75 {
76 mSdiWindow = 0;
77
78 // Save geometry
79 saveSettings();
80
81 EVAF_INFO("%s destroyed", qPrintable(objectName()));
82 }
83
84 QString SdiWindow::Internal::MainWindow::getMainPanelName(QString const & args) const
85 {
86 QXmlStreamReader xml(args);
87 while (!xml.atEnd()) {
88 xml.readNext();
89 if (xml.isStartElement() && xml.name() == "attributes") {
90 if (xml.attributes().hasAttribute("mainPanelName"))
91 return xml.attributes().value("mainPanelName").toString();
92 }
93 }
94 return QString();
95 }
96
97 bool SdiWindow::Internal::MainWindow::init(QString const & args)
98 {
99 mMainPanelName = getMainPanelName(args);
100
101 Common::iRegistry::instance()->registerInterface("iSdiWindow", this);
102
103 setWindowTitle(Common::iApp::instance()->name());
104
105 show();
106
107 mReady = true;
108
109 EVAF_INFO("%s initialized", qPrintable(objectName()));
110
111 return true;
112 }
113
114 void SdiWindow::Internal::MainWindow::done()
115 {
116 mReady = false;
117
118 close();
119
120 // Delete all the panels
121 for (int i = mPanels.size() - 1; i >= 0; --i) {
122 disconnect(mPanels.at(i), SIGNAL(destroyed(QObject *)), this, SLOT(panelDestroyed(QObject *)));
123 delete mPanels.at(i);
124 }
125 mPanels.clear();
126 mMinimizedPanels.clear();
127 mPanelNames.clear();
128 mMainPanel = 0;
129 mMainPanelName.clear();
130
131 EVAF_INFO("%s finalized", qPrintable(objectName()));
132 }
133
134 void SdiWindow::Internal::MainWindow::addPanel(QString const & name, Gui::Panel * panel)
135 {
136 connect(panel, SIGNAL(destroyed(QObject *)), this, SLOT(panelDestroyed(QObject*)));
137 mPanels.append(panel);
138 mPanelNames.insert(name, panel);
139
140 // If this is the predefined main panel, add it to this window
141 if (!mMainPanelName.isEmpty()) {
142 if (name == mMainPanelName) {
143 mMainPanel = panel;
144 mLayout->addWidget(panel);
145 }
146 }
147
148 // If the predefined main panel name is not set, use the first panel
149 else {
150 if (!mMainPanel) {
151 mMainPanel = panel;
152 mLayout->addWidget(panel);
153 }
154 }
155 }
156
157 Gui::Panel * SdiWindow::Internal::MainWindow::panel(QString const & name) const
158 {
159 QHash<QString, Gui::Panel *>::const_iterator it = mPanelNames.constFind(name);
160 if (it != mPanelNames.constEnd())
161 return it.value();
162 return 0;
163 }
164
165 bool SdiWindow::Internal::MainWindow::showPanel(QString const & name)
166 {
167 Gui::Panel * p = panel(name);
168 if (p) {
169 p->show();
170 return true;
171 }
172 return false;
173 }
174
175 void SdiWindow::Internal::MainWindow::saveSettings()
176 {
177 static int ver[4] = {VER_FILE_VERSION};
178 QSettings settings(VER_COMPANY_NAME_STR, Common::iApp::instance()->name());
179 settings.setValue(QString("%1/version/major").arg(objectName()), ver[0]);
180 settings.setValue(QString("%1/version/minor").arg(objectName()), ver[1]);
181 settings.setValue(QString("%1/geometry").arg(objectName()), saveGeometry());
182 }
183
184 void SdiWindow::Internal::MainWindow::restoreSettings()
185 {
186 static int ver[4] = {VER_FILE_VERSION};
187 QSettings settings(VER_COMPANY_NAME_STR, Common::iApp::instance()->name());
188
189 // Ignore saved settings if the version number is not the same
190 // More intelligent checks can be implemented to allow upgrading from previous versions
191 QVariant v = settings.value(QString("%1/version/major").arg(objectName()));
192 if (!v.isValid() || v.toInt() != ver[0])
193 return;
194 v = settings.value(QString("%1/version/minor").arg(objectName()));
195 if (!v.isValid() || v.toInt() != ver[1])
196 return;
197
198 // Restore the geometry
199 restoreGeometry(settings.value(QString("%1/geometry").arg(objectName())).toByteArray());
200 }
201
202 void SdiWindow::Internal::MainWindow::setWindowSize()
203 {
204 // a) Get window size from properties
205 int w = Common::iProp::instance()->getValue("windowWidth", 0).toInt();
206 int h = Common::iProp::instance()->getValue("windowHeight", 0).toInt();
207
208 // b) Use command line arguments
209 QStringList args = QApplication::arguments();
210 for (int i = 1; i < args.size(); ++i) {
211 QStringList arg = args.at(i).simplified().split('=');
212 if (QRegExp("-[-]?w[idth]?").exactMatch(arg.at(0)) && arg.size() > 1) {
213 bool ok;
214 int v = arg.at(1).toInt(&ok);
215 if (ok)
216 w = v;
217 }
218 if (QRegExp("-[-]?h[eight]?").exactMatch(arg.at(0)) && arg.size() > 1) {
219 bool ok;
220 int v = arg.at(1).toInt(&ok);
221 if (ok)
222 h = v;
223 }
224 }
225
226 // Resize the window
227 if (w > 0 || h > 0) {
228 QSize sz = sizeHint();
229 if (w > 0)
230 sz.setWidth(w);
231 if (h > 0)
232 sz.setHeight(h);
233 resize(sz);
234 }
235 }
236
237 void SdiWindow::Internal::MainWindow::closeEvent(QCloseEvent * e)
238 {
239 // Try to close all the managed panels; ignore the event if one of the managed panels refuses to close
240 foreach (Gui::Panel * p, mPanels) {
241 if (!p->close()) {
242 e->ignore();
243 return;
244 }
245 }
246
247 QWidget::closeEvent(e);
248 }
249
250 void SdiWindow::Internal::MainWindow::changeEvent(QEvent * e)
251 {
252 if (e->type() == QEvent::WindowStateChange) {
253 QWindowStateChangeEvent * wse = static_cast<QWindowStateChangeEvent *>(e);
254
255 if (windowState() == Qt::WindowNoState && wse->oldState() == Qt::WindowMinimized) {
256
257 // Restore all the managed panels that were previously minimized
258 foreach (Gui::Panel * p, mMinimizedPanels) {
259 if (p->isVisible())
260 p->showNormal();
261 }
262 mMinimizedPanels.clear();
263 }
264
265 else if (windowState() == Qt::WindowMinimized && wse->oldState() != Qt::WindowMinimized) {
266
267 // Minimize all the managed panels that are not minimized yet
268 mMinimizedPanels.clear();
269 foreach (Gui::Panel * p, mPanels) {
270 if (p->windowState() != Qt::WindowMinimized && p->isVisible()) {
271 mMinimizedPanels.append(p);
272 p->showMinimized();
273 }
274 }
275 }
276 }
277 QWidget::changeEvent(e);
278 }
279
280 void SdiWindow::Internal::MainWindow::panelDestroyed(QObject * obj)
281 {
282 // Remove panels that are deleted
283 {
284 QList<Gui::Panel *>::iterator it = mPanels.begin();
285 while (it != mPanels.end()) {
286 if (*it == obj) {
287 it = mPanels.erase(it);
288 }
289 else {
290 ++it;
291 }
292 }
293 }
294
295 // Do the same with panel names
296 {
297 QHash<QString, Gui::Panel *>::iterator it = mPanelNames.begin();
298 while (it != mPanelNames.end()) {
299 if (it.value() == obj) {
300 it = mPanelNames.erase(it);
301 }
302 else {
303 ++it;
304 }
305 }
306 }
307
308 if (mMainPanel == obj) {
309 mMainPanel = 0;
310 }
311 }
312
313
314 //-------------------------------------------------------------------
315
316 SdiWindow::Internal::SdiWindowPlugin::SdiWindowPlugin()
317 : Plugins::iPlugin()
318 {
319 setObjectName(VER_MODULE_NAME_STR);
320
321 mWindow = new MainWindow;
322
323 EVAF_INFO("%s created", qPrintable(objectName()));
324 }
325
326 SdiWindow::Internal::SdiWindowPlugin::~SdiWindowPlugin()
327 {
328 delete mWindow;
329
330 EVAF_INFO("%s destroyed", qPrintable(objectName()));
331 }
332
333 bool SdiWindow::Internal::SdiWindowPlugin::init(const QString & args)
334 {
335 if (!mWindow->init(args))
336 return false;
337
338 EVAF_INFO("%s initialized", qPrintable(objectName()));
339
340 return true;
341 }
342
343 void SdiWindow::Internal::SdiWindowPlugin::done()
344 {
345 mWindow->done();
346
347 EVAF_INFO("%s finalized", qPrintable(objectName()));
348 }