2009-06-23 23:56:46 +04:00
/*
2011-01-21 04:21:09 +03:00
* OpenSCAD ( www . openscad . org )
* Copyright ( C ) 2009 - 2011 Clifford Wolf < clifford @ clifford . at > and
* Marius Kintel < marius @ kintel . net >
2009-06-23 23:56:46 +04:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
2010-02-01 12:34:18 +03:00
* As a special exception , you have permission to link this program
* with the CGAL library and distribute executables , as long as you
* follow the requirements of the GNU GPL in regard to all of the
* software in the executable aside from CGAL .
*
2009-06-23 23:56:46 +04:00
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*
*/
2014-09-14 22:14:14 +04:00
# include <iostream>
2014-12-23 05:56:17 +03:00
# include "openscad.h"
2013-03-28 01:50:25 +04:00
# include "GeometryCache.h"
2012-02-04 04:43:53 +04:00
# include "ModuleCache.h"
2009-12-09 17:25:09 +03:00
# include "MainWindow.h"
2011-12-25 01:02:37 +04:00
# include "parsersettings.h"
2014-08-15 01:16:24 +04:00
# include "rendersettings.h"
2010-01-15 04:00:41 +03:00
# include "Preferences.h"
2009-12-09 17:25:09 +03:00
# include "printutils.h"
2010-01-30 07:26:05 +03:00
# include "node.h"
# include "polyset.h"
# include "csgterm.h"
# include "highlighter.h"
# include "export.h"
# include "builtin.h"
2014-12-26 01:27:13 +03:00
# include "memory.h"
2014-06-21 03:28:34 +04:00
# include "expression.h"
2010-02-09 16:48:09 +03:00
# include "progress.h"
2011-10-01 03:36:30 +04:00
# include "dxfdim.h"
2014-06-07 19:40:35 +04:00
# include "legacyeditor.h"
2014-09-25 00:18:14 +04:00
# include "settings.h"
2014-08-14 02:52:01 +04:00
# ifdef USE_SCINTILLA_EDITOR
2014-06-07 19:40:35 +04:00
# include "scintillaeditor.h"
2014-08-14 02:52:01 +04:00
# endif
2012-08-04 20:49:45 +04:00
# include "AboutDialog.h"
2013-11-21 04:01:42 +04:00
# include "FontListDialog.h"
2014-09-15 06:08:18 +04:00
# include "LibraryInfoDialog.h"
2010-02-10 19:43:43 +03:00
# ifdef ENABLE_OPENCSG
2011-07-31 03:58:51 +04:00
# include "CSGTermEvaluator.h"
2011-08-04 02:45:40 +04:00
# include "OpenCSGRenderer.h"
2012-01-14 04:22:46 +04:00
# include <opencsg.h>
2010-02-10 19:43:43 +03:00
# endif
2010-02-10 18:13:12 +03:00
# include "ProgressWidget.h"
2011-08-04 02:45:40 +04:00
# include "ThrownTogetherRenderer.h"
2011-12-26 22:15:51 +04:00
# include "csgtermnormalizer.h"
2013-02-24 04:50:20 +04:00
# include "QGLView.h"
2013-02-08 00:01:31 +04:00
# ifdef Q_OS_MAC
# include "CocoaUtils.h"
# endif
2013-05-22 02:02:16 +04:00
# include "PlatformUtils.h"
2014-11-10 23:01:34 +03:00
# ifdef OPENSCAD_UPDATER
# include "AutoUpdater.h"
# endif
2009-06-23 23:56:46 +04:00
# include <QMenu>
2009-07-03 11:51:22 +04:00
# include <QTime>
2009-06-23 23:56:46 +04:00
# include <QMenuBar>
# include <QSplitter>
2009-06-24 02:32:08 +04:00
# include <QFileDialog>
# include <QApplication>
2009-07-28 19:15:29 +04:00
# include <QHBoxLayout>
# include <QVBoxLayout>
# include <QLabel>
2009-09-24 12:38:28 +04:00
# include <QFileInfo>
2010-01-07 00:35:01 +03:00
# include <QTextStream>
2009-10-14 13:44:41 +04:00
# include <QStatusBar>
2009-10-29 00:08:25 +03:00
# include <QDropEvent>
# include <QMimeData>
# include <QUrl>
2009-12-09 17:25:09 +03:00
# include <QTimer>
2009-12-13 01:04:32 +03:00
# include <QMessageBox>
2009-12-13 01:19:53 +03:00
# include <QDesktopServices>
2009-12-13 23:24:15 +03:00
# include <QSettings>
2011-12-26 02:00:30 +04:00
# include <QProgressDialog>
# include <QMutexLocker>
2014-02-13 09:15:35 +04:00
# include <QTemporaryFile>
2014-05-13 00:47:42 +04:00
# include <QDockWidget>
2014-09-20 00:35:20 +04:00
# include <QClipboard>
2014-10-20 02:22:22 +04:00
# include <QDesktopWidget>
2010-05-09 17:27:05 +04:00
2011-09-08 00:04:02 +04:00
# include <fstream>
2010-09-07 04:02:22 +04:00
# include <algorithm>
2012-02-18 00:08:55 +04:00
# include <boost/version.hpp>
2011-09-04 22:35:23 +04:00
# include <boost/foreach.hpp>
2012-02-14 04:30:39 +04:00
# include <sys/stat.h>
2010-09-07 04:02:22 +04:00
2009-11-22 16:42:37 +03:00
# ifdef ENABLE_CGAL
2011-09-11 12:51:55 +04:00
# include "CGALCache.h"
2013-10-31 08:45:00 +04:00
# include "GeometryEvaluator.h"
2011-09-04 03:59:06 +04:00
# include "CGALRenderer.h"
2011-09-01 06:09:06 +04:00
# include "CGAL_Nef_polyhedron.h"
# include "cgal.h"
2011-12-26 02:00:30 +04:00
# include "cgalworker.h"
2013-12-22 10:43:08 +04:00
# include "cgalutils.h"
2013-01-30 20:58:19 +04:00
2010-01-15 04:00:41 +03:00
# endif // ENABLE_CGAL
2009-11-22 16:42:37 +03:00
2013-05-27 05:45:28 +04:00
# include "boosty.h"
2014-01-19 06:05:00 +04:00
# include "FontCache.h"
2013-05-27 05:45:28 +04:00
2014-02-21 11:09:30 +04:00
// Keeps track of open window
QSet < MainWindow * > * MainWindow : : windows = NULL ;
2014-10-10 06:13:18 +04:00
QSet < MainWindow * > * MainWindow : : getWindows ( )
{
if ( ! MainWindow : : windows ) MainWindow : : windows = new QSet < MainWindow * > ;
return MainWindow : : windows ;
}
2010-11-06 18:03:01 +03:00
// Global application state
unsigned int GuiLocker : : gui_locked = 0 ;
2009-12-13 03:22:07 +03:00
static char copyrighttext [ ] =
2014-03-06 09:29:08 +04:00
" Copyright (C) 2009-2014 The OpenSCAD Developers \n "
2009-12-13 01:04:32 +03:00
" \n "
2012-08-22 05:08:55 +04:00
" This program is free software; you can redistribute it and/or modify "
" it under the terms of the GNU General Public License as published by "
" the Free Software Foundation; either version 2 of the License, or "
2009-12-13 01:04:32 +03:00
" (at your option) any later version. " ;
2011-07-04 01:42:55 +04:00
static void
settings_setValueList ( const QString & key , const QList < int > & list )
{
QSettings settings ;
settings . beginWriteArray ( key ) ;
for ( int i = 0 ; i < list . size ( ) ; + + i ) {
settings . setArrayIndex ( i ) ;
settings . setValue ( " entry " , list [ i ] ) ;
}
settings . endArray ( ) ;
}
QList < int >
settings_valueList ( const QString & key , const QList < int > & defaultList = QList < int > ( ) )
{
QSettings settings ;
QList < int > result ;
if ( settings . contains ( key + " /size " ) ) {
int length = settings . beginReadArray ( key ) ;
for ( int i = 0 ; i < length ; + + i ) {
settings . setArrayIndex ( i ) ;
result + = settings . value ( " entry " ) . toInt ( ) ;
}
settings . endArray ( ) ;
return result ;
} else {
return defaultList ;
}
}
2014-05-13 00:47:42 +04:00
bool MainWindow : : mdiMode = false ;
bool MainWindow : : undockMode = false ;
2014-11-01 20:55:48 +03:00
bool MainWindow : : reorderMode = false ;
2014-05-13 00:47:42 +04:00
2013-10-04 07:21:26 +04:00
MainWindow : : MainWindow ( const QString & filename )
2014-11-06 10:14:04 +03:00
: root_inst ( " group " ) , library_info_dialog ( NULL ) , font_list_dialog ( NULL ) , tempFile ( NULL ) , progresswidget ( NULL ) , contentschanged ( false )
2009-06-23 23:56:46 +04:00
{
2014-06-07 19:19:38 +04:00
setupUi ( this ) ;
2014-06-07 19:42:41 +04:00
2014-11-01 20:55:48 +03:00
editorDockTitleWidget = new QWidget ( ) ;
consoleDockTitleWidget = new QWidget ( ) ;
2014-10-31 10:45:04 +03:00
this - > editorDock - > setConfigKey ( " view/hideEditor " ) ;
this - > editorDock - > setAction ( this - > viewActionHideEditor ) ;
this - > consoleDock - > setConfigKey ( " view/hideConsole " ) ;
this - > consoleDock - > setAction ( this - > viewActionHideConsole ) ;
2014-12-23 08:24:57 +03:00
this - > versionLabel = NULL ; // must be initialized before calling updateStatusBar()
updateStatusBar ( NULL ) ;
2014-12-23 05:33:42 +03:00
2014-11-01 01:30:52 +03:00
QSettings settings ;
editortype = settings . value ( " editor/editortype " ) . toString ( ) ;
useScintilla = ( editortype ! = " Simple Editor " ) ;
2014-09-14 22:14:14 +04:00
2014-06-07 19:40:35 +04:00
# ifdef USE_SCINTILLA_EDITOR
2014-08-18 08:13:43 +04:00
if ( useScintilla ) {
2014-08-14 02:52:01 +04:00
editor = new ScintillaEditor ( editorDockContents ) ;
2014-12-27 04:17:15 +03:00
2014-08-18 08:13:43 +04:00
}
else
2014-06-07 19:40:35 +04:00
# endif
2014-09-13 23:19:44 +04:00
editor = new LegacyEditor ( editorDockContents ) ;
2014-07-17 23:28:23 +04:00
2014-11-16 21:35:16 +03:00
Preferences : : create ( editor - > colorSchemes ( ) ) ;
2014-11-01 01:30:52 +03:00
2014-12-27 04:17:15 +03:00
# ifdef USE_SCINTILLA_EDITOR
if ( useScintilla ) {
connect ( Preferences : : inst ( ) , SIGNAL ( editorConfigChanged ( ) ) , editor , SLOT ( applySettings ( ) ) ) ;
2014-12-30 15:03:51 +03:00
Preferences : : inst ( ) - > fireEditorConfigChanged ( ) ;
2014-12-27 04:17:15 +03:00
}
# endif
2014-06-07 19:40:35 +04:00
editorDockContents - > layout ( ) - > addWidget ( editor ) ;
2014-06-07 19:19:38 +04:00
2014-05-13 00:47:42 +04:00
setCorner ( Qt : : TopLeftCorner , Qt : : LeftDockWidgetArea ) ;
setCorner ( Qt : : TopRightCorner , Qt : : RightDockWidgetArea ) ;
setCorner ( Qt : : BottomLeftCorner , Qt : : LeftDockWidgetArea ) ;
setCorner ( Qt : : BottomRightCorner , Qt : : RightDockWidgetArea ) ;
2009-12-09 17:25:09 +03:00
2014-04-05 08:40:23 +04:00
this - > setAttribute ( Qt : : WA_DeleteOnClose ) ;
2014-02-21 11:09:30 +04:00
2014-10-10 06:13:18 +04:00
MainWindow : : getWindows ( ) - > insert ( this ) ;
2009-12-09 17:25:09 +03:00
2013-01-30 20:58:19 +04:00
# ifdef ENABLE_CGAL
2011-12-26 02:00:30 +04:00
this - > cgalworker = new CGALWorker ( ) ;
2013-12-22 10:43:08 +04:00
connect ( this - > cgalworker , SIGNAL ( done ( shared_ptr < const Geometry > ) ) ,
this , SLOT ( actionRenderDone ( shared_ptr < const Geometry > ) ) ) ;
2013-01-30 20:58:19 +04:00
# endif
2011-12-26 02:00:30 +04:00
2013-04-24 17:17:25 +04:00
top_ctx . registerBuiltin ( ) ;
2009-10-20 15:34:16 +04:00
2009-06-23 23:56:46 +04:00
root_module = NULL ;
2009-07-01 15:09:19 +04:00
absolute_root_node = NULL ;
2012-01-27 14:12:00 +04:00
this - > root_chain = NULL ;
2009-06-24 14:59:15 +04:00
# ifdef ENABLE_CGAL
2011-07-30 23:29:40 +04:00
this - > cgalRenderer = NULL ;
2009-06-24 14:59:15 +04:00
# endif
2011-07-30 23:29:40 +04:00
# ifdef ENABLE_OPENCSG
this - > opencsgRenderer = NULL ;
# endif
this - > thrownTogetherRenderer = NULL ;
2009-06-23 23:56:46 +04:00
2009-07-01 15:09:19 +04:00
highlights_chain = NULL ;
2009-07-23 16:05:05 +04:00
background_chain = NULL ;
2009-07-01 15:09:19 +04:00
root_node = NULL ;
2009-07-28 19:15:29 +04:00
tval = 0 ;
fps = 0 ;
2009-07-28 22:17:29 +04:00
fsteps = 1 ;
2009-07-28 19:15:29 +04:00
2014-05-13 00:47:42 +04:00
const QString importStatement = " import( \" %1 \" ); \n " ;
const QString surfaceStatement = " surface( \" %1 \" ); \n " ;
knownFileExtensions [ " stl " ] = importStatement ;
knownFileExtensions [ " off " ] = importStatement ;
knownFileExtensions [ " dxf " ] = importStatement ;
knownFileExtensions [ " dat " ] = surfaceStatement ;
knownFileExtensions [ " png " ] = surfaceStatement ;
knownFileExtensions [ " scad " ] = " " ;
2014-05-16 00:32:25 +04:00
knownFileExtensions [ " csg " ] = " " ;
2014-05-13 00:47:42 +04:00
2015-01-13 04:26:12 +03:00
editActionZoomTextIn - > setShortcuts ( QList < QKeySequence > ( ) < < editActionZoomTextIn - > shortcuts ( ) < < QKeySequence ( " CTRL+= " ) ) ;
2014-04-11 03:18:08 +04:00
2014-02-17 23:19:42 +04:00
connect ( this , SIGNAL ( highlightError ( int ) ) , editor , SLOT ( highlightError ( int ) ) ) ;
connect ( this , SIGNAL ( unhighlightLastError ( ) ) , editor , SLOT ( unhighlightLastError ( ) ) ) ;
2009-10-25 23:35:03 +03:00
2013-02-21 05:56:30 +04:00
this - > qglview - > statusLabel = new QLabel ( this ) ;
statusBar ( ) - > addWidget ( this - > qglview - > statusLabel ) ;
2009-10-14 13:44:41 +04:00
2009-07-28 19:15:29 +04:00
animate_timer = new QTimer ( this ) ;
connect ( animate_timer , SIGNAL ( timeout ( ) ) , this , SLOT ( updateTVal ( ) ) ) ;
2010-05-09 17:27:05 +04:00
autoReloadTimer = new QTimer ( this ) ;
autoReloadTimer - > setSingleShot ( false ) ;
2013-05-28 09:25:03 +04:00
autoReloadTimer - > setInterval ( 200 ) ;
2010-05-09 17:27:05 +04:00
connect ( autoReloadTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( checkAutoReload ( ) ) ) ;
2013-05-28 09:25:03 +04:00
waitAfterReloadTimer = new QTimer ( this ) ;
waitAfterReloadTimer - > setSingleShot ( true ) ;
waitAfterReloadTimer - > setInterval ( 200 ) ;
connect ( waitAfterReloadTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( waitAfterReload ( ) ) ) ;
2013-12-22 10:43:08 +04:00
connect ( this - > e_tval , SIGNAL ( textChanged ( QString ) ) , this , SLOT ( actionRenderPreview ( ) ) ) ;
2012-02-14 04:30:39 +04:00
connect ( this - > e_fps , SIGNAL ( textChanged ( QString ) ) , this , SLOT ( updatedFps ( ) ) ) ;
2009-07-28 19:15:29 +04:00
animate_panel - > hide ( ) ;
2014-02-01 14:46:05 +04:00
find_panel - > hide ( ) ;
2015-01-07 05:14:46 +03:00
frameCompileResult - > hide ( ) ;
this - > labelCompileResultMessage - > setOpenExternalLinks ( false ) ;
connect ( this - > labelCompileResultMessage , SIGNAL ( linkActivated ( QString ) ) , SLOT ( showConsole ( ) ) ) ;
2009-07-28 19:15:29 +04:00
2009-12-09 17:25:09 +03:00
// File menu
2014-09-14 22:00:26 +04:00
connect ( this - > fileActionNew , SIGNAL ( triggered ( ) ) , this , SLOT ( actionNew ( ) ) ) ;
2009-12-09 17:25:09 +03:00
connect ( this - > fileActionOpen , SIGNAL ( triggered ( ) ) , this , SLOT ( actionOpen ( ) ) ) ;
connect ( this - > fileActionSave , SIGNAL ( triggered ( ) ) , this , SLOT ( actionSave ( ) ) ) ;
connect ( this - > fileActionSaveAs , SIGNAL ( triggered ( ) ) , this , SLOT ( actionSaveAs ( ) ) ) ;
connect ( this - > fileActionReload , SIGNAL ( triggered ( ) ) , this , SLOT ( actionReload ( ) ) ) ;
2010-01-26 00:39:34 +03:00
connect ( this - > fileActionQuit , SIGNAL ( triggered ( ) ) , this , SLOT ( quit ( ) ) ) ;
2013-05-22 02:02:16 +04:00
connect ( this - > fileShowLibraryFolder , SIGNAL ( triggered ( ) ) , this , SLOT ( actionShowLibraryFolder ( ) ) ) ;
2009-12-09 17:25:09 +03:00
# ifndef __APPLE__
2011-10-30 05:25:57 +04:00
QList < QKeySequence > shortcuts = this - > fileActionSave - > shortcuts ( ) ;
shortcuts . push_back ( QKeySequence ( Qt : : Key_F2 ) ) ;
this - > fileActionSave - > setShortcuts ( shortcuts ) ;
shortcuts = this - > fileActionReload - > shortcuts ( ) ;
shortcuts . push_back ( QKeySequence ( Qt : : Key_F3 ) ) ;
this - > fileActionReload - > setShortcuts ( shortcuts ) ;
2009-12-09 17:25:09 +03:00
# endif
2009-12-13 23:24:15 +03:00
// Open Recent
2014-09-14 04:08:57 +04:00
for ( int i = 0 ; i < UIUtils : : maxRecentFiles ; i + + ) {
2009-12-13 23:24:15 +03:00
this - > actionRecentFile [ i ] = new QAction ( this ) ;
this - > actionRecentFile [ i ] - > setVisible ( false ) ;
this - > menuOpenRecent - > addAction ( this - > actionRecentFile [ i ] ) ;
connect ( this - > actionRecentFile [ i ] , SIGNAL ( triggered ( ) ) ,
this , SLOT ( actionOpenRecent ( ) ) ) ;
}
this - > menuOpenRecent - > addSeparator ( ) ;
this - > menuOpenRecent - > addAction ( this - > fileActionClearRecent ) ;
connect ( this - > fileActionClearRecent , SIGNAL ( triggered ( ) ) ,
this , SLOT ( clearRecentFiles ( ) ) ) ;
2014-05-03 22:24:07 +04:00
2014-09-14 04:08:57 +04:00
show_examples ( ) ;
2010-01-22 18:20:52 +03:00
2009-12-09 17:25:09 +03:00
// Edit menu
connect ( this - > editActionUndo , SIGNAL ( triggered ( ) ) , editor , SLOT ( undo ( ) ) ) ;
connect ( this - > editActionRedo , SIGNAL ( triggered ( ) ) , editor , SLOT ( redo ( ) ) ) ;
connect ( this - > editActionCut , SIGNAL ( triggered ( ) ) , editor , SLOT ( cut ( ) ) ) ;
connect ( this - > editActionCopy , SIGNAL ( triggered ( ) ) , editor , SLOT ( copy ( ) ) ) ;
connect ( this - > editActionPaste , SIGNAL ( triggered ( ) ) , editor , SLOT ( paste ( ) ) ) ;
2010-04-03 07:05:14 +04:00
connect ( this - > editActionIndent , SIGNAL ( triggered ( ) ) , editor , SLOT ( indentSelection ( ) ) ) ;
connect ( this - > editActionUnindent , SIGNAL ( triggered ( ) ) , editor , SLOT ( unindentSelection ( ) ) ) ;
connect ( this - > editActionComment , SIGNAL ( triggered ( ) ) , editor , SLOT ( commentSelection ( ) ) ) ;
connect ( this - > editActionUncomment , SIGNAL ( triggered ( ) ) , editor , SLOT ( uncommentSelection ( ) ) ) ;
2014-09-20 01:25:49 +04:00
connect ( this - > editActionConvertTabsToSpaces , SIGNAL ( triggered ( ) ) , this , SLOT ( convertTabsToSpaces ( ) ) ) ;
2009-12-09 17:25:09 +03:00
connect ( this - > editActionPasteVPT , SIGNAL ( triggered ( ) ) , this , SLOT ( pasteViewportTranslation ( ) ) ) ;
connect ( this - > editActionPasteVPR , SIGNAL ( triggered ( ) ) , this , SLOT ( pasteViewportRotation ( ) ) ) ;
2015-01-13 04:26:12 +03:00
connect ( this - > editActionZoomTextIn , SIGNAL ( triggered ( ) ) , editor , SLOT ( zoomIn ( ) ) ) ;
connect ( this - > editActionZoomTextOut , SIGNAL ( triggered ( ) ) , editor , SLOT ( zoomOut ( ) ) ) ;
2010-01-15 04:00:41 +03:00
connect ( this - > editActionPreferences , SIGNAL ( triggered ( ) ) , this , SLOT ( preferences ( ) ) ) ;
2014-02-01 14:46:05 +04:00
// Edit->Find
connect ( this - > editActionFind , SIGNAL ( triggered ( ) ) , this , SLOT ( find ( ) ) ) ;
2014-02-01 18:53:18 +04:00
connect ( this - > editActionFindAndReplace , SIGNAL ( triggered ( ) ) , this , SLOT ( findAndReplace ( ) ) ) ;
2014-02-01 14:46:05 +04:00
connect ( this - > editActionFindNext , SIGNAL ( triggered ( ) ) , this , SLOT ( findNext ( ) ) ) ;
connect ( this - > editActionFindPrevious , SIGNAL ( triggered ( ) ) , this , SLOT ( findPrev ( ) ) ) ;
2014-09-19 21:52:01 +04:00
connect ( this - > editActionUseSelectionForFind , SIGNAL ( triggered ( ) ) , this , SLOT ( useSelectionForFind ( ) ) ) ;
2009-12-09 17:25:09 +03:00
// Design menu
2010-05-09 17:27:05 +04:00
connect ( this - > designActionAutoReload , SIGNAL ( toggled ( bool ) ) , this , SLOT ( autoReloadSet ( bool ) ) ) ;
2013-12-22 10:43:08 +04:00
connect ( this - > designActionReloadAndPreview , SIGNAL ( triggered ( ) ) , this , SLOT ( actionReloadRenderPreview ( ) ) ) ;
connect ( this - > designActionPreview , SIGNAL ( triggered ( ) ) , this , SLOT ( actionRenderPreview ( ) ) ) ;
2009-12-13 03:22:07 +03:00
# ifdef ENABLE_CGAL
2013-12-22 10:43:08 +04:00
connect ( this - > designActionRender , SIGNAL ( triggered ( ) ) , this , SLOT ( actionRender ( ) ) ) ;
2009-12-13 03:22:07 +03:00
# else
2013-12-22 10:43:08 +04:00
this - > designActionRender - > setVisible ( false ) ;
2009-12-13 03:22:07 +03:00
# endif
2014-02-03 18:10:46 +04:00
connect ( this - > designCheckValidity , SIGNAL ( triggered ( ) ) , this , SLOT ( actionCheckValidity ( ) ) ) ;
2009-12-09 17:25:09 +03:00
connect ( this - > designActionDisplayAST , SIGNAL ( triggered ( ) ) , this , SLOT ( actionDisplayAST ( ) ) ) ;
connect ( this - > designActionDisplayCSGTree , SIGNAL ( triggered ( ) ) , this , SLOT ( actionDisplayCSGTree ( ) ) ) ;
connect ( this - > designActionDisplayCSGProducts , SIGNAL ( triggered ( ) ) , this , SLOT ( actionDisplayCSGProducts ( ) ) ) ;
connect ( this - > designActionExportSTL , SIGNAL ( triggered ( ) ) , this , SLOT ( actionExportSTL ( ) ) ) ;
connect ( this - > designActionExportOFF , SIGNAL ( triggered ( ) ) , this , SLOT ( actionExportOFF ( ) ) ) ;
2014-02-11 02:43:57 +04:00
connect ( this - > designActionExportAMF , SIGNAL ( triggered ( ) ) , this , SLOT ( actionExportAMF ( ) ) ) ;
2010-01-06 05:04:49 +03:00
connect ( this - > designActionExportDXF , SIGNAL ( triggered ( ) ) , this , SLOT ( actionExportDXF ( ) ) ) ;
2014-03-02 22:26:17 +04:00
connect ( this - > designActionExportSVG , SIGNAL ( triggered ( ) ) , this , SLOT ( actionExportSVG ( ) ) ) ;
2011-10-19 19:35:14 +04:00
connect ( this - > designActionExportCSG , SIGNAL ( triggered ( ) ) , this , SLOT ( actionExportCSG ( ) ) ) ;
2011-06-05 22:05:55 +04:00
connect ( this - > designActionExportImage , SIGNAL ( triggered ( ) ) , this , SLOT ( actionExportImage ( ) ) ) ;
2010-01-08 00:08:47 +03:00
connect ( this - > designActionFlushCaches , SIGNAL ( triggered ( ) ) , this , SLOT ( actionFlushCaches ( ) ) ) ;
2009-12-09 17:25:09 +03:00
// View menu
# ifndef ENABLE_OPENCSG
2013-12-22 10:43:08 +04:00
this - > viewActionPreview - > setVisible ( false ) ;
2009-12-09 17:25:09 +03:00
# else
2013-12-22 10:43:08 +04:00
connect ( this - > viewActionPreview , SIGNAL ( triggered ( ) ) , this , SLOT ( viewModePreview ( ) ) ) ;
2013-02-21 05:56:30 +04:00
if ( ! this - > qglview - > hasOpenCSGSupport ( ) ) {
2013-12-22 10:43:08 +04:00
this - > viewActionPreview - > setEnabled ( false ) ;
2009-07-01 02:30:22 +04:00
}
2009-06-23 23:56:46 +04:00
# endif
2009-12-13 03:22:07 +03:00
# ifdef ENABLE_CGAL
2013-12-22 10:43:08 +04:00
connect ( this - > viewActionSurfaces , SIGNAL ( triggered ( ) ) , this , SLOT ( viewModeSurface ( ) ) ) ;
connect ( this - > viewActionWireframe , SIGNAL ( triggered ( ) ) , this , SLOT ( viewModeWireframe ( ) ) ) ;
2009-12-13 03:22:07 +03:00
# else
2013-12-22 10:43:08 +04:00
this - > viewActionSurfaces - > setVisible ( false ) ;
this - > viewActionWireframe - > setVisible ( false ) ;
2009-12-13 03:22:07 +03:00
# endif
2009-12-09 17:25:09 +03:00
connect ( this - > viewActionThrownTogether , SIGNAL ( triggered ( ) ) , this , SLOT ( viewModeThrownTogether ( ) ) ) ;
connect ( this - > viewActionShowEdges , SIGNAL ( triggered ( ) ) , this , SLOT ( viewModeShowEdges ( ) ) ) ;
connect ( this - > viewActionShowAxes , SIGNAL ( triggered ( ) ) , this , SLOT ( viewModeShowAxes ( ) ) ) ;
connect ( this - > viewActionShowCrosshairs , SIGNAL ( triggered ( ) ) , this , SLOT ( viewModeShowCrosshairs ( ) ) ) ;
2015-01-02 10:32:37 +03:00
connect ( this - > viewActionShowScaleProportional , SIGNAL ( triggered ( ) ) , this , SLOT ( viewModeShowScaleProportional ( ) ) ) ;
2009-12-09 17:25:09 +03:00
connect ( this - > viewActionAnimate , SIGNAL ( triggered ( ) ) , this , SLOT ( viewModeAnimate ( ) ) ) ;
connect ( this - > viewActionTop , SIGNAL ( triggered ( ) ) , this , SLOT ( viewAngleTop ( ) ) ) ;
connect ( this - > viewActionBottom , SIGNAL ( triggered ( ) ) , this , SLOT ( viewAngleBottom ( ) ) ) ;
connect ( this - > viewActionLeft , SIGNAL ( triggered ( ) ) , this , SLOT ( viewAngleLeft ( ) ) ) ;
connect ( this - > viewActionRight , SIGNAL ( triggered ( ) ) , this , SLOT ( viewAngleRight ( ) ) ) ;
connect ( this - > viewActionFront , SIGNAL ( triggered ( ) ) , this , SLOT ( viewAngleFront ( ) ) ) ;
connect ( this - > viewActionBack , SIGNAL ( triggered ( ) ) , this , SLOT ( viewAngleBack ( ) ) ) ;
connect ( this - > viewActionDiagonal , SIGNAL ( triggered ( ) ) , this , SLOT ( viewAngleDiagonal ( ) ) ) ;
connect ( this - > viewActionCenter , SIGNAL ( triggered ( ) ) , this , SLOT ( viewCenter ( ) ) ) ;
2013-11-01 01:54:05 +04:00
connect ( this - > viewActionResetView , SIGNAL ( triggered ( ) ) , this , SLOT ( viewResetView ( ) ) ) ;
2014-06-22 00:12:55 +04:00
connect ( this - > viewActionViewAll , SIGNAL ( triggered ( ) ) , this , SLOT ( viewAll ( ) ) ) ;
2009-12-09 17:25:09 +03:00
connect ( this - > viewActionPerspective , SIGNAL ( triggered ( ) ) , this , SLOT ( viewPerspective ( ) ) ) ;
connect ( this - > viewActionOrthogonal , SIGNAL ( triggered ( ) ) , this , SLOT ( viewOrthogonal ( ) ) ) ;
2014-05-13 00:47:42 +04:00
connect ( this - > viewActionZoomIn , SIGNAL ( triggered ( ) ) , qglview , SLOT ( ZoomIn ( ) ) ) ;
connect ( this - > viewActionZoomOut , SIGNAL ( triggered ( ) ) , qglview , SLOT ( ZoomOut ( ) ) ) ;
2014-10-01 01:18:40 +04:00
connect ( this - > viewActionHideToolBars , SIGNAL ( triggered ( ) ) , this , SLOT ( hideToolbars ( ) ) ) ;
connect ( this - > viewActionHideEditor , SIGNAL ( triggered ( ) ) , this , SLOT ( hideEditor ( ) ) ) ;
connect ( this - > viewActionHideConsole , SIGNAL ( triggered ( ) ) , this , SLOT ( hideConsole ( ) ) ) ;
2009-12-09 17:25:09 +03:00
2009-12-16 12:44:24 +03:00
// Help menu
2009-12-13 01:04:32 +03:00
connect ( this - > helpActionAbout , SIGNAL ( triggered ( ) ) , this , SLOT ( helpAbout ( ) ) ) ;
2010-02-20 13:20:18 +03:00
connect ( this - > helpActionHomepage , SIGNAL ( triggered ( ) ) , this , SLOT ( helpHomepage ( ) ) ) ;
2009-12-13 01:19:53 +03:00
connect ( this - > helpActionManual , SIGNAL ( triggered ( ) ) , this , SLOT ( helpManual ( ) ) ) ;
2015-01-14 22:01:53 +03:00
connect ( this - > helpActionCheatSheet , SIGNAL ( triggered ( ) ) , this , SLOT ( helpCheatSheet ( ) ) ) ;
2012-02-15 04:26:38 +04:00
connect ( this - > helpActionLibraryInfo , SIGNAL ( triggered ( ) ) , this , SLOT ( helpLibrary ( ) ) ) ;
2013-11-21 04:01:42 +04:00
connect ( this - > helpActionFontInfo , SIGNAL ( triggered ( ) ) , this , SLOT ( helpFontInfo ( ) ) ) ;
2009-12-13 01:04:32 +03:00
2014-11-10 23:01:34 +03:00
# ifdef OPENSCAD_UPDATER
this - > menuBar ( ) - > addMenu ( AutoUpdater : : updater ( ) - > updateMenu ) ;
# endif
2010-02-28 23:54:55 +03:00
setCurrentOutput ( ) ;
2009-06-27 14:04:57 +04:00
2014-12-23 07:57:34 +03:00
std : : string helptitle = openscad_version + " \n http://www.openscad.org \n \n " ;
2009-12-13 03:22:07 +03:00
PRINT ( helptitle ) ;
PRINT ( copyrighttext ) ;
2009-06-27 14:04:57 +04:00
PRINT ( " " ) ;
2009-06-23 23:56:46 +04:00
2010-02-23 23:47:54 +03:00
if ( ! filename . isEmpty ( ) ) {
2009-12-13 03:22:07 +03:00
openFile ( filename ) ;
2009-06-27 14:20:24 +04:00
} else {
2009-12-13 23:24:15 +03:00
setFileName ( " " ) ;
2009-06-23 23:56:46 +04:00
}
2011-09-08 11:52:02 +04:00
updateRecentFileActions ( ) ;
2009-06-23 23:56:46 +04:00
2014-08-23 02:39:12 +04:00
connect ( editor , SIGNAL ( contentsChanged ( ) ) , this , SLOT ( animateUpdateDocChanged ( ) ) ) ;
2014-11-06 10:14:04 +03:00
connect ( editor , SIGNAL ( contentsChanged ( ) ) , this , SLOT ( setContentsChanged ( ) ) ) ;
2014-08-23 02:39:12 +04:00
connect ( editor , SIGNAL ( modificationChanged ( bool ) ) , this , SLOT ( setWindowModified ( bool ) ) ) ;
2013-02-21 05:56:30 +04:00
connect ( this - > qglview , SIGNAL ( doAnimateUpdate ( ) ) , this , SLOT ( animateUpdate ( ) ) ) ;
2009-10-22 23:42:52 +04:00
2013-02-21 05:56:30 +04:00
connect ( Preferences : : inst ( ) , SIGNAL ( requestRedraw ( ) ) , this - > qglview , SLOT ( updateGL ( ) ) ) ;
2014-05-13 00:47:42 +04:00
connect ( Preferences : : inst ( ) , SIGNAL ( updateMdiMode ( bool ) ) , this , SLOT ( updateMdiMode ( bool ) ) ) ;
2014-11-01 20:55:48 +03:00
connect ( Preferences : : inst ( ) , SIGNAL ( updateReorderMode ( bool ) ) , this , SLOT ( updateReorderMode ( bool ) ) ) ;
2014-05-13 00:47:42 +04:00
connect ( Preferences : : inst ( ) , SIGNAL ( updateUndockMode ( bool ) ) , this , SLOT ( updateUndockMode ( bool ) ) ) ;
connect ( Preferences : : inst ( ) , SIGNAL ( fontChanged ( const QString & , uint ) ) ,
2014-08-15 12:43:58 +04:00
editor , SLOT ( initFont ( const QString & , uint ) ) ) ;
2012-01-14 04:22:46 +04:00
connect ( Preferences : : inst ( ) , SIGNAL ( openCSGSettingsChanged ( ) ) ,
this , SLOT ( openCSGSettingsChanged ( ) ) ) ;
2014-04-11 03:18:08 +04:00
connect ( Preferences : : inst ( ) , SIGNAL ( syntaxHighlightChanged ( const QString & ) ) ,
2014-02-27 08:39:07 +04:00
editor , SLOT ( setHighlightScheme ( const QString & ) ) ) ;
2014-08-15 01:16:24 +04:00
connect ( Preferences : : inst ( ) , SIGNAL ( colorSchemeChanged ( const QString & ) ) ,
this , SLOT ( setColorScheme ( const QString & ) ) ) ;
2010-01-25 23:52:43 +03:00
Preferences : : inst ( ) - > apply ( ) ;
2014-08-15 01:16:24 +04:00
QString cs = Preferences : : inst ( ) - > getValue ( " 3dview/colorscheme " ) . toString ( ) ;
this - > setColorScheme ( cs ) ;
2014-08-18 08:13:43 +04:00
//find and replace panel
2014-02-01 18:53:18 +04:00
connect ( this - > findTypeComboBox , SIGNAL ( currentIndexChanged ( int ) ) , this , SLOT ( selectFindType ( int ) ) ) ;
2014-08-14 02:52:01 +04:00
connect ( this - > findInputField , SIGNAL ( textChanged ( QString ) ) , this , SLOT ( findString ( QString ) ) ) ;
2014-02-01 19:06:53 +04:00
connect ( this - > findInputField , SIGNAL ( returnPressed ( ) ) , this - > nextButton , SLOT ( animateClick ( ) ) ) ;
2014-02-01 14:46:05 +04:00
find_panel - > installEventFilter ( this ) ;
2014-09-20 00:35:20 +04:00
if ( QApplication : : clipboard ( ) - > supportsFindBuffer ( ) ) {
connect ( this - > findInputField , SIGNAL ( textChanged ( QString ) ) , this , SLOT ( updateFindBuffer ( QString ) ) ) ;
connect ( QApplication : : clipboard ( ) , SIGNAL ( findBufferChanged ( ) ) , this , SLOT ( findBufferChanged ( ) ) ) ;
// With Qt 4.8.6, there seems to be a bug that often gives an incorrect findbuffer content when
// the app receives focus for the first time
this - > findInputField - > setText ( QApplication : : clipboard ( ) - > text ( QClipboard : : FindBuffer ) ) ;
}
2014-02-01 14:46:05 +04:00
connect ( this - > prevButton , SIGNAL ( clicked ( ) ) , this , SLOT ( findPrev ( ) ) ) ;
connect ( this - > nextButton , SIGNAL ( clicked ( ) ) , this , SLOT ( findNext ( ) ) ) ;
connect ( this - > hideFindButton , SIGNAL ( clicked ( ) ) , find_panel , SLOT ( hide ( ) ) ) ;
2014-02-01 18:53:18 +04:00
connect ( this - > replaceButton , SIGNAL ( clicked ( ) ) , this , SLOT ( replace ( ) ) ) ;
connect ( this - > replaceAllButton , SIGNAL ( clicked ( ) ) , this , SLOT ( replaceAll ( ) ) ) ;
2014-02-01 19:06:53 +04:00
connect ( this - > replaceInputField , SIGNAL ( returnPressed ( ) ) , this - > replaceButton , SLOT ( animateClick ( ) ) ) ;
2014-09-14 21:51:40 +04:00
2014-10-01 00:47:14 +04:00
addKeyboardShortCut ( this - > viewerToolBar - > actions ( ) ) ;
2014-09-19 00:55:06 +04:00
addKeyboardShortCut ( this - > editortoolbar - > actions ( ) ) ;
2015-01-09 21:04:43 +03:00
initActionIcon ( fileActionNew , " :/images/blackNew.png " , " :/images/Document-New-128.png " ) ;
initActionIcon ( fileActionOpen , " :/images/Open-32.png " , " :/images/Open-128.png " ) ;
initActionIcon ( fileActionSave , " :/images/Save-32.png " , " :/images/Save-128.png " ) ;
2015-01-13 04:26:12 +03:00
initActionIcon ( editActionZoomTextIn , " :/images/zoom-text-in.png " , " :/images/zoom-text-in-white.png " ) ;
initActionIcon ( editActionZoomTextOut , " :/images/zoom-text-out.png " , " :/images/zoom-text-out-white.png " ) ;
2015-01-22 01:43:04 +03:00
initActionIcon ( designActionRender , " :/images/render-32.png " , " :/images/render-32-white.png " ) ;
2015-01-09 21:04:43 +03:00
initActionIcon ( viewActionShowAxes , " :/images/blackaxes.png " , " :/images/axes.png " ) ;
initActionIcon ( viewActionShowEdges , " :/images/Rotation-32.png " , " :/images/grid.png " ) ;
initActionIcon ( viewActionZoomIn , " :/images/zoomin.png " , " :/images/Zoom-In-32.png " ) ;
initActionIcon ( viewActionZoomOut , " :/images/zoomout.png " , " :/images/Zoom-Out-32.png " ) ;
initActionIcon ( viewActionTop , " :/images/blackUp.png " , " :/images/up.png " ) ;
initActionIcon ( viewActionBottom , " :/images/blackbottom.png " , " :/images/bottom.png " ) ;
initActionIcon ( viewActionLeft , " :/images/blackleft (copy).png " , " :/images/left.png " ) ;
initActionIcon ( viewActionRight , " :/images/rightright.png " , " :/images/right.png " ) ;
initActionIcon ( viewActionFront , " :/images/blackfront.png " , " :/images/front.png " ) ;
initActionIcon ( viewActionBack , " :/images/blackback.png " , " :/images/back.png " ) ;
initActionIcon ( viewActionSurfaces , " :/images/surface.png " , " :/images/surfaceWhite.png " ) ;
initActionIcon ( viewActionWireframe , " :/images/wireframe1.png " , " :/images/wireframeWhite.png " ) ;
initActionIcon ( viewActionShowCrosshairs , " :/images/cross.png " , " :/images/crosswhite.png " ) ;
initActionIcon ( viewActionPerspective , " :/images/perspective1.png " , " :/images/perspective1white.png " ) ;
initActionIcon ( viewActionOrthogonal , " :/images/orthogonal.png " , " :/images/orthogonalwhite.png " ) ;
2015-01-22 01:43:04 +03:00
initActionIcon ( designActionPreview , " :/images/preview-32.png " , " :/images/preview-32-white.png " ) ;
2015-01-09 21:04:43 +03:00
initActionIcon ( viewActionAnimate , " :/images/animate.png " , " :/images/animate.png " ) ;
2015-01-18 05:49:18 +03:00
initActionIcon ( designActionExportSTL , " :/images/STL.png " , " :/images/STL-white.png " ) ;
initActionIcon ( designActionExportAMF , " :/images/AMF.png " , " :/images/AMF-white.png " ) ;
initActionIcon ( designActionExportOFF , " :/images/OFF.png " , " :/images/OFF-white.png " ) ;
initActionIcon ( designActionExportDXF , " :/images/DXF.png " , " :/images/DXF-white.png " ) ;
initActionIcon ( designActionExportSVG , " :/images/SVG.png " , " :/images/SVG-white.png " ) ;
initActionIcon ( designActionExportCSG , " :/images/CSG.png " , " :/images/CSG-white.png " ) ;
initActionIcon ( designActionExportImage , " :/images/PNG.png " , " :/images/PNG-white.png " ) ;
2015-01-09 21:04:43 +03:00
initActionIcon ( viewActionViewAll , " :/images/zoom-all.png " , " :/images/zoom-all-white.png " ) ;
2015-01-09 21:24:04 +03:00
initActionIcon ( editActionUndo , " :/images/Command-Undo-32.png " , " :/images/Command-Undo-32-white.png " ) ;
initActionIcon ( editActionRedo , " :/images/Command-Redo-32.png " , " :/images/Command-Redo-32-white.png " ) ;
initActionIcon ( editActionUnindent , " :/images/Decrease-Indent-32.png " , " :/images/Decrease-Indent-32-white.png " ) ;
initActionIcon ( editActionIndent , " :/images/Increase-Indent-32.png " , " :/images/Increase-Indent-32-white.png " ) ;
initActionIcon ( viewActionResetView , " :/images/Command-Reset-32.png " , " :/images/Command-Reset-32-white.png " ) ;
2015-01-10 04:06:19 +03:00
initActionIcon ( viewActionShowScaleProportional , " :/images/scalemarkers.png " , " :/images/scalemarkers-white.png " ) ;
2014-09-14 22:14:14 +04:00
2011-07-04 01:42:55 +04:00
// make sure it looks nice..
2014-05-11 19:33:14 +04:00
QByteArray windowState = settings . value ( " window/state " , QByteArray ( ) ) . toByteArray ( ) ;
restoreState ( windowState ) ;
2011-07-04 01:42:55 +04:00
resize ( settings . value ( " window/size " , QSize ( 800 , 600 ) ) . toSize ( ) ) ;
move ( settings . value ( " window/position " , QPoint ( 0 , 0 ) ) . toPoint ( ) ) ;
2010-01-21 22:18:21 +03:00
2014-05-11 19:33:14 +04:00
if ( windowState . size ( ) = = 0 ) {
/*
* This triggers only in case the configuration file has no
* window state information ( or no configuration file at all ) .
* When this happens , the editor would default to a very ugly
* width due to the dock widget layout . This overwrites the
* value reported via sizeHint ( ) to a width a bit smaller than
* half the main window size ( either the one loaded from the
* configuration or the default value of 800 ) .
* The height is only a dummy value which will be essentially
* ignored by the layouting as the editor is set to expand to
* fill the available space .
*/
editor - > setInitialSizeHint ( QSize ( ( 5 * this - > width ( ) / 11 ) , 100 ) ) ;
2014-10-20 02:22:22 +04:00
} else {
# ifdef Q_OS_WIN
// Try moving the main window into the display range, this
// can occur when closing OpenSCAD on a second monitor which
// is not available at the time the application is started
// again.
// On Windows that causes the main window to open in a not
// easily reachable place.
QDesktopWidget * desktop = QApplication : : desktop ( ) ;
QRect desktopRect = desktop - > frameGeometry ( ) . adjusted ( 250 , 150 , - 250 , - 150 ) . normalized ( ) ;
QRect windowRect = frameGeometry ( ) ;
if ( ! desktopRect . intersects ( windowRect ) ) {
windowRect . moveCenter ( desktopRect . center ( ) ) ;
windowRect = windowRect . intersected ( desktopRect ) ;
move ( windowRect . topLeft ( ) ) ;
resize ( windowRect . size ( ) ) ;
}
# endif
2014-05-11 19:33:14 +04:00
}
2014-05-13 00:47:42 +04:00
connect ( this - > editorDock , SIGNAL ( topLevelChanged ( bool ) ) , this , SLOT ( editorTopLevelChanged ( bool ) ) ) ;
connect ( this - > consoleDock , SIGNAL ( topLevelChanged ( bool ) ) , this , SLOT ( consoleTopLevelChanged ( bool ) ) ) ;
2009-10-19 23:20:18 +04:00
// display this window and check for OpenGL 2.0 (OpenCSG) support
viewModeThrownTogether ( ) ;
show ( ) ;
2009-06-25 02:38:31 +04:00
# ifdef ENABLE_OPENCSG
2013-12-22 10:43:08 +04:00
viewModePreview ( ) ;
2009-06-25 02:38:31 +04:00
# else
2009-06-25 12:12:41 +04:00
viewModeThrownTogether ( ) ;
2009-06-25 02:38:31 +04:00
# endif
2011-07-04 00:57:07 +04:00
loadViewSettings ( ) ;
2011-07-06 03:43:05 +04:00
loadDesignSettings ( ) ;
2009-06-23 23:56:46 +04:00
2009-10-29 00:08:25 +03:00
setAcceptDrops ( true ) ;
2010-02-28 23:54:55 +03:00
clearCurrentOutput ( ) ;
2009-06-23 23:56:46 +04:00
}
2015-01-09 21:04:43 +03:00
void MainWindow : : initActionIcon ( QAction * action , const char * darkResource , const char * lightResource )
{
int defaultcolor = viewerToolBar - > palette ( ) . background ( ) . color ( ) . lightness ( ) ;
const char * resource = ( defaultcolor > 165 ) ? darkResource : lightResource ;
action - > setIcon ( QIcon ( resource ) ) ;
}
2014-09-19 00:55:06 +04:00
void MainWindow : : addKeyboardShortCut ( const QList < QAction * > & actions )
{
foreach ( QAction * action , actions ) {
// prevent adding shortcut twice if action is added to multiple toolbars
if ( action - > toolTip ( ) . contains ( " " ) ) {
continue ;
}
const QString shortCut ( action - > shortcut ( ) . toString ( QKeySequence : : NativeText ) ) ;
if ( shortCut . isEmpty ( ) ) {
continue ;
}
const QString toolTip ( " %1 <span style= \" color: gray; font-size: small; font-style: italic \" >%2</span> " ) ;
action - > setToolTip ( toolTip . arg ( action - > toolTip ( ) , shortCut ) ) ;
}
}
2014-08-18 08:13:43 +04:00
void MainWindow : : loadViewSettings ( ) {
2011-07-04 00:57:07 +04:00
QSettings settings ;
if ( settings . value ( " view/showEdges " ) . toBool ( ) ) {
viewActionShowEdges - > setChecked ( true ) ;
viewModeShowEdges ( ) ;
}
if ( settings . value ( " view/showAxes " ) . toBool ( ) ) {
viewActionShowAxes - > setChecked ( true ) ;
viewModeShowAxes ( ) ;
}
if ( settings . value ( " view/showCrosshairs " ) . toBool ( ) ) {
viewActionShowCrosshairs - > setChecked ( true ) ;
viewModeShowCrosshairs ( ) ;
}
Add optional menu driven scaling tics to the large axes
Tim Deagan 12/26/2014
While add-on rulers can be extremely useful, there are many times that a quick scaling marker would be handy. This feature generates tics every 10 units, driven off the log10 of the l variable defining axes length. As you zoom in or out, the tics automatically re-scale themselves. Every tenth tic is slightly larger. A menu item is added to the view menu to enable or disable the feature.
I experimented with menu driven scaling (.01, .1, 1, 10, etc.), but using small increments when zoomed out brought the app to it's knees. Adding a visual indicator of the current scaling might be nice, but I'm nto sure where to put it (possibly below the small axes,) since it changes as zooming and would clutter the console.
Changes to be committed:
new file: images/scalemarkers.png
modified: openscad.qrc
modified: src/GLView.cc
modified: src/GLView.h
modified: src/MainWindow.h
modified: src/MainWindow.ui
modified: src/QGLView.h
modified: src/mainwin.cc
2014-12-27 06:44:31 +03:00
if ( settings . value ( " view/showScaleProportional " ) . toBool ( ) ) {
viewActionShowScaleProportional - > setChecked ( true ) ;
viewModeShowScaleProportional ( ) ;
}
2011-07-04 00:57:07 +04:00
if ( settings . value ( " view/orthogonalProjection " ) . toBool ( ) ) {
viewOrthogonal ( ) ;
} else {
viewPerspective ( ) ;
}
2014-10-01 01:18:40 +04:00
viewActionHideConsole - > setChecked ( settings . value ( " view/hideConsole " ) . toBool ( ) ) ;
2014-06-14 17:30:48 +04:00
hideConsole ( ) ;
2014-10-01 01:18:40 +04:00
viewActionHideEditor - > setChecked ( settings . value ( " view/hideEditor " ) . toBool ( ) ) ;
2014-06-14 17:30:48 +04:00
hideEditor ( ) ;
2014-10-01 01:18:40 +04:00
viewActionHideToolBars - > setChecked ( settings . value ( " view/hideToolbar " ) . toBool ( ) ) ;
hideToolbars ( ) ;
2014-05-13 00:47:42 +04:00
updateMdiMode ( settings . value ( " advanced/mdi " ) . toBool ( ) ) ;
updateUndockMode ( settings . value ( " advanced/undockableWindows " ) . toBool ( ) ) ;
2014-11-01 20:55:48 +03:00
updateReorderMode ( settings . value ( " advanced/reorderWindows " ) . toBool ( ) ) ;
2011-07-04 00:57:07 +04:00
}
2014-08-18 08:13:43 +04:00
void MainWindow : : loadDesignSettings ( )
2011-07-06 03:43:05 +04:00
{
QSettings settings ;
2012-01-06 22:10:33 +04:00
if ( settings . value ( " design/autoReload " ) . toBool ( ) ) {
2011-07-06 03:43:05 +04:00
designActionAutoReload - > setChecked ( true ) ;
2012-01-06 22:10:33 +04:00
}
2012-01-10 03:55:46 +04:00
uint polySetCacheSize = Preferences : : inst ( ) - > getValue ( " advanced/polysetCacheSize " ) . toUInt ( ) ;
2013-03-28 01:50:25 +04:00
GeometryCache : : instance ( ) - > setMaxSize ( polySetCacheSize ) ;
2013-01-30 20:58:19 +04:00
# ifdef ENABLE_CGAL
2012-01-10 03:55:46 +04:00
uint cgalCacheSize = Preferences : : inst ( ) - > getValue ( " advanced/cgalCacheSize " ) . toUInt ( ) ;
2012-01-06 22:10:33 +04:00
CGALCache : : instance ( ) - > setMaxSize ( cgalCacheSize ) ;
2013-01-30 20:58:19 +04:00
# endif
2011-07-06 03:43:05 +04:00
}
2014-05-13 00:47:42 +04:00
void MainWindow : : updateMdiMode ( bool mdi )
{
MainWindow : : mdiMode = mdi ;
}
void MainWindow : : updateUndockMode ( bool undockMode )
{
MainWindow : : undockMode = undockMode ;
if ( undockMode ) {
editorDock - > setFeatures ( editorDock - > features ( ) | QDockWidget : : DockWidgetFloatable ) ;
consoleDock - > setFeatures ( consoleDock - > features ( ) | QDockWidget : : DockWidgetFloatable ) ;
} else {
2014-11-01 20:55:48 +03:00
if ( editorDock - > isFloating ( ) ) {
editorDock - > setFloating ( false ) ;
}
2014-05-13 00:47:42 +04:00
editorDock - > setFeatures ( editorDock - > features ( ) & ~ QDockWidget : : DockWidgetFloatable ) ;
2014-11-01 20:55:48 +03:00
if ( consoleDock - > isFloating ( ) ) {
consoleDock - > setFloating ( false ) ;
}
2014-05-13 00:47:42 +04:00
consoleDock - > setFeatures ( consoleDock - > features ( ) & ~ QDockWidget : : DockWidgetFloatable ) ;
}
}
2014-11-01 20:55:48 +03:00
void MainWindow : : updateReorderMode ( bool reorderMode )
{
MainWindow : : reorderMode = reorderMode ;
editorDock - > setTitleBarWidget ( reorderMode ? 0 : editorDockTitleWidget ) ;
consoleDock - > setTitleBarWidget ( reorderMode ? 0 : consoleDockTitleWidget ) ;
}
2009-06-23 23:56:46 +04:00
MainWindow : : ~ MainWindow ( )
{
2011-07-30 23:29:40 +04:00
if ( root_module ) delete root_module ;
if ( root_node ) delete root_node ;
2014-03-25 01:58:15 +04:00
if ( root_chain ) delete root_chain ;
2009-06-24 14:59:15 +04:00
# ifdef ENABLE_CGAL
2013-12-22 10:43:08 +04:00
this - > root_geom . reset ( ) ;
2011-07-30 23:29:40 +04:00
delete this - > cgalRenderer ;
# endif
# ifdef ENABLE_OPENCSG
delete this - > opencsgRenderer ;
2009-06-24 14:59:15 +04:00
# endif
2014-03-25 01:58:15 +04:00
delete this - > thrownTogetherRenderer ;
2014-10-10 06:13:18 +04:00
MainWindow : : getWindows ( ) - > remove ( this ) ;
2014-12-23 21:05:53 +03:00
if ( MainWindow : : getWindows ( ) - > size ( ) = = 0 ) {
// Quit application even in case some other windows like
// Preferences are still open.
qApp - > quit ( ) ;
}
2009-06-23 23:56:46 +04:00
}
2010-02-12 18:43:56 +03:00
void MainWindow : : showProgress ( )
{
2014-12-23 08:24:57 +03:00
updateStatusBar ( qobject_cast < ProgressWidget * > ( sender ( ) ) ) ;
2010-02-12 18:43:56 +03:00
}
2011-12-26 02:00:30 +04:00
void MainWindow : : report_func ( const class AbstractNode * , void * vp , int mark )
2010-02-09 16:48:09 +03:00
{
2011-12-26 02:00:30 +04:00
MainWindow * thisp = static_cast < MainWindow * > ( vp ) ;
2013-06-05 05:52:03 +04:00
int v = ( int ) ( ( mark * 1000.0 ) / progress_report_count ) ;
2014-04-11 03:18:08 +04:00
int permille = v < 1000 ? v : 999 ;
2013-06-05 05:52:03 +04:00
if ( permille > thisp - > progresswidget - > value ( ) ) {
2011-12-26 02:00:30 +04:00
QMetaObject : : invokeMethod ( thisp - > progresswidget , " setValue " , Qt : : QueuedConnection ,
2013-06-05 05:52:03 +04:00
Q_ARG ( int , permille ) ) ;
2012-01-26 02:35:25 +04:00
QApplication : : processEvents ( ) ;
2011-12-26 02:00:30 +04:00
}
2013-01-17 22:31:12 +04:00
// FIXME: Check if cancel was requested by e.g. Application quit
2011-12-26 02:00:30 +04:00
if ( thisp - > progresswidget - > wasCanceled ( ) ) throw ProgressCancelException ( ) ;
2010-02-09 16:48:09 +03:00
}
2009-12-13 00:27:54 +03:00
/*!
Requests to open a file from an external event , e . g . by double - clicking a filename .
*/
void MainWindow : : requestOpenFile ( const QString & filename )
{
2014-05-03 20:20:37 +04:00
// if we have an empty open window, use that one
2014-10-10 06:13:18 +04:00
QSetIterator < MainWindow * > i ( * MainWindow : : getWindows ( ) ) ;
2014-05-03 20:20:37 +04:00
while ( i . hasNext ( ) ) {
MainWindow * w = i . next ( ) ;
if ( w - > editor - > toPlainText ( ) . isEmpty ( ) ) {
w - > openFile ( filename ) ;
return ;
}
}
// otherwise, create a new one
2010-02-23 23:47:54 +03:00
new MainWindow ( filename ) ;
2009-12-13 00:27:54 +03:00
}
2014-05-13 00:47:42 +04:00
/*!
Open the given file . In MDI mode a new window is created if the current
one is not empty . Otherwise the current window content is overwritten .
Any check whether to replace the content have to be made before .
*/
2014-08-18 08:13:43 +04:00
void MainWindow : : openFile ( const QString & new_filename )
2009-12-13 00:27:54 +03:00
{
2014-05-13 00:47:42 +04:00
if ( MainWindow : : mdiMode ) {
if ( ! editor - > toPlainText ( ) . isEmpty ( ) ) {
new MainWindow ( new_filename ) ;
return ;
}
2009-12-13 00:27:54 +03:00
}
2014-05-13 00:47:42 +04:00
setCurrentOutput ( ) ;
2013-11-29 08:40:28 +04:00
editor - > setPlainText ( " " ) ;
2014-02-11 04:17:39 +04:00
this - > last_compiled_doc = " " ;
2009-12-14 07:24:51 +03:00
2014-05-13 00:47:42 +04:00
const QFileInfo fileInfo ( new_filename ) ;
const QString suffix = fileInfo . suffix ( ) . toLower ( ) ;
const bool knownFileType = knownFileExtensions . contains ( suffix ) ;
const QString cmd = knownFileExtensions [ suffix ] ;
if ( knownFileType & & cmd . isEmpty ( ) ) {
setFileName ( new_filename ) ;
updateRecentFiles ( ) ;
} else {
setFileName ( " " ) ;
editor - > setPlainText ( cmd . arg ( new_filename ) ) ;
}
2013-06-06 05:40:30 +04:00
fileChangedOnDisk ( ) ; // force cached autoReloadId to update
2012-02-14 04:30:39 +04:00
refreshDocument ( ) ;
2014-05-13 00:47:42 +04:00
clearCurrentOutput ( ) ;
2009-12-13 00:27:54 +03:00
}
2014-08-18 08:13:43 +04:00
void MainWindow : : setFileName ( const QString & filename )
2009-12-13 23:24:15 +03:00
{
if ( filename . isEmpty ( ) ) {
this - > fileName . clear ( ) ;
2014-10-19 02:39:32 +04:00
setWindowFilePath ( _ ( " Untitled.scad " ) ) ;
2014-05-13 00:47:42 +04:00
2013-04-24 17:17:25 +04:00
this - > top_ctx . setDocumentPath ( currentdir ) ;
2014-05-13 00:47:42 +04:00
} else {
2009-12-13 23:24:15 +03:00
QFileInfo fileinfo ( filename ) ;
2014-05-13 00:47:42 +04:00
this - > fileName = fileinfo . exists ( ) ? fileinfo . absoluteFilePath ( ) : fileinfo . fileName ( ) ;
2014-10-13 23:34:47 +04:00
QString fn = fileinfo . absoluteFilePath ( ) ;
setWindowFilePath ( fn ) ;
2009-12-13 23:24:15 +03:00
QDir : : setCurrent ( fileinfo . dir ( ) . absolutePath ( ) ) ;
2014-05-13 00:47:42 +04:00
this - > top_ctx . setDocumentPath ( fileinfo . dir ( ) . absolutePath ( ) . toLocal8Bit ( ) . constData ( ) ) ;
2009-12-13 23:24:15 +03:00
}
2014-05-13 00:35:50 +04:00
editorTopLevelChanged ( editorDock - > isFloating ( ) ) ;
consoleTopLevelChanged ( consoleDock - > isFloating ( ) ) ;
2011-09-08 11:52:02 +04:00
}
void MainWindow : : updateRecentFiles ( )
{
// Check that the canonical file path exists - only update recent files
// if it does. Should prevent empty list items on initial open etc.
QFileInfo fileinfo ( this - > fileName ) ;
QString infoFileName = fileinfo . absoluteFilePath ( ) ;
QSettings settings ; // already set up properly via main.cpp
QStringList files = settings . value ( " recentFileList " ) . toStringList ( ) ;
files . removeAll ( infoFileName ) ;
files . prepend ( infoFileName ) ;
2014-09-14 04:08:57 +04:00
while ( files . size ( ) > UIUtils : : maxRecentFiles ) files . removeLast ( ) ;
2011-09-08 11:52:02 +04:00
settings . setValue ( " recentFileList " , files ) ;
2009-12-13 23:24:15 +03:00
foreach ( QWidget * widget , QApplication : : topLevelWidgets ( ) ) {
MainWindow * mainWin = qobject_cast < MainWindow * > ( widget ) ;
if ( mainWin ) {
mainWin - > updateRecentFileActions ( ) ;
}
}
}
2009-07-28 19:15:29 +04:00
void MainWindow : : updatedFps ( )
{
bool fps_ok ;
2012-02-14 04:30:39 +04:00
double fps = this - > e_fps - > text ( ) . toDouble ( & fps_ok ) ;
2009-10-22 23:42:52 +04:00
animate_timer - > stop ( ) ;
if ( fps_ok & & fps > 0 ) {
animate_timer - > setSingleShot ( false ) ;
2012-02-14 04:30:39 +04:00
animate_timer - > setInterval ( int ( 1000 / this - > e_fps - > text ( ) . toDouble ( ) ) ) ;
2009-07-28 19:15:29 +04:00
animate_timer - > start ( ) ;
}
}
void MainWindow : : updateTVal ( )
{
2009-10-22 23:42:52 +04:00
bool fps_ok ;
2012-02-14 04:30:39 +04:00
double fps = this - > e_fps - > text ( ) . toDouble ( & fps_ok ) ;
2009-10-22 23:42:52 +04:00
if ( fps_ok ) {
if ( fps < = 0 ) {
2013-12-22 10:43:08 +04:00
actionRenderPreview ( ) ;
2009-10-22 23:42:52 +04:00
} else {
2012-02-14 04:30:39 +04:00
double s = this - > e_fsteps - > text ( ) . toDouble ( ) ;
double t = this - > e_tval - > text ( ) . toDouble ( ) + 1 / s ;
2009-10-22 23:42:52 +04:00
QString txt ;
txt . sprintf ( " %.5f " , t > = 1.0 ? 0.0 : t ) ;
2012-02-14 04:30:39 +04:00
this - > e_tval - > setText ( txt ) ;
2009-10-22 23:42:52 +04:00
}
}
2009-07-28 19:15:29 +04:00
}
2012-02-14 04:30:39 +04:00
void MainWindow : : refreshDocument ( )
2009-06-23 23:56:46 +04:00
{
2010-02-28 23:54:55 +03:00
setCurrentOutput ( ) ;
2009-12-14 07:24:51 +03:00
if ( ! this - > fileName . isEmpty ( ) ) {
2010-01-07 00:35:01 +03:00
QFile file ( this - > fileName ) ;
if ( ! file . open ( QIODevice : : ReadOnly | QIODevice : : Text ) ) {
2014-04-11 03:18:08 +04:00
PRINTB ( " Failed to open file %s: %s " ,
2013-03-12 06:14:00 +04:00
this - > fileName . toLocal8Bit ( ) . constData ( ) % file . errorString ( ) . toLocal8Bit ( ) . constData ( ) ) ;
2010-01-07 00:35:01 +03:00
}
else {
2012-12-08 12:53:53 +04:00
QTextStream reader ( & file ) ;
reader . setCodec ( " UTF-8 " ) ;
QString text = reader . readAll ( ) ;
2013-03-12 06:14:00 +04:00
PRINTB ( " Loaded design '%s'. " , this - > fileName . toLocal8Bit ( ) . constData ( ) ) ;
2014-11-06 10:14:04 +03:00
if ( editor - > toPlainText ( ) ! = text ) {
2014-05-11 00:41:46 +04:00
editor - > setPlainText ( text ) ;
2014-11-06 10:14:04 +03:00
this - > contentschanged = true ;
}
2009-06-24 02:32:08 +04:00
}
}
2010-02-28 23:54:55 +03:00
setCurrentOutput ( ) ;
2009-06-23 23:56:46 +04:00
}
2010-02-09 16:48:09 +03:00
/*!
2013-05-28 09:25:03 +04:00
compiles the design . Calls compileDone ( ) if anything was compiled
2010-02-09 16:48:09 +03:00
*/
2013-05-28 09:25:03 +04:00
void MainWindow : : compile ( bool reload , bool forcedone )
{
bool shouldcompiletoplevel = false ;
bool didcompile = false ;
2015-01-07 05:14:46 +03:00
compileErrors = 0 ;
compileWarnings = 0 ;
2014-12-17 02:01:25 +03:00
this - > renderingTime . start ( ) ;
2013-05-28 09:25:03 +04:00
// Reload checks the timestamp of the toplevel file and refreshes if necessary,
if ( reload ) {
2013-06-05 05:15:01 +04:00
// Refresh files if it has changed on disk
2013-05-28 09:25:03 +04:00
if ( fileChangedOnDisk ( ) & & checkEditorModified ( ) ) {
shouldcompiletoplevel = true ;
refreshDocument ( ) ;
}
2013-06-05 05:15:01 +04:00
// If the file hasn't changed, we might still need to compile it
// if we haven't yet compiled the current text.
else {
QString current_doc = editor - > toPlainText ( ) ;
2013-09-19 06:53:50 +04:00
if ( current_doc ! = last_compiled_doc & & last_compiled_doc . size ( ) = = 0 ) {
shouldcompiletoplevel = true ;
}
2013-06-05 05:15:01 +04:00
}
2013-05-28 09:25:03 +04:00
}
else {
shouldcompiletoplevel = true ;
}
2013-05-29 00:29:53 +04:00
if ( ! shouldcompiletoplevel & & this - > root_module & & this - > root_module - > includesChanged ( ) ) {
2013-05-28 09:25:03 +04:00
shouldcompiletoplevel = true ;
}
if ( shouldcompiletoplevel ) {
2013-05-29 00:29:53 +04:00
console - > clear ( ) ;
2014-02-18 09:00:33 +04:00
if ( editor - > isContentModified ( ) ) saveBackup ( ) ;
2013-05-28 09:25:03 +04:00
compileTopLevelDocument ( ) ;
didcompile = true ;
}
if ( this - > root_module ) {
if ( this - > root_module - > handleDependencies ( ) ) {
PRINTB ( " Module cache size: %d modules " , ModuleCache : : instance ( ) - > size ( ) ) ;
didcompile = true ;
}
}
// If we're auto-reloading, listen for a cascade of changes by starting a timer
// if something changed _and_ there are any external dependencies
if ( reload & & didcompile & & this - > root_module ) {
2013-05-29 00:29:53 +04:00
if ( this - > root_module - > hasIncludes ( ) | |
this - > root_module - > usesLibraries ( ) ) {
2013-05-28 09:25:03 +04:00
this - > waitAfterReloadTimer - > start ( ) ;
return ;
}
}
2014-02-17 23:19:42 +04:00
if ( ! reload & & didcompile ) {
if ( ! animate_panel - > isVisible ( ) ) {
emit unhighlightLastError ( ) ;
if ( ! this - > root_module ) {
emit highlightError ( parser_error_pos ) ;
}
}
}
2013-05-28 09:25:03 +04:00
compileDone ( didcompile | forcedone ) ;
}
void MainWindow : : waitAfterReload ( )
{
if ( this - > root_module - > handleDependencies ( ) ) {
this - > waitAfterReloadTimer - > start ( ) ;
return ;
}
else {
compile ( true , true ) ; // In case file itself or top-level includes changed during dependency updates
}
}
2015-01-09 20:20:07 +03:00
void MainWindow : : on_toolButtonCompileResultClose_clicked ( )
2015-01-07 05:14:46 +03:00
{
frameCompileResult - > hide ( ) ;
}
void MainWindow : : updateCompileResult ( )
{
if ( ( compileErrors = = 0 ) & & ( compileWarnings = = 0 ) ) {
frameCompileResult - > hide ( ) ;
return ;
}
2015-01-10 02:54:52 +03:00
Settings : : Settings * s = Settings : : Settings : : inst ( ) ;
if ( ! s - > get ( Settings : : Settings : : showWarningsIn3dView ) . toBool ( ) ) {
return ;
}
2015-01-07 05:14:46 +03:00
QString msg ;
if ( compileErrors > 0 ) {
if ( fileName . isEmpty ( ) ) {
msg = QString ( _ ( " Compile error. " ) ) ;
} else {
QFileInfo fileInfo ( fileName ) ;
msg = QString ( _ ( " Error while compiling '%1'. " ) ) . arg ( fileInfo . fileName ( ) ) ;
}
2015-01-09 20:20:07 +03:00
toolButtonCompileResultIcon - > setIcon ( QIcon ( QString : : fromUtf8 ( " :/icons/information-icons-error.png " ) ) ) ;
2015-01-07 05:14:46 +03:00
} else {
2015-01-09 20:20:07 +03:00
const char * fmt = ngettext ( " Compilation generated %1 warning. " , " Compilation generated %1 warnings. " , compileWarnings ) ;
msg = QString ( fmt ) . arg ( compileWarnings ) ;
toolButtonCompileResultIcon - > setIcon ( QIcon ( QString : : fromUtf8 ( " :/icons/information-icons-warning.png " ) ) ) ;
2015-01-07 05:14:46 +03:00
}
2015-01-10 19:21:56 +03:00
QFontMetrics fm ( labelCompileResultMessage - > font ( ) ) ;
int sizeIcon = std : : max ( 12 , std : : min ( 32 , fm . height ( ) ) ) ;
int sizeClose = std : : max ( 10 , std : : min ( 32 , fm . height ( ) ) - 4 ) ;
toolButtonCompileResultIcon - > setIconSize ( QSize ( sizeIcon , sizeIcon ) ) ;
toolButtonCompileResultClose - > setIconSize ( QSize ( sizeClose , sizeClose ) ) ;
2015-01-07 05:14:46 +03:00
msg + = _ ( " For details see <a href= \" #console \" >console window</a>. " ) ;
labelCompileResultMessage - > setText ( msg ) ;
frameCompileResult - > show ( ) ;
}
2013-05-28 09:25:03 +04:00
void MainWindow : : compileDone ( bool didchange )
{
const char * callslot ;
if ( didchange ) {
instantiateRoot ( ) ;
2014-11-30 00:44:40 +03:00
updateCamera ( ) ;
2015-01-07 05:14:46 +03:00
updateCompileResult ( ) ;
2013-05-28 09:25:03 +04:00
callslot = afterCompileSlot ;
}
else {
callslot = " compileEnded " ;
}
this - > procevents = false ;
QMetaObject : : invokeMethod ( this , callslot ) ;
}
void MainWindow : : compileEnded ( )
{
clearCurrentOutput ( ) ;
GuiLocker : : unlock ( ) ;
if ( designActionAutoReload - > isChecked ( ) ) autoReloadTimer - > start ( ) ;
}
void MainWindow : : instantiateRoot ( )
2009-06-23 23:56:46 +04:00
{
2013-05-28 09:25:03 +04:00
// Go on and instantiate root_node, then call the continuation slot
2009-06-24 19:39:08 +04:00
2011-07-30 23:29:40 +04:00
// Invalidate renderers before we kill the CSG tree
2013-02-21 05:56:30 +04:00
this - > qglview - > setRenderer ( NULL ) ;
2012-02-14 04:30:39 +04:00
delete this - > opencsgRenderer ;
this - > opencsgRenderer = NULL ;
delete this - > thrownTogetherRenderer ;
this - > thrownTogetherRenderer = NULL ;
2010-01-07 00:35:01 +03:00
// Remove previous CSG tree
2012-02-14 04:30:39 +04:00
delete this - > absolute_root_node ;
this - > absolute_root_node = NULL ;
2009-06-23 23:56:46 +04:00
2011-12-06 04:16:54 +04:00
this - > root_raw_term . reset ( ) ;
this - > root_norm_term . reset ( ) ;
2009-06-24 19:39:08 +04:00
2012-02-14 04:30:39 +04:00
delete this - > root_chain ;
this - > root_chain = NULL ;
2009-06-23 23:56:46 +04:00
2010-07-12 05:27:12 +04:00
this - > highlight_terms . clear ( ) ;
2010-09-07 04:02:22 +04:00
delete this - > highlights_chain ;
this - > highlights_chain = NULL ;
2010-07-12 05:27:12 +04:00
this - > background_terms . clear ( ) ;
2010-09-07 04:02:22 +04:00
delete this - > background_chain ;
this - > background_chain = NULL ;
2010-07-12 05:27:12 +04:00
this - > root_node = NULL ;
2010-11-06 18:03:01 +03:00
this - > tree . setRoot ( NULL ) ;
2009-07-01 15:09:19 +04:00
2012-02-14 04:30:39 +04:00
if ( this - > root_module ) {
// Evaluate CSG tree
PRINT ( " Compiling design (CSG Tree generation)... " ) ;
2013-05-28 09:25:03 +04:00
if ( this - > procevents ) QApplication : : processEvents ( ) ;
2014-04-11 03:18:08 +04:00
2012-02-14 04:30:39 +04:00
AbstractNode : : resetIndexCounter ( ) ;
2013-06-07 23:24:07 +04:00
// split these two lines - gcc 4.7 bug
ModuleInstantiation mi = ModuleInstantiation ( " group " ) ;
2014-04-11 03:18:08 +04:00
this - > root_inst = mi ;
2013-06-07 23:24:07 +04:00
2013-04-24 17:17:25 +04:00
this - > absolute_root_node = this - > root_module - > instantiate ( & top_ctx , & this - > root_inst , NULL ) ;
2014-04-11 03:18:08 +04:00
2012-02-14 04:30:39 +04:00
if ( this - > absolute_root_node ) {
// Do we have an explicit root node (! modifier)?
if ( ! ( this - > root_node = find_root_tag ( this - > absolute_root_node ) ) ) {
this - > root_node = this - > absolute_root_node ;
}
// FIXME: Consider giving away ownership of root_node to the Tree, or use reference counted pointers
this - > tree . setRoot ( this - > root_node ) ;
// Dump the tree (to initialize caches).
// FIXME: We shouldn't really need to do this explicitly..
this - > tree . getString ( * this - > root_node ) ;
2009-11-07 01:41:57 +03:00
}
}
2009-06-27 14:04:57 +04:00
2012-02-14 04:30:39 +04:00
if ( ! this - > root_node ) {
2010-02-09 16:48:09 +03:00
if ( parser_error_pos < 0 ) {
PRINT ( " ERROR: Compilation failed! (no top level object found) " ) ;
} else {
2011-09-08 07:14:52 +04:00
PRINT ( " ERROR: Compilation failed! " ) ;
2010-02-09 16:48:09 +03:00
}
2013-05-28 09:25:03 +04:00
if ( this - > procevents ) QApplication : : processEvents ( ) ;
2010-02-09 16:48:09 +03:00
}
}
/*!
Generates CSG tree for OpenCSG evaluation .
2012-02-14 04:30:39 +04:00
Assumes that the design has been parsed and evaluated ( this - > root_node is set )
2010-02-09 16:48:09 +03:00
*/
void MainWindow : : compileCSG ( bool procevents )
{
assert ( this - > root_node ) ;
2009-06-27 14:04:57 +04:00
PRINT ( " Compiling design (CSG Products generation)... " ) ;
2013-06-06 21:44:17 +04:00
if ( procevents ) QApplication : : processEvents ( ) ;
2009-06-24 19:39:08 +04:00
2010-01-15 20:07:40 +03:00
// Main CSG evaluation
2011-12-26 02:00:30 +04:00
this - > progresswidget = new ProgressWidget ( this ) ;
connect ( this - > progresswidget , SIGNAL ( requestShow ( ) ) , this , SLOT ( showProgress ( ) ) ) ;
2009-06-24 19:39:08 +04:00
2012-01-26 02:35:25 +04:00
progress_report_prep ( this - > root_node , report_func , this ) ;
2010-02-09 16:48:09 +03:00
try {
2013-01-30 20:58:19 +04:00
# ifdef ENABLE_CGAL
2013-10-31 08:45:00 +04:00
GeometryEvaluator geomevaluator ( this - > tree ) ;
2013-01-30 20:58:19 +04:00
# else
2013-10-31 08:45:00 +04:00
// FIXME: Will we support this?
2013-01-30 20:58:19 +04:00
# endif
2013-10-31 08:45:00 +04:00
CSGTermEvaluator csgrenderer ( this - > tree , & geomevaluator ) ;
2013-06-06 21:44:17 +04:00
if ( procevents ) QApplication : : processEvents ( ) ;
2011-12-06 04:16:54 +04:00
this - > root_raw_term = csgrenderer . evaluateCSGTerm ( * root_node , highlight_terms , background_terms ) ;
2013-03-28 01:50:25 +04:00
GeometryCache : : instance ( ) - > print ( ) ;
2013-01-30 20:58:19 +04:00
# ifdef ENABLE_CGAL
2011-09-11 12:51:55 +04:00
CGALCache : : instance ( ) - > print ( ) ;
2013-01-30 20:58:19 +04:00
# endif
2013-06-06 21:44:17 +04:00
if ( procevents ) QApplication : : processEvents ( ) ;
2009-06-24 21:40:19 +04:00
}
2012-10-09 04:49:02 +04:00
catch ( const ProgressCancelException & e ) {
2010-02-10 18:13:12 +03:00
PRINT ( " CSG generation cancelled. " ) ;
2009-07-03 01:21:05 +04:00
}
2010-02-09 16:48:09 +03:00
progress_report_fin ( ) ;
2014-12-23 08:24:57 +03:00
updateStatusBar ( NULL ) ;
2009-07-03 01:21:05 +04:00
2014-11-05 20:24:09 +03:00
PRINT ( " Compiling design (CSG Products normalization)... " ) ;
if ( procevents ) QApplication : : processEvents ( ) ;
2014-04-11 03:18:08 +04:00
2014-11-05 20:24:09 +03:00
size_t normalizelimit = 2 * Preferences : : inst ( ) - > getValue ( " advanced/openCSGLimit " ) . toUInt ( ) ;
CSGTermNormalizer normalizer ( normalizelimit ) ;
if ( root_raw_term ) {
2012-07-01 04:08:45 +04:00
this - > root_norm_term = normalizer . normalize ( this - > root_raw_term ) ;
2012-01-27 14:12:00 +04:00
if ( this - > root_norm_term ) {
this - > root_chain = new CSGChain ( ) ;
this - > root_chain - > import ( this - > root_norm_term ) ;
}
else {
this - > root_chain = NULL ;
PRINT ( " WARNING: CSG normalization resulted in an empty tree " ) ;
2013-06-06 21:44:17 +04:00
if ( procevents ) QApplication : : processEvents ( ) ;
2012-01-27 14:12:00 +04:00
}
2014-11-05 20:24:09 +03:00
}
2014-04-11 03:18:08 +04:00
2014-11-05 20:24:09 +03:00
if ( highlight_terms . size ( ) > 0 ) {
PRINTB ( " Compiling highlights (%d CSG Trees)... " , highlight_terms . size ( ) ) ;
if ( procevents ) QApplication : : processEvents ( ) ;
highlights_chain = new CSGChain ( ) ;
for ( unsigned int i = 0 ; i < highlight_terms . size ( ) ; i + + ) {
highlight_terms [ i ] = normalizer . normalize ( highlight_terms [ i ] ) ;
highlights_chain - > import ( highlight_terms [ i ] ) ;
2009-07-23 16:05:05 +04:00
}
2014-11-05 20:24:09 +03:00
}
if ( background_terms . size ( ) > 0 ) {
PRINTB ( " Compiling background (%d CSG Trees)... " , background_terms . size ( ) ) ;
if ( procevents ) QApplication : : processEvents ( ) ;
background_chain = new CSGChain ( ) ;
for ( unsigned int i = 0 ; i < background_terms . size ( ) ; i + + ) {
background_terms [ i ] = normalizer . normalize ( background_terms [ i ] ) ;
background_chain - > import ( background_terms [ i ] ) ;
2010-01-13 15:23:44 +03:00
}
2014-11-05 20:24:09 +03:00
}
2011-07-30 23:29:40 +04:00
2014-11-05 20:24:09 +03:00
if ( this - > root_chain & &
( this - > root_chain - > objects . size ( ) >
Preferences : : inst ( ) - > getValue ( " advanced/openCSGLimit " ) . toUInt ( ) ) ) {
PRINTB ( " WARNING: Normalized tree has %d elements! " , this - > root_chain - > objects . size ( ) ) ;
PRINT ( " WARNING: OpenCSG rendering has been disabled. " ) ;
2009-06-27 14:04:57 +04:00
}
2014-11-05 20:24:09 +03:00
else {
PRINTB ( " Normalized CSG tree has %d elements " ,
( this - > root_chain ? this - > root_chain - > objects . size ( ) : 0 ) ) ;
this - > opencsgRenderer = new OpenCSGRenderer ( this - > root_chain ,
this - > highlights_chain ,
this - > background_chain ,
this - > qglview - > shaderinfo ) ;
}
this - > thrownTogetherRenderer = new ThrownTogetherRenderer ( this - > root_chain ,
this - > highlights_chain ,
this - > background_chain ) ;
2014-12-17 02:01:25 +03:00
PRINT ( " Compile and preview finished. " ) ;
int s = this - > renderingTime . elapsed ( ) / 1000 ;
2014-11-05 20:24:09 +03:00
PRINTB ( " Total rendering time: %d hours, %d minutes, %d seconds " , ( s / ( 60 * 60 ) ) % ( ( s / 60 ) % 60 ) % ( s % 60 ) ) ;
if ( procevents ) QApplication : : processEvents ( ) ;
2009-06-27 14:04:57 +04:00
}
2009-06-27 14:20:24 +04:00
void MainWindow : : actionNew ( )
{
2014-05-13 00:47:42 +04:00
if ( MainWindow : : mdiMode ) {
new MainWindow ( QString ( ) ) ;
} else {
if ( ! maybeSave ( ) )
return ;
2010-07-03 00:59:16 +04:00
2014-05-13 00:47:42 +04:00
setFileName ( " " ) ;
editor - > setPlainText ( " " ) ;
}
2009-06-27 14:20:24 +04:00
}
void MainWindow : : actionOpen ( )
{
2014-09-14 04:08:57 +04:00
QFileInfo fileInfo = UIUtils : : openFile ( this ) ;
if ( ! fileInfo . exists ( ) ) {
return ;
2014-01-29 05:36:14 +04:00
}
2014-09-14 04:08:57 +04:00
2014-05-13 00:47:42 +04:00
if ( ! MainWindow : : mdiMode & & ! maybeSave ( ) ) {
2014-09-14 04:08:57 +04:00
return ;
2011-09-06 20:19:29 +04:00
}
2014-09-14 04:08:57 +04:00
openFile ( fileInfo . filePath ( ) ) ;
2009-06-27 14:20:24 +04:00
}
2009-12-13 23:24:15 +03:00
void MainWindow : : actionOpenRecent ( )
{
2014-05-13 00:47:42 +04:00
if ( ! MainWindow : : mdiMode & & ! maybeSave ( ) ) {
2010-07-03 00:59:16 +04:00
return ;
2009-12-13 23:24:15 +03:00
}
2014-05-13 00:47:42 +04:00
QAction * action = qobject_cast < QAction * > ( sender ( ) ) ;
openFile ( action - > data ( ) . toString ( ) ) ;
2009-12-13 23:24:15 +03:00
}
void MainWindow : : clearRecentFiles ( )
{
QSettings settings ; // already set up properly via main.cpp
QStringList files ;
settings . setValue ( " recentFileList " , files ) ;
2010-01-07 01:27:24 +03:00
2009-12-13 23:24:15 +03:00
updateRecentFileActions ( ) ;
}
void MainWindow : : updateRecentFileActions ( )
{
2014-09-14 04:08:57 +04:00
QStringList files = UIUtils : : recentFiles ( ) ;
2009-12-13 23:24:15 +03:00
2014-09-14 04:08:57 +04:00
for ( int i = 0 ; i < files . size ( ) ; + + i ) {
this - > actionRecentFile [ i ] - > setText ( QFileInfo ( files [ i ] ) . fileName ( ) ) ;
this - > actionRecentFile [ i ] - > setData ( files [ i ] ) ;
this - > actionRecentFile [ i ] - > setVisible ( true ) ;
}
for ( int i = files . size ( ) ; i < UIUtils : : maxRecentFiles ; + + i ) {
this - > actionRecentFile [ i ] - > setVisible ( false ) ;
}
2009-12-13 23:24:15 +03:00
}
2014-05-03 23:13:06 +04:00
void MainWindow : : show_examples ( )
{
2014-08-01 21:02:55 +04:00
bool found_example = false ;
2014-08-18 08:59:38 +04:00
2014-09-14 04:08:57 +04:00
foreach ( const QString & cat , UIUtils : : exampleCategories ( ) ) {
QFileInfoList examples = UIUtils : : exampleFiles ( cat ) ;
2014-10-19 02:39:32 +04:00
QMenu * menu = this - > menuExamples - > addMenu ( gettext ( cat . toStdString ( ) . c_str ( ) ) ) ;
2014-08-01 21:02:55 +04:00
2014-09-14 04:08:57 +04:00
foreach ( const QFileInfo & ex , examples ) {
QAction * openAct = new QAction ( ex . fileName ( ) , this ) ;
2014-08-01 21:02:55 +04:00
connect ( openAct , SIGNAL ( triggered ( ) ) , this , SLOT ( actionOpenExample ( ) ) ) ;
menu - > addAction ( openAct ) ;
2014-09-14 04:08:57 +04:00
openAct - > setData ( ex . canonicalFilePath ( ) ) ;
2014-08-01 21:02:55 +04:00
found_example = true ;
2014-05-03 23:13:06 +04:00
}
2014-08-01 21:02:55 +04:00
}
2014-05-03 23:13:06 +04:00
2014-08-01 21:02:55 +04:00
if ( ! found_example ) {
delete this - > menuExamples ;
this - > menuExamples = NULL ;
}
2014-05-03 23:13:06 +04:00
}
2010-01-22 18:20:52 +03:00
void MainWindow : : actionOpenExample ( )
{
2014-05-13 00:47:42 +04:00
if ( ! MainWindow : : mdiMode & & ! maybeSave ( ) ) {
return ;
}
2014-09-14 04:08:57 +04:00
const QAction * action = qobject_cast < QAction * > ( sender ( ) ) ;
2010-01-22 18:20:52 +03:00
if ( action ) {
2014-09-14 04:08:57 +04:00
const QString path = action - > data ( ) . toString ( ) ;
openFile ( path ) ;
2010-01-22 18:20:52 +03:00
}
}
2014-02-13 09:15:35 +04:00
void MainWindow : : writeBackup ( QFile * file )
{
// see MainWindow::saveBackup()
file - > resize ( 0 ) ;
QTextStream writer ( file ) ;
writer . setCodec ( " UTF-8 " ) ;
writer < < this - > editor - > toPlainText ( ) ;
2014-04-11 03:18:08 +04:00
2014-12-21 19:11:44 +03:00
PRINTB ( " Saved backup file: %s " , file - > fileName ( ) . toUtf8 ( ) . constData ( ) ) ;
2014-02-13 09:15:35 +04:00
}
void MainWindow : : saveBackup ( )
{
std : : string path = PlatformUtils : : backupPath ( ) ;
if ( ( ! fs : : exists ( path ) ) & & ( ! PlatformUtils : : createBackupPath ( ) ) ) {
PRINTB ( " WARNING: Cannot create backup path: %s " , path ) ;
return ;
}
2014-12-21 19:11:44 +03:00
QString backupPath = QString : : fromLocal8Bit ( path . c_str ( ) ) ;
2014-02-13 09:15:35 +04:00
if ( ! backupPath . endsWith ( " / " ) ) backupPath . append ( " / " ) ;
2014-02-21 09:02:09 +04:00
QString basename = " unsaved " ;
if ( ! this - > fileName . isEmpty ( ) ) {
QFileInfo fileInfo = QFileInfo ( this - > fileName ) ;
basename = fileInfo . baseName ( ) ;
2014-02-13 09:15:35 +04:00
}
2014-02-21 09:02:09 +04:00
if ( ! this - > tempFile ) {
this - > tempFile = new QTemporaryFile ( backupPath . append ( basename + " -backup-XXXXXXXX.scad " ) ) ;
}
2014-02-13 09:15:35 +04:00
2014-02-21 09:02:09 +04:00
if ( ( ! this - > tempFile - > isOpen ( ) ) & & ( ! this - > tempFile - > open ( ) ) ) {
PRINT ( " WARNING: Failed to create backup file " ) ;
2014-02-13 09:15:35 +04:00
return ;
}
2014-02-21 09:02:09 +04:00
return writeBackup ( this - > tempFile ) ;
2014-02-13 09:15:35 +04:00
}
2014-10-13 23:34:47 +04:00
/*!
Save current document .
Should _always_ write to disk , since this is called by SaveAs - i . e . don ' t try to be
smart and check for document modification here .
*/
2009-06-27 14:20:24 +04:00
void MainWindow : : actionSave ( )
{
2009-12-14 07:24:51 +03:00
if ( this - > fileName . isEmpty ( ) ) {
actionSaveAs ( ) ;
}
else {
2010-02-28 23:54:55 +03:00
setCurrentOutput ( ) ;
2010-01-07 00:35:01 +03:00
QFile file ( this - > fileName ) ;
if ( ! file . open ( QIODevice : : WriteOnly | QIODevice : : Truncate | QIODevice : : Text ) ) {
2014-08-18 08:59:38 +04:00
PRINTB ( " Failed to open file for writing: %s (%s) " ,
this - > fileName . toLocal8Bit ( ) . constData ( ) % file . errorString ( ) . toLocal8Bit ( ) . constData ( ) ) ;
2013-05-27 15:31:25 +04:00
QMessageBox : : warning ( this , windowTitle ( ) , tr ( " Failed to open file for writing: \n %1 (%2) " )
. arg ( this - > fileName ) . arg ( file . errorString ( ) ) ) ;
2010-01-07 00:35:01 +03:00
}
else {
2012-12-08 12:53:53 +04:00
QTextStream writer ( & file ) ;
writer . setCodec ( " UTF-8 " ) ;
writer < < this - > editor - > toPlainText ( ) ;
2013-03-12 06:14:00 +04:00
PRINTB ( " Saved design '%s'. " , this - > fileName . toLocal8Bit ( ) . constData ( ) ) ;
2010-04-03 07:05:14 +04:00
this - > editor - > setContentModified ( false ) ;
2009-12-14 07:24:51 +03:00
}
2010-02-28 23:54:55 +03:00
clearCurrentOutput ( ) ;
2011-09-08 11:52:02 +04:00
updateRecentFiles ( ) ;
2009-06-27 14:20:24 +04:00
}
}
void MainWindow : : actionSaveAs ( )
{
2014-10-19 02:39:32 +04:00
QString new_filename = QFileDialog : : getSaveFileName ( this , _ ( " Save File " ) ,
this - > fileName . isEmpty ( ) ? _ ( " Untitled.scad " ) : this - > fileName ,
_ ( " OpenSCAD Designs (*.scad) " ) ) ;
2009-06-27 14:20:24 +04:00
if ( ! new_filename . isEmpty ( ) ) {
2010-01-06 07:12:50 +03:00
if ( QFileInfo ( new_filename ) . suffix ( ) . isEmpty ( ) ) {
new_filename . append ( " .scad " ) ;
2010-01-06 09:07:23 +03:00
// Manual overwrite check since Qt doesn't do it, when using the
2010-01-06 07:12:50 +03:00
// defaultSuffix property
QFileInfo info ( new_filename ) ;
if ( info . exists ( ) ) {
if ( QMessageBox : : warning ( this , windowTitle ( ) ,
2014-10-19 02:39:32 +04:00
QString ( _ ( " %1 already exists. \n Do you want to replace it? " ) ) . arg ( info . fileName ( ) ) ,
2010-01-06 09:07:23 +03:00
QMessageBox : : Yes | QMessageBox : : No , QMessageBox : : No ) ! = QMessageBox : : Yes ) {
2010-01-06 07:12:50 +03:00
return ;
}
}
}
2014-10-13 23:34:47 +04:00
setFileName ( new_filename ) ;
2009-06-27 14:20:24 +04:00
actionSave ( ) ;
}
}
2013-05-22 02:02:16 +04:00
void MainWindow : : actionShowLibraryFolder ( )
{
2014-08-28 00:00:15 +04:00
std : : string path = PlatformUtils : : userLibraryPath ( ) ;
2013-05-27 05:45:28 +04:00
if ( ! fs : : exists ( path ) ) {
PRINTB ( " WARNING: Library path %s doesnt exist. Creating " , path ) ;
2014-08-28 00:00:15 +04:00
if ( ! PlatformUtils : : createUserLibraryPath ( ) ) {
2013-05-27 05:45:28 +04:00
PRINTB ( " ERROR: Cannot create library path: %s " , path ) ;
}
}
2014-08-28 00:00:15 +04:00
QString url = QString : : fromStdString ( path ) ;
2013-05-27 05:45:28 +04:00
//PRINTB("Opening file browser for %s", url.toStdString() );
2014-08-28 00:00:15 +04:00
QDesktopServices : : openUrl ( QUrl : : fromLocalFile ( url ) ) ;
2013-05-22 02:02:16 +04:00
}
2009-06-27 14:20:24 +04:00
void MainWindow : : actionReload ( )
{
2013-06-06 05:40:30 +04:00
if ( checkEditorModified ( ) ) {
fileChangedOnDisk ( ) ; // force cached autoReloadId to update
refreshDocument ( ) ;
}
2009-06-27 14:20:24 +04:00
}
2009-10-14 11:59:44 +04:00
void MainWindow : : pasteViewportTranslation ( )
{
QString txt ;
2013-03-03 20:52:25 +04:00
txt . sprintf ( " [ %.2f, %.2f, %.2f ] " , - qglview - > cam . object_trans . x ( ) , - qglview - > cam . object_trans . y ( ) , - qglview - > cam . object_trans . z ( ) ) ;
2014-08-22 22:22:33 +04:00
this - > editor - > insert ( txt ) ;
2009-10-14 11:59:44 +04:00
}
void MainWindow : : pasteViewportRotation ( )
{
QString txt ;
2009-10-19 22:27:47 +04:00
txt . sprintf ( " [ %.2f, %.2f, %.2f ] " ,
2014-09-13 23:19:44 +04:00
fmodf ( 360 - qglview - > cam . object_rot . x ( ) + 90 , 360 ) ,
fmodf ( 360 - qglview - > cam . object_rot . y ( ) , 360 ) ,
fmodf ( 360 - qglview - > cam . object_rot . z ( ) , 360 ) ) ;
2014-08-22 22:22:33 +04:00
this - > editor - > insert ( txt ) ;
2009-10-14 11:59:44 +04:00
}
2014-02-01 14:46:05 +04:00
void MainWindow : : find ( )
{
2014-02-01 18:53:18 +04:00
findTypeComboBox - > setCurrentIndex ( 0 ) ;
replaceInputField - > hide ( ) ;
replaceButton - > hide ( ) ;
replaceAllButton - > hide ( ) ;
2014-02-01 14:46:05 +04:00
find_panel - > show ( ) ;
2014-09-20 00:36:08 +04:00
if ( ! editor - > selectedText ( ) . isEmpty ( ) ) {
findInputField - > setText ( editor - > selectedText ( ) ) ;
}
2014-02-01 14:46:05 +04:00
findInputField - > setFocus ( ) ;
2014-08-23 09:25:29 +04:00
findInputField - > selectAll ( ) ;
2014-08-07 06:04:37 +04:00
}
2014-08-14 02:52:01 +04:00
void MainWindow : : findString ( QString textToFind )
2014-08-07 06:04:37 +04:00
{
2014-08-14 02:52:01 +04:00
editor - > find ( textToFind , false , false ) ;
2014-02-01 14:46:05 +04:00
}
2014-02-01 18:53:18 +04:00
void MainWindow : : findAndReplace ( )
{
findTypeComboBox - > setCurrentIndex ( 1 ) ;
replaceInputField - > show ( ) ;
replaceButton - > show ( ) ;
replaceAllButton - > show ( ) ;
find_panel - > show ( ) ;
2014-09-20 00:36:08 +04:00
if ( ! editor - > selectedText ( ) . isEmpty ( ) ) {
findInputField - > setText ( editor - > selectedText ( ) ) ;
}
2014-02-01 18:53:18 +04:00
findInputField - > setFocus ( ) ;
findInputField - > selectAll ( ) ;
}
2014-09-20 01:25:49 +04:00
void MainWindow : : selectFindType ( int type )
{
2014-02-01 18:53:18 +04:00
if ( type = = 0 ) find ( ) ;
if ( type = = 1 ) findAndReplace ( ) ;
}
2014-09-20 01:25:49 +04:00
void MainWindow : : replace ( )
{
2014-08-23 02:10:58 +04:00
this - > editor - > replaceSelectedText ( this - > replaceInputField - > text ( ) ) ;
this - > editor - > find ( this - > findInputField - > text ( ) ) ;
2014-02-01 18:53:18 +04:00
}
2014-09-20 01:25:49 +04:00
void MainWindow : : replaceAll ( )
{
2014-08-23 02:10:58 +04:00
while ( this - > editor - > find ( this - > findInputField - > text ( ) , true ) ) {
this - > editor - > replaceSelectedText ( this - > replaceInputField - > text ( ) ) ;
2014-02-01 14:46:05 +04:00
}
}
2014-09-20 01:25:49 +04:00
void MainWindow : : convertTabsToSpaces ( )
{
const QString text = this - > editor - > toPlainText ( ) ;
QString converted ;
int cnt = 4 ;
for ( int idx = 0 ; idx < text . length ( ) ; idx + + ) {
QChar c = text . at ( idx ) ;
if ( c = = ' \t ' ) {
for ( ; cnt > 0 ; cnt - - ) {
converted . append ( ' ' ) ;
}
} else {
converted . append ( c ) ;
}
if ( cnt < = 0 | | c = = ' \n ' ) {
cnt = 5 ;
}
cnt - - ;
}
this - > editor - > replaceAll ( converted ) ;
}
2014-02-01 14:46:05 +04:00
void MainWindow : : findNext ( )
{
2014-08-14 02:52:01 +04:00
editor - > find ( this - > findInputField - > text ( ) , true ) ;
2014-02-01 14:46:05 +04:00
}
void MainWindow : : findPrev ( )
{
2014-08-14 02:52:01 +04:00
editor - > find ( this - > findInputField - > text ( ) , true , true ) ;
2014-02-01 14:46:05 +04:00
}
2014-09-19 21:52:01 +04:00
void MainWindow : : useSelectionForFind ( )
{
findInputField - > setText ( editor - > selectedText ( ) ) ;
}
2014-09-20 00:35:20 +04:00
void MainWindow : : updateFindBuffer ( QString s ) {
QApplication : : clipboard ( ) - > setText ( s , QClipboard : : FindBuffer ) ;
}
void MainWindow : : findBufferChanged ( ) {
QString t = QApplication : : clipboard ( ) - > text ( QClipboard : : FindBuffer ) ;
// The convention seems to be to not update the search field if the findbuffer is empty
if ( ! t . isEmpty ( ) ) {
findInputField - > setText ( t ) ;
}
}
2014-02-01 14:46:05 +04:00
bool MainWindow : : eventFilter ( QObject * obj , QEvent * event )
{
if ( obj = = find_panel )
{
if ( event - > type ( ) = = QEvent : : KeyPress )
{
QKeyEvent * keyEvent = static_cast < QKeyEvent * > ( event ) ;
if ( keyEvent - > key ( ) = = Qt : : Key_Escape )
{
find_panel - > hide ( ) ;
return true ;
}
}
return false ;
}
return QMainWindow : : eventFilter ( obj , event ) ;
}
2012-02-14 04:30:39 +04:00
void MainWindow : : updateTemporalVariables ( )
{
2014-11-23 08:59:17 +03:00
this - > top_ctx . set_variable ( " $t " , ValuePtr ( this - > e_tval - > text ( ) . toDouble ( ) ) ) ;
2014-04-11 03:18:08 +04:00
2012-03-28 02:05:00 +04:00
Value : : VectorType vpt ;
2013-03-03 20:52:25 +04:00
vpt . push_back ( Value ( - qglview - > cam . object_trans . x ( ) ) ) ;
vpt . push_back ( Value ( - qglview - > cam . object_trans . y ( ) ) ) ;
vpt . push_back ( Value ( - qglview - > cam . object_trans . z ( ) ) ) ;
2013-04-24 17:17:25 +04:00
this - > top_ctx . set_variable ( " $vpt " , Value ( vpt ) ) ;
2014-04-11 03:18:08 +04:00
2012-03-28 02:05:00 +04:00
Value : : VectorType vpr ;
2013-03-03 20:52:25 +04:00
vpr . push_back ( Value ( fmodf ( 360 - qglview - > cam . object_rot . x ( ) + 90 , 360 ) ) ) ;
vpr . push_back ( Value ( fmodf ( 360 - qglview - > cam . object_rot . y ( ) , 360 ) ) ) ;
vpr . push_back ( Value ( fmodf ( 360 - qglview - > cam . object_rot . z ( ) , 360 ) ) ) ;
2014-11-23 08:59:17 +03:00
top_ctx . set_variable ( " $vpr " , ValuePtr ( vpr ) ) ;
2014-06-21 00:20:08 +04:00
2015-01-05 20:34:08 +03:00
top_ctx . set_variable ( " $vpd " , ValuePtr ( qglview - > cam . zoomValue ( ) ) ) ;
2012-02-14 04:30:39 +04:00
}
2014-06-21 03:28:34 +04:00
/*!
* Update the viewport camera by evaluating the special variables . If they
* are assigned on top - level , the values are used to change the camera
* rotation , translation and distance .
*/
void MainWindow : : updateCamera ( )
{
if ( ! root_module )
return ;
bool camera_set = false ;
2014-06-29 02:59:19 +04:00
Camera cam ( qglview - > cam ) ;
cam . gimbalDefaultTranslate ( ) ;
double tx = cam . object_trans . x ( ) ;
double ty = cam . object_trans . y ( ) ;
double tz = cam . object_trans . z ( ) ;
double rx = cam . object_rot . x ( ) ;
double ry = cam . object_rot . y ( ) ;
double rz = cam . object_rot . z ( ) ;
2015-01-05 20:34:08 +03:00
double d = cam . zoomValue ( ) ;
2014-06-29 02:58:16 +04:00
2014-11-30 00:44:40 +03:00
double x , y , z ;
2014-12-02 01:07:01 +03:00
const ValuePtr vpr = root_module - > lookup_variable ( " $vpr " ) ;
if ( vpr - > getVec3 ( x , y , z ) ) {
2014-11-30 00:44:40 +03:00
rx = x ;
ry = y ;
rz = z ;
camera_set = true ;
}
2014-12-02 01:07:01 +03:00
const ValuePtr vpt = root_module - > lookup_variable ( " $vpt " ) ;
if ( vpt - > getVec3 ( x , y , z ) ) {
2014-11-30 00:44:40 +03:00
tx = x ;
ty = y ;
tz = z ;
camera_set = true ;
}
2014-12-02 01:07:01 +03:00
const ValuePtr vpd = root_module - > lookup_variable ( " $vpd " ) ;
if ( vpd - > type ( ) = = Value : : NUMBER ) {
d = vpd - > toDouble ( ) ;
2014-11-30 00:44:40 +03:00
camera_set = true ;
2014-06-21 03:28:34 +04:00
}
if ( camera_set ) {
std : : vector < double > params ;
params . push_back ( tx ) ;
params . push_back ( ty ) ;
params . push_back ( tz ) ;
params . push_back ( rx ) ;
params . push_back ( ry ) ;
params . push_back ( rz ) ;
params . push_back ( d ) ;
qglview - > cam . setup ( params ) ;
2014-06-29 02:59:19 +04:00
qglview - > cam . gimbalDefaultTranslate ( ) ;
2014-06-21 03:28:34 +04:00
qglview - > updateGL ( ) ;
}
2012-02-14 04:30:39 +04:00
}
2014-02-18 09:00:33 +04:00
/*!
Returns true if the current document is a file on disk and that file has new content .
Returns false if a file on disk has disappeared or if we haven ' t yet saved .
*/
2012-02-14 04:30:39 +04:00
bool MainWindow : : fileChangedOnDisk ( )
2010-05-09 17:27:05 +04:00
{
2011-10-04 02:34:49 +04:00
if ( ! this - > fileName . isEmpty ( ) ) {
2012-02-14 04:30:39 +04:00
struct stat st ;
memset ( & st , 0 , sizeof ( struct stat ) ) ;
2013-05-31 00:51:00 +04:00
bool valid = ( stat ( this - > fileName . toLocal8Bit ( ) , & st ) = = 0 ) ;
// If file isn't there, just return and use current editor text
if ( ! valid ) return false ;
2012-02-14 04:30:39 +04:00
std : : string newid = str ( boost : : format ( " %x.%x " ) % st . st_mtime % st . st_size ) ;
if ( newid ! = this - > autoReloadId ) {
this - > autoReloadId = newid ;
return true ;
}
2011-10-04 02:34:49 +04:00
}
2012-02-14 04:30:39 +04:00
return false ;
}
/*!
2012-02-18 02:05:36 +04:00
Returns true if anything was compiled .
2012-02-14 04:30:39 +04:00
*/
2013-05-28 09:25:03 +04:00
void MainWindow : : compileTopLevelDocument ( )
2012-02-14 04:30:39 +04:00
{
2013-05-28 09:25:03 +04:00
updateTemporalVariables ( ) ;
2014-03-03 07:09:10 +04:00
resetPrintedDeprecations ( ) ;
2014-04-11 03:18:08 +04:00
2013-05-28 09:25:03 +04:00
this - > last_compiled_doc = editor - > toPlainText ( ) ;
2014-06-07 19:42:41 +04:00
2014-04-11 03:18:08 +04:00
std : : string fulltext =
2014-12-16 23:31:00 +03:00
std : : string ( this - > last_compiled_doc . toUtf8 ( ) . constData ( ) ) +
2013-05-28 09:25:03 +04:00
" \n " + commandline_commands ;
2014-12-16 23:31:00 +03:00
2013-05-28 09:25:03 +04:00
delete this - > root_module ;
this - > root_module = NULL ;
2014-04-11 03:18:08 +04:00
2013-05-28 09:25:03 +04:00
this - > root_module = parse ( fulltext . c_str ( ) ,
2014-08-18 08:13:43 +04:00
this - > fileName . isEmpty ( ) ? " " :
QFileInfo ( this - > fileName ) . absolutePath ( ) . toLocal8Bit ( ) , false ) ;
2012-02-14 04:30:39 +04:00
}
void MainWindow : : checkAutoReload ( )
{
2013-05-28 09:25:03 +04:00
if ( ! this - > fileName . isEmpty ( ) ) {
2013-12-22 10:43:08 +04:00
actionReloadRenderPreview ( ) ;
2013-05-28 09:25:03 +04:00
}
2010-05-09 17:27:05 +04:00
}
void MainWindow : : autoReloadSet ( bool on )
{
2011-07-06 03:07:26 +04:00
QSettings settings ;
settings . setValue ( " design/autoReload " , designActionAutoReload - > isChecked ( ) ) ;
2010-05-09 17:27:05 +04:00
if ( on ) {
autoReloadTimer - > start ( 200 ) ;
} else {
autoReloadTimer - > stop ( ) ;
}
}
2012-02-22 16:50:38 +04:00
bool MainWindow : : checkEditorModified ( )
2009-06-27 14:20:24 +04:00
{
2010-05-08 15:38:30 +04:00
if ( editor - > isContentModified ( ) ) {
QMessageBox : : StandardButton ret ;
2014-10-19 02:39:32 +04:00
ret = QMessageBox : : warning ( this , _ ( " Application " ) ,
_ ( " The document has been modified. \n "
" Do you really want to reload the file? " ) ,
2010-05-08 15:38:30 +04:00
QMessageBox : : Yes | QMessageBox : : No ) ;
if ( ret ! = QMessageBox : : Yes ) {
2010-05-09 17:27:05 +04:00
designActionAutoReload - > setChecked ( false ) ;
2010-06-13 03:30:42 +04:00
return false ;
2010-05-08 15:38:30 +04:00
}
}
2010-06-13 03:30:42 +04:00
return true ;
}
2013-12-22 10:43:08 +04:00
void MainWindow : : actionReloadRenderPreview ( )
2010-06-13 03:30:42 +04:00
{
2010-11-06 18:03:01 +03:00
if ( GuiLocker : : isLocked ( ) ) return ;
2013-05-28 09:25:03 +04:00
GuiLocker : : lock ( ) ;
autoReloadTimer - > stop ( ) ;
2012-02-18 02:05:36 +04:00
setCurrentOutput ( ) ;
2009-06-27 14:20:24 +04:00
2012-02-18 02:05:36 +04:00
// PRINT("Parsing design (AST generation)...");
// QApplication::processEvents();
2013-05-28 09:25:03 +04:00
this - > afterCompileSlot = " csgReloadRender " ;
this - > procevents = true ;
compile ( true ) ;
}
void MainWindow : : csgReloadRender ( )
{
2010-02-09 16:48:09 +03:00
if ( this - > root_node ) compileCSG ( true ) ;
2009-06-27 14:20:24 +04:00
2011-08-27 23:11:27 +04:00
// Go to non-CGAL view mode
if ( viewActionThrownTogether - > isChecked ( ) ) {
viewModeThrownTogether ( ) ;
}
else {
2009-06-27 14:20:24 +04:00
# ifdef ENABLE_OPENCSG
2013-12-22 10:43:08 +04:00
viewModePreview ( ) ;
2011-08-27 23:11:27 +04:00
# else
viewModeThrownTogether ( ) ;
2009-06-27 14:20:24 +04:00
# endif
}
2013-05-28 09:25:03 +04:00
compileEnded ( ) ;
2009-06-27 14:20:24 +04:00
}
2013-12-22 10:43:08 +04:00
void MainWindow : : actionRenderPreview ( )
2009-06-27 14:04:57 +04:00
{
2010-11-06 18:03:01 +03:00
if ( GuiLocker : : isLocked ( ) ) return ;
2013-05-28 09:25:03 +04:00
GuiLocker : : lock ( ) ;
autoReloadTimer - > stop ( ) ;
2010-02-28 23:54:55 +03:00
setCurrentOutput ( ) ;
2009-06-27 14:04:57 +04:00
2012-02-14 04:30:39 +04:00
PRINT ( " Parsing design (AST generation)... " ) ;
QApplication : : processEvents ( ) ;
2013-05-28 09:25:03 +04:00
this - > afterCompileSlot = " csgRender " ;
this - > procevents = ! viewActionAnimate - > isChecked ( ) ;
compile ( false ) ;
}
void MainWindow : : csgRender ( )
{
2010-02-09 16:48:09 +03:00
if ( this - > root_node ) compileCSG ( ! viewActionAnimate - > isChecked ( ) ) ;
2009-06-27 14:04:57 +04:00
2010-01-15 17:01:56 +03:00
// Go to non-CGAL view mode
2011-07-30 23:29:40 +04:00
if ( viewActionThrownTogether - > isChecked ( ) ) {
viewModeThrownTogether ( ) ;
}
else {
2010-02-28 21:17:23 +03:00
# ifdef ENABLE_OPENCSG
2013-12-22 10:43:08 +04:00
viewModePreview ( ) ;
2010-02-28 21:17:23 +03:00
# else
viewModeThrownTogether ( ) ;
# endif
2009-06-27 14:04:57 +04:00
}
2010-01-15 17:01:56 +03:00
if ( viewActionAnimate - > isChecked ( ) & & e_dump - > isChecked ( ) ) {
2015-01-14 06:29:33 +03:00
// Force reading from front buffer. Some configurations will read from the back buffer here.
glReadBuffer ( GL_FRONT ) ;
2013-02-21 05:56:30 +04:00
QImage img = this - > qglview - > grabFrameBuffer ( ) ;
2010-01-15 17:01:56 +03:00
QString filename ;
2012-02-14 04:30:39 +04:00
double s = this - > e_fsteps - > text ( ) . toDouble ( ) ;
double t = this - > e_tval - > text ( ) . toDouble ( ) ;
2010-01-15 17:01:56 +03:00
filename . sprintf ( " frame%05d.png " , int ( round ( s * t ) ) ) ;
img . save ( filename , " PNG " ) ;
}
2014-04-11 03:18:08 +04:00
2013-05-28 09:25:03 +04:00
compileEnded ( ) ;
2009-06-23 23:56:46 +04:00
}
# ifdef ENABLE_CGAL
2013-12-22 10:43:08 +04:00
void MainWindow : : actionRender ( )
2009-06-23 23:56:46 +04:00
{
2010-11-06 18:03:01 +03:00
if ( GuiLocker : : isLocked ( ) ) return ;
2013-05-28 09:25:03 +04:00
GuiLocker : : lock ( ) ;
autoReloadTimer - > stop ( ) ;
2010-02-28 23:54:55 +03:00
setCurrentOutput ( ) ;
2009-06-27 14:04:57 +04:00
2012-02-14 04:30:39 +04:00
PRINT ( " Parsing design (AST generation)... " ) ;
QApplication : : processEvents ( ) ;
2013-05-28 09:25:03 +04:00
this - > afterCompileSlot = " cgalRender " ;
this - > procevents = true ;
compile ( false ) ;
}
2009-06-23 23:56:46 +04:00
2013-05-28 09:25:03 +04:00
void MainWindow : : cgalRender ( )
{
2010-07-12 01:29:01 +04:00
if ( ! this - > root_module | | ! this - > root_node ) {
2014-02-13 09:06:48 +04:00
compileEnded ( ) ;
2009-06-23 23:56:46 +04:00
return ;
2010-07-12 01:29:01 +04:00
}
2009-06-23 23:56:46 +04:00
2013-02-21 05:56:30 +04:00
this - > qglview - > setRenderer ( NULL ) ;
2011-07-30 23:29:40 +04:00
delete this - > cgalRenderer ;
this - > cgalRenderer = NULL ;
2013-12-22 10:43:08 +04:00
this - > root_geom . reset ( ) ;
2009-06-23 23:56:46 +04:00
2009-06-27 14:04:57 +04:00
PRINT ( " Rendering Polygon Mesh using CGAL... " ) ;
2011-12-26 02:00:30 +04:00
this - > progresswidget = new ProgressWidget ( this ) ;
connect ( this - > progresswidget , SIGNAL ( requestShow ( ) ) , this , SLOT ( showProgress ( ) ) ) ;
2009-07-03 11:51:22 +04:00
2011-12-26 02:00:30 +04:00
progress_report_prep ( this - > root_node , report_func , this ) ;
2010-02-10 18:13:12 +03:00
2011-12-26 02:00:30 +04:00
this - > cgalworker - > start ( this - > tree ) ;
}
2009-06-27 14:04:57 +04:00
2013-12-22 10:43:08 +04:00
void MainWindow : : actionRenderDone ( shared_ptr < const Geometry > root_geom )
2011-12-26 02:00:30 +04:00
{
2009-06-23 23:56:46 +04:00
progress_report_fin ( ) ;
2013-12-22 10:43:08 +04:00
if ( root_geom ) {
2013-03-28 01:50:25 +04:00
GeometryCache : : instance ( ) - > print ( ) ;
2013-01-30 20:58:19 +04:00
# ifdef ENABLE_CGAL
2011-12-26 02:00:30 +04:00
CGALCache : : instance ( ) - > print ( ) ;
2013-01-30 20:58:19 +04:00
# endif
2013-12-22 10:43:08 +04:00
2014-12-17 02:01:25 +03:00
int s = this - > renderingTime . elapsed ( ) / 1000 ;
2013-12-22 10:43:08 +04:00
PRINTB ( " Total rendering time: %d hours, %d minutes, %d seconds " , ( s / ( 60 * 60 ) ) % ( ( s / 60 ) % 60 ) % ( s % 60 ) ) ;
2013-01-08 22:26:25 +04:00
2014-12-09 02:25:48 +03:00
if ( root_geom & & ! root_geom - > isEmpty ( ) ) {
if ( const CGAL_Nef_polyhedron * N = dynamic_cast < const CGAL_Nef_polyhedron * > ( root_geom . get ( ) ) ) {
2013-12-22 10:43:08 +04:00
if ( N - > getDimension ( ) = = 3 ) {
2015-01-21 19:18:22 +03:00
bool simple = N - > p3 - > is_simple ( ) ;
2013-12-22 10:43:08 +04:00
PRINT ( " Top level object is a 3D object: " ) ;
2015-01-21 19:18:22 +03:00
PRINTB ( " Simple: %6s " , ( simple ? " yes " : " no " ) ) ;
2013-12-22 10:43:08 +04:00
PRINTB ( " Vertices: %6d " , N - > p3 - > number_of_vertices ( ) ) ;
PRINTB ( " Halfedges: %6d " , N - > p3 - > number_of_halfedges ( ) ) ;
PRINTB ( " Edges: %6d " , N - > p3 - > number_of_edges ( ) ) ;
PRINTB ( " Halffacets: %6d " , N - > p3 - > number_of_halffacets ( ) ) ;
PRINTB ( " Facets: %6d " , N - > p3 - > number_of_facets ( ) ) ;
PRINTB ( " Volumes: %6d " , N - > p3 - > number_of_volumes ( ) ) ;
2015-01-21 19:18:22 +03:00
if ( ! simple ) {
PRINT ( " WARNING: Object may not be a valid 2-manifold and may need repair! " ) ;
}
2013-12-22 10:43:08 +04:00
}
2013-01-08 22:26:25 +04:00
}
2014-12-09 02:25:48 +03:00
else if ( const PolySet * ps = dynamic_cast < const PolySet * > ( root_geom . get ( ) ) ) {
assert ( ps - > getDimension ( ) = = 3 ) ;
PRINT ( " Top level object is a 3D object: " ) ;
PRINTB ( " Facets: %6d " , ps - > numPolygons ( ) ) ;
} else if ( const Polygon2d * poly = dynamic_cast < const Polygon2d * > ( root_geom . get ( ) ) ) {
PRINT ( " Top level object is a 2D object: " ) ;
PRINTB ( " Contours: %6d " , poly - > outlines ( ) . size ( ) ) ;
} else {
assert ( false & & " Unknown geometry type " ) ;
}
2013-12-22 10:43:08 +04:00
}
PRINT ( " Rendering finished. " ) ;
2009-06-27 04:07:55 +04:00
2013-12-22 10:43:08 +04:00
this - > root_geom = root_geom ;
2013-12-24 10:09:46 +04:00
this - > cgalRenderer = new CGALRenderer ( root_geom ) ;
// Go to CGAL view mode
if ( viewActionWireframe - > isChecked ( ) ) viewModeWireframe ( ) ;
else viewModeSurface ( ) ;
2010-02-09 16:48:09 +03:00
}
2013-12-22 10:43:08 +04:00
else {
PRINT ( " WARNING: No top level geometry to render " ) ;
}
2009-06-27 14:04:57 +04:00
2014-12-23 08:24:57 +03:00
updateStatusBar ( NULL ) ;
2014-11-06 10:14:04 +03:00
this - > contentschanged = false ;
2013-05-28 09:25:03 +04:00
compileEnded ( ) ;
2009-06-23 23:56:46 +04:00
}
# endif /* ENABLE_CGAL */
2014-12-23 08:24:57 +03:00
/**
* Switch version label and progress widget . When switching to the progress
* widget , the new instance is passed by the caller .
* In case of resetting back to the version label , NULL will be passed and
* multiple calls can happen . So this method must guard against adding the
* version label multiple times .
*
* @ param progressWidget a pointer to the progress widget to show or NULL in
* case the display should switch back to the version label .
*/
void MainWindow : : updateStatusBar ( ProgressWidget * progressWidget )
{
QStatusBar * sb = this - > statusBar ( ) ;
if ( progressWidget = = NULL ) {
if ( this - > progresswidget ! = NULL ) {
sb - > removeWidget ( this - > progresswidget ) ;
delete this - > progresswidget ;
this - > progresswidget = NULL ;
}
if ( versionLabel = = NULL ) {
versionLabel = new QLabel ( openscad_version . c_str ( ) ) ;
sb - > addPermanentWidget ( this - > versionLabel ) ;
}
} else {
if ( this - > versionLabel ! = NULL ) {
sb - > removeWidget ( this - > versionLabel ) ;
delete this - > versionLabel ;
this - > versionLabel = NULL ;
}
sb - > addPermanentWidget ( progressWidget ) ;
}
}
2009-06-23 23:56:46 +04:00
void MainWindow : : actionDisplayAST ( )
{
2010-02-28 23:54:55 +03:00
setCurrentOutput ( ) ;
2010-01-15 20:55:12 +03:00
QTextEdit * e = new QTextEdit ( this ) ;
e - > setWindowFlags ( Qt : : Window ) ;
2009-06-23 23:56:46 +04:00
e - > setTabStopWidth ( 30 ) ;
e - > setWindowTitle ( " AST Dump " ) ;
2010-01-15 20:07:40 +03:00
e - > setReadOnly ( true ) ;
2009-06-23 23:56:46 +04:00
if ( root_module ) {
2014-12-16 23:31:00 +03:00
e - > setPlainText ( QString : : fromUtf8 ( root_module - > dump ( " " , " " ) . c_str ( ) ) ) ;
2009-06-23 23:56:46 +04:00
} else {
e - > setPlainText ( " No AST to dump. Please try compiling first... " ) ;
}
e - > show ( ) ;
e - > resize ( 600 , 400 ) ;
2010-02-28 23:54:55 +03:00
clearCurrentOutput ( ) ;
2009-06-23 23:56:46 +04:00
}
2009-06-24 14:59:15 +04:00
void MainWindow : : actionDisplayCSGTree ( )
2009-06-23 23:56:46 +04:00
{
2010-02-28 23:54:55 +03:00
setCurrentOutput ( ) ;
2010-01-15 20:55:12 +03:00
QTextEdit * e = new QTextEdit ( this ) ;
e - > setWindowFlags ( Qt : : Window ) ;
2009-06-23 23:56:46 +04:00
e - > setTabStopWidth ( 30 ) ;
2009-06-25 12:12:41 +04:00
e - > setWindowTitle ( " CSG Tree Dump " ) ;
2010-01-15 20:55:12 +03:00
e - > setReadOnly ( true ) ;
2010-07-12 01:29:01 +04:00
if ( this - > root_node ) {
2014-12-16 23:31:00 +03:00
e - > setPlainText ( QString : : fromUtf8 ( this - > tree . getString ( * this - > root_node ) . c_str ( ) ) ) ;
2009-06-23 23:56:46 +04:00
} else {
e - > setPlainText ( " No CSG to dump. Please try compiling first... " ) ;
}
e - > show ( ) ;
e - > resize ( 600 , 400 ) ;
2010-02-28 23:54:55 +03:00
clearCurrentOutput ( ) ;
2009-06-23 23:56:46 +04:00
}
2009-06-24 14:59:15 +04:00
void MainWindow : : actionDisplayCSGProducts ( )
{
2010-02-28 23:54:55 +03:00
setCurrentOutput ( ) ;
2010-01-15 20:55:12 +03:00
QTextEdit * e = new QTextEdit ( this ) ;
e - > setWindowFlags ( Qt : : Window ) ;
2009-06-24 14:59:15 +04:00
e - > setTabStopWidth ( 30 ) ;
2009-06-25 12:12:41 +04:00
e - > setWindowTitle ( " CSG Products Dump " ) ;
2010-01-15 20:55:12 +03:00
e - > setReadOnly ( true ) ;
2013-03-12 06:14:00 +04:00
e - > setPlainText ( QString ( " \n CSG before normalization: \n %1 \n \n \n CSG after normalization: \n %2 \n \n \n CSG rendering chain: \n %3 \n \n \n Highlights CSG rendering chain: \n %4 \n \n \n Background CSG rendering chain: \n %5 \n " )
2014-08-18 08:59:38 +04:00
2014-12-16 23:31:00 +03:00
. arg ( root_raw_term ? QString : : fromUtf8 ( root_raw_term - > dump ( ) . c_str ( ) ) : " N/A " ,
root_norm_term ? QString : : fromUtf8 ( root_norm_term - > dump ( ) . c_str ( ) ) : " N/A " ,
this - > root_chain ? QString : : fromUtf8 ( this - > root_chain - > dump ( ) . c_str ( ) ) : " N/A " ,
highlights_chain ? QString : : fromUtf8 ( highlights_chain - > dump ( ) . c_str ( ) ) : " N/A " ,
background_chain ? QString : : fromUtf8 ( background_chain - > dump ( ) . c_str ( ) ) : " N/A " ) ) ;
2014-08-18 08:59:38 +04:00
2009-06-24 14:59:15 +04:00
e - > show ( ) ;
e - > resize ( 600 , 400 ) ;
2010-02-28 23:54:55 +03:00
clearCurrentOutput ( ) ;
2009-06-24 14:59:15 +04:00
}
2014-02-03 18:10:46 +04:00
void MainWindow : : actionCheckValidity ( ) {
if ( GuiLocker : : isLocked ( ) ) return ;
GuiLocker lock ;
# ifdef ENABLE_CGAL
setCurrentOutput ( ) ;
if ( ! this - > root_geom ) {
PRINT ( " Nothing to validate! Try building first (press F6). " ) ;
clearCurrentOutput ( ) ;
return ;
}
if ( this - > root_geom - > getDimension ( ) ! = 3 ) {
PRINT ( " Current top level object is not a 3D object. " ) ;
clearCurrentOutput ( ) ;
return ;
}
bool valid = false ;
2014-12-26 01:27:13 +03:00
shared_ptr < const CGAL_Nef_polyhedron > N ;
if ( const PolySet * ps = dynamic_cast < const PolySet * > ( this - > root_geom . get ( ) ) ) {
N . reset ( CGALUtils : : createNefPolyhedronFromGeometry ( * ps ) ) ;
}
if ( N | | ( N = dynamic_pointer_cast < const CGAL_Nef_polyhedron > ( this - > root_geom ) ) ) {
2015-01-06 07:30:51 +03:00
valid = N - > p3 ? N - > p3 - > is_valid ( ) : false ;
2014-12-26 01:27:13 +03:00
}
2014-02-03 18:10:46 +04:00
PRINTB ( " Valid: %6s " , ( valid ? " yes " : " no " ) ) ;
clearCurrentOutput ( ) ;
# endif /* ENABLE_CGAL */
}
2009-11-01 21:26:38 +03:00
# ifdef ENABLE_CGAL
2014-02-11 02:43:57 +04:00
void MainWindow : : actionExport ( export_type_e export_type , const char * type_name , const char * suffix )
2009-11-01 21:26:38 +03:00
# else
2014-02-11 02:43:57 +04:00
void MainWindow : : actionExport ( export_type_e , QString , QString )
2009-11-01 21:26:38 +03:00
# endif
2009-06-23 23:56:46 +04:00
{
2010-11-06 18:03:01 +03:00
if ( GuiLocker : : isLocked ( ) ) return ;
GuiLocker lock ;
2010-01-06 05:04:49 +03:00
# ifdef ENABLE_CGAL
2010-02-28 23:54:55 +03:00
setCurrentOutput ( ) ;
2009-07-10 19:09:43 +04:00
2013-12-22 10:43:08 +04:00
if ( ! this - > root_geom ) {
2015-01-12 19:31:14 +03:00
PRINT ( " WARNING: Nothing to export! Try building first (press F6). " ) ;
2010-02-28 23:54:55 +03:00
clearCurrentOutput ( ) ;
2009-07-10 19:09:43 +04:00
return ;
}
2014-11-06 10:14:04 +03:00
// editor has changed since last F6
if ( this - > contentschanged ) {
QMessageBox : : StandardButton ret ;
ret = QMessageBox : : warning ( this , " Application " ,
" The document has been modified since the last render (F6). \n "
" Do you really want to export the previous content? " ,
QMessageBox : : Yes | QMessageBox : : No ) ;
if ( ret ! = QMessageBox : : Yes ) {
return ;
}
}
2013-12-22 10:43:08 +04:00
if ( this - > root_geom - > getDimension ( ) ! = 3 ) {
2009-12-28 02:49:27 +03:00
PRINT ( " Current top level object is not a 3D object. " ) ;
2010-02-28 23:54:55 +03:00
clearCurrentOutput ( ) ;
2009-12-28 02:49:27 +03:00
return ;
}
2014-08-17 20:41:45 +04:00
if ( this - > root_geom - > isEmpty ( ) ) {
PRINT ( " Current top level object is empty. " ) ;
clearCurrentOutput ( ) ;
return ;
}
2013-12-22 10:43:08 +04:00
const CGAL_Nef_polyhedron * N = dynamic_cast < const CGAL_Nef_polyhedron * > ( this - > root_geom . get ( ) ) ;
2013-12-31 11:53:04 +04:00
if ( N & & ! N - > p3 - > is_simple ( ) ) {
2014-12-21 04:11:02 +03:00
PRINT ( " WARNING: Object may not be a valid 2-manifold and may need repair! See http://en.wikibooks.org/wiki/OpenSCAD_User_Manual/STL_Import_and_Export " ) ;
2009-07-10 19:09:43 +04:00
}
2014-10-19 02:39:32 +04:00
QString title = QString ( _ ( " Export %1 File " ) ) . arg ( type_name ) ;
QString filter = QString ( _ ( " %1 Files (*%2) " ) ) . arg ( type_name , suffix ) ;
QString filename = this - > fileName . isEmpty ( ) ? QString ( _ ( " Untitled " ) ) + suffix : QFileInfo ( this - > fileName ) . baseName ( ) + suffix ;
2014-02-11 02:43:57 +04:00
QString export_filename = QFileDialog : : getSaveFileName ( this , title , filename , filter ) ;
if ( export_filename . isEmpty ( ) ) {
2010-02-28 23:54:55 +03:00
clearCurrentOutput ( ) ;
2009-07-10 19:09:43 +04:00
return ;
}
2014-05-03 19:44:22 +04:00
enum FileFormat format = ( enum FileFormat ) - 1 ;
switch ( export_type ) {
case EXPORT_TYPE_STL : format = OPENSCAD_STL ; break ;
case EXPORT_TYPE_OFF : format = OPENSCAD_OFF ; break ;
case EXPORT_TYPE_AMF : format = OPENSCAD_AMF ; break ;
default :
assert ( false & & " Unknown export type " ) ;
break ;
2010-07-09 02:49:36 +04:00
}
2014-05-03 19:44:22 +04:00
exportFileByName ( this - > root_geom . get ( ) , format , export_filename . toUtf8 ( ) ,
export_filename . toLocal8Bit ( ) . constData ( ) ) ;
PRINTB ( " %s export finished. " , type_name ) ;
2010-01-06 05:04:49 +03:00
2010-02-28 23:54:55 +03:00
clearCurrentOutput ( ) ;
2010-01-06 05:04:49 +03:00
# endif /* ENABLE_CGAL */
2009-06-23 23:56:46 +04:00
}
2009-10-18 12:50:01 +04:00
void MainWindow : : actionExportSTL ( )
{
2014-02-11 02:43:57 +04:00
actionExport ( EXPORT_TYPE_STL , " STL " , " .stl " ) ;
2009-10-18 12:50:01 +04:00
}
2009-06-23 23:56:46 +04:00
void MainWindow : : actionExportOFF ( )
{
2014-02-11 02:43:57 +04:00
actionExport ( EXPORT_TYPE_OFF , " OFF " , " .off " ) ;
2009-06-23 23:56:46 +04:00
}
2014-02-11 02:43:57 +04:00
void MainWindow : : actionExportAMF ( )
2010-01-06 05:04:49 +03:00
{
2014-02-11 02:43:57 +04:00
actionExport ( EXPORT_TYPE_AMF , " AMF " , " .amf " ) ;
2009-06-23 23:56:46 +04:00
}
2014-03-02 22:26:17 +04:00
QString MainWindow : : get2dExportFilename ( QString format , QString extension ) {
2010-02-28 23:54:55 +03:00
setCurrentOutput ( ) ;
2010-01-06 05:04:49 +03:00
2013-12-22 10:43:08 +04:00
if ( ! this - > root_geom ) {
2015-01-12 19:31:14 +03:00
PRINT ( " WARNING: Nothing to export! Try building first (press F6). " ) ;
2010-02-28 23:54:55 +03:00
clearCurrentOutput ( ) ;
2014-03-02 22:26:17 +04:00
return QString ( ) ;
2010-01-06 05:04:49 +03:00
}
2013-12-22 10:43:08 +04:00
if ( this - > root_geom - > getDimension ( ) ! = 2 ) {
2015-01-12 19:31:14 +03:00
PRINT ( " WARNING: Current top level object is not a 2D object. " ) ;
2010-02-28 23:54:55 +03:00
clearCurrentOutput ( ) ;
2014-03-02 22:26:17 +04:00
return QString ( ) ;
2010-01-06 05:04:49 +03:00
}
2014-10-19 02:39:32 +04:00
QString caption = QString ( _ ( " Export %1 File " ) ) . arg ( format ) ;
2014-03-02 22:26:17 +04:00
QString suggestion = this - > fileName . isEmpty ( )
2014-10-19 02:39:32 +04:00
? QString ( _ ( " Untitled%1 " ) ) . arg ( extension )
2014-03-02 22:26:17 +04:00
: QFileInfo ( this - > fileName ) . baseName ( ) + extension ;
2014-10-19 02:39:32 +04:00
QString filter = QString ( _ ( " %1 Files (*%2) " ) ) . arg ( format , extension ) ;
2014-03-02 22:26:17 +04:00
QString exportFilename = QFileDialog : : getSaveFileName ( this , caption , suggestion , filter ) ;
if ( exportFilename . isEmpty ( ) ) {
2012-01-25 06:11:12 +04:00
PRINT ( " No filename specified. DXF export aborted. " ) ;
2010-02-28 23:54:55 +03:00
clearCurrentOutput ( ) ;
2014-03-02 22:26:17 +04:00
return QString ( ) ;
}
return exportFilename ;
}
void MainWindow : : actionExportDXF ( )
{
# ifdef ENABLE_CGAL
QString dxf_filename = get2dExportFilename ( " DXF " , " .dxf " ) ;
if ( dxf_filename . isEmpty ( ) ) {
2010-01-06 05:04:49 +03:00
return ;
}
2014-05-03 19:44:22 +04:00
exportFileByName ( this - > root_geom . get ( ) , OPENSCAD_DXF , dxf_filename . toUtf8 ( ) ,
dxf_filename . toLocal8Bit ( ) . constData ( ) ) ;
PRINT ( " DXF export finished. " ) ;
2010-01-06 05:04:49 +03:00
2010-02-28 23:54:55 +03:00
clearCurrentOutput ( ) ;
2010-01-06 05:04:49 +03:00
# endif /* ENABLE_CGAL */
}
2014-03-02 22:26:17 +04:00
void MainWindow : : actionExportSVG ( )
{
QString svg_filename = get2dExportFilename ( " SVG " , " .svg " ) ;
if ( svg_filename . isEmpty ( ) ) {
return ;
}
2014-05-03 19:44:22 +04:00
exportFileByName ( this - > root_geom . get ( ) , OPENSCAD_SVG , svg_filename . toUtf8 ( ) ,
svg_filename . toLocal8Bit ( ) . constData ( ) ) ;
PRINT ( " SVG export finished. " ) ;
2014-03-02 22:26:17 +04:00
clearCurrentOutput ( ) ;
}
2011-10-19 19:35:14 +04:00
void MainWindow : : actionExportCSG ( )
{
setCurrentOutput ( ) ;
if ( ! this - > root_node ) {
2015-01-12 19:31:14 +03:00
PRINT ( " WARNING: Nothing to export. Please try compiling first... " ) ;
2011-10-19 19:35:14 +04:00
clearCurrentOutput ( ) ;
return ;
}
2014-10-19 02:39:32 +04:00
QString csg_filename = QFileDialog : : getSaveFileName ( this , _ ( " Export CSG File " ) ,
this - > fileName . isEmpty ( ) ? _ ( " Untitled.csg " ) : QFileInfo ( this - > fileName ) . baseName ( ) + " .csg " ,
_ ( " CSG Files (*.csg) " ) ) ;
2014-08-18 08:13:43 +04:00
2011-10-19 19:35:14 +04:00
if ( csg_filename . isEmpty ( ) ) {
2012-01-25 06:11:12 +04:00
PRINT ( " No filename specified. CSG export aborted. " ) ;
2011-10-19 19:35:14 +04:00
clearCurrentOutput ( ) ;
return ;
}
2014-08-15 01:16:24 +04:00
std : : ofstream fstream ( csg_filename . toLocal8Bit ( ) ) ;
2011-10-19 19:35:14 +04:00
if ( ! fstream . is_open ( ) ) {
2013-03-12 06:14:00 +04:00
PRINTB ( " Can't open file \" %s \" for export " , csg_filename . toLocal8Bit ( ) . constData ( ) ) ;
2011-10-19 19:35:14 +04:00
}
else {
fstream < < this - > tree . getString ( * this - > root_node ) < < " \n " ;
fstream . close ( ) ;
2012-01-25 06:11:12 +04:00
PRINT ( " CSG export finished. " ) ;
2011-10-19 19:35:14 +04:00
}
clearCurrentOutput ( ) ;
}
2011-06-05 22:05:55 +04:00
void MainWindow : : actionExportImage ( )
{
setCurrentOutput ( ) ;
QString img_filename = QFileDialog : : getSaveFileName ( this ,
2014-10-19 02:39:32 +04:00
_ ( " Export Image " ) , " " , _ ( " PNG Files (*.png) " ) ) ;
2011-06-05 22:05:55 +04:00
if ( img_filename . isEmpty ( ) ) {
2012-01-25 06:11:12 +04:00
PRINT ( " No filename specified. Image export aborted. " ) ;
2013-02-21 15:49:19 +04:00
} else {
2013-03-12 06:14:00 +04:00
qglview - > save ( img_filename . toLocal8Bit ( ) . constData ( ) ) ;
2011-06-05 22:05:55 +04:00
}
clearCurrentOutput ( ) ;
2013-02-21 15:49:19 +04:00
return ;
2011-06-05 22:05:55 +04:00
}
2010-01-08 00:08:47 +03:00
void MainWindow : : actionFlushCaches ( )
{
2013-03-28 01:50:25 +04:00
GeometryCache : : instance ( ) - > clear ( ) ;
2010-02-01 13:01:05 +03:00
# ifdef ENABLE_CGAL
2011-09-12 05:46:13 +04:00
CGALCache : : instance ( ) - > clear ( ) ;
2010-02-01 13:01:05 +03:00
# endif
2010-01-10 16:32:22 +03:00
dxf_dim_cache . clear ( ) ;
dxf_cross_cache . clear ( ) ;
2012-02-04 04:43:53 +04:00
ModuleCache : : instance ( ) - > clear ( ) ;
2014-01-19 06:05:00 +04:00
FontCache : : instance ( ) - > clear ( ) ;
2010-01-08 00:08:47 +03:00
}
2009-06-25 02:38:31 +04:00
void MainWindow : : viewModeActionsUncheck ( )
{
2013-12-22 10:43:08 +04:00
viewActionPreview - > setChecked ( false ) ;
2009-06-25 02:38:31 +04:00
# ifdef ENABLE_CGAL
2013-12-22 10:43:08 +04:00
viewActionSurfaces - > setChecked ( false ) ;
viewActionWireframe - > setChecked ( false ) ;
2009-06-25 02:38:31 +04:00
# endif
2009-12-09 17:25:09 +03:00
viewActionThrownTogether - > setChecked ( false ) ;
2009-06-25 02:38:31 +04:00
}
# ifdef ENABLE_OPENCSG
2010-01-07 00:35:01 +03:00
/*!
Go to the OpenCSG view mode .
Falls back to thrown together mode if OpenCSG is not available
*/
2013-12-22 10:43:08 +04:00
void MainWindow : : viewModePreview ( )
2009-06-25 02:38:31 +04:00
{
2013-02-21 05:56:30 +04:00
if ( this - > qglview - > hasOpenCSGSupport ( ) ) {
2009-10-19 23:20:18 +04:00
viewModeActionsUncheck ( ) ;
2013-12-22 10:43:08 +04:00
viewActionPreview - > setChecked ( true ) ;
2013-02-21 05:56:30 +04:00
this - > qglview - > setRenderer ( this - > opencsgRenderer ? ( Renderer * ) this - > opencsgRenderer : ( Renderer * ) this - > thrownTogetherRenderer ) ;
2014-08-15 01:16:24 +04:00
this - > qglview - > updateColorScheme ( ) ;
2013-02-24 01:34:06 +04:00
this - > qglview - > updateGL ( ) ;
2009-10-19 23:20:18 +04:00
} else {
viewModeThrownTogether ( ) ;
}
2009-06-25 02:38:31 +04:00
}
# endif /* ENABLE_OPENCSG */
# ifdef ENABLE_CGAL
2013-12-22 10:43:08 +04:00
void MainWindow : : viewModeSurface ( )
2009-06-25 02:38:31 +04:00
{
viewModeActionsUncheck ( ) ;
2013-12-22 10:43:08 +04:00
viewActionSurfaces - > setChecked ( true ) ;
2013-02-21 05:56:30 +04:00
this - > qglview - > setShowFaces ( true ) ;
this - > qglview - > setRenderer ( this - > cgalRenderer ) ;
2014-08-15 01:16:24 +04:00
this - > qglview - > updateColorScheme ( ) ;
2013-02-21 05:56:30 +04:00
this - > qglview - > updateGL ( ) ;
2009-06-25 02:38:31 +04:00
}
2013-12-22 10:43:08 +04:00
void MainWindow : : viewModeWireframe ( )
2009-06-25 02:38:31 +04:00
{
viewModeActionsUncheck ( ) ;
2013-12-22 10:43:08 +04:00
viewActionWireframe - > setChecked ( true ) ;
2013-02-21 05:56:30 +04:00
this - > qglview - > setShowFaces ( false ) ;
this - > qglview - > setRenderer ( this - > cgalRenderer ) ;
2014-08-15 01:16:24 +04:00
this - > qglview - > updateColorScheme ( ) ;
2013-02-24 01:34:06 +04:00
this - > qglview - > updateGL ( ) ;
2009-06-25 02:38:31 +04:00
}
# endif /* ENABLE_CGAL */
2009-06-25 12:12:41 +04:00
void MainWindow : : viewModeThrownTogether ( )
2009-06-25 02:38:31 +04:00
{
viewModeActionsUncheck ( ) ;
2009-12-09 17:25:09 +03:00
viewActionThrownTogether - > setChecked ( true ) ;
2013-02-21 05:56:30 +04:00
this - > qglview - > setRenderer ( this - > thrownTogetherRenderer ) ;
2014-08-15 01:16:24 +04:00
this - > qglview - > updateColorScheme ( ) ;
2013-02-24 01:34:06 +04:00
this - > qglview - > updateGL ( ) ;
2009-06-25 02:38:31 +04:00
}
2009-06-23 23:56:46 +04:00
2009-07-02 19:12:10 +04:00
void MainWindow : : viewModeShowEdges ( )
2009-06-29 22:03:06 +04:00
{
2011-07-04 00:57:07 +04:00
QSettings settings ;
settings . setValue ( " view/showEdges " , viewActionShowEdges - > isChecked ( ) ) ;
2013-02-21 05:56:30 +04:00
this - > qglview - > setShowEdges ( viewActionShowEdges - > isChecked ( ) ) ;
this - > qglview - > updateGL ( ) ;
2009-06-29 15:03:15 +04:00
}
2009-10-26 15:16:41 +03:00
void MainWindow : : viewModeShowAxes ( )
2009-10-12 18:49:31 +04:00
{
2011-07-04 00:57:07 +04:00
QSettings settings ;
settings . setValue ( " view/showAxes " , viewActionShowAxes - > isChecked ( ) ) ;
2013-02-21 05:56:30 +04:00
this - > qglview - > setShowAxes ( viewActionShowAxes - > isChecked ( ) ) ;
this - > qglview - > updateGL ( ) ;
2009-10-12 18:49:31 +04:00
}
2009-10-14 06:07:23 +04:00
void MainWindow : : viewModeShowCrosshairs ( )
{
2011-07-04 00:57:07 +04:00
QSettings settings ;
settings . setValue ( " view/showCrosshairs " , viewActionShowCrosshairs - > isChecked ( ) ) ;
2013-02-21 05:56:30 +04:00
this - > qglview - > setShowCrosshairs ( viewActionShowCrosshairs - > isChecked ( ) ) ;
this - > qglview - > updateGL ( ) ;
2009-10-14 06:07:23 +04:00
}
Add optional menu driven scaling tics to the large axes
Tim Deagan 12/26/2014
While add-on rulers can be extremely useful, there are many times that a quick scaling marker would be handy. This feature generates tics every 10 units, driven off the log10 of the l variable defining axes length. As you zoom in or out, the tics automatically re-scale themselves. Every tenth tic is slightly larger. A menu item is added to the view menu to enable or disable the feature.
I experimented with menu driven scaling (.01, .1, 1, 10, etc.), but using small increments when zoomed out brought the app to it's knees. Adding a visual indicator of the current scaling might be nice, but I'm nto sure where to put it (possibly below the small axes,) since it changes as zooming and would clutter the console.
Changes to be committed:
new file: images/scalemarkers.png
modified: openscad.qrc
modified: src/GLView.cc
modified: src/GLView.h
modified: src/MainWindow.h
modified: src/MainWindow.ui
modified: src/QGLView.h
modified: src/mainwin.cc
2014-12-27 06:44:31 +03:00
void MainWindow : : viewModeShowScaleProportional ( )
{
QSettings settings ;
settings . setValue ( " view/showScaleProportional " , viewActionShowScaleProportional - > isChecked ( ) ) ;
this - > qglview - > setShowScaleProportional ( viewActionShowScaleProportional - > isChecked ( ) ) ;
this - > qglview - > updateGL ( ) ;
}
2009-07-28 19:15:29 +04:00
void MainWindow : : viewModeAnimate ( )
{
2009-12-09 17:25:09 +03:00
if ( viewActionAnimate - > isChecked ( ) ) {
2009-07-28 19:15:29 +04:00
animate_panel - > show ( ) ;
2013-12-22 10:43:08 +04:00
actionRenderPreview ( ) ;
2009-07-28 19:15:29 +04:00
updatedFps ( ) ;
} else {
animate_panel - > hide ( ) ;
animate_timer - > stop ( ) ;
}
}
2009-11-07 01:41:57 +03:00
void MainWindow : : animateUpdateDocChanged ( )
{
2014-06-07 19:42:41 +04:00
QString current_doc = editor - > toPlainText ( ) ;
2009-11-07 01:41:57 +03:00
if ( current_doc ! = last_compiled_doc )
animateUpdate ( ) ;
}
2009-10-22 23:42:52 +04:00
void MainWindow : : animateUpdate ( )
{
if ( animate_panel - > isVisible ( ) ) {
bool fps_ok ;
2012-02-14 04:30:39 +04:00
double fps = this - > e_fps - > text ( ) . toDouble ( & fps_ok ) ;
2009-10-22 23:42:52 +04:00
if ( fps_ok & & fps < = 0 & & ! animate_timer - > isActive ( ) ) {
animate_timer - > stop ( ) ;
animate_timer - > setSingleShot ( true ) ;
animate_timer - > setInterval ( 50 ) ;
animate_timer - > start ( ) ;
}
}
}
2009-10-05 15:23:23 +04:00
void MainWindow : : viewAngleTop ( )
{
2013-03-03 20:52:25 +04:00
qglview - > cam . object_rot < < 90 , 0 , 0 ;
2013-02-21 05:56:30 +04:00
this - > qglview - > updateGL ( ) ;
2009-10-05 15:23:23 +04:00
}
void MainWindow : : viewAngleBottom ( )
{
2013-03-03 20:52:25 +04:00
qglview - > cam . object_rot < < 270 , 0 , 0 ;
2013-02-21 05:56:30 +04:00
this - > qglview - > updateGL ( ) ;
2009-10-05 15:23:23 +04:00
}
void MainWindow : : viewAngleLeft ( )
{
2013-03-03 20:52:25 +04:00
qglview - > cam . object_rot < < 0 , 0 , 90 ;
2013-02-21 05:56:30 +04:00
this - > qglview - > updateGL ( ) ;
2009-10-05 15:23:23 +04:00
}
void MainWindow : : viewAngleRight ( )
{
2013-03-03 20:52:25 +04:00
qglview - > cam . object_rot < < 0 , 0 , 270 ;
2013-02-21 05:56:30 +04:00
this - > qglview - > updateGL ( ) ;
2009-10-05 15:23:23 +04:00
}
void MainWindow : : viewAngleFront ( )
{
2013-03-03 20:52:25 +04:00
qglview - > cam . object_rot < < 0 , 0 , 0 ;
2013-02-21 05:56:30 +04:00
this - > qglview - > updateGL ( ) ;
2009-10-05 15:23:23 +04:00
}
void MainWindow : : viewAngleBack ( )
{
2013-03-03 20:52:25 +04:00
qglview - > cam . object_rot < < 0 , 0 , 180 ;
2013-02-21 05:56:30 +04:00
this - > qglview - > updateGL ( ) ;
2009-10-05 15:23:23 +04:00
}
void MainWindow : : viewAngleDiagonal ( )
{
2013-03-03 20:52:25 +04:00
qglview - > cam . object_rot < < 35 , 0 , - 25 ;
2013-02-21 05:56:30 +04:00
this - > qglview - > updateGL ( ) ;
2009-10-22 23:42:52 +04:00
}
void MainWindow : : viewCenter ( )
{
2013-03-03 20:52:25 +04:00
qglview - > cam . object_trans < < 0 , 0 , 0 ;
2013-02-21 05:56:30 +04:00
this - > qglview - > updateGL ( ) ;
2009-10-05 15:23:23 +04:00
}
2009-10-12 15:31:54 +04:00
void MainWindow : : viewPerspective ( )
{
2011-07-04 00:57:07 +04:00
QSettings settings ;
settings . setValue ( " view/orthogonalProjection " , false ) ;
2009-12-09 17:25:09 +03:00
viewActionPerspective - > setChecked ( true ) ;
viewActionOrthogonal - > setChecked ( false ) ;
2013-02-21 05:56:30 +04:00
this - > qglview - > setOrthoMode ( false ) ;
this - > qglview - > updateGL ( ) ;
2009-10-12 15:31:54 +04:00
}
void MainWindow : : viewOrthogonal ( )
{
2011-07-04 00:57:07 +04:00
QSettings settings ;
settings . setValue ( " view/orthogonalProjection " , true ) ;
2009-12-09 17:25:09 +03:00
viewActionPerspective - > setChecked ( false ) ;
viewActionOrthogonal - > setChecked ( true ) ;
2013-02-21 05:56:30 +04:00
this - > qglview - > setOrthoMode ( true ) ;
this - > qglview - > updateGL ( ) ;
2009-10-12 15:31:54 +04:00
}
2013-11-01 01:54:05 +04:00
void MainWindow : : viewResetView ( )
{
this - > qglview - > resetView ( ) ;
this - > qglview - > updateGL ( ) ;
}
2014-06-22 00:12:55 +04:00
void MainWindow : : viewAll ( )
{
this - > qglview - > viewAll ( ) ;
this - > qglview - > updateGL ( ) ;
2013-11-01 01:54:05 +04:00
}
2014-10-20 02:21:06 +04:00
void MainWindow : : on_editorDock_visibilityChanged ( bool )
2009-12-20 15:48:32 +03:00
{
2014-05-13 00:47:42 +04:00
editorTopLevelChanged ( editorDock - > isFloating ( ) ) ;
}
2014-10-20 02:21:06 +04:00
void MainWindow : : on_consoleDock_visibilityChanged ( bool )
2009-12-20 15:48:32 +03:00
{
2014-05-13 00:47:42 +04:00
consoleTopLevelChanged ( consoleDock - > isFloating ( ) ) ;
}
void MainWindow : : editorTopLevelChanged ( bool topLevel )
{
2014-10-19 02:39:32 +04:00
setDockWidgetTitle ( editorDock , QString ( _ ( " Editor " ) ) , topLevel ) ;
2014-05-13 00:47:42 +04:00
}
void MainWindow : : consoleTopLevelChanged ( bool topLevel )
{
2014-10-19 02:39:32 +04:00
setDockWidgetTitle ( consoleDock , QString ( _ ( " Console " ) ) , topLevel ) ;
2014-05-13 00:47:42 +04:00
}
void MainWindow : : setDockWidgetTitle ( QDockWidget * dockWidget , QString prefix , bool topLevel )
{
QString title ( prefix ) ;
if ( topLevel ) {
const QFileInfo fileInfo ( windowFilePath ( ) ) ;
title + = " ( " + fileInfo . fileName ( ) + " ) " ;
}
dockWidget - > setWindowTitle ( title ) ;
}
2014-10-01 01:18:40 +04:00
void MainWindow : : hideToolbars ( )
2014-09-14 21:51:40 +04:00
{
2014-10-31 10:45:04 +03:00
QSettings settings ;
bool shouldHide = viewActionHideToolBars - > isChecked ( ) ;
settings . setValue ( " view/hideToolbar " , shouldHide ) ;
if ( shouldHide ) {
2014-10-01 00:47:14 +04:00
viewerToolBar - > hide ( ) ;
editortoolbar - > hide ( ) ;
2014-09-14 21:51:40 +04:00
} else {
2014-10-01 00:47:14 +04:00
viewerToolBar - > show ( ) ;
editortoolbar - > show ( ) ;
2014-09-14 21:51:40 +04:00
}
}
2014-05-13 00:47:42 +04:00
void MainWindow : : hideEditor ( )
{
2014-10-01 01:18:40 +04:00
if ( viewActionHideEditor - > isChecked ( ) ) {
2014-05-13 00:47:42 +04:00
editorDock - > close ( ) ;
} else {
editorDock - > show ( ) ;
}
}
2015-01-07 05:14:46 +03:00
void MainWindow : : showConsole ( )
{
viewActionHideConsole - > setChecked ( false ) ;
consoleDock - > show ( ) ;
frameCompileResult - > hide ( ) ;
}
2014-09-14 21:51:40 +04:00
2015-01-07 05:14:46 +03:00
void MainWindow : : hideConsole ( )
2014-05-13 00:47:42 +04:00
{
2014-10-01 01:18:40 +04:00
if ( viewActionHideConsole - > isChecked ( ) ) {
2014-05-13 00:47:42 +04:00
consoleDock - > hide ( ) ;
2009-12-20 15:48:32 +03:00
} else {
2014-05-13 00:47:42 +04:00
consoleDock - > show ( ) ;
2009-12-20 15:48:32 +03:00
}
}
2009-10-29 00:08:25 +03:00
void MainWindow : : dragEnterEvent ( QDragEnterEvent * event )
{
if ( event - > mimeData ( ) - > hasUrls ( ) )
event - > acceptProposedAction ( ) ;
}
void MainWindow : : dropEvent ( QDropEvent * event )
{
2010-02-28 23:54:55 +03:00
setCurrentOutput ( ) ;
2009-10-29 00:08:25 +03:00
const QList < QUrl > urls = event - > mimeData ( ) - > urls ( ) ;
for ( int i = 0 ; i < urls . size ( ) ; i + + ) {
if ( urls [ i ] . scheme ( ) ! = " file " )
continue ;
2014-05-13 00:47:42 +04:00
handleFileDrop ( urls [ i ] . toLocalFile ( ) ) ;
2009-10-29 00:08:25 +03:00
}
2010-02-28 23:54:55 +03:00
clearCurrentOutput ( ) ;
2009-10-29 00:08:25 +03:00
}
2014-05-13 00:47:42 +04:00
void MainWindow : : handleFileDrop ( const QString & filename )
{
const QFileInfo fileInfo ( filename ) ;
const QString suffix = fileInfo . suffix ( ) . toLower ( ) ;
const QString cmd = knownFileExtensions [ suffix ] ;
if ( cmd . isEmpty ( ) ) {
if ( ! MainWindow : : mdiMode & & ! maybeSave ( ) ) {
return ;
}
openFile ( filename ) ;
} else {
2014-08-22 22:17:24 +04:00
editor - > insert ( cmd . arg ( filename ) ) ;
2014-05-13 00:47:42 +04:00
}
}
2014-08-18 08:59:38 +04:00
void MainWindow : : helpAbout ( )
2009-12-13 01:04:32 +03:00
{
qApp - > setWindowIcon ( QApplication : : windowIcon ( ) ) ;
2012-08-04 20:49:45 +04:00
AboutDialog * dialog = new AboutDialog ( this ) ;
dialog - > exec ( ) ;
2009-12-13 01:04:32 +03:00
}
2014-08-18 08:59:38 +04:00
void MainWindow : : helpHomepage ( )
2010-02-20 13:20:18 +03:00
{
2014-09-14 04:08:57 +04:00
UIUtils : : openHomepageURL ( ) ;
2010-02-20 13:20:18 +03:00
}
2014-08-18 08:59:38 +04:00
void MainWindow : : helpManual ( )
2009-12-13 01:19:53 +03:00
{
2014-09-14 04:08:57 +04:00
UIUtils : : openUserManualURL ( ) ;
2009-12-13 01:19:53 +03:00
}
2015-01-14 22:01:53 +03:00
void MainWindow : : helpCheatSheet ( )
{
UIUtils : : openCheatSheetURL ( ) ;
}
2012-02-15 04:26:38 +04:00
void MainWindow : : helpLibrary ( )
2011-12-09 06:43:06 +04:00
{
2014-09-15 06:08:18 +04:00
if ( ! this - > library_info_dialog ) {
QString rendererInfo ( qglview - > getRendererInfo ( ) . c_str ( ) ) ;
LibraryInfoDialog * dialog = new LibraryInfoDialog ( rendererInfo ) ;
this - > library_info_dialog = dialog ;
}
this - > library_info_dialog - > show ( ) ;
2011-12-09 06:43:06 +04:00
}
2013-11-21 04:01:42 +04:00
void MainWindow : : helpFontInfo ( )
{
if ( ! this - > font_list_dialog ) {
FontListDialog * dialog = new FontListDialog ( ) ;
this - > font_list_dialog = dialog ;
}
this - > font_list_dialog - > update_font_list ( ) ;
this - > font_list_dialog - > show ( ) ;
}
2009-12-14 07:24:51 +03:00
/*!
2010-07-03 00:59:16 +04:00
FIXME : In MDI mode , should this be called on both reload functions ?
2009-12-14 07:24:51 +03:00
*/
2014-08-18 08:59:38 +04:00
bool MainWindow : : maybeSave ( )
2009-12-14 07:24:51 +03:00
{
2010-04-03 07:05:14 +04:00
if ( editor - > isContentModified ( ) ) {
2009-12-14 07:24:51 +03:00
QMessageBox : : StandardButton ret ;
2014-05-03 21:56:15 +04:00
QMessageBox box ( this ) ;
2014-10-19 02:39:32 +04:00
box . setText ( _ ( " The document has been modified. " ) ) ;
box . setInformativeText ( _ ( " Do you want to save your changes? " ) ) ;
2014-05-03 21:56:15 +04:00
box . setStandardButtons ( QMessageBox : : Save | QMessageBox : : Discard | QMessageBox : : Cancel ) ;
box . setDefaultButton ( QMessageBox : : Save ) ;
box . setIcon ( QMessageBox : : Warning ) ;
box . setWindowModality ( Qt : : ApplicationModal ) ;
# ifdef Q_OS_MAC
// Cmd-D is the standard shortcut for this button on Mac
box . button ( QMessageBox : : Discard ) - > setShortcut ( QKeySequence ( " Ctrl+D " ) ) ;
box . button ( QMessageBox : : Discard ) - > setShortcutEnabled ( true ) ;
# endif
ret = ( QMessageBox : : StandardButton ) box . exec ( ) ;
2009-12-14 07:24:51 +03:00
if ( ret = = QMessageBox : : Save ) {
actionSave ( ) ;
2014-05-03 21:56:15 +04:00
// Returns false on failed save
return ! editor - > isContentModified ( ) ;
2009-12-14 07:24:51 +03:00
}
else if ( ret = = QMessageBox : : Cancel ) {
return false ;
}
}
return true ;
}
void MainWindow : : closeEvent ( QCloseEvent * event )
{
if ( maybeSave ( ) ) {
2011-07-04 01:42:55 +04:00
QSettings settings ;
settings . setValue ( " window/size " , size ( ) ) ;
settings . setValue ( " window/position " , pos ( ) ) ;
2014-05-13 00:47:42 +04:00
settings . setValue ( " window/state " , saveState ( ) ) ;
2014-02-13 09:15:35 +04:00
if ( this - > tempFile ) {
delete this - > tempFile ;
this - > tempFile = NULL ;
}
2009-12-14 07:24:51 +03:00
event - > accept ( ) ;
} else {
event - > ignore ( ) ;
}
}
2010-01-08 00:08:47 +03:00
2014-08-18 08:59:38 +04:00
void MainWindow : : preferences ( )
2010-01-15 04:00:41 +03:00
{
Preferences : : inst ( ) - > show ( ) ;
2010-01-22 16:17:41 +03:00
Preferences : : inst ( ) - > activateWindow ( ) ;
Preferences : : inst ( ) - > raise ( ) ;
2010-01-15 04:00:41 +03:00
}
2010-01-22 15:28:30 +03:00
2014-08-15 01:16:24 +04:00
void MainWindow : : setColorScheme ( const QString & scheme )
{
RenderSettings : : inst ( ) - > colorscheme = scheme . toStdString ( ) ;
this - > qglview - > setColorScheme ( scheme . toStdString ( ) ) ;
this - > qglview - > updateGL ( ) ;
}
2010-01-22 15:28:30 +03:00
void MainWindow : : setFont ( const QString & family , uint size )
{
2011-12-29 17:28:38 +04:00
QFont font ;
2010-01-22 15:28:30 +03:00
if ( ! family . isEmpty ( ) ) font . setFamily ( family ) ;
2011-12-29 18:24:38 +04:00
else font . setFixedPitch ( true ) ;
2010-01-22 15:28:30 +03:00
if ( size > 0 ) font . setPointSize ( size ) ;
font . setStyleHint ( QFont : : TypeWriter ) ;
editor - > setFont ( font ) ;
}
2010-01-26 00:39:34 +03:00
void MainWindow : : quit ( )
{
QCloseEvent ev ;
QApplication : : sendEvent ( QApplication : : instance ( ) , & ev ) ;
if ( ev . isAccepted ( ) ) QApplication : : instance ( ) - > quit ( ) ;
2013-01-17 22:31:12 +04:00
// FIXME: Cancel any CGAL calculations
2013-02-08 00:01:31 +04:00
# ifdef Q_OS_MAC
CocoaUtils : : endApplication ( ) ;
# endif
2010-01-26 00:39:34 +03:00
}
2010-02-28 23:54:55 +03:00
2011-12-26 02:00:30 +04:00
void MainWindow : : consoleOutput ( const std : : string & msg , void * userdata )
{
// Invoke the append function in the main thread in case the output
2014-12-21 04:11:02 +03:00
// originates in a worker thread.
2011-12-26 02:00:30 +04:00
MainWindow * thisp = static_cast < MainWindow * > ( userdata ) ;
2014-12-21 04:11:02 +03:00
QString qmsg = QString : : fromUtf8 ( msg . c_str ( ) ) ;
2015-01-07 19:05:31 +03:00
if ( qmsg . startsWith ( " WARNING: " ) | | qmsg . startsWith ( " DEPRECATED: " ) ) {
2015-01-07 05:14:46 +03:00
thisp - > compileWarnings + + ;
2014-12-21 04:11:02 +03:00
qmsg = " <html><span style= \" color: black; background-color: #ffffb0; \" > " + qmsg + " </span></html> " ;
} else if ( qmsg . startsWith ( " ERROR: " ) ) {
2015-01-07 05:14:46 +03:00
thisp - > compileErrors + + ;
2014-12-21 04:11:02 +03:00
qmsg = " <html><span style= \" color: black; background-color: #ffb0b0; \" > " + qmsg + " </span></html> " ;
}
QMetaObject : : invokeMethod ( thisp - > console , " append " , Qt : : QueuedConnection , Q_ARG ( QString , qmsg ) ) ;
2014-03-29 13:43:28 +04:00
if ( thisp - > procevents ) QApplication : : processEvents ( ) ;
2011-12-26 02:00:30 +04:00
}
2010-02-28 23:54:55 +03:00
void MainWindow : : setCurrentOutput ( )
{
2012-02-18 17:48:11 +04:00
set_output_handler ( & MainWindow : : consoleOutput , this ) ;
2010-02-28 23:54:55 +03:00
}
void MainWindow : : clearCurrentOutput ( )
{
set_output_handler ( NULL , NULL ) ;
}
2012-01-14 04:22:46 +04:00
void MainWindow : : openCSGSettingsChanged ( )
{
# ifdef ENABLE_OPENCSG
2014-08-18 08:13:43 +04:00
OpenCSG : : setOption ( OpenCSG : : AlgorithmSetting , Preferences : : inst ( ) - > getValue ( " advanced/forceGoldfeather " ) . toBool ( ) ?
OpenCSG : : Goldfeather : OpenCSG : : Automatic ) ;
2012-01-14 04:22:46 +04:00
# endif
}
2014-11-06 10:14:04 +03:00
void MainWindow : : setContentsChanged ( )
{
this - > contentschanged = true ;
}