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<ers"));
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