1 /****************************************************************************
2 * MeshLab                                                           o o     *
3 * An extendible mesh processor                                    o     o   *
4 *                                                                _   O  _   *
5 * Copyright(C) 2005, 2006                                          \/)\/    *
6 * Visual Computing Lab                                            /\/|      *
7 * ISTI - Italian National Research Council                           |      *
8 *                                                                    \      *
9 * All rights reserved.                                                      *
10 *                                                                           *
11 * This program is free software; you can redistribute it and/or modify      *
12 * it under the terms of the GNU General Public License as published by      *
13 * the Free Software Foundation; either version 2 of the License, or         *
14 * (at your option) any later version.                                       *
15 *                                                                           *
16 * This program is distributed in the hope that it will be useful,           *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
19 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
20 * for more details.                                                         *
21 *                                                                           *
22 ****************************************************************************/
23 
24 
25 #include "../common/interfaces.h"
26 #include "../common/xmlfilterinfo.h"
27 #include "../common/searcher.h"
28 #include "../common/mlapplication.h"
29 
30 #include <QToolBar>
31 #include <QProgressBar>
32 #include <QNetworkAccessManager>
33 #include <QNetworkRequest>
34 #include <QNetworkReply>
35 #include <QFileOpenEvent>
36 #include <QFile>
37 #include <QtXml>
38 #include <QSysInfo>
39 #include <QDesktopServices>
40 #include <QStatusBar>
41 #include <QMenuBar>
42 #include <QWidgetAction>
43 #include "mainwindow.h"
44 #include "plugindialog.h"
45 #include "customDialog.h"
46 #include "saveSnapshotDialog.h"
47 #include "ui_congratsDialog.h"
48 
49 
50 
51 QProgressBar *MainWindow::qb;
52 
MainWindow()53 MainWindow::MainWindow()
54 	:mwsettings(), gpumeminfo(NULL), xmlfiltertimer(), wama()
55 {
56 	_currviewcontainer = NULL;
57 	//xmlfiltertimer will be called repeatedly, so like Qt documentation suggests, the first time start function should be called.
58 	//Subsequently restart function will be invoked.
59 	setContextMenuPolicy(Qt::NoContextMenu);
60 	xmlfiltertimer.start();
61 	//xmlfiltertimer.elapsed();
62 
63 	//workspace = new QWorkspace(this);
64 	mdiarea = new QMdiArea(this);
65 	layerDialog = new LayerDialog(this);
66 	connect(layerDialog, SIGNAL(toBeShow()), this, SLOT(updateLayerDialog()));
67 	layerDialog->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
68 	layerDialog->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
69 	addDockWidget(Qt::RightDockWidgetArea, layerDialog);
70 
71 
72 	//setCentralWidget(workspace);
73 	setCentralWidget(mdiarea);
74 	windowMapper = new QSignalMapper(this);
75 	// Permette di passare da una finestra all'altra e tenere aggiornato il workspace
76 	connect(windowMapper, SIGNAL(mapped(QWidget*)), this, SLOT(wrapSetActiveSubWindow(QWidget *)));
77 	// Quando si passa da una finestra all'altra aggiorna lo stato delle toolbar e dei menu
78 	connect(mdiarea, SIGNAL(subWindowActivated(QMdiSubWindow *)), this, SLOT(switchCurrentContainer(QMdiSubWindow *)));
79 	httpReq = new QNetworkAccessManager(this);
80 	connect(httpReq, SIGNAL(finished(QNetworkReply*)), this, SLOT(connectionDone(QNetworkReply*)));
81 
82 	QIcon icon;
83 	icon.addPixmap(QPixmap(":images/eye48.png"));
84 	setWindowIcon(icon);
85 	PM.loadPlugins(defaultGlobalParams);
86 	QSettings settings;
87 	QVariant vers = settings.value(MeshLabApplication::versionRegisterKeyName());
88 	//should update those values only after I run MeshLab for the very first time or after I installed a new version
89 	if (!vers.isValid() || vers.toString() < MeshLabApplication::appVer())
90 	{
91 		settings.setValue(MeshLabApplication::pluginsPathRegisterKeyName(), PluginManager::getDefaultPluginDirPath());
92 		settings.setValue(MeshLabApplication::versionRegisterKeyName(), MeshLabApplication::appVer());
93 		settings.setValue(MeshLabApplication::wordSizeKeyName(), QSysInfo::WordSize);
94 		foreach(QString plfile, PM.pluginsLoaded)
95 			settings.setValue(PluginManager::osIndependentPluginName(plfile), MeshLabApplication::appVer());
96 	}
97 	// Now load from the registry the settings and  merge the hardwired values got from the PM.loadPlugins with the ones found in the registry.
98 	loadMeshLabSettings();
99 	mwsettings.updateGlobalParameterSet(currentGlobalParams);
100 	createActions();
101 	createToolBars();
102 	createMenus();
103 	gpumeminfo = new vcg::QtThreadSafeMemoryInfo(mwsettings.maxgpumem);
104 	stddialog = 0;
105 	xmldialog = 0;
106 	setAcceptDrops(true);
107 	mdiarea->setAcceptDrops(true);
108 	setWindowTitle(MeshLabApplication::shortName());
109 	setStatusBar(new QStatusBar(this));
110 	globalStatusBar() = statusBar();
111 	qb = new QProgressBar(this);
112 	qb->setMaximum(100);
113 	qb->setMinimum(0);
114 	qb->reset();
115 	statusBar()->addPermanentWidget(qb, 0);
116 
117 	nvgpumeminfo = new QProgressBar(this);
118     nvgpumeminfo->setStyleSheet(" QProgressBar { background-color: #d0d0d0; border: 2px solid grey; border-radius: 0px; text-align: center; }"
119                                 " QProgressBar::chunk {background-color: #80c080; width: 1px;}");
120 	statusBar()->addPermanentWidget(nvgpumeminfo, 0);
121 	//updateMenus();
122 	newProject();
123 	//PM should be initialized before passing it to PluginGeneratorGUI
124 	plugingui = new PluginGeneratorGUI(PM, this);
125 	plugingui->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::BottomDockWidgetArea | Qt::RightDockWidgetArea);
126 	addDockWidget(Qt::LeftDockWidgetArea, plugingui);
127 	updateCustomSettings();
128 	connect(plugingui, SIGNAL(scriptCodeExecuted(const QScriptValue&, const int, const QString&)), this, SLOT(scriptCodeExecuted(const QScriptValue&, const int, const QString&)));
129 	connect(plugingui, SIGNAL(insertXMLPluginRequested(const QString&, const QString&)), this, SLOT(loadAndInsertXMLPlugin(const QString&, const QString&)));
130 	connect(plugingui, SIGNAL(historyRequest()), this, SLOT(sendHistory()));
131 	//QWidget* wid = reinterpret_cast<QWidget*>(ar->parent());
132 	//wid->showMaximized();
133 	//ar->update();
134 
135 	//qb->setAutoClose(true);
136 	//qb->setMinimumDuration(0);
137 	//qb->reset();
138 	connect(this, SIGNAL(updateLayerTable()), this, SLOT(updateLayerDialog()));
139 	connect(layerDialog, SIGNAL(removeDecoratorRequested(QAction*)), this, SLOT(switchOffDecorator(QAction*)));
140 }
141 
~MainWindow()142 MainWindow::~MainWindow()
143 {
144 	delete gpumeminfo;
145 }
146 
createActions()147 void MainWindow::createActions()
148 {
149 	searchShortCut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_F), this);
150 	searchShortCut->setAutoRepeat(false);
151 	searchShortCut->setContext(Qt::ApplicationShortcut);
152 	//////////////Action Menu File ////////////////////////////////////////////////////////////////////////////
153 	newProjectAct = new QAction(QIcon(":/images/new_project.png"), tr("New Empty Project..."), this);
154 	newProjectAct->setShortcutContext(Qt::ApplicationShortcut);
155 	newProjectAct->setShortcut(Qt::CTRL + Qt::Key_N);
156 	connect(newProjectAct, SIGNAL(triggered()), this, SLOT(newProject()));
157 
158 	openProjectAct = new QAction(QIcon(":/images/open_project.png"), tr("&Open project..."), this);
159 	openProjectAct->setShortcutContext(Qt::ApplicationShortcut);
160 	openProjectAct->setShortcut(Qt::CTRL + Qt::Key_O);
161 	connect(openProjectAct, SIGNAL(triggered()), this, SLOT(openProject()));
162 
163 	appendProjectAct = new QAction(tr("Append project to current..."), this);
164 	connect(appendProjectAct, SIGNAL(triggered()), this, SLOT(appendProject()));
165 
166 	saveProjectAct = new QAction(QIcon(":/images/save.png"), tr("&Save Project As..."), this);
167 	saveProjectAct->setShortcutContext(Qt::ApplicationShortcut);
168 	saveProjectAct->setShortcut(Qt::CTRL + Qt::Key_S);
169 	connect(saveProjectAct, SIGNAL(triggered()), this, SLOT(saveProject()));
170 
171 	closeProjectAct = new QAction(tr("Close Project"), this);
172 	//closeProjectAct->setShortcutContext(Qt::ApplicationShortcut);
173 	//closeAct->setShortcut(Qt::CTRL+Qt::Key_C);
174 	connect(closeProjectAct, SIGNAL(triggered()), mdiarea, SLOT(closeActiveSubWindow()));
175 	importMeshAct = new QAction(QIcon(":/images/import_mesh.png"), tr("&Import Mesh..."), this);
176 	importMeshAct->setShortcutContext(Qt::ApplicationShortcut);
177 	importMeshAct->setShortcut(Qt::CTRL + Qt::Key_I);
178 	connect(importMeshAct, SIGNAL(triggered()), this, SLOT(importMeshWithLayerManagement()));
179 
180 	exportMeshAct = new QAction(QIcon(":/images/save.png"), tr("&Export Mesh..."), this);
181 	exportMeshAct->setShortcutContext(Qt::ApplicationShortcut);
182 	exportMeshAct->setShortcut(Qt::CTRL + Qt::Key_E);
183 	connect(exportMeshAct, SIGNAL(triggered()), this, SLOT(save()));
184 
185 	exportMeshAsAct = new QAction(QIcon(":/images/save.png"), tr("&Export Mesh As..."), this);
186 	exportMeshAsAct->setShortcutContext(Qt::ApplicationShortcut);
187 	exportMeshAsAct->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_E);
188 	connect(exportMeshAsAct, SIGNAL(triggered()), this, SLOT(saveAs()));
189 
190 	reloadMeshAct = new QAction(QIcon(":/images/reload.png"), tr("&Reload"), this);
191 	reloadMeshAct->setShortcutContext(Qt::ApplicationShortcut);
192 	reloadMeshAct->setShortcut(Qt::ALT + Qt::Key_R);
193 	connect(reloadMeshAct, SIGNAL(triggered()), this, SLOT(reload()));
194 
195 	reloadAllMeshAct = new QAction(tr("&Reload All"), this);
196 	reloadAllMeshAct->setShortcutContext(Qt::ApplicationShortcut);
197 	reloadAllMeshAct->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_R);
198 	connect(reloadAllMeshAct, SIGNAL(triggered()), this, SLOT(reloadAllMesh()));
199 
200 	importRasterAct = new QAction(QIcon(":/images/open.png"), tr("Import Raster..."), this);
201 	connect(importRasterAct, SIGNAL(triggered()), this, SLOT(importRaster()));
202 
203 	saveSnapshotAct = new QAction(QIcon(":/images/snapshot.png"), tr("Save snapsho&t"), this);
204 	connect(saveSnapshotAct, SIGNAL(triggered()), this, SLOT(saveSnapshot()));
205 
206 	for (int i = 0; i < MAXRECENTFILES; ++i)
207 	{
208 		recentProjActs[i] = new QAction(this);
209 		recentProjActs[i]->setVisible(true);
210 		recentProjActs[i]->setEnabled(true);
211 		recentProjActs[i]->setShortcut(QKeySequence(Qt::ALT + Qt::SHIFT + Qt::Key_1 + i));
212 
213 		recentFileActs[i] = new QAction(this);
214 		recentFileActs[i]->setVisible(true);
215 		recentFileActs[i]->setEnabled(true);
216 		recentFileActs[i]->setShortcutContext(Qt::ApplicationShortcut);
217 		recentFileActs[i]->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_1 + i));
218 		connect(recentProjActs[i], SIGNAL(triggered()), this, SLOT(openRecentProj()));
219 		connect(recentFileActs[i], SIGNAL(triggered()), this, SLOT(openRecentMesh()));
220 	}
221 
222 	exitAct = new QAction(tr("E&xit"), this);
223 	exitAct->setShortcut(Qt::CTRL + Qt::Key_Q);
224 	connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));
225 
226 	//////////////Render Actions for Toolbar and Menu /////////////////////////////////////////////////////////
227 
228 
229 	//renderModeTextureWedgeAct  = new RenderModeTexturePerWedgeAction(this);
230 	//renderModeTextureWedgeAct->setCheckable(true);
231 	//rendlist.push_back(renderModeTextureWedgeAct);
232 
233 
234 
235 /* QList<RenderModeAction*> rendlist;
236 
237 setLightAct	  = new RenderModeLightOnOffAction(this);
238 setLightAct->setCheckable(true);
239 rendlist.push_back(setLightAct);
240 
241 setDoubleLightingAct = new RenderModeDoubleLightingAction(this);
242 setDoubleLightingAct->setCheckable(true);
243 setDoubleLightingAct->setShortcutContext(Qt::ApplicationShortcut);
244 setDoubleLightingAct->setShortcut(Qt::CTRL+Qt::Key_D);
245 rendlist.push_back(setDoubleLightingAct);
246 
247 setFancyLightingAct   = new RenderModeFancyLightingAction(this);
248 setFancyLightingAct->setCheckable(true);
249 setFancyLightingAct->setShortcutContext(Qt::ApplicationShortcut);
250 setFancyLightingAct->setShortcut(Qt::CTRL+Qt::Key_Y);
251 rendlist.push_back(setFancyLightingAct);
252 
253 backFaceCullAct 	  = new RenderModeFaceCullAction(this);
254 backFaceCullAct->setCheckable(true);
255 backFaceCullAct->setShortcutContext(Qt::ApplicationShortcut);
256 backFaceCullAct->setShortcut(Qt::CTRL+Qt::Key_K);
257 rendlist.push_back(backFaceCullAct);
258 
259 connectRenderModeActionList(rendlist);*/
260 
261 //////////////Action Menu View ////////////////////////////////////////////////////////////////////////////
262 	fullScreenAct = new QAction(tr("&FullScreen"), this);
263 	fullScreenAct->setCheckable(true);
264 	fullScreenAct->setShortcutContext(Qt::ApplicationShortcut);
265 	fullScreenAct->setShortcut(Qt::ALT + Qt::Key_Return);
266 	connect(fullScreenAct, SIGNAL(triggered()), this, SLOT(fullScreen()));
267 
268 	showToolbarStandardAct = new QAction(tr("&Standard"), this);
269 	showToolbarStandardAct->setCheckable(true);
270 	showToolbarStandardAct->setChecked(true);
271 	connect(showToolbarStandardAct, SIGNAL(triggered()), this, SLOT(showToolbarFile()));
272 
273 	showInfoPaneAct = new QAction(tr("Show Info &Panel"), this);
274 	showInfoPaneAct->setCheckable(true);
275 	connect(showInfoPaneAct, SIGNAL(triggered()), this, SLOT(showInfoPane()));
276 
277 
278 	showTrackBallAct = new QAction(tr("Show &Trackball"), this);
279 	showTrackBallAct->setCheckable(true);
280 	showTrackBallAct->setShortcut(Qt::SHIFT + Qt::Key_H);
281 	connect(showTrackBallAct, SIGNAL(triggered()), this, SLOT(showTrackBall()));
282 
283 	resetTrackBallAct = new QAction(tr("Reset &Trackball"), this);
284 	resetTrackBallAct->setShortcutContext(Qt::ApplicationShortcut);
285 #if defined(Q_OS_MAC)
286 	resetTrackBallAct->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_H);
287 #else
288 	resetTrackBallAct->setShortcut(Qt::CTRL + Qt::Key_H);
289 #endif
290 	connect(resetTrackBallAct, SIGNAL(triggered()), this, SLOT(resetTrackBall()));
291 
292 	showLayerDlgAct = new QAction(QIcon(":/images/layers.png"), tr("Show Layer Dialog"), this);
293 	showLayerDlgAct->setCheckable(true);
294 	showLayerDlgAct->setChecked(true);
295 	showLayerDlgAct->setShortcut(Qt::CTRL + Qt::Key_L);
296 	connect(showLayerDlgAct, SIGNAL(triggered(bool)), this, SLOT(showLayerDlg(bool)));
297 
298 
299 	showRasterAct = new QAction(QIcon(":/images/view_raster.png"), tr("Show Current Raster Mode"), this);
300 	showRasterAct->setCheckable(true);
301 	showRasterAct->setChecked(true);
302 	showRasterAct->setShortcut(Qt::SHIFT + Qt::Key_R);
303 	connect(showRasterAct, SIGNAL(triggered()), this, SLOT(showRaster()));
304 
305 	//////////////Action Menu EDIT /////////////////////////////////////////////////////////////////////////
306 	suspendEditModeAct = new QAction(QIcon(":/images/no_edit.png"), tr("Not editing"), this);
307 	suspendEditModeAct->setShortcut(Qt::Key_Escape);
308 	suspendEditModeAct->setCheckable(true);
309 	suspendEditModeAct->setChecked(true);
310 	connect(suspendEditModeAct, SIGNAL(triggered()), this, SLOT(suspendEditMode()));
311 
312 	//////////////Action Menu WINDOWS /////////////////////////////////////////////////////////////////////////
313 	windowsTileAct = new QAction(tr("&Tile"), this);
314 	connect(windowsTileAct, SIGNAL(triggered()), mdiarea, SLOT(tileSubWindows()));
315 
316 	windowsCascadeAct = new QAction(tr("&Cascade"), this);
317 	connect(windowsCascadeAct, SIGNAL(triggered()), mdiarea, SLOT(cascadeSubWindows()));
318 
319 	windowsNextAct = new QAction(tr("&Next"), this);
320 	connect(windowsNextAct, SIGNAL(triggered()), mdiarea, SLOT(activateNextSubWindow()));
321 
322 	closeAllAct = new QAction(tr("Close &All Windows"), this);
323 	connect(closeAllAct, SIGNAL(triggered()), mdiarea, SLOT(closeAllSubWindows()));
324 
325 	setSplitGroupAct = new QActionGroup(this);	setSplitGroupAct->setExclusive(true);
326 
327 	setSplitHAct = new QAction(QIcon(":/images/splitH.png"), tr("&Horizontally"), setSplitGroupAct);
328 	setSplitVAct = new QAction(QIcon(":/images/splitV.png"), tr("&Vertically"), setSplitGroupAct);
329 
330 	connect(setSplitGroupAct, SIGNAL(triggered(QAction *)), this, SLOT(setSplit(QAction *)));
331 
332 	setUnsplitAct = new QAction(tr("&Close current view"), this);
333 	connect(setUnsplitAct, SIGNAL(triggered()), this, SLOT(setUnsplit()));
334 
335 	linkViewersAct = new QAction(tr("Link Viewers"), this);
336 	linkViewersAct->setCheckable(true);
337 	connect(linkViewersAct, SIGNAL(triggered()), this, SLOT(linkViewers()));
338 
339 	viewFromGroupAct = new QActionGroup(this); viewFromGroupAct->setExclusive(true);
340 	viewFrontAct = new QAction(tr("Front"), viewFromGroupAct);
341 	viewBackAct = new QAction(tr("Back"), viewFromGroupAct);
342 	viewRightAct = new QAction(tr("Right"), viewFromGroupAct);
343 	viewLeftAct = new QAction(tr("Left"), viewFromGroupAct);
344 	viewTopAct = new QAction(tr("Top"), viewFromGroupAct);
345 	viewBottomAct = new QAction(tr("Bottom"), viewFromGroupAct);
346 	// scene uses "engineering" reference system, with Z as vertical axis
347 	viewFrontYAct = new QAction(tr("Front (Z is up)"), viewFromGroupAct);
348 	viewBackYAct = new QAction(tr("Back (Z is up)"), viewFromGroupAct);
349 	viewRightYAct = new QAction(tr("Right (Z is up)"), viewFromGroupAct);
350 	viewLeftYAct = new QAction(tr("Left (Z is up)"), viewFromGroupAct);
351 	viewTopYAct = new QAction(tr("Top (Z is up)"), viewFromGroupAct);
352 	viewBottomYAct = new QAction(tr("Bottom (Z is up)"), viewFromGroupAct);
353 
354 	// keyboard shortcuts for canonical viewdirections, blender style
355 	viewFrontAct->setShortcut(Qt::KeypadModifier + Qt::Key_1);
356 	viewBackAct->setShortcut(Qt::CTRL + Qt::KeypadModifier + Qt::Key_1);
357 	viewRightAct->setShortcut(Qt::KeypadModifier + Qt::Key_3);
358 	viewLeftAct->setShortcut(Qt::CTRL + Qt::KeypadModifier + Qt::Key_3);
359 	viewTopAct->setShortcut(Qt::KeypadModifier + Qt::Key_7);
360 	viewBottomAct->setShortcut(Qt::CTRL + Qt::KeypadModifier + Qt::Key_7);
361 	// scene uses "engineering" reference system, with Z as vertical axis
362 	viewFrontYAct->setShortcut(Qt::ALT + Qt::KeypadModifier + Qt::Key_1);
363 	viewBackYAct->setShortcut(Qt::CTRL + Qt::ALT + Qt::KeypadModifier + Qt::Key_1);
364 	viewRightYAct->setShortcut(Qt::ALT + Qt::KeypadModifier + Qt::Key_3);
365 	viewLeftYAct->setShortcut(Qt::CTRL + Qt::ALT + Qt::KeypadModifier + Qt::Key_3);
366 	viewTopYAct->setShortcut(Qt::ALT + Qt::KeypadModifier + Qt::Key_7);
367 	viewBottomYAct->setShortcut(Qt::CTRL + Qt::ALT + Qt::KeypadModifier + Qt::Key_7);
368 
369 	connect(viewFromGroupAct, SIGNAL(triggered(QAction *)), this, SLOT(viewFrom(QAction *)));
370 
371 	// other view-changing acts
372 	toggleOrthoAct = new QAction(tr("Toggle Orthographic Camera"), this);
373 	toggleOrthoAct->setShortcutContext(Qt::ApplicationShortcut);
374 	toggleOrthoAct->setShortcut(Qt::KeypadModifier + Qt::Key_5);
375 	connect(toggleOrthoAct, SIGNAL(triggered()), this, SLOT(toggleOrtho()));
376 
377 	trackballStepGroupAct = new QActionGroup(this); trackballStepGroupAct->setExclusive(true);
378 	trackballStepHP = new QAction(tr("Horizontal +"), trackballStepGroupAct);
379 	trackballStepHM = new QAction(tr("Horizontal -"), trackballStepGroupAct);
380 	trackballStepVP = new QAction(tr("Vertical +"), trackballStepGroupAct);
381 	trackballStepVM = new QAction(tr("Vertical -"), trackballStepGroupAct);
382 	trackballStepSP = new QAction(tr("Axial +"), trackballStepGroupAct);
383 	trackballStepSM = new QAction(tr("Axial -"), trackballStepGroupAct);
384 	trackballStepHP->setShortcut(Qt::KeypadModifier + Qt::Key_4);
385 	trackballStepHM->setShortcut(Qt::KeypadModifier + Qt::Key_6);
386 	trackballStepVP->setShortcut(Qt::KeypadModifier + Qt::Key_8);
387 	trackballStepVM->setShortcut(Qt::KeypadModifier + Qt::Key_2);
388 	trackballStepSP->setShortcut(Qt::KeypadModifier + Qt::Key_9);
389 	trackballStepSM->setShortcut(Qt::CTRL +  Qt::KeypadModifier + Qt::Key_9);
390 	connect(trackballStepGroupAct, SIGNAL(triggered(QAction *)), this, SLOT(trackballStep(QAction *)));
391 
392 	viewFromMeshAct = new QAction(tr("View from Mesh Camera"), this);
393 	viewFromRasterAct = new QAction(tr("View from Raster Camera"), this);
394 	viewFromRasterAct->setShortcut(Qt::CTRL + Qt::Key_J);
395 	readViewFromFileAct = new QAction(tr("Read camera settings from file"), this);
396 	readViewFromFileAct->setToolTip(tr("Restore camera settings from an XML description stored in a file."));
397 	saveViewToFileAct = new QAction(tr("Save camera settings to file"), this);
398 	saveViewToFileAct->setToolTip(tr("Save camera settings to a file as an XML description."));
399 	connect(viewFromMeshAct, SIGNAL(triggered()), this, SLOT(viewFromCurrentMeshShot()));
400 	connect(viewFromRasterAct, SIGNAL(triggered()), this, SLOT(viewFromCurrentRasterShot()));
401 	connect(readViewFromFileAct, SIGNAL(triggered()), this, SLOT(readViewFromFile()));
402 	connect(saveViewToFileAct, SIGNAL(triggered()), this, SLOT(saveViewToFile()));
403 
404 	copyShotToClipboardAct = new QAction(tr("Copy camera settings to clipboard"), this);
405 	copyShotToClipboardAct->setToolTip(tr("Save current camera settings to clipboard as a XML document that you can share or restore anytime."));
406 	connect(copyShotToClipboardAct, SIGNAL(triggered()), this, SLOT(copyViewToClipBoard()));
407 
408 	pasteShotFromClipboardAct = new QAction(tr("Paste clipboard to camera settings"), this);
409 	pasteShotFromClipboardAct->setToolTip(tr("Restore camera settings from a XML description stored in the clipboard."));
410 	connect(pasteShotFromClipboardAct, SIGNAL(triggered()), this, SLOT(pasteViewFromClipboard()));
411 
412 	//////////////Action Menu Filters /////////////////////////////////////////////////////////////////////
413 	lastFilterAct = new QAction(tr("Apply filter"), this);
414 	lastFilterAct->setShortcutContext(Qt::ApplicationShortcut);
415 	lastFilterAct->setShortcut(Qt::CTRL + Qt::Key_P);
416 	lastFilterAct->setEnabled(false);
417 	connect(lastFilterAct, SIGNAL(triggered()), this, SLOT(applyLastFilter()));
418 
419 	showFilterScriptAct = new QAction(tr("Show current filter script"), this);
420 	showFilterScriptAct->setEnabled(false);
421 	connect(showFilterScriptAct, SIGNAL(triggered()), this, SLOT(showFilterScript()));
422 
423 	//////////////Action Menu Preferences /////////////////////////////////////////////////////////////////////
424 	setCustomizeAct = new QAction(tr("&Options..."), this);
425 	connect(setCustomizeAct, SIGNAL(triggered()), this, SLOT(setCustomize()));
426 
427 	//////////////Action Menu About ///////////////////////////////////////////////////////////////////////////
428 	aboutAct = new QAction(tr("&About"), this);
429 	connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
430 
431 	aboutPluginsAct = new QAction(tr("Plugin Info"), this);
432 	connect(aboutPluginsAct, SIGNAL(triggered()), this, SLOT(aboutPlugins()));
433 
434 	onlineHelpAct = new QAction(tr("Online &Documentation"), this);
435 	connect(onlineHelpAct, SIGNAL(triggered()), this, SLOT(helpOnline()));
436 
437 	submitBugAct = new QAction(tr("Submit Bug"), this);
438 	connect(submitBugAct, SIGNAL(triggered()), this, SLOT(submitBug()));
439 
440 	onscreenHelpAct = new QAction(tr("On screen quick help"), this);
441 	onscreenHelpAct->setShortcut(Qt::Key_F1);
442 	onscreenHelpAct->setShortcutContext(Qt::ApplicationShortcut);
443 	connect(onscreenHelpAct, SIGNAL(triggered()), this, SLOT(helpOnscreen()));
444 
445 	checkUpdatesAct = new QAction(tr("Check for updates"), this);
446 	connect(checkUpdatesAct, SIGNAL(triggered()), this, SLOT(checkForUpdates()));
447 
448 	///////////////Action Menu Split/Unsplit from handle////////////////////////////////////////////////////////
449 	splitGroupAct = new QActionGroup(this);
450 	unsplitGroupAct = new QActionGroup(this);
451 
452 	splitUpAct = new QAction(tr("&Up"), splitGroupAct);
453 	splitDownAct = new QAction(tr("&Down"), splitGroupAct);
454 	unsplitUpAct = new QAction(tr("&Up"), unsplitGroupAct);
455 	unsplitDownAct = new QAction(tr("&Down"), unsplitGroupAct);
456 	splitRightAct = new QAction(tr("&Right"), splitGroupAct);
457 	splitLeftAct = new QAction(tr("&Left"), splitGroupAct);
458 
459 	unsplitRightAct = new QAction(tr("&Right"), unsplitGroupAct);
460 	unsplitLeftAct = new QAction(tr("&Left"), unsplitGroupAct);
461 
462 	connect(splitGroupAct, SIGNAL(triggered(QAction *)), this, SLOT(splitFromHandle(QAction *)));
463 
464 	connect(unsplitGroupAct, SIGNAL(triggered(QAction *)), this, SLOT(unsplitFromHandle(QAction *)));
465 
466 	//TOOL MENU
467 	showFilterEditAct = new QAction(tr("XML Plugin Editor GUI"), this);
468 	showFilterEditAct->setEnabled(true);
469 	connect(showFilterEditAct, SIGNAL(triggered()), this, SLOT(showXMLPluginEditorGui()));
470 
471 }
472 
createToolBars()473 void MainWindow::createToolBars()
474 {
475 #if defined(Q_OS_MAC)
476 	this->setStyleSheet("QToolBar {spacing: 0px; } QToolButton {border-radius: 0px;} QToolButton:checked {background: darkgray}");
477 #endif
478 
479 	mainToolBar = addToolBar(tr("Standard"));
480 	//	mainToolBar->setIconSize(QSize(32,32));
481 	mainToolBar->addAction(this->newProjectAct);
482 	mainToolBar->addAction(this->openProjectAct);
483 	mainToolBar->addAction(importMeshAct);
484 	mainToolBar->addAction(reloadMeshAct);
485 	//  mainToolBar->addAction(reloadAllMeshAct);
486 	mainToolBar->addAction(exportMeshAct);
487 	mainToolBar->addAction(saveSnapshotAct);
488 	mainToolBar->addAction(showLayerDlgAct);
489 	mainToolBar->addAction(showRasterAct);
490 
491 
492 	mainToolBar->addSeparator();
493 	globrendtoolbar = new MLRenderingGlobalToolbar(this);
494 	connect(globrendtoolbar, SIGNAL(updateRenderingDataAccordingToActions(QList<MLRenderingGlobalAction*>)), this, SLOT(updateRenderingDataAccordingToActions(QList<MLRenderingGlobalAction*>)));
495 
496 	mainToolBar->addWidget(globrendtoolbar);
497 
498 
499 
500 	decoratorToolBar = addToolBar("Decorator");
501 	foreach(MeshDecorateInterface *iDecorate, PM.meshDecoratePlugins())
502 	{
503 		foreach(QAction *decorateAction, iDecorate->actions())
504 		{
505 			if (!decorateAction->icon().isNull())
506 				decoratorToolBar->addAction(decorateAction);
507 		}
508 	}
509 
510 	editToolBar = addToolBar(tr("Edit"));
511 	editToolBar->addAction(suspendEditModeAct);
512 	foreach(MeshEditInterfaceFactory *iEditFactory, PM.meshEditFactoryPlugins())
513 	{
514 		foreach(QAction* editAction, iEditFactory->actions())
515 		{
516 			if (!editAction->icon().isNull())
517 			{
518 				editToolBar->addAction(editAction);
519 			}
520 			else qDebug() << "action was null";
521 		}
522 	}
523 	editToolBar->addSeparator();
524 
525 	filterToolBar = addToolBar(tr("Filter"));
526 	filterToolBar->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
527 
528 	foreach(MeshFilterInterface *iFilter, PM.meshFilterPlugins())
529 	{
530 		foreach(QAction* filterAction, iFilter->actions())
531 		{
532 			if (!filterAction->icon().isNull())
533 			{
534 				// tooltip = iFilter->filterInfo(filterAction) + "<br>" + getDecoratedFileName(filterAction->data().toString());
535 				if (filterAction->priority() != QAction::LowPriority)
536 					filterToolBar->addAction(filterAction);
537 			} //else qDebug() << "action was null";
538 		}
539 	}
540 
541 	QWidget *spacerWidget = new QWidget();
542 	spacerWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
543 	spacerWidget->setVisible(true);
544 	searchToolBar = addToolBar(tr("Search"));
545 	searchToolBar->addWidget(spacerWidget);
546 	searchToolBar->setMovable(false);
547 	searchToolBar->setFloatable(false);
548 	searchToolBar->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
549 	searchButton = new MyToolButton(0, this);
550 	//searchButton->setPopupMode(QToolButton::InstantPopup);
551 	searchButton->setIcon(QIcon(":/images/search.png"));
552 
553 	searchToolBar->addWidget(searchButton);
554 }
555 
556 
createMenus()557 void MainWindow::createMenus()
558 {
559 	//////////////////// Menu File ////////////////////////////////////////////////////////////////////////////
560 	fileMenu = menuBar()->addMenu(tr("&File"));
561 	fileMenu->addAction(newProjectAct);
562 	fileMenu->addAction(openProjectAct);
563 	fileMenu->addAction(appendProjectAct);
564 	fileMenu->addAction(saveProjectAct);
565 	fileMenu->addAction(closeProjectAct);
566 	fileMenu->addSeparator();
567 
568 	fileMenu->addAction(importMeshAct);
569 	fileMenu->addAction(exportMeshAct);
570 	fileMenu->addAction(exportMeshAsAct);
571 	fileMenu->addAction(reloadMeshAct);
572 	fileMenu->addAction(reloadAllMeshAct);
573 	fileMenu->addSeparator();
574 	fileMenu->addAction(importRasterAct);
575 	fileMenu->addSeparator();
576 
577 	fileMenu->addAction(saveSnapshotAct);
578 	fileMenu->addSeparator();
579 	recentProjMenu = fileMenu->addMenu(tr("Recent Projects"));
580 	recentFileMenu = fileMenu->addMenu(tr("Recent Files"));
581 
582 
583 	for (int i = 0; i < MAXRECENTFILES; ++i)
584 	{
585 		recentProjMenu->addAction(recentProjActs[i]);
586 		recentFileMenu->addAction(recentFileActs[i]);
587 	}
588 	//updateRecentFileActions();
589 	fileMenu->addSeparator();
590 	fileMenu->addAction(exitAct);
591 
592 	//////////////////// Menu Edit //////////////////////////////////////////////////////////////////////////
593 	editMenu = menuBar()->addMenu(tr("&Edit"));
594 	editMenu->addAction(suspendEditModeAct);
595 
596 	//////////////////// Menu Filter //////////////////////////////////////////////////////////////////////////
597 	filterMenu = menuBar()->addMenu(tr("Fi&lters"));
598 	fillFilterMenu();
599 
600 	//////////////////// Menu Render //////////////////////////////////////////////////////////////////////////
601 	renderMenu = menuBar()->addMenu(tr("&Render"));
602 
603 	// Shaders SUBmenu
604 	shadersMenu = renderMenu->addMenu(tr("&Shaders"));
605 	renderMenu->addSeparator();
606 
607 	//////////////////// Menu View ////////////////////////////////////////////////////////////////////////////
608 	viewMenu = menuBar()->addMenu(tr("&View"));
609 	viewMenu->addAction(fullScreenAct);
610 	viewMenu->addSeparator();
611 	viewMenu->addAction(showLayerDlgAct);
612 	viewMenu->addAction(showRasterAct);
613 	viewMenu->addSeparator();
614 	viewMenu->addAction(showTrackBallAct);
615 	viewMenu->addAction(resetTrackBallAct);
616 	viewMenu->addSeparator();
617 	viewMenu->addAction(toggleOrthoAct);
618 	viewMenu->addSeparator();
619 	viewMenu->addAction(showInfoPaneAct);
620 	viewMenu->addSeparator();
621 	toolBarMenu = viewMenu->addMenu(tr("&ToolBars"));
622 	toolBarMenu->addAction(showToolbarStandardAct);
623 	//connect(toolBarMenu, SIGNAL(aboutToShow()), this, SLOT(updateMenus()));
624 
625 	//////////////////// Menu Windows /////////////////////////////////////////////////////////////////////////
626 	windowsMenu = menuBar()->addMenu(tr("&Windows"));
627 	windowsMenu->setToolTipsVisible(true);
628     updateWindowMenu();
629 	menuBar()->addSeparator();
630 
631 	//////////////////// Menu Preferences /////////////////////////////////////////////////////////////////////
632 	preferencesMenu = menuBar()->addMenu(tr("&Tools"));
633 	/*preferencesMenu->addAction(showFilterEditAct);
634 	preferencesMenu->addSeparator();*/
635 	preferencesMenu->addAction(setCustomizeAct);
636 
637 	//////////////////// Menu Help ////////////////////////////////////////////////////////////////
638 	helpMenu = menuBar()->addMenu(tr("&Help"));
639 	helpMenu->addAction(aboutAct);
640 	helpMenu->addAction(aboutPluginsAct);
641 	helpMenu->addAction(onlineHelpAct);
642 	helpMenu->addAction(onscreenHelpAct);
643 	helpMenu->addAction(submitBugAct);
644 	helpMenu->addAction(checkUpdatesAct);
645 
646 	fillEditMenu();
647 	fillRenderMenu();
648 	fillDecorateMenu();
649 
650 	//////////////////// Menu Split/Unsplit from handle
651 	handleMenu = new QMenu(this);
652 	splitMenu = handleMenu->addMenu(tr("&Split"));
653 	unSplitMenu = handleMenu->addMenu("&Close");
654 
655 	//SearchMenu
656 	if (searchButton != NULL)
657 	{
658 		initSearchEngine();
659 		int longest = longestActionWidthInAllMenus();
660 		searchMenu = new SearchMenu(wama, 15, searchButton, longest);
661 		searchButton->setMenu(searchMenu);
662 		connect(searchShortCut, SIGNAL(activated()), searchButton, SLOT(openMenu()));
663 	}
664 }
665 
initSearchEngine()666 void MainWindow::initSearchEngine()
667 {
668 	for (QMap<QString, QAction*>::iterator it = PM.actionFilterMap.begin(); it != PM.actionFilterMap.end(); ++it)
669 		initItemForSearching(it.value());
670 
671 	for (QMap<QString, MeshLabXMLFilterContainer>::iterator it = PM.stringXMLFilterMap.begin(); it != PM.stringXMLFilterMap.end(); ++it)
672 		initItemForSearching(it.value().act);
673 
674 	initMenuForSearching(editMenu);
675 	initMenuForSearching(renderMenu);
676 }
677 
initMenuForSearching(QMenu * menu)678 void MainWindow::initMenuForSearching(QMenu* menu)
679 {
680 	if (menu == NULL)
681 		return;
682 	const QList<QAction*>& acts = menu->actions();
683 	foreach(QAction* act, acts)
684 	{
685 		QMenu* submenu = act->menu();
686 		if (!act->isSeparator() && (submenu == NULL))
687 			initItemForSearching(act);
688 		else if (!act->isSeparator())
689 			initMenuForSearching(submenu);
690 	}
691 }
692 
initItemForSearching(QAction * act)693 void MainWindow::initItemForSearching(QAction* act)
694 {
695 	QString tx = act->text() + " " + act->toolTip();
696 	wama.addWordsPerAction(*act, tx);
697 }
698 
getDecoratedFileName(const QString & name)699 QString MainWindow::getDecoratedFileName(const QString& name)
700 {
701 	return  QString("<br><b><i>(") + name + ")</i></b>";
702 }
703 
fillFilterMenu()704 void MainWindow::fillFilterMenu()
705 {
706 	filterMenu->clear();
707 	filterMenu->addAction(lastFilterAct);
708 	filterMenu->addAction(showFilterScriptAct);
709 	filterMenu->addSeparator();
710 	//filterMenu->addMenu(new SearcherMenu(this,filterMenu));
711 	//filterMenu->addSeparator();
712 	// Connects the events of the actions within colorize to the method which shows their tooltip
713 
714 	filterMenuSelect = new MenuWithToolTip(tr("Selection"), this);
715 	filterMenu->addMenu(filterMenuSelect);
716 	filterMenuClean = new MenuWithToolTip(tr("Cleaning and Repairing"), this);
717 	filterMenu->addMenu(filterMenuClean);
718 	filterMenuCreate = new MenuWithToolTip(tr("Create New Mesh Layer"), this);
719 	filterMenu->addMenu(filterMenuCreate);
720 	filterMenuRemeshing = new MenuWithToolTip(tr("Remeshing, Simplification and Reconstruction"), this);
721 	filterMenu->addMenu(filterMenuRemeshing);
722 	filterMenuPolygonal = new MenuWithToolTip(tr("Polygonal and Quad Mesh"), this);
723 	filterMenu->addMenu(filterMenuPolygonal);
724 	filterMenuColorize = new MenuWithToolTip(tr("Color Creation and Processing"), this);
725 	filterMenu->addMenu(filterMenuColorize);
726 	filterMenuSmoothing = new MenuWithToolTip(tr("Smoothing, Fairing and Deformation"), this);
727 	filterMenu->addMenu(filterMenuSmoothing);
728 	filterMenuQuality = new MenuWithToolTip(tr("Quality Measure and Computations"), this);
729 	filterMenu->addMenu(filterMenuQuality);
730 	filterMenuNormal = new MenuWithToolTip(tr("Normals, Curvatures and Orientation"), this);
731 	filterMenu->addMenu(filterMenuNormal);
732 	filterMenuMeshLayer = new MenuWithToolTip(tr("Mesh Layer"), this);
733 	filterMenu->addMenu(filterMenuMeshLayer);
734 	filterMenuRasterLayer = new MenuWithToolTip(tr("Raster Layer"), this);
735 	filterMenu->addMenu(filterMenuRasterLayer);
736 	filterMenuRangeMap = new MenuWithToolTip(tr("Range Map"), this);
737 	filterMenu->addMenu(filterMenuRangeMap);
738 	filterMenuPointSet = new MenuWithToolTip(tr("Point Set"), this);
739 	filterMenu->addMenu(filterMenuPointSet);
740 	filterMenuSampling = new MenuWithToolTip(tr("Sampling"), this);
741 	filterMenu->addMenu(filterMenuSampling);
742 	filterMenuTexture = new MenuWithToolTip(tr("Texture"), this);
743 	filterMenu->addMenu(filterMenuTexture);
744 	filterMenuCamera = new MenuWithToolTip(tr("Camera"), this);
745 	filterMenu->addMenu(filterMenuCamera);
746 
747 
748 	QMap<QString, MeshFilterInterface *>::iterator msi;
749 	for (msi = PM.stringFilterMap.begin(); msi != PM.stringFilterMap.end(); ++msi)
750 	{
751 		MeshFilterInterface * iFilter = msi.value();
752 		QAction *filterAction = iFilter->AC((msi.key()));
753 		QString tooltip = iFilter->filterInfo(filterAction) + "<br>" + getDecoratedFileName(filterAction->data().toString());
754 		filterAction->setToolTip(tooltip);
755 		//connect(filterAction, SIGNAL(hovered()), this, SLOT(showActionMenuTooltip()) );
756 		connect(filterAction, SIGNAL(triggered()), this, SLOT(startFilter()));
757 
758 		int filterClass = iFilter->getClass(filterAction);
759 		if (filterClass & MeshFilterInterface::FaceColoring)
760 		{
761 			filterMenuColorize->addAction(filterAction);
762 		}
763 		if (filterClass & MeshFilterInterface::VertexColoring)
764 		{
765 			filterMenuColorize->addAction(filterAction);
766 		}
767 		if (filterClass & MeshFilterInterface::MeshColoring)
768 		{
769 			filterMenuColorize->addAction(filterAction);
770 		}
771 		if (filterClass & MeshFilterInterface::Selection)
772 		{
773 			filterMenuSelect->addAction(filterAction);
774 		}
775 		if (filterClass & MeshFilterInterface::Cleaning)
776 		{
777 			filterMenuClean->addAction(filterAction);
778 		}
779 		if (filterClass & MeshFilterInterface::Remeshing)
780 		{
781 			filterMenuRemeshing->addAction(filterAction);
782 		}
783 		if (filterClass & MeshFilterInterface::Smoothing)
784 		{
785 			filterMenuSmoothing->addAction(filterAction);
786 		}
787 		if (filterClass & MeshFilterInterface::Normal)
788 		{
789 			filterMenuNormal->addAction(filterAction);
790 		}
791 		if (filterClass & MeshFilterInterface::Quality)
792 		{
793 			filterMenuQuality->addAction(filterAction);
794 		}
795 		if (filterClass & MeshFilterInterface::Measure)
796 		{
797 			filterMenuQuality->addAction(filterAction);
798 		}
799 		if (filterClass & MeshFilterInterface::Layer)
800 		{
801 			filterMenuMeshLayer->addAction(filterAction);
802 		}
803 		if (filterClass & MeshFilterInterface::RasterLayer)
804 		{
805 			filterMenuRasterLayer->addAction(filterAction);
806 		}
807 		if (filterClass & MeshFilterInterface::MeshCreation)
808 		{
809 			filterMenuCreate->addAction(filterAction);
810 		}
811 		if (filterClass & MeshFilterInterface::RangeMap)
812 		{
813 			filterMenuRangeMap->addAction(filterAction);
814 		}
815 		if (filterClass & MeshFilterInterface::PointSet)
816 		{
817 			filterMenuPointSet->addAction(filterAction);
818 		}
819 		if (filterClass & MeshFilterInterface::Sampling)
820 		{
821 			filterMenuSampling->addAction(filterAction);
822 		}
823 		if (filterClass & MeshFilterInterface::Texture)
824 		{
825 			filterMenuTexture->addAction(filterAction);
826 		}
827 		if (filterClass & MeshFilterInterface::Polygonal)
828 		{
829 			filterMenuPolygonal->addAction(filterAction);
830 		}
831 		if (filterClass & MeshFilterInterface::Camera)
832 		{
833 			filterMenuCamera->addAction(filterAction);
834 		}
835 		//  MeshFilterInterface::Generic :
836 		if (filterClass == 0)
837 		{
838 			filterMenu->addAction(filterAction);
839 		}
840 		//if(!filterAction->icon().isNull())
841 		//    filterToolBar->addAction(filterAction);
842 
843 
844 	}
845 
846 	QMap<QString, MeshLabXMLFilterContainer>::iterator xmlit;
847 	for (xmlit = PM.stringXMLFilterMap.begin(); xmlit != PM.stringXMLFilterMap.end(); ++xmlit)
848 	{
849 		try
850 		{
851 			//MeshLabFilterInterface * iFilter= xmlit.value().filterInterface;
852 			QAction *filterAction = xmlit.value().act;
853 			if (filterAction == NULL)
854 				throw MLException("Invalid filter action value.");
855 			MLXMLPluginInfo* info = xmlit.value().xmlInfo;
856 			if (filterAction == NULL)
857 				throw MLException("Invalid filter info value.");
858 			QString filterName = xmlit.key();
859 
860 			QString help = info->filterHelp(filterName);
861 			filterAction->setToolTip(help + getDecoratedFileName(filterAction->data().toString()));
862 			connect(filterAction, SIGNAL(triggered()), this, SLOT(startFilter()));
863 			QString filterClasses = info->filterAttribute(filterName, MLXMLElNames::filterClass);
864 			QStringList filterClassesList = filterClasses.split(QRegExp("\\W+"), QString::SkipEmptyParts);
865 			foreach(QString nameClass, filterClassesList)
866 			{
867 				if (nameClass == QString("FaceColoring"))
868 				{
869 					filterMenuColorize->addAction(filterAction);
870 				}
871 				if (nameClass == QString("VertexColoring"))
872 				{
873 					filterMenuColorize->addAction(filterAction);
874 				}
875 				if (nameClass == QString("Selection"))
876 				{
877 					filterMenuSelect->addAction(filterAction);
878 				}
879 				if (nameClass == QString("Cleaning"))
880 				{
881 					filterMenuClean->addAction(filterAction);
882 				}
883 				if (nameClass == QString("Remeshing"))
884 				{
885 					filterMenuRemeshing->addAction(filterAction);
886 				}
887 				if (nameClass == QString("Smoothing"))
888 				{
889 					filterMenuSmoothing->addAction(filterAction);
890 				}
891 				if (nameClass == QString("Normal"))
892 				{
893 					filterMenuNormal->addAction(filterAction);
894 				}
895 				if (nameClass == QString("Quality"))
896 				{
897 					filterMenuQuality->addAction(filterAction);
898 				}
899 				if (nameClass == QString("Measure"))
900 				{
901 					filterMenuQuality->addAction(filterAction);
902 				}
903 				if (nameClass == QString("Layer"))
904 				{
905 					filterMenuMeshLayer->addAction(filterAction);
906 				}
907 				if (nameClass == QString("RasterLayer"))
908 				{
909 					filterMenuRasterLayer->addAction(filterAction);
910 				}
911 				if (nameClass == QString("MeshCreation"))
912 				{
913 					filterMenuCreate->addAction(filterAction);
914 				}
915 				if (nameClass == QString("RangeMap"))
916 				{
917 					filterMenuRangeMap->addAction(filterAction);
918 				}
919 				if (nameClass == QString("PointSet"))
920 				{
921 					filterMenuPointSet->addAction(filterAction);
922 				}
923 				if (nameClass == QString("Sampling"))
924 				{
925 					filterMenuSampling->addAction(filterAction);
926 				}
927 				if (nameClass == QString("Texture"))
928 				{
929 					filterMenuTexture->addAction(filterAction);
930 				}
931 				if (nameClass == QString("Polygonal"))
932 				{
933 					filterMenuPolygonal->addAction(filterAction);
934 				}
935 				if (nameClass == QString("Camera"))
936 				{
937 					filterMenuCamera->addAction(filterAction);
938 				}
939 				//  //  MeshFilterInterface::Generic :
940 				if (nameClass == QString("Generic"))
941 				{
942 					filterMenu->addAction(filterAction);
943 				}
944 				//if(!filterAction->icon().isNull())
945 				//    filterToolBar->addAction(filterAction);
946 			}
947 		}
948 		catch (ParsingException &e)
949 		{
950 			meshDoc()->Log.Log(GLLogStream::SYSTEM, e.what());
951 		}
952 	}
953 }
954 
fillDecorateMenu()955 void MainWindow::fillDecorateMenu()
956 {
957 	foreach(MeshDecorateInterface *iDecorate, PM.meshDecoratePlugins())
958 	{
959 		foreach(QAction *decorateAction, iDecorate->actions())
960 		{
961 			connect(decorateAction, SIGNAL(triggered()), this, SLOT(applyDecorateMode()));
962 			decorateAction->setToolTip(iDecorate->decorationInfo(decorateAction));
963 			renderMenu->addAction(decorateAction);
964 		}
965 	}
966 	connect(renderMenu, SIGNAL(hovered(QAction*)), this, SLOT(showTooltip(QAction*)));
967 }
968 
fillRenderMenu()969 void MainWindow::fillRenderMenu()
970 {
971 	QAction * qaNone = new QAction("None", this);
972 	qaNone->setCheckable(false);
973 	shadersMenu->addAction(qaNone);
974 	connect(qaNone, SIGNAL(triggered()), this, SLOT(applyRenderMode()));
975 	foreach(MeshRenderInterface *iRender, PM.meshRenderPlugins())
976 	{
977 		addToMenu(iRender->actions(), shadersMenu, SLOT(applyRenderMode()));
978 	}
979 }
980 
fillEditMenu()981 void MainWindow::fillEditMenu()
982 {
983 	foreach(MeshEditInterfaceFactory *iEditFactory, PM.meshEditFactoryPlugins())
984 	{
985 		foreach(QAction* editAction, iEditFactory->actions())
986 		{
987 			editMenu->addAction(editAction);
988 			connect(editAction, SIGNAL(triggered()), this, SLOT(applyEditMode()));
989 		}
990 	}
991 }
992 
993 
loadMeshLabSettings()994 void MainWindow::loadMeshLabSettings()
995 {
996 	// I have already loaded the plugins so the default parameters for the settings
997 	// of the plugins are already in the <defaultGlobalParams> .
998 	// we just miss the globals default of meshlab itself
999 	MainWindowSetting::initGlobalParameterSet(&defaultGlobalParams);
1000 	GLArea::initGlobalParameterSet(&defaultGlobalParams);
1001 
1002 	QSettings settings;
1003 	QStringList klist = settings.allKeys();
1004 
1005 	// 1) load saved values into the <currentGlobalParams>
1006 	for (int ii = 0; ii < klist.size(); ++ii)
1007 	{
1008 		QDomDocument doc;
1009 		doc.setContent(settings.value(klist.at(ii)).toString());
1010 
1011 		QString st = settings.value(klist.at(ii)).toString();
1012 		QDomElement docElem = doc.firstChild().toElement();
1013 
1014 		RichParameter* rpar = NULL;
1015 		if (!docElem.isNull())
1016 		{
1017 			bool ret = RichParameterAdapter::create(docElem, &rpar);
1018 			if (!ret)
1019 			{
1020 				//  qDebug("Warning Ignored parameter '%s' = '%s'. Malformed.", qUtf8Printable(docElem.attribute("name")), qUtf8Printable(docElem.attribute("value")));
1021 				continue;
1022 			}
1023 			if (!defaultGlobalParams.hasParameter(rpar->name))
1024 			{
1025 				//  qDebug("Warning Ignored parameter %s. In the saved parameters there are ones that are not in the HardWired ones. "
1026 				//         "It happens if you are running MeshLab with only a subset of the plugins. ", qUtf8Printable(rpar->name));
1027 			}
1028 			else
1029 				currentGlobalParams.addParam(rpar);
1030 		}
1031 	}
1032 
1033 	// 2) eventually fill missing values with the hardwired defaults
1034 	for (int ii = 0; ii < defaultGlobalParams.paramList.size(); ++ii)
1035 	{
1036 		//		qDebug("Searching param[%i] %s of the default into the loaded settings. ", ii, qUtf8Printable(defaultGlobalParams.paramList.at(ii)->name));
1037 		if (!currentGlobalParams.hasParameter(defaultGlobalParams.paramList.at(ii)->name))
1038 		{
1039 			qDebug("Warning! a default param was not found in the saved settings. This should happen only on the first run...");
1040 			RichParameterCopyConstructor v;
1041 			defaultGlobalParams.paramList.at(ii)->accept(v);
1042 			currentGlobalParams.paramList.push_back(v.lastCreated);
1043 
1044 			QDomDocument doc("MeshLabSettings");
1045 			RichParameterXMLVisitor vxml(doc);
1046 			v.lastCreated->accept(vxml);
1047 			doc.appendChild(vxml.parElem);
1048 			QString docstring = doc.toString();
1049 			QSettings setting;
1050 			setting.setValue(v.lastCreated->name, QVariant(docstring));
1051 		}
1052 	}
1053 
1054 	//emit dispatchCustomSettings(currentGlobalParams);
1055 }
1056 
addToMenu(QList<QAction * > actionList,QMenu * menu,const char * slot)1057 void MainWindow::addToMenu(QList<QAction *> actionList, QMenu *menu, const char *slot)
1058 {
1059 	foreach(QAction *a, actionList)
1060 	{
1061 		connect(a, SIGNAL(triggered()), this, slot);
1062 		menu->addAction(a);
1063 	}
1064 }
1065 
1066 // this function update the app settings with the current recent file list
1067 // and update the loaded mesh counter
saveRecentFileList(const QString & fileName)1068 void MainWindow::saveRecentFileList(const QString &fileName)
1069 {
1070 	QSettings settings;
1071 	QStringList files = settings.value("recentFileList").toStringList();
1072 	files.removeAll(fileName);
1073 	files.prepend(fileName);
1074 	while (files.size() > MAXRECENTFILES)
1075 		files.removeLast();
1076 
1077 	//avoid the slash/back-slash path ambiguity
1078 	for (int ii = 0; ii < files.size(); ++ii)
1079 		files[ii] = QDir::fromNativeSeparators(files[ii]);
1080 	settings.setValue("recentFileList", files);
1081 
1082 	foreach(QWidget *widget, QApplication::topLevelWidgets()) {
1083 		MainWindow *mainWin = qobject_cast<MainWindow *>(widget);
1084 		if (mainWin) mainWin->updateRecentFileActions();
1085 	}
1086 
1087 	settings.setValue("totalKV", settings.value("totalKV", 0).toInt() + (GLA()->mm()->cm.vn) / 1000);
1088 	settings.setValue("loadedMeshCounter", settings.value("loadedMeshCounter", 0).toInt() + 1);
1089 }
1090 
sendUsAMail()1091 void MainWindow::sendUsAMail()
1092 {
1093 	QSettings settings;
1094 
1095 	// Check if the user specified not to be reminded to send email
1096 	const QString dontRemindMeToSendEmailVar("dontRemindMeToSendEmail");
1097 	bool dontRemindMeToSendEmailVal = false;
1098 	if (settings.contains(dontRemindMeToSendEmailVar))
1099 		dontRemindMeToSendEmailVal = settings.value(dontRemindMeToSendEmailVar).toBool();
1100 	if (dontRemindMeToSendEmailVal)
1101 		return;
1102 
1103 	int loadedMeshCounter = settings.value("loadedMeshCounter").toInt();
1104 	//int connectionInterval = settings.value("connectionInterval", 20).toInt();
1105 	//int lastComunicatedValue = settings.value("lastComunicatedValue", 0).toInt();
1106 
1107 	int congratsMeshCounter = settings.value("congratsMeshCounter", 50).toInt();
1108 	if (loadedMeshCounter > congratsMeshCounter)
1109 	{
1110 		QDialog *congratsDialog = new QDialog();
1111 		Ui::CongratsDialog temp;
1112 		temp.setupUi(congratsDialog);
1113 		temp.buttonBox->addButton("Send Mail", QDialogButtonBox::AcceptRole);
1114 
1115 		QCheckBox dontRemindMeCheckBox("Don't show this message again.");
1116 		dontRemindMeCheckBox.blockSignals(true);
1117 		temp.buttonBox->addButton(&dontRemindMeCheckBox, QDialogButtonBox::ActionRole);
1118 
1119 		congratsDialog->exec();
1120 		if (congratsDialog->result() == QDialog::Accepted)
1121 			QDesktopServices::openUrl(QUrl("mailto:paolo.cignoni@isti.cnr.it;alessandro.muntoni@isti.cnr.it?subject=[MeshLab] Reporting Info on MeshLab Usage - V"+MeshLabApplication::appVer()));
1122 		// This preference values store when you did the last request for a mail
1123 		settings.setValue("congratsMeshCounter", congratsMeshCounter * 2);
1124 
1125 		// See if the user checked the box to not be reminded again
1126 		if (dontRemindMeCheckBox.checkState() == Qt::Checked)
1127 			settings.setValue(dontRemindMeToSendEmailVar, true);
1128 	}
1129 }
1130 
saveRecentProjectList(const QString & projName)1131 void MainWindow::saveRecentProjectList(const QString &projName)
1132 {
1133 	QSettings settings;
1134 	QStringList files = settings.value("recentProjList").toStringList();
1135 	files.removeAll(projName);
1136 	files.prepend(projName);
1137 	while (files.size() > MAXRECENTFILES)
1138 		files.removeLast();
1139 
1140 	for (int ii = 0; ii < files.size(); ++ii)
1141 		files[ii] = QDir::fromNativeSeparators(files[ii]);
1142 
1143 	settings.setValue("recentProjList", files);
1144 
1145 	foreach(QWidget *widget, QApplication::topLevelWidgets())
1146 	{
1147 		MainWindow *mainWin = qobject_cast<MainWindow *>(widget);
1148 		if (mainWin)
1149 			mainWin->updateRecentProjActions();
1150 	}
1151 }
1152 
checkForUpdates(bool verboseFlag)1153 void MainWindow::checkForUpdates(bool verboseFlag)
1154 {
1155 	VerboseCheckingFlag = verboseFlag;
1156 	QSettings settings;
1157 	int totalKV = settings.value("totalKV", 0).toInt();
1158 	int loadedMeshCounter = settings.value("loadedMeshCounter", 0).toInt();
1159 	int savedMeshCounter = settings.value("savedMeshCounter", 0).toInt();
1160 	QString UID = settings.value("UID", QString("")).toString();
1161 	if (UID.isEmpty())
1162 	{
1163 		UID = QUuid::createUuid().toString();
1164 		settings.setValue("UID", UID);
1165 	}
1166 
1167 	QString BaseCommand("/~cignoni/meshlab_latest.php");
1168 
1169 #ifdef Q_OS_WIN
1170 	QString OS = "Win";
1171 #elif defined( Q_OS_OSX)
1172 	QString OS = "Mac";
1173 #else
1174 	QString OS = "Lin";
1175 #endif
1176 	QString message = BaseCommand + QString("?code=%1&count=%2&scount=%3&totkv=%4&ver=%5&os=%6").arg(UID).arg(loadedMeshCounter).arg(savedMeshCounter).arg(totalKV).arg(MeshLabApplication::appVer()).arg(OS);
1177 	//idHost=httpReq->setHost(MeshLabApplication::organizationHost()); // id == 1
1178 	httpReq->get(QNetworkRequest(MeshLabApplication::organizationHost() + message));
1179 	//idGet=httpReq->get(message,&myLocalBuf);     // id == 2
1180 }
1181 
connectionDone(QNetworkReply * reply)1182 void MainWindow::connectionDone(QNetworkReply *reply)
1183 {
1184     QString answer = reply->readAll();
1185 
1186     QSettings settings;
1187     QSettings::setDefaultFormat(QSettings::NativeFormat);
1188 
1189     // Check if the user specified not to be reminded to upgrade
1190     const QString dontRemindMeAboutUpgradeVar("dontRemindMeAboutUpgrade");
1191     bool dontRemindMeAboutUpgradeVal = false;
1192     if (settings.contains(dontRemindMeAboutUpgradeVar))
1193         dontRemindMeAboutUpgradeVal = settings.value(dontRemindMeAboutUpgradeVar).toBool();
1194 
1195     // This block is for debugging. Uncomment the lines below
1196     // to force the message box to appear.
1197     // answer = QString("NEW You must upgrade.");
1198     // dontRemindMeAboutUpgradeVal = false;
1199 
1200     if (dontRemindMeAboutUpgradeVal)
1201         return;
1202 
1203     // Set up a message box for the user
1204     QMessageBox msgBox(this);
1205     msgBox.setWindowTitle("MeshLab Version Checking");
1206     msgBox.addButton(QMessageBox::Ok);
1207     QCheckBox dontShowCheckBox("Don't show this message again.");
1208     dontShowCheckBox.blockSignals(true);
1209     msgBox.addButton(&dontShowCheckBox, QMessageBox::ResetRole);
1210 
1211     if (answer.left(3) == QString("NEW"))
1212     {
1213         msgBox.setText(answer.remove(0, 3));
1214     }
1215     else if (VerboseCheckingFlag)
1216     {
1217         if (answer.left(2) == QString("ok"))
1218             msgBox.setText("Your MeshLab version is the most recent one.");
1219         else
1220             msgBox.setText("Warning. Update Checking server did not answer correctly: " + answer);
1221     }
1222     reply->deleteLater();
1223 
1224     // Showing the dialog only if there is a new version or if we are verbose
1225     if (answer.left(3) == QString("NEW") || VerboseCheckingFlag)
1226     {
1227         int userReply = msgBox.exec();
1228         if (userReply == QMessageBox::Ok && dontShowCheckBox.checkState() == Qt::Checked)
1229             settings.setValue(dontRemindMeAboutUpgradeVar, true);
1230     }
1231 
1232     int loadedMeshCounter = settings.value("loadedMeshCounter", 0).toInt();
1233     settings.setValue("lastComunicatedValue", loadedMeshCounter);
1234 }
1235 
1236 
submitBug()1237 void MainWindow::submitBug()
1238 {
1239 	QMessageBox mb(QMessageBox::NoIcon, MeshLabApplication::appName(), MeshLabApplication::appName(), QMessageBox::NoButton, this);
1240 	//mb.setWindowTitle(tr("MeshLab"));
1241 	QPushButton *submitBug = mb.addButton("Submit Bug", QMessageBox::AcceptRole);
1242 	mb.addButton(QMessageBox::Cancel);
1243 	mb.setText(tr("If Meshlab closed in unexpected way (e.g. it crashed badly) and"
1244 		"if you are able to repeat the bug, please consider to submit a report using the github issue tracking system.\n"
1245 	));
1246 	mb.setInformativeText(tr(
1247 		"Hints for a good, useful bug report:\n"
1248 		"- Be verbose and descriptive\n"
1249 		"- Report meshlab version and OS\n"
1250 		"- Describe the sequence of actions that bring you to the crash.\n"
1251 		"- Consider submitting the mesh file causing a particular crash.\n"
1252 	));
1253 
1254 	mb.exec();
1255 
1256 	if (mb.clickedButton() == submitBug)
1257 		QDesktopServices::openUrl(QUrl("https://github.com/cnr-isti-vclab/meshlab/issues"));
1258 
1259 }
1260 
wrapSetActiveSubWindow(QWidget * window)1261 void MainWindow::wrapSetActiveSubWindow(QWidget* window) {
1262 	QMdiSubWindow* subwindow;
1263 	subwindow = dynamic_cast<QMdiSubWindow*>(window);
1264 	if (subwindow != NULL)
1265 	{
1266 		mdiarea->setActiveSubWindow(subwindow);
1267 	}
1268 	else {
1269 		qDebug("Type of window is not a QMdiSubWindow*");
1270 	}
1271 }
1272 
longestActionWidthInMenu(QMenu * m,const int longestwidth)1273 int MainWindow::longestActionWidthInMenu(QMenu* m, const int longestwidth)
1274 {
1275 	int longest = longestwidth;
1276 
1277 	const QList<QAction*>& acts = m->actions();
1278 	foreach(QAction* act, acts)
1279 	{
1280 		QMenu* submenu = act->menu();
1281 		if (!act->isSeparator() && (submenu == NULL))
1282 			longest = std::max(longest, m->actionGeometry(act).width());
1283 
1284 		else if (!act->isSeparator())
1285 			longest = std::max(longest, longestActionWidthInMenu(submenu, longest));
1286 	}
1287 	return longest;
1288 }
1289 
longestActionWidthInMenu(QMenu * m)1290 int MainWindow::longestActionWidthInMenu(QMenu* m)
1291 {
1292 	return longestActionWidthInMenu(m, 0);
1293 }
1294 
longestActionWidthInAllMenus()1295 int MainWindow::longestActionWidthInAllMenus()
1296 {
1297 	int longest = 0;
1298 	QList<QMenu*> list = menuBar()->findChildren<QMenu*>();
1299 	foreach(QMenu* m, list)
1300 		longest = std::max(longest, longestActionWidthInMenu(m));
1301 	return longest;
1302 }
1303 
initGlobalParameterSet(RichParameterSet * glbset)1304 void MainWindowSetting::initGlobalParameterSet(RichParameterSet* glbset)
1305 {
1306 	glbset->addParam(new RichInt(maximumDedicatedGPUMem(), 350, "Maximum GPU Memory Dedicated to MeshLab (Mb)", "Maximum GPU Memory Dedicated to MeshLab (megabyte) for the storing of the geometry attributes. The dedicated memory must NOT be all the GPU memory presents on the videocard."));
1307 	glbset->addParam(new RichInt(perBatchPrimitives(), 100000, "Per batch primitives loaded in GPU", "Per batch primitives (vertices and faces) loaded in the GPU memory. It's used in order to do not overwhelm the system memory with an entire temporary copy of a mesh."));
1308 	glbset->addParam(new RichInt(minPolygonNumberPerSmoothRendering(), 50000, "Default Face number per smooth rendering", "Minimum number of faces in order to automatically render a newly created mesh layer with the per vertex normal attribute activated."));
1309 
1310 //	glbset->addParam(new RichBool(perMeshRenderingToolBar(), true, "Show Per-Mesh Rendering Side ToolBar", "If true the per-mesh rendering side toolbar will be redendered inside the layerdialog."));
1311 
1312 	if (MeshLabScalarTest<Scalarm>::doublePrecision())
1313 		glbset->addParam(new RichBool(highPrecisionRendering(), false, "High Precision Rendering", "If true all the models in the scene will be rendered at the center of the world"));
1314 	glbset->addParam(new RichInt(maxTextureMemoryParam(), 256, "Max Texture Memory (in MB)", "The maximum quantity of texture memory allowed to load mesh textures"));
1315 }
1316 
updateGlobalParameterSet(RichParameterSet & rps)1317 void MainWindowSetting::updateGlobalParameterSet(RichParameterSet& rps)
1318 {
1319 	maxgpumem = (std::ptrdiff_t)rps.getInt(maximumDedicatedGPUMem()) * (float)(1024 * 1024);
1320 	perbatchprimitives = (size_t)rps.getInt(perBatchPrimitives());
1321 	minpolygonpersmoothrendering = (size_t)rps.getInt(minPolygonNumberPerSmoothRendering());
1322 //	permeshtoolbar = rps.getBool(perMeshRenderingToolBar());
1323 	highprecision = false;
1324 	if (MeshLabScalarTest<Scalarm>::doublePrecision())
1325 		highprecision = rps.getBool(highPrecisionRendering());
1326 	maxTextureMemory = (std::ptrdiff_t) rps.getInt(this->maxTextureMemoryParam()) * (float)(1024 * 1024);
1327 }
1328 
defaultPerViewRenderingData(MLRenderingData & dt) const1329 void MainWindow::defaultPerViewRenderingData(MLRenderingData& dt) const
1330 {
1331 	MLRenderingData::RendAtts tmpatts;
1332 	tmpatts[MLRenderingData::ATT_NAMES::ATT_VERTPOSITION] = true;
1333 	tmpatts[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL] = true;
1334 	tmpatts[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR] = true;
1335 	tmpatts[MLRenderingData::ATT_NAMES::ATT_WEDGETEXTURE] = true;
1336 	dt.set(MLRenderingData::PR_SOLID, tmpatts);
1337 	MLPerViewGLOptions opts;
1338 	dt.set(opts);
1339 }
1340