diff --git a/Changelog b/Changelog
index 21f41d8f0..f3e2c84b0 100644
--- a/Changelog
+++ b/Changelog
@@ -1,46 +1,46 @@
0.25.1 (2018-02-23):
-* Enhancements: build compatibility with MacOS, Qt 5.9.
- Qt 4.6+4.7 supported as well with restrictions:
+* Enhancements: build compatibility with MacOS and Qt 5.9.
+ Qt 4.6 supported now as well with one restriction:
the package installation feature is not working.
-* Bugfix: Package manager
+* Bugfixs: Package manager
- Remove button wasn't enabled if multiple packages were selected
- A potential crash ob removing packages was fixed
* Enhancement: 64 bit coordinate support enabled on Windows builds
* Further bugfixes: See links
- https://github.com/klayoutmatthias/klayout/issues/21 (Autorun(-early) doesn't seem to run when lym files are inside a package)
- - https://github.com/klayoutmatthias/klayout/issues/24 (Text insert dialog possible)
+ - https://github.com/klayoutmatthias/klayout/issues/24 (Text insert dialog bug - Ok button isn't working)
- https://github.com/klayoutmatthias/klayout/issues/26 (Exceptions are reported every time they propagate up in the call chain in the ruby debugger)
- https://github.com/klayoutmatthias/klayout/issues/28 (CIF format detection failed)
- https://github.com/klayoutmatthias/klayout/issues/30 (Writer options dialog non-functional on a fresh configuration)
- - https://github.com/klayoutmatthias/klayout/issues/32 (rounding issue with instance properties)
+ - https://github.com/klayoutmatthias/klayout/issues/32 (Rounding issue with instance properties)
- https://github.com/klayoutmatthias/klayout/issues/33 (Plugin factory not working when using with Python)
- - https://github.com/klayoutmatthias/klayout/issues/36 (hardening against destruction of object inside event handler)
+ - https://github.com/klayoutmatthias/klayout/issues/36 (Hardening against destruction of object inside event handler)
- https://github.com/klayoutmatthias/klayout/issues/39 (Action cannot be reassigned)
- https://github.com/klayoutmatthias/klayout/issues/40 (Crash in Python binding)
- https://github.com/klayoutmatthias/klayout/issues/41 (Polygon#touches? issue)
- - https://github.com/klayoutmatthias/klayout/issues/42 (headless mode support with Qt5/-zz)
- - https://github.com/klayoutmatthias/klayout/issues/43 (crash when using Qt specific command line options)
+ - https://github.com/klayoutmatthias/klayout/issues/42 (Headless mode support with Qt5/-zz)
+ - https://github.com/klayoutmatthias/klayout/issues/43 (Crash when using Qt specific command line options)
- https://github.com/klayoutmatthias/klayout/issues/44 (Transformation constructor with x,y not working)
- https://github.com/klayoutmatthias/klayout/issues/45 (Partial selection does not capture instance)
- https://github.com/klayoutmatthias/klayout/issues/48 (Cancel does not reset current tool)
- https://github.com/klayoutmatthias/klayout/issues/51 (Segmentation fault on return to main window and other opportunities)
- - https://github.com/klayoutmatthias/klayout/issues/53 (unreadable 'about' text)
- - https://github.com/klayoutmatthias/klayout/issues/59 (async download of package index and details)
+ - https://github.com/klayoutmatthias/klayout/issues/53 (Unreadable 'about' text)
- https://github.com/klayoutmatthias/klayout/issues/62 (QXmlSimpleReader#parse cannot be called)
- - https://github.com/klayoutmatthias/klayout/issues/63 (wrong output on DRC non_interacting with empty second input)
- - https://github.com/klayoutmatthias/klayout/issues/64 (crash on exit)
+ - https://github.com/klayoutmatthias/klayout/issues/63 (Wrong output on DRC non_interacting with empty second input)
+ - https://github.com/klayoutmatthias/klayout/issues/64 (Crash on exit)
- https://github.com/klayoutmatthias/klayout/issues/68 (OASIS reader issue with degenerated shapes)
- https://github.com/klayoutmatthias/klayout/issues/69 (DRC: 'inside' does not merge shapes of second input)
- - https://github.com/klayoutmatthias/klayout/issues/71 (target cell argument is required)
+ - https://github.com/klayoutmatthias/klayout/issues/71 (Target cell argument is required)
- https://github.com/klayoutmatthias/klayout/issues/72 (Edges/Region NOT issue)
- - https://github.com/klayoutmatthias/klayout/issues/73 (allow 'change layers' on PCells which support a single layer parameter)
- - https://github.com/klayoutmatthias/klayout/issues/74 (small-corner boolean issue)
+ - https://github.com/klayoutmatthias/klayout/issues/73 (Allow 'change layers' on PCells which support a single layer parameter)
+ - https://github.com/klayoutmatthias/klayout/issues/74 (Small-corner boolean issue)
- https://github.com/klayoutmatthias/klayout/issues/75 (Python PCell issue when parameters are called 'layer')
- https://github.com/klayoutmatthias/klayout/issues/79 (Replace function enabled also for read-only macros)
* Further enhancements: see links
- - https://github.com/klayoutmatthias/klayout/issues/29 (permissive mode for OASIS writer on odd-width paths)
+ - https://github.com/klayoutmatthias/klayout/issues/29 (Permissive mode for OASIS writer on odd-width paths)
+ - https://github.com/klayoutmatthias/klayout/issues/59 (Async download of package index and details)
- https://github.com/klayoutmatthias/klayout/issues/66 (Authentication dialog indicates retry)
- - https://github.com/klayoutmatthias/klayout/issues/77 (copy_tree works in non-editable mode too)
+ - https://github.com/klayoutmatthias/klayout/issues/77 (Layout#copy_tree now works in non-editable mode too)
0.25 (2017-11-04):
* Enhancement: Menu customization
diff --git a/macbuild/.gitignore b/macbuild/.gitignore
new file mode 100644
index 000000000..0d20b6487
--- /dev/null
+++ b/macbuild/.gitignore
@@ -0,0 +1 @@
+*.pyc
diff --git a/macbuild/ReadMe.md b/macbuild/ReadMe.md
index 7412de414..f27677548 100644
--- a/macbuild/ReadMe.md
+++ b/macbuild/ReadMe.md
@@ -62,7 +62,7 @@ $ ./build4mac.py -r mp24 -p mp36
```
$ ./build4mac.py -r mp24 -p mp36 -Y
```
-* [-Y|--DEPOLY] option deploys KLayout's dylibs and executables only.
+* [-Y|--DEPLOY] option deploys KLayout's dylibs and executables only.
That is, paths to other modules (Ruby, Python, and Qt5 Frameworks) remain unchanged (absolute paths in your development environment).
5. Copy/move generated bundles ("klayout.app" and "klayout.scripts/") to your "/Applications" directory for installation.
@@ -84,4 +84,25 @@ $ ./makeDMG4mac.py -p qt5.pkg.macos-HighSierra-release -m
```
By: Kazzz (January 16, 2018)
+
+# 5. Alternative building options
+### 5.1 Python 3.6 from brew, Qt 5.9.4 from offline installer
+
+Homebrew's installation of python3 places a `Python.framework` in `/usr/local/opt/python/Frameworks/Python.framework/`, which you can use to build KLayout from. Qt can be downloaded for [offline installation](https://www1.qt.io/offline-installers/). You can place it in your home folder: e.g. `/home/username/Qt5.9.4/`. Given these two dependencies, you can successfully compile KLayout with the following commands:
+
+```
+# Build step
+./build4mac.py -p B36 -q Qt5Custom
+
+# Deploy step
+./build4mac.py -p B36 -q Qt5Custom -y # normal deploy
+./build4mac.py -p B36 -q Qt5Custom -y -v 3 2>&1 | tee qt5.pkg.macos-HighSierra-release.log # deploy with debug options
+
+# Packaging step
+./makeDMG4mac.py -p qt5.pkg.macos-HighSierra-release -m -q Qt594
+
+```
+
+PS: If you get a syntax error in one of ruby's libraries because it is not compatible with C++11, do not fret. You only have to change one offending file.
+
[End of File]
diff --git a/macbuild/ReadMe.txt b/macbuild/ReadMe.txt
index c8519bab3..87921776f 100644
--- a/macbuild/ReadMe.txt
+++ b/macbuild/ReadMe.txt
@@ -60,7 +60,7 @@ Relevant KLayout version: 0.25.1
to deploy executables and libraries under "klayout.app" bundle.
The buddy command line tools (strm*) will also be deployed.
$ ./build4mac.py -r mp24 -p mp36 -Y
- * [-Y|--DEPOLY] option deploys KLayout's dylibs and executables only.
+ * [-Y|--DEPLOY] option deploys KLayout's dylibs and executables only.
That is, paths to other modules (Ruby, Python, and Qt5 Frameworks)
remain unchanged (absolute paths in your development environment).
(5) Copy/move generated bundles ("klayout.app" and "klayout.scripts/") to your
diff --git a/macbuild/Resources/Info.plist.template b/macbuild/Resources/Info.plist.template
index 74090cbb3..65fa6d47a 100644
--- a/macbuild/Resources/Info.plist.template
+++ b/macbuild/Resources/Info.plist.template
@@ -18,6 +18,21 @@
APPL
CFBundleVersion
${VERSION}
+ CFBundleShortVersionString
+ ${VERSION}
+ CFBundleDocumentTypes
+
+
+ CFBundleTypeExtensions
+
+ gds
+
+ CFBundleTypeRole
+ Editor
+ CFBundleTypeIconFile
+ ${ICONFILE}
+
+
CFBundleSignature
????
NSPrincipalClass
diff --git a/macbuild/Resources/KLayoutDMG.applescript b/macbuild/Resources/KLayoutDMG.applescript
new file mode 100644
index 000000000..91a80a3ec
--- /dev/null
+++ b/macbuild/Resources/KLayoutDMG.applescript
@@ -0,0 +1,116 @@
+-------------------------------------------------------------------------------------------------
+(*
+ * Template File:
+ * macbuild/Resources/template-KLayoutDMG.applescript
+ *
+ * Actual AppleScrip File to be generated:
+ * macbuild/Resources/KLayoutDMG.applescript
+ *
+ * Description:
+ * A template AppleScript to make a fancy DMG installer of KLayout
+ * (http://www.klayout.de/index.php) bundles.
+ * "makeDMG4mac.py" will read this template and generate the actual AppleScript to execute.
+ * Values to be found and replaced by "makeDMG4mac.py" are marked by ${KEYWORD}.
+ *
+ * The background image was designed using Logoist2 (http://www.syniumsoftware.com/en/logoist)
+ * and exported to a PNG file of 1000 x 700 pix size.
+ *-----------------------------------------------------------------------------------------------
+ * This is a derivative work of Ref. 2) below. Refer to "macbuild/LICENSE" file.
+ * Ref.
+ * 1) https://el-tramo.be/guides/fancy-dmg/
+ * 2) https://github.com/andreyvit/create-dmg.git
+ *)
+-------------------------------------------------------------------------------------------------
+on run (volumeName) -- most likely, the volume name is "KLayout"
+ tell application "Finder"
+ tell disk (volumeName as string)
+ -- [1] Open the volume
+ open
+
+ -- [2] Set the key coordinates and windows size
+ -- The size of given background PNG image is 1000 x 700 pix
+ -- ORGX = [50] pix
+ -- ORGY = [100] pix
+ -- WIN_WIDTH = [1000] pix
+ -- WIN_HEIGHT = [700] pix
+ set posMargin to 50
+ set negMargin to 10
+ set theTopLeftX to 50
+ set theTopLeftY to 100
+ set theWidth to 1000
+ set theHeight to 700
+ set theBottomRightX to (theTopLeftX + theWidth + posMargin)
+ set theBottomRightY to (theTopLeftY + theHeight + posMargin)
+
+ -- [3] Set the full path to .DS_Store file
+ set dotDSStore to "/Volumes/KLayout/.DS_Store"
+
+ -- [4] Set global view options
+ tell container window
+ set current view to icon view
+ set toolbar visible to false
+ set statusbar visible to false
+ set statusbar visible to false
+ set bounds to {theTopLeftX, theTopLeftY, theBottomRightX, theBottomRightY}
+ set position of every item to {theTopLeftX + 150, theTopLeftY + 350}
+ end tell
+
+ -- [5] Set icon view options
+ set opts to the icon view options of container window
+ tell opts
+ set icon size to 80
+ set text size to 16
+ set arrangement to not arranged
+ end tell
+
+ -- [6] Set the background PNG image (1000 x 700 pix) file name stored
+ set background picture of opts to file ".background:KLayoutDMG-Back.png"
+
+ -- [7] Set positions of each icon
+ -- ITEM_1 = klayout.app {960, 140}
+ -- ITEM_2 = klayout.scripts {610, 140}
+ -- ITEM_3 = Applications {790, 140}
+ set position of item "klayout.app" to {960, 140}
+ set position of item "klayout.scripts" to {610, 140}
+ set position of item "Applications" to {790, 140}
+
+ -- [8] Update the contents of container
+ close
+ open
+ update without registering applications
+
+ -- [9] Force save the negatively resized window size
+ delay 2
+ tell container window
+ set statusbar visible to false
+ set bounds to {theTopLeftX, theTopLeftY, theBottomRightX - negMargin, theBottomRightY - negMargin}
+ end tell
+ update without registering applications
+ end tell
+
+ -- [10] Restore back the original window size
+ delay 2
+ tell disk (volumeName as string)
+ tell container window
+ set statusbar visible to false
+ set bounds to {theTopLeftX, theTopLeftY, theBottomRightX, theBottomRightY}
+ end tell
+ update without registering applications
+ end tell
+
+ -- [11] Wait for some time so that "Finder" can complete writing to .DS_Store file
+ delay 3
+ set elapsedTime to 0
+ set ejected to false
+ repeat while ejected is false
+ delay 1
+ set elapsedTime to elapsedTime + 1
+ if (do shell script "[ -f " & dotDSStore & " ]; echo $?") = "0" then set ejected to true
+ end repeat
+ log "### Elapsed <" & elapsedTime & "> [sec] for writing .DS_Store file."
+ end tell
+end run
+
+--
+-- End of file
+--
diff --git a/macbuild/Resources/qt.conf b/macbuild/Resources/qt.conf
new file mode 100644
index 000000000..df50e9dba
--- /dev/null
+++ b/macbuild/Resources/qt.conf
@@ -0,0 +1,4 @@
+[Paths]
+Plugins = ../PlugIns
+Imports = ../Resources/qml
+Qml2Imports = ../Resources/qml
diff --git a/macbuild/build4mac.py b/macbuild/build4mac.py
index 9eaeaca8b..c4ca6933f 100755
--- a/macbuild/build4mac.py
+++ b/macbuild/build4mac.py
@@ -65,9 +65,9 @@ def SetGlobals():
Usage += " : 'nil' = not to support the script language | \n"
Usage += " : 'Sys' = using the OS standard script language | \n"
Usage += " : Refer to 'macbuild/build4mac_env.py' for details | \n"
- Usage += " [-q|--qt ] : type=['Qt4MacPorts', 'Qt5MacPorts'] | qt5macports \n"
- Usage += " [-r|--ruby ] : type=['nil', 'Sys', 'Src24', 'MP24'] | sys \n"
- Usage += " [-p|--python ] : type=['nil', 'Sys', 'Ana27', 'Ana36', 'MP36'] | sys \n"
+ Usage += " [-q|--qt ] : type=['Qt4MacPorts', 'Qt5MacPorts', 'Qt5Custom'] | qt5macports \n"
+ Usage += " [-r|--ruby ] : type=['nil', 'Sys', 'Src24', 'MP24', 'B25'] | sys \n"
+ Usage += " [-p|--python ] : type=['nil', 'Sys', 'Ana27', 'Ana36', 'MP36', 'B36'] | sys \n"
Usage += " [-n|--noqtbinding] : don't create Qt bindings for ruby scripts | disabled \n"
Usage += " [-m|--make ] : option passed to 'make' | -j4 \n"
Usage += " [-d|--debug] : enable debug mode build | disabled \n"
@@ -239,7 +239,7 @@ def ParseCommandLineArguments():
quit()
# Determine Qt type
- candidates = [ i.upper() for i in ['Qt4MacPorts', 'Qt5MacPorts'] ]
+ candidates = [ i.upper() for i in ['Qt4MacPorts', 'Qt5MacPorts', 'Qt5Custom'] ]
ModuleQt = ""
index = 0
for item in candidates:
@@ -250,6 +250,9 @@ def ParseCommandLineArguments():
elif index == 1:
ModuleQt = 'Qt5MacPorts'
break
+ elif index == 2:
+ ModuleQt = 'Qt5Custom'
+ break
else:
index += 1
if ModuleQt == "":
@@ -262,7 +265,7 @@ def ParseCommandLineArguments():
NonOSStdLang = False
# Determine Ruby type
- candidates = [ i.upper() for i in ['nil', 'Sys', 'Src24', 'MP24'] ]
+ candidates = [ i.upper() for i in ['nil', 'Sys', 'Src24', 'MP24', 'B25'] ]
ModuleRuby = ""
index = 0
for item in candidates:
@@ -288,6 +291,9 @@ def ParseCommandLineArguments():
elif index == 3:
ModuleRuby = 'Ruby24MacPorts'
NonOSStdLang = True
+ elif index == 4:
+ ModuleRuby = 'Ruby25Brew'
+ NonOSStdLang = True
else:
index += 1
if ModuleRuby == "":
@@ -297,7 +303,7 @@ def ParseCommandLineArguments():
quit()
# Determine Python type
- candidates = [ i.upper() for i in ['nil', 'Sys', 'Ana27', 'Ana36', 'MP36'] ]
+ candidates = [ i.upper() for i in ['nil', 'Sys', 'Ana27', 'Ana36', 'MP36', 'B36'] ]
ModulePython = ""
index = 0
for item in candidates:
@@ -326,6 +332,9 @@ def ParseCommandLineArguments():
elif index == 4:
ModulePython = 'Python36MacPorts'
NonOSStdLang = True
+ elif index == 5:
+ ModulePython = 'Python36Brew'
+ NonOSStdLang = True
else:
index += 1
if ModulePython == "":
@@ -427,6 +436,20 @@ def RunMainBuildBash():
AbsMacBuildLog = "%s/qt5.build.macos-%s-%s.log" % (ProjectDir, Platform, mode)
parameters += " \\\n -bin %s" % MacBinDir
parameters += " \\\n -build %s" % MacBuildDir
+ elif ModuleQt == 'Qt5Custom':
+ parameters += " \\\n -qt5"
+ parameters += " \\\n -qmake %s" % Qt5Custom['qmake']
+ MacPkgDir = "./qt5.pkg.macos-%s-%s" % (Platform, mode)
+ MacBinDir = "./qt5.bin.macos-%s-%s" % (Platform, mode)
+ MacBuildDir = "./qt5.build.macos-%s-%s" % (Platform, mode)
+ MacBuildLog = "./qt5.build.macos-%s-%s.log" % (Platform, mode)
+ AbsMacPkgDir = "%s/qt5.pkg.macos-%s-%s" % (ProjectDir, Platform, mode)
+ AbsMacBinDir = "%s/qt5.bin.macos-%s-%s" % (ProjectDir, Platform, mode)
+ AbsMacBuildDir = "%s/qt5.build.macos-%s-%s" % (ProjectDir, Platform, mode)
+ AbsMacBuildLog = "%s/qt5.build.macos-%s-%s.log" % (ProjectDir, Platform, mode)
+ parameters += " \\\n -bin %s" % MacBinDir
+ parameters += " \\\n -build %s" % MacBuildDir
+ parameters += " \\\n -rpath %s" % "@executable_path/../Frameworks"
# (C) want Qt bindings with Ruby scripts?
if NoQtBindings:
@@ -524,9 +547,9 @@ def DeployBinariesForBundle():
if not DeploymentF and not DeploymentP:
return 1
if DeploymentF and NonOSStdLang:
- print( "!!! You chose <-y|--deploy> while using non-OS-standard script language.", file=sys.stderr )
+ print( "WARNING!!! You chose <-y|--deploy> while using non-OS-standard script language.", file=sys.stderr )
print( " Use <-Y|--DEPLOY> instead", file=sys.stderr )
- return 1
+ #return 1
if not os.path.isfile(MacBuildLog):
print( "!!! Build log file <%s> does not present !!!" % MacBuildLog, file=sys.stderr )
return 1
@@ -629,7 +652,7 @@ def DeployBinariesForBundle():
# e.g. [ 'libklayout_lay', '0', '25', '0', 'dylib' ]
nameStyle3 = fullName[0] + "." + fullName[1] + ".dylib"
shutil.copy2( item, nameStyle3 )
- os.chmod( nameStyle3, 0755 )
+ os.chmod( nameStyle3, 0o0755 )
#-------------------------------------------------------------------
# (B) Then get inter-library dependencies
#-------------------------------------------------------------------
@@ -676,17 +699,20 @@ def DeployBinariesForBundle():
shutil.copy2( sourceDir0 + "/PkgInfo", targetDir0 ) # this file is not mandatory
shutil.copy2( sourceDir1 + "/klayout", targetDirM )
shutil.copy2( sourceDir2 + "/klayout.icns", targetDirR )
+ shutil.copy2( sourceDir2 + "/qt.conf", targetDirM )
- os.chmod( targetDir0 + "/PkgInfo", 0644 )
- os.chmod( targetDir0 + "/Info.plist", 0644 )
- os.chmod( targetDirM + "/klayout", 0755 )
- os.chmod( targetDirR + "/klayout.icns", 0644 )
+
+ os.chmod( targetDir0 + "/PkgInfo", 0o0644 )
+ os.chmod( targetDir0 + "/Info.plist", 0o0644 )
+ os.chmod( targetDirM + "/klayout", 0o0755 )
+ os.chmod( targetDirM + "/qt.conf", 0o0644 )
+ os.chmod( targetDirR + "/klayout.icns", 0o0644 )
buddies = glob.glob( sourceDir3 + "/strm*" )
for item in buddies:
shutil.copy2( item, targetDirB )
buddy = os.path.basename(item)
- os.chmod( targetDirB + "/" + buddy, 0755 )
+ os.chmod( targetDirB + "/" + buddy, 0o0755 )
print( " [7] Setting and changing the identification names of KLayout's libraries in each executable ..." )
@@ -729,10 +755,15 @@ def DeployBinariesForBundle():
deploytool = Qt5MacPorts['deploy']
app_bundle = "klayout.app"
options = macdepQtOpt + verbose
+ elif ModuleQt == 'Qt5Custom':
+ deploytool = Qt5Custom['deploy']
+ app_bundle = "klayout.app"
+ options = macdepQtOpt + verbose
os.chdir(ProjectDir)
os.chdir(MacPkgDir)
command = "%s %s %s" % ( deploytool, app_bundle, options )
+ print(command)
if subprocess.call( command, shell=True ) != 0:
msg = "!!! Failed to deploy applications on OSX !!!"
print( msg, file=sys.stderr )
@@ -834,10 +865,10 @@ def DeployScriptBundles():
shutil.copy2( resourceDir + "/klayout-red.icns", targetDirRE )
shutil.copy2( resourceDir + "/klayout-blue.icns", targetDirRV )
- os.chmod( targetDirME + "/KLayoutEditor.sh", 0755 )
- os.chmod( targetDirMV + "/KLayoutViewer.sh", 0755 )
- os.chmod( targetDirRE + "/klayout-red.icns", 0644 )
- os.chmod( targetDirRV + "/klayout-blue.icns", 0644 )
+ os.chmod( targetDirME + "/KLayoutEditor.sh", 0o0755 )
+ os.chmod( targetDirMV + "/KLayoutViewer.sh", 0o0755 )
+ os.chmod( targetDirRE + "/klayout-red.icns", 0o0644 )
+ os.chmod( targetDirRV + "/klayout-blue.icns", 0o0644 )
tmpfileE = ProjectDir + "/macbuild/Resources/Info.plist.template"
keydicE = { 'exe': 'KLayoutEditor.sh', 'icon': 'klayout-red.icns', 'bname': 'klayout', 'ver': Version }
diff --git a/macbuild/build4mac_env.py b/macbuild/build4mac_env.py
index d35148d89..dfc2d9f68 100755
--- a/macbuild/build4mac_env.py
+++ b/macbuild/build4mac_env.py
@@ -21,7 +21,7 @@ XcodeToolChain = { 'nameID': '/usr/bin/install_name_tool -id ',
#-----------------------------------------------------
# [1] Qt
#-----------------------------------------------------
-Qts = [ 'Qt4MacPorts', 'Qt5MacPorts' ]
+Qts = [ 'Qt4MacPorts', 'Qt5MacPorts', 'Qt5Custom' ]
#-----------------------------------------------------
# Whereabout of different components of Qt4
@@ -41,11 +41,23 @@ Qt5MacPorts = { 'qmake' : '/opt/local/libexec/qt5/bin/qmake',
'deploy': '/opt/local/libexec/qt5/bin/macdeployqt'
}
+# # Qt5 from Brew
+# # [Key Type Name] = 'Qt5Brew'
+# Qt5Brew = { 'qmake' : '/usr/local/Cellar/qt5/5.10.0_1/bin/qmake',
+# 'deploy': '/usr/local/Cellar/qt5/5.10.0_1/bin/macdeployqt'
+# }
+
+# Qt5 Custom (https://www1.qt.io/offline-installers/)
+# [Key Type Name] = 'Qt5Custom'
+Qt5Custom = { 'qmake' : '~/Qt5.9.4/5.9.4/clang_64/bin/qmake',
+ 'deploy': '~/Qt5.9.4/5.9.4/clang_64/bin/macdeployqt'
+ }
+
#-----------------------------------------------------
# [2] Ruby
#-----------------------------------------------------
Rubies = [ 'nil', 'RubyYosemite', 'RubyElCapitan', 'RubySierra', 'RubyHighSierra' ]
-Rubies += [ 'Ruby24SrcBuild', 'Ruby24MacPorts' ]
+Rubies += [ 'Ruby24SrcBuild', 'Ruby24MacPorts', 'Ruby24Brew' ]
#-----------------------------------------------------
# Whereabout of different components of Ruby
@@ -94,6 +106,13 @@ Ruby24MacPorts = { 'exe': '/opt/local/bin/ruby2.4',
'lib': '/opt/local/lib/libruby.2.4.dylib'
}
+# Ruby 2.5 from Brew *+*+*+ EXPERIMENTAL *+*+*+
+# [Key Type Name] = 'Brew25'
+Ruby25Brew = { 'exe': '/usr/local/bin/ruby',
+ 'inc': '/usr/local/include/ruby-2.5.0',
+ 'lib': '/usr/local/lib/libruby.2.5.0.dylib'
+ }
+
# Consolidated dictionary kit for Ruby
RubyDictionary = { 'nil' : None,
'RubyYosemite' : RubyYosemite,
@@ -101,14 +120,15 @@ RubyDictionary = { 'nil' : None,
'RubySierra' : RubySierra,
'RubyHighSierra': RubyHighSierra,
'Ruby24SrcBuild': Ruby24SrcBuild,
- 'Ruby24MacPorts': Ruby24MacPorts
+ 'Ruby24MacPorts': Ruby24MacPorts,
+ 'Ruby25Brew' : Ruby25Brew
}
#-----------------------------------------------------
# [3] Python
#-----------------------------------------------------
Pythons = [ 'nil', 'PythonYosemite', 'PythonElCapitan', 'PythonSierra', 'PythonHighSierra' ]
-Pythons += [ 'Anaconda27', 'Anaconda36', 'Python36MacPorts' ]
+Pythons += [ 'Anaconda27', 'Anaconda36', 'Python36MacPorts', 'Python36Brew' ]
#-----------------------------------------------------
# Whereabout of different components of Python
@@ -170,6 +190,13 @@ Python36MacPorts= { 'exe': '/opt/local/Library/Frameworks/Python.framework/Versi
'lib': '/opt/local/Library/Frameworks/Python.framework/Versions/3.6/lib/libpython3.6m.dylib'
}
+# Python 3.6 from Brew *+*+*+ EXPERIMENTAL *+*+*+
+# [Key Type Name] = 'pybrew'
+Python36Brew= { 'exe': '/usr/local/opt/python3/Frameworks/Python.framework/Versions/Current/bin/python3.6m' ,
+ 'inc': '/usr/local/opt/python3/Frameworks/Python.framework/Versions/Current/include/python3.6m',
+ 'lib': '/usr/local/opt/python3/Frameworks/Python.framework/Versions/Current/lib/libpython3.6m.dylib'
+ }
+
# Consolidated dictionary kit for Python
PythonDictionary= { 'nil' : None,
'PythonYosemite' : PythonYosemite,
@@ -178,7 +205,8 @@ PythonDictionary= { 'nil' : None,
'PythonHighSierra': PythonHighSierra,
'Anaconda27' : Anaconda27,
'Anaconda36' : Anaconda36,
- 'Python36MacPorts': Python36MacPorts
+ 'Python36MacPorts': Python36MacPorts,
+ 'Python36Brew' : Python36Brew,
}
#-----------------------------------------------------
diff --git a/macbuild/build4mac_env.pyc b/macbuild/build4mac_env.pyc
new file mode 100644
index 000000000..906f510e1
Binary files /dev/null and b/macbuild/build4mac_env.pyc differ
diff --git a/macbuild/build4mac_util.py b/macbuild/build4mac_util.py
index fe002014e..e8357aee2 100755
--- a/macbuild/build4mac_util.py
+++ b/macbuild/build4mac_util.py
@@ -143,7 +143,7 @@ def SetChangeLibIdentificationName( executable, relativedir ):
otoolOut = os.popen( otoolCm ).read()
exedepdic = DecomposeLibraryDependency( executable + ":\n" + otoolOut )
keys = exedepdic.keys()
- deplibs = exedepdic[ keys[0] ]
+ deplibs = exedepdic[ list(keys)[0] ]
for lib in deplibs:
#-----------------------------------------------------------
diff --git a/macbuild/build4mac_util.pyc b/macbuild/build4mac_util.pyc
new file mode 100644
index 000000000..e1194a0e0
Binary files /dev/null and b/macbuild/build4mac_util.pyc differ
diff --git a/src/db/db/dbEdges.cc b/src/db/db/dbEdges.cc
index 3890d4fbd..00f7b7542 100644
--- a/src/db/db/dbEdges.cc
+++ b/src/db/db/dbEdges.cc
@@ -883,20 +883,31 @@ struct JoinEdgesCluster
void finish ()
{
std::multimap objects_by_p1;
- std::multiset p2;
+ std::multimap objects_by_p2;
for (iterator o = begin (); o != end (); ++o) {
if (o->first->p1 () != o->first->p2 ()) {
objects_by_p1.insert (std::make_pair (o->first->p1 (), o));
- p2.insert (o->first->p2 ());
+ objects_by_p2.insert (std::make_pair (o->first->p2 (), o));
}
}
- while (! p2.empty ()) {
+ while (! objects_by_p2.empty ()) {
tl_assert (! objects_by_p1.empty ());
// Find the beginning of a new sequence
- std::multimap::iterator j = objects_by_p1.begin ();
+ std::multimap::iterator j0 = objects_by_p1.begin ();
+ std::multimap::iterator j = j0;
+ do {
+ std::multimap::iterator jj = objects_by_p2.find (j->first);
+ if (jj == objects_by_p2.end ()) {
+ break;
+ } else {
+ j = objects_by_p1.find (jj->second->first->p1 ());
+ tl_assert (j != objects_by_p1.end ());
+ }
+ } while (j != j0);
+
iterator i = j->second;
// determine a sequence
@@ -906,12 +917,22 @@ struct JoinEdgesCluster
do {
+ // record the next point
pts.push_back (i->first->p2 ());
- std::multiset::iterator ip2 = p2.find (i->first->p2 ());
- tl_assert (ip2 != p2.end ());
- p2.erase (ip2);
+
+ // remove the edge as it's taken
+ std::multimap::iterator jj;
+ for (jj = objects_by_p2.find (i->first->p2 ()); jj != objects_by_p2.end () && jj->first == i->first->p2 (); ++jj) {
+ if (jj->second == i) {
+ break;
+ }
+ }
+ tl_assert (jj != objects_by_p2.end () && jj->second == i);
+ objects_by_p2.erase (jj);
objects_by_p1.erase (j);
+ // process along the edge to the next one
+ // TODO: this chooses any solution in case of forks. Choose a specific one?
j = objects_by_p1.find (i->first->p2 ());
if (j != objects_by_p1.end ()) {
i = j->second;
diff --git a/src/db/unit_tests/dbEdges.cc b/src/db/unit_tests/dbEdges.cc
index cf6d78a15..6a5a3c7b1 100644
--- a/src/db/unit_tests/dbEdges.cc
+++ b/src/db/unit_tests/dbEdges.cc
@@ -311,7 +311,40 @@ TEST(6)
EXPECT_EQ (r.to_string (), "(-20,-20;-20,220;120,220;120,-20/-10,-10;110,-10;110,210;-10,210)");
}
-TEST(7)
+TEST(6b)
+{
+ // Ticket #90: order of edges as input to the edge collector should not matter
+
+ db::Edges e;
+ e.insert (db::Edge (db::Point (0, -200), db::Point (100, -200)));
+ e.insert (db::Edge (db::Point (250, -200), db::Point (300, 0)));
+ e.insert (db::Edge (db::Point (0, 0), db::Point (0, -200)));
+ e.insert (db::Edge (db::Point (200, 0), db::Point (250, -200)));
+
+ db::Region r;
+ e.extended (r, 0, 0, 20, 0, true);
+ EXPECT_EQ (r.to_string (), "(0,-200;0,0;20,0;20,-180;100,-180;100,-200);(250,-200;200,0;219,5;250,-118;281,5;300,0)");
+}
+
+TEST(6c)
+{
+ // A more complex scenario with forks
+
+ db::Edges e;
+ e.insert (db::Edge (db::Point (0, -200), db::Point (100, -200)));
+ e.insert (db::Edge (db::Point (250, -200), db::Point (300, 0)));
+ e.insert (db::Edge (db::Point (0, 0), db::Point (0, -200)));
+ e.insert (db::Edge (db::Point (0, -100), db::Point (0, -200)));
+ e.insert (db::Edge (db::Point (200, 0), db::Point (250, -200)));
+ e.insert (db::Edge (db::Point (0, -200), db::Point (200, -200)));
+ e.insert (db::Edge (db::Point (250, -200), db::Point (350, 0)));
+
+ db::Region r;
+ e.extended (r, 0, 0, 20, 0, true);
+ EXPECT_EQ (r.to_string (), "(0,-200;0,0;20,0;20,-180;100,-180;100,-200);(0,-200;0,-100;20,-100;20,-180;200,-180;200,-200);(250,-200;200,0;219,5;250,-118;281,5;300,0);(250,-200;232,-191;332,9;350,0)");
+}
+
+TEST(7)
{
db::Edges e;
e.insert (db::Edge (db::Point (0, 0), db::Point (0, 200)));
diff --git a/src/drc/drc/built-in-macros/drc.lym b/src/drc/drc/built-in-macros/drc.lym
index 514b59a4d..012250912 100644
--- a/src/drc/drc/built-in-macros/drc.lym
+++ b/src/drc/drc/built-in-macros/drc.lym
@@ -7,7 +7,7 @@
true
- false
+ true
false
diff --git a/src/klayout.pri b/src/klayout.pri
index 684be68ba..28c1f6cbc 100644
--- a/src/klayout.pri
+++ b/src/klayout.pri
@@ -62,6 +62,7 @@ QMAKE_CXXFLAGS_WARN_ON += \
-Wno-long-long \
-Wno-strict-aliasing \
-Wno-deprecated-declarations \
+ -Wno-reserved-user-defined-literal \
QT += network xml sql
diff --git a/src/lay/lay/MacroEditorSetupDialog.ui b/src/lay/lay/MacroEditorSetupPage.ui
similarity index 85%
rename from src/lay/lay/MacroEditorSetupDialog.ui
rename to src/lay/lay/MacroEditorSetupPage.ui
index 2479c3fbe..21947b9c5 100644
--- a/src/lay/lay/MacroEditorSetupDialog.ui
+++ b/src/lay/lay/MacroEditorSetupPage.ui
@@ -1,7 +1,7 @@
- MacroEditorSetupDialog
-
+ MacroEditorSetupPage
+
0
@@ -32,7 +32,7 @@
-
- 0
+ 3
@@ -452,10 +452,71 @@
-
-
-
- Ask whether to stop in debugger on exception
+
+
+ As&k whether to stop in debugger on exception
+
+ true
+
+
+ false
+
+
+ -
+
+
+ Don't stop inside these files:
+
+
+ Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft
+
+
+
+ -
+
+
+ Clear List
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QSizePolicy::Fixed
+
+
+
+ 32
+ 20
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ QAbstractItemView::NoSelection
+
+
+
+
-
@@ -475,16 +536,6 @@
- -
-
-
- Qt::Horizontal
-
-
- QDialogButtonBox::Cancel|QDialogButtonBox::Ok
-
-
-
@@ -495,38 +546,5 @@
-
-
- buttonBox
- accepted()
- MacroEditorSetupDialog
- accept()
-
-
- 248
- 254
-
-
- 157
- 274
-
-
-
-
- buttonBox
- rejected()
- MacroEditorSetupDialog
- reject()
-
-
- 316
- 260
-
-
- 286
- 274
-
-
-
-
+
diff --git a/src/lay/lay/lay.pro b/src/lay/lay/lay.pro
index 45371f44c..b17a5fe2b 100644
--- a/src/lay/lay/lay.pro
+++ b/src/lay/lay/lay.pro
@@ -20,7 +20,6 @@ HEADERS = \
layLogViewerDialog.h \
layMacroEditorDialog.h \
layMacroEditorPage.h \
- layMacroEditorSetupDialog.h \
layMacroEditorTree.h \
layMacroPropertiesDialog.h \
layMacroVariableView.h \
@@ -57,7 +56,8 @@ HEADERS = \
layLibraryController.h \
layFontController.h \
layNativePlugin.h \
- laySystemPaths.h
+ laySystemPaths.h \
+ layMacroEditorSetupPage.h
FORMS = \
ClipDialog.ui \
@@ -69,7 +69,6 @@ FORMS = \
LayoutStatistics.ui \
LogViewerDialog.ui \
MacroEditorDialog.ui \
- MacroEditorSetupDialog.ui \
MacroPropertiesDialog.ui \
MacroTemplateSelectionDialog.ui \
MainConfigPage.ui \
@@ -106,7 +105,8 @@ FORMS = \
SaltGrainPropertiesDialog.ui \
SaltGrainTemplateSelectionDialog.ui \
SaltManagerInstallConfirmationDialog.ui \
- CustomizeMenuConfigPage.ui
+ CustomizeMenuConfigPage.ui \
+ MacroEditorSetupPage.ui
SOURCES = \
gsiDeclLayApplication.cc \
@@ -125,7 +125,6 @@ SOURCES = \
layLogViewerDialog.cc \
layMacroEditorDialog.cc \
layMacroEditorPage.cc \
- layMacroEditorSetupDialog.cc \
layMacroEditorTree.cc \
layMacroPropertiesDialog.cc \
layMacroVariableView.cc \
@@ -161,7 +160,8 @@ SOURCES = \
layLibraryController.cc \
layFontController.cc \
layNativePlugin.cc \
- laySystemPaths.cc
+ laySystemPaths.cc \
+ layMacroEditorSetupPage.cc
RESOURCES = layBuildInMacros.qrc \
layHelpResources.qrc \
diff --git a/src/lay/lay/layApplication.cc b/src/lay/lay/layApplication.cc
index ac4f3dea4..ac26af7fe 100644
--- a/src/lay/lay/layApplication.cc
+++ b/src/lay/lay/layApplication.cc
@@ -1391,6 +1391,35 @@ GuiApplication::force_update_app_menu ()
#endif
}
+#if defined(__APPLE__)
+// By Thomas Lima (March 7, 2018)
+//
+// This event interceptor catches MacOS "Open With" event, and KLayout should respond
+// similarly to the Drop event in MainWindow::dropEvent.
+//
+// This particular implementation always creates a new window.
+//
+// This was implemented with the inspiration of http://doc.qt.io/qt-5/qfileopenevent.html
+bool
+GuiApplication::event (QEvent *event)
+{
+ if (event->type() == QEvent::FileOpen) {
+ QFileOpenEvent *openEvent = static_cast(event);
+ if (mp_mw)
+ {
+ const std::string tech = mp_mw->initial_technology();
+ const std::string file = tl::to_string (openEvent->file());
+ const int mode = 1; // open in new window
+ mp_mw->load_layout (file, tech, mode);
+ mp_mw->add_mru (file, tech);
+ }
+ }
+
+ return QApplication::event(event);
+}
+#endif
+
+
int
GuiApplication::exec ()
{
diff --git a/src/lay/lay/layApplication.h b/src/lay/lay/layApplication.h
index 7eceea849..e82681e2f 100644
--- a/src/lay/lay/layApplication.h
+++ b/src/lay/lay/layApplication.h
@@ -28,6 +28,9 @@
#include
#include
+#ifdef __APPLE__
+# include
+#endif
#include "gsi.h"
@@ -438,6 +441,14 @@ public:
*/
void force_update_app_menu ();
+ /**
+ * @brief Handles MacOS file open
+ * This function is used to process the "Open With" event sent by MacOS.
+ */
+#ifdef __APPLE__
+ bool event (QEvent *event);
+#endif
+
protected:
virtual void setup ();
virtual void shutdown ();
diff --git a/src/lay/lay/layMacroEditorDialog.cc b/src/lay/lay/layMacroEditorDialog.cc
index a866660f0..81c8c6290 100644
--- a/src/lay/lay/layMacroEditorDialog.cc
+++ b/src/lay/lay/layMacroEditorDialog.cc
@@ -22,10 +22,11 @@
#include "ui_MacroTemplateSelectionDialog.h"
+#include "layConfigurationDialog.h"
#include "layMacroController.h"
#include "layMacroEditorTree.h"
#include "layMacroEditorDialog.h"
-#include "layMacroEditorSetupDialog.h"
+#include "layMacroEditorSetupPage.h"
#include "layMacroPropertiesDialog.h"
#include "layFileDialog.h"
#include "layMainWindow.h"
@@ -58,6 +59,9 @@
#include
#include
+namespace lay
+{
+
const std::string cfg_macro_editor_styles ("macro-editor-styles");
const std::string cfg_macro_editor_save_all_on_run ("macro-editor-save-all-on-run");
const std::string cfg_macro_editor_stop_on_exception ("macro-editor-stop-on-exception");
@@ -74,9 +78,7 @@ const std::string cfg_macro_editor_current_macro ("macro-editor-current-macro");
const std::string cfg_macro_editor_active_macro ("macro-editor-active-macro");
const std::string cfg_macro_editor_watch_expressions ("macro-editor-watch-expressions");
const std::string cfg_macro_editor_debugging_enabled ("macro-editor-debugging-enabled");
-
-namespace lay
-{
+const std::string cfg_macro_editor_ignore_exception_list ("macro-editor-ignore-exception-list");
// -----------------------------------------------------------------------------------------
// Implementation of the macro template selection dialog
@@ -225,8 +227,10 @@ public:
static lay::MacroEditorDialog *s_macro_editor_instance = 0;
-MacroEditorDialog::MacroEditorDialog (QWidget * /*parent*/, lym::MacroCollection *root)
+MacroEditorDialog::MacroEditorDialog (lay::MainWindow *mw, lym::MacroCollection *root)
: QDialog (0 /*show as individual top widget*/, Qt::Window),
+ lay::Plugin (mw, true),
+ mp_plugin_root (mw),
mp_root (root),
m_first_show (true), m_in_processing (false), m_debugging_on (true),
mp_run_macro (0),
@@ -245,6 +249,7 @@ MacroEditorDialog::MacroEditorDialog (QWidget * /*parent*/, lym::MacroCollection
m_eval_context (-1),
m_process_events_interval (0.0),
m_window_closed (true),
+ m_needs_update (true),
m_ntab (8),
m_nindent (2),
m_save_all_on_run (false),
@@ -598,6 +603,8 @@ MacroEditorDialog::MacroEditorDialog (QWidget * /*parent*/, lym::MacroCollection
if (! s_macro_editor_instance) {
s_macro_editor_instance = this;
}
+
+ config_setup ();
}
MacroEditorDialog::~MacroEditorDialog ()
@@ -716,6 +723,113 @@ MacroEditorDialog::current_macro_tree ()
return t;
}
+void
+MacroEditorDialog::config_finalize ()
+{
+ if (m_needs_update) {
+
+ for (int i = 0; i < tabWidget->count (); ++i) {
+ MacroEditorPage *page = dynamic_cast (tabWidget->widget (i));
+ if (page) {
+ page->set_ntab (m_ntab);
+ page->set_nindent (m_nindent);
+ page->apply_attributes ();
+ page->set_font (m_font_family, m_font_size);
+ }
+ }
+
+ refresh_file_watcher ();
+
+ m_needs_update = false;
+
+ }
+}
+
+bool
+MacroEditorDialog::configure (const std::string &name, const std::string &value)
+{
+ // Reads the dynamic configuration
+
+ if (name == cfg_macro_editor_styles) {
+
+ if (m_styles != value) {
+ m_styles = value;
+ m_needs_update = true;
+ }
+ m_highlighters.load (value);
+ return true;
+
+ } else if (name == cfg_macro_editor_save_all_on_run) {
+ tl::from_string (value, m_save_all_on_run);
+ return true;
+ } else if (name == cfg_macro_editor_stop_on_exception) {
+ tl::from_string (value, m_stop_on_exception);
+ return true;
+ } else if (name == cfg_macro_editor_file_watcher_enabled) {
+
+ bool en = m_file_watcher_enabled;
+ tl::from_string (value, en);
+ if (en != m_file_watcher_enabled) {
+ m_file_watcher_enabled = en;
+ m_needs_update = true;
+ }
+ return true;
+
+ } else if (name == cfg_macro_editor_font_family) {
+
+ if (m_font_family != value) {
+ m_font_family = value;
+ m_needs_update = true;
+ }
+ return true;
+
+ } else if (name == cfg_macro_editor_font_size) {
+
+ int v = m_font_size;
+ tl::from_string (value, v);
+ if (v != m_font_size) {
+ m_font_size = v;
+ m_needs_update = true;
+ }
+ return true;
+
+ } else if (name == cfg_macro_editor_tab_width) {
+
+ int v = m_ntab;
+ tl::from_string (value, v);
+ if (v != m_ntab) {
+ m_ntab = v;
+ m_needs_update = true;
+ }
+ return true;
+
+ } else if (name == cfg_macro_editor_indent) {
+
+ int v = m_nindent;
+ tl::from_string (value, v);
+ if (v != m_nindent) {
+ m_nindent = v;
+ m_needs_update = true;
+ }
+ return true;
+
+ } else if (name == cfg_macro_editor_ignore_exception_list) {
+
+ m_ignore_exception_list.clear ();
+ tl::Extractor ex (value.c_str ());
+ while (! ex.at_end ()) {
+ std::string f;
+ ex.read_word_or_quoted (f);
+ ex.test (";");
+ m_ignore_exception_list.insert (f);
+ }
+ return true;
+
+ } else {
+ return lay::Plugin::configure (name, value);
+ }
+}
+
void
MacroEditorDialog::showEvent (QShowEvent *)
{
@@ -726,29 +840,19 @@ MacroEditorDialog::showEvent (QShowEvent *)
m_window_closed = false;
- // read configuration
- std::string styles;
- if (MainWindow::instance ()->config_get (cfg_macro_editor_styles, styles)) {
- m_highlighters.load (styles);
- }
- MainWindow::instance ()->config_get (cfg_macro_editor_save_all_on_run, m_save_all_on_run);
- MainWindow::instance ()->config_get (cfg_macro_editor_stop_on_exception, m_stop_on_exception);
- MainWindow::instance ()->config_get (cfg_macro_editor_file_watcher_enabled, m_file_watcher_enabled);
- MainWindow::instance ()->config_get (cfg_macro_editor_font_family, m_font_family);
- MainWindow::instance ()->config_get (cfg_macro_editor_font_size, m_font_size);
- MainWindow::instance ()->config_get (cfg_macro_editor_tab_width, m_ntab);
- MainWindow::instance ()->config_get (cfg_macro_editor_indent, m_nindent);
- MainWindow::instance ()->config_get (cfg_macro_editor_debugging_enabled, m_debugging_on);
+ // read debugger environment from configuration
+
+ mp_plugin_root->config_get (cfg_macro_editor_debugging_enabled, m_debugging_on);
std::string ws;
- MainWindow::instance ()->config_get (cfg_macro_editor_window_state, ws);
+ mp_plugin_root->config_get (cfg_macro_editor_window_state, ws);
lay::restore_dialog_state (this, ws);
input_field->clear ();
try {
std::string hi;
- MainWindow::instance ()->config_get (cfg_macro_editor_console_mru, hi);
+ mp_plugin_root->config_get (cfg_macro_editor_console_mru, hi);
tl::Extractor ex (hi.c_str ());
while (! ex.at_end ()) {
std::string h;
@@ -770,7 +874,7 @@ MacroEditorDialog::showEvent (QShowEvent *)
}
std::string ci;
- MainWindow::instance ()->config_get (cfg_macro_editor_console_interpreter, ci);
+ mp_plugin_root->config_get (cfg_macro_editor_console_interpreter, ci);
if (ci == "ruby") {
pythonLangSel->setChecked (false);
rubyLangSel->setChecked (true);
@@ -784,7 +888,7 @@ MacroEditorDialog::showEvent (QShowEvent *)
m_watch_expressions.clear ();
std::string we;
- MainWindow::instance ()->config_get (cfg_macro_editor_watch_expressions, we);
+ mp_plugin_root->config_get (cfg_macro_editor_watch_expressions, we);
tl::Extractor ex (we.c_str ());
while (! ex.at_end ()) {
@@ -806,7 +910,7 @@ MacroEditorDialog::showEvent (QShowEvent *)
try {
std::string om;
- MainWindow::instance ()->config_get (cfg_macro_editor_open_macros, om);
+ mp_plugin_root->config_get (cfg_macro_editor_open_macros, om);
tl::Extractor ex (om.c_str ());
while (! ex.at_end ()) {
std::string h;
@@ -818,7 +922,7 @@ MacroEditorDialog::showEvent (QShowEvent *)
} catch (...) { }
std::string am;
- MainWindow::instance ()->config_get (cfg_macro_editor_active_macro, am);
+ mp_plugin_root->config_get (cfg_macro_editor_active_macro, am);
if (! am.empty ()) {
lym::Macro *macro = mp_root->find_macro (am);
if (macro) {
@@ -829,7 +933,7 @@ MacroEditorDialog::showEvent (QShowEvent *)
dbgOn->setChecked (m_debugging_on);
std::string cm;
- MainWindow::instance ()->config_get (cfg_macro_editor_current_macro, cm);
+ mp_plugin_root->config_get (cfg_macro_editor_current_macro, cm);
if (! cm.empty ()) {
// this will make that macro the current one
editor_for_file (cm);
@@ -866,10 +970,10 @@ void
MacroEditorDialog::closeEvent (QCloseEvent *)
{
// save the debugging enabled state
- MainWindow::instance ()->config_set (cfg_macro_editor_debugging_enabled, m_debugging_on);
+ mp_plugin_root->config_set (cfg_macro_editor_debugging_enabled, m_debugging_on);
// save the window state
- MainWindow::instance ()->config_set (cfg_macro_editor_window_state, lay::save_dialog_state (this));
+ mp_plugin_root->config_set (cfg_macro_editor_window_state, lay::save_dialog_state (this));
// save the console history (at maximum the last 200 entries)
std::string hi;
@@ -879,7 +983,7 @@ MacroEditorDialog::closeEvent (QCloseEvent *)
}
hi += tl::to_quoted_string (tl::to_string (input_field->itemText (i)));
}
- MainWindow::instance ()->config_set (cfg_macro_editor_console_mru, hi);
+ mp_plugin_root->config_set (cfg_macro_editor_console_mru, hi);
// save the open macro list
std::string om;
@@ -892,7 +996,7 @@ MacroEditorDialog::closeEvent (QCloseEvent *)
om += tl::to_quoted_string (page->macro ()->path ());
}
}
- MainWindow::instance ()->config_set (cfg_macro_editor_open_macros, om);
+ mp_plugin_root->config_set (cfg_macro_editor_open_macros, om);
// save the watch expressions
std::string we;
@@ -908,15 +1012,15 @@ MacroEditorDialog::closeEvent (QCloseEvent *)
we += ":";
we += tl::to_quoted_string (i->second);
}
- MainWindow::instance ()->config_set (cfg_macro_editor_watch_expressions, we);
+ mp_plugin_root->config_set (cfg_macro_editor_watch_expressions, we);
// save the active (run) macro
- MainWindow::instance ()->config_set (cfg_macro_editor_active_macro, mp_run_macro ? mp_run_macro->path () : std::string ());
+ mp_plugin_root->config_set (cfg_macro_editor_active_macro, mp_run_macro ? mp_run_macro->path () : std::string ());
// save the current macro
MacroEditorPage *page = dynamic_cast (tabWidget->currentWidget ());
std::string cm = page && page->macro () ? page->macro ()->path () : std::string ();
- MainWindow::instance ()->config_set (cfg_macro_editor_current_macro, cm);
+ mp_plugin_root->config_set (cfg_macro_editor_current_macro, cm);
// save the current interpreter in the console
std::string ci;
@@ -925,7 +1029,7 @@ MacroEditorDialog::closeEvent (QCloseEvent *)
} else if (pythonLangSel->isChecked ()) {
ci = "python";
}
- MainWindow::instance ()->config_set (cfg_macro_editor_console_interpreter, ci);
+ mp_plugin_root->config_set (cfg_macro_editor_console_interpreter, ci);
// stop execution when the window is closed
m_in_exec = false;
@@ -1914,73 +2018,9 @@ MacroEditorDialog::setup_button_clicked ()
return;
}
- // fill data
-
- lay::MacroEditorSetupDialogData data;
- data.tab_width = m_ntab;
- data.indent = m_nindent;
- data.save_all_on_run = m_save_all_on_run;
- data.stop_on_exception = m_stop_on_exception;
- data.file_watcher_enabled = m_file_watcher_enabled;
- data.font_family = m_font_family;
- data.font_size = m_font_size;
-
- if (m_highlighters.basic_attributes ()) {
- data.basic_attributes.assign (*m_highlighters.basic_attributes ());
- }
- for (MacroEditorHighlighters::const_iterator a = m_highlighters.begin (); a != m_highlighters.end (); ++a) {
- data.specific_attributes.push_back (std::make_pair (a->first, GenericSyntaxHighlighterAttributes (& data.basic_attributes)));
- data.specific_attributes.back ().second.assign (a->second);
- }
-
- lay::MacroEditorSetupDialog dialog (this);
- if (dialog.exec_dialog (data)) {
-
- m_ntab = data.tab_width;
- m_nindent = data.indent;
- m_stop_on_exception = data.stop_on_exception;
- m_file_watcher_enabled = data.file_watcher_enabled;
- m_font_family = data.font_family;
- m_font_size = data.font_size;
-
- if (m_highlighters.basic_attributes ()) {
- m_highlighters.basic_attributes ()->assign (data.basic_attributes);
- }
-
- for (MacroEditorHighlighters::iterator a = m_highlighters.begin (); a != m_highlighters.end (); ++a) {
- for (std::vector< std::pair >::const_iterator i = data.specific_attributes.begin (); i != data.specific_attributes.end (); ++i) {
- if (i->first == a->first) {
- a->second.assign (i->second);
- break;
- }
- }
- }
-
- m_save_all_on_run = data.save_all_on_run;
-
- for (int i = 0; i < tabWidget->count (); ++i) {
- MacroEditorPage *page = dynamic_cast (tabWidget->widget (i));
- if (page) {
- page->set_ntab (m_ntab);
- page->set_nindent (m_nindent);
- page->apply_attributes ();
- page->set_font (m_font_family, m_font_size);
- }
- }
-
- // write configuration
- MainWindow::instance ()->config_set (cfg_macro_editor_styles, m_highlighters.to_string ());
- MainWindow::instance ()->config_set (cfg_macro_editor_save_all_on_run, m_save_all_on_run);
- MainWindow::instance ()->config_set (cfg_macro_editor_file_watcher_enabled, m_file_watcher_enabled);
- MainWindow::instance ()->config_set (cfg_macro_editor_stop_on_exception, m_stop_on_exception);
- MainWindow::instance ()->config_set (cfg_macro_editor_tab_width, m_ntab);
- MainWindow::instance ()->config_set (cfg_macro_editor_indent, m_nindent);
- MainWindow::instance ()->config_set (cfg_macro_editor_font_family, m_font_family);
- MainWindow::instance ()->config_set (cfg_macro_editor_font_size, m_font_size);
- MainWindow::instance ()->config_end ();
-
+ lay::ConfigurationDialog config_dialog (this, mp_plugin_root, "MacroEditor");
+ if (config_dialog.exec ()) {
refresh_file_watcher ();
-
}
}
@@ -2253,12 +2293,12 @@ MacroEditorDialog::ensure_writeable_collection_selected ()
}
static std::vector >
-get_custom_paths ()
+get_custom_paths (lay::PluginRoot *root)
{
std::vector > paths;
std::string mp;
- MainWindow::instance ()->config_get (cfg_custom_macro_paths, mp);
+ root->config_get (cfg_custom_macro_paths, mp);
try {
@@ -2281,7 +2321,7 @@ get_custom_paths ()
}
static void
-set_custom_paths (const std::vector > &paths)
+set_custom_paths (lay::PluginRoot *root, const std::vector > &paths)
{
std::string mp;
@@ -2295,7 +2335,7 @@ set_custom_paths (const std::vector > &paths
mp += p->second;
}
- MainWindow::instance ()->config_set (cfg_custom_macro_paths, mp);
+ root->config_set (cfg_custom_macro_paths, mp);
}
void
@@ -2494,7 +2534,7 @@ BEGIN_PROTECTED
std::string cat = current_macro_tree ()->category ();
- std::vector > paths = get_custom_paths ();
+ std::vector > paths = get_custom_paths (mp_plugin_root);
std::string new_path = tl::to_string (QFileInfo (new_dir).absoluteFilePath ());
paths.push_back (std::make_pair (new_path, cat));
@@ -2503,7 +2543,7 @@ BEGIN_PROTECTED
throw tl::Exception (tl::to_string (QObject::tr ("The selected directory is already installed as custom location")));
}
- set_custom_paths (paths);
+ set_custom_paths (mp_plugin_root, paths);
if (c->has_autorun ()) {
if (QMessageBox::question (this, QObject::tr ("Run Macros"), QObject::tr ("The selected folder has macros configured to run automatically.\n\nChoose 'Yes' to run these macros now. Choose 'No' to not run them."), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
@@ -2538,7 +2578,7 @@ BEGIN_PROTECTED
throw tl::Exception (tl::to_string (QObject::tr ("Select tree location to remove")));
}
- std::vector > paths = get_custom_paths ();
+ std::vector > paths = get_custom_paths (mp_plugin_root);
bool found = false;
@@ -2560,7 +2600,7 @@ BEGIN_PROTECTED
mp_root->erase (collection);
// save the new paths
- set_custom_paths (paths);
+ set_custom_paths (mp_plugin_root, paths);
END_PROTECTED
}
@@ -2809,10 +2849,34 @@ MacroEditorDialog::exception_thrown (gsi::Interpreter *interpreter, size_t file_
return;
}
- if (QMessageBox::critical (this, QObject::tr ("Exception Caught"),
- tl::to_qstring (tl::to_string (QObject::tr ("Caught the following exception:\n")) + emsg + " (Class " + eclass + ")\n\n" + tl::to_string (QObject::tr ("Press 'Ok' to continue and 'Cancel' to stop in the debugger"))),
- QMessageBox::Cancel, QMessageBox::Ok) == QMessageBox::Ok) {
+ std::string p;
+ if (file_id > 0 && file_id <= m_file_to_widget.size () && m_file_to_widget [file_id - 1].first) {
+ p = m_file_to_widget [file_id - 1].first->path ();
+ if (m_ignore_exception_list.find (p) != m_ignore_exception_list.end ()) {
+ return;
+ }
+ }
+
+ int res = QMessageBox::critical (this, QObject::tr ("Exception Caught"),
+ tl::to_qstring (tl::to_string (QObject::tr ("Caught the following exception:\n")) + emsg + " (Class " + eclass + ")\n\n" + tl::to_string (QObject::tr ("Press 'Ok' to continue.\nPress 'Ignore' to ignore this and future exceptions from this file.\nPress 'Cancel' to stop in the debugger"))),
+ QMessageBox::Cancel | QMessageBox::Ok | QMessageBox::Ignore,
+ QMessageBox::Ok);
+
+ if (res == QMessageBox::Ok) {
+
return;
+
+ } else if (res == QMessageBox::Ignore) {
+
+ std::string il;
+ il += tl::to_quoted_string (p);
+ for (std::set::const_iterator i = m_ignore_exception_list.begin (); i != m_ignore_exception_list.end (); ++i) {
+ il += ";";
+ il += tl::to_quoted_string (*i);
+ }
+ mp_plugin_root->config_set (cfg_macro_editor_ignore_exception_list, il);
+ return;
+
}
write_str (emsg.c_str (), OS_stderr);
@@ -3399,6 +3463,12 @@ class MacroEditorPluginDeclaration
: public lay::PluginDeclaration
{
public:
+ virtual lay::ConfigPage *config_page (QWidget *parent, std::string &title) const
+ {
+ title = tl::to_string (QObject::tr ("Application|Macro Development IDE"));
+ return new MacroEditorSetupPage (parent);
+ }
+
virtual void get_options (std::vector < std::pair > &options) const
{
options.push_back (std::pair (cfg_macro_editor_styles, ""));
diff --git a/src/lay/lay/layMacroEditorDialog.h b/src/lay/lay/layMacroEditorDialog.h
index 6e92402e1..bb492c71e 100644
--- a/src/lay/lay/layMacroEditorDialog.h
+++ b/src/lay/lay/layMacroEditorDialog.h
@@ -29,6 +29,7 @@
#include "ui_MacroEditorDialog.h"
#include "layMacroEditorPage.h"
#include "layMacroController.h"
+#include "layPlugin.h"
#include "tlDeferredExecution.h"
#include "tlTimer.h"
#include "tlFileSystemWatcher.h"
@@ -50,11 +51,34 @@ class QTreeWidgetItem;
namespace lay
{
+extern const std::string cfg_macro_editor_styles;
+extern const std::string cfg_macro_editor_save_all_on_run;
+extern const std::string cfg_macro_editor_stop_on_exception;
+extern const std::string cfg_macro_editor_file_watcher_enabled;
+extern const std::string cfg_macro_editor_font_family;
+extern const std::string cfg_macro_editor_font_size;
+extern const std::string cfg_macro_editor_tab_width;
+extern const std::string cfg_macro_editor_indent;
+extern const std::string cfg_macro_editor_window_state;
+extern const std::string cfg_macro_editor_console_mru;
+extern const std::string cfg_macro_editor_console_interpreter;
+extern const std::string cfg_macro_editor_open_macros;
+extern const std::string cfg_macro_editor_current_macro;
+extern const std::string cfg_macro_editor_active_macro;
+extern const std::string cfg_macro_editor_watch_expressions;
+extern const std::string cfg_macro_editor_debugging_enabled;
+extern const std::string cfg_macro_editor_ignore_exception_list;
+
class MacroEditorTree;
class BrowserPanel;
+class MainWindow;
class MacroEditorDialog
- : public QDialog, public gsi::Console, private Ui::MacroEditorDialog, public gsi::ExecutionHandler
+ : public QDialog,
+ public lay::Plugin,
+ public gsi::Console,
+ public gsi::ExecutionHandler,
+ private Ui::MacroEditorDialog
{
Q_OBJECT
@@ -74,7 +98,7 @@ public:
/**
* @brief Constructor
*/
- MacroEditorDialog (QWidget *parent, lym::MacroCollection *root);
+ MacroEditorDialog (lay::MainWindow *parent, lym::MacroCollection *root);
/**
* @brief Destructor
@@ -262,7 +286,10 @@ private:
lym::Macro *new_macro ();
void do_search_edited ();
void select_trace (size_t index);
+ bool configure (const std::string &name, const std::string &value);
+ void config_finalize ();
+ lay::PluginRoot *mp_plugin_root;
lym::MacroCollection *mp_root;
bool m_first_show;
bool m_in_processing;
@@ -294,10 +321,13 @@ private:
double m_process_events_interval;
tl::Clock m_last_process_events;
bool m_window_closed;
+ bool m_needs_update;
+ std::string m_styles;
int m_ntab;
int m_nindent;
bool m_save_all_on_run;
bool m_stop_on_exception;
+ std::set m_ignore_exception_list;
bool m_file_watcher_enabled;
std::string m_font_family;
int m_font_size;
diff --git a/src/lay/lay/layMacroEditorSetupDialog.cc b/src/lay/lay/layMacroEditorSetupPage.cc
similarity index 58%
rename from src/lay/lay/layMacroEditorSetupDialog.cc
rename to src/lay/lay/layMacroEditorSetupPage.cc
index 339f47ec5..9dc60c5ae 100644
--- a/src/lay/lay/layMacroEditorSetupDialog.cc
+++ b/src/lay/lay/layMacroEditorSetupPage.cc
@@ -21,15 +21,114 @@
*/
-#include "layMacroEditorSetupDialog.h"
+#include "layMacroEditorSetupPage.h"
+#include "layMacroEditorPage.h"
+#include "layMacroEditorDialog.h"
+#include "layGenericSyntaxHighlighter.h"
+
+#include "lymMacro.h"
#include "tlString.h"
+#include
#include
namespace lay
{
+struct MacroEditorSetupDialogData
+{
+ MacroEditorSetupDialogData ()
+ : basic_attributes (0), tab_width (8), indent (2), save_all_on_run (true), stop_on_exception (true), file_watcher_enabled (true), font_size (0)
+ {
+ }
+
+ GenericSyntaxHighlighterAttributes basic_attributes;
+ std::vector > specific_attributes;
+ int tab_width;
+ int indent;
+ bool save_all_on_run;
+ bool stop_on_exception;
+ bool file_watcher_enabled;
+ std::string font_family;
+ int font_size;
+ std::set ignore_exceptions_list;
+
+ void setup (lay::PluginRoot *root)
+ {
+ lay::MacroEditorHighlighters highlighters (0);
+ std::string styles;
+ root->config_get (cfg_macro_editor_styles, styles);
+ highlighters.load (styles);
+
+ if (highlighters.basic_attributes ()) {
+ basic_attributes.assign (*highlighters.basic_attributes ());
+ }
+ for (lay::MacroEditorHighlighters::const_iterator a = highlighters.begin (); a != highlighters.end (); ++a) {
+ specific_attributes.push_back (std::make_pair (a->first, GenericSyntaxHighlighterAttributes (& basic_attributes)));
+ specific_attributes.back ().second.assign (a->second);
+ }
+
+ root->config_get (cfg_macro_editor_save_all_on_run, save_all_on_run);
+ root->config_get (cfg_macro_editor_file_watcher_enabled, file_watcher_enabled);
+ root->config_get (cfg_macro_editor_stop_on_exception, stop_on_exception);
+ root->config_get (cfg_macro_editor_tab_width, tab_width);
+ root->config_get (cfg_macro_editor_indent, indent);
+ root->config_get (cfg_macro_editor_font_family, font_family);
+ root->config_get (cfg_macro_editor_font_size, font_size);
+
+ std::string il;
+ root->config_get (cfg_macro_editor_ignore_exception_list, il);
+ ignore_exceptions_list.clear ();
+ tl::Extractor ex (il.c_str ());
+ while (! ex.at_end ()) {
+ std::string f;
+ ex.read_word_or_quoted (f);
+ ex.test (";");
+ ignore_exceptions_list.insert (f);
+ }
+ }
+
+ void commit (lay::PluginRoot *root)
+ {
+ lay::MacroEditorHighlighters highlighters (0);
+
+ if (highlighters.basic_attributes ()) {
+ highlighters.basic_attributes ()->assign (basic_attributes);
+ }
+
+ for (MacroEditorHighlighters::iterator a = highlighters.begin (); a != highlighters.end (); ++a) {
+ for (std::vector< std::pair >::const_iterator i = specific_attributes.begin (); i != specific_attributes.end (); ++i) {
+ if (i->first == a->first) {
+ a->second.assign (i->second);
+ break;
+ }
+ }
+ }
+
+ // write configuration
+
+ root->config_set (cfg_macro_editor_styles, highlighters.to_string ());
+ root->config_set (cfg_macro_editor_save_all_on_run, save_all_on_run);
+ root->config_set (cfg_macro_editor_file_watcher_enabled, file_watcher_enabled);
+ root->config_set (cfg_macro_editor_stop_on_exception, stop_on_exception);
+ root->config_set (cfg_macro_editor_tab_width, tab_width);
+ root->config_set (cfg_macro_editor_indent, indent);
+ root->config_set (cfg_macro_editor_font_family, font_family);
+ root->config_set (cfg_macro_editor_font_size, font_size);
+
+ std::string il;
+ for (std::set::const_iterator i = ignore_exceptions_list.begin (); i != ignore_exceptions_list.end (); ++i) {
+ if (! il.empty ()) {
+ il += ";";
+ }
+ il += tl::to_quoted_string (*i);
+ }
+ root->config_set (cfg_macro_editor_ignore_exception_list, il);
+
+ }
+};
+
static void
update_item (QListWidgetItem *item, QTextCharFormat format)
{
@@ -38,8 +137,8 @@ update_item (QListWidgetItem *item, QTextCharFormat format)
item->setData (Qt::BackgroundRole, format.background ());
}
-MacroEditorSetupDialog::MacroEditorSetupDialog (QWidget *parent)
- : QDialog (parent), mp_data (0)
+MacroEditorSetupPage::MacroEditorSetupPage (QWidget *parent)
+ : lay::ConfigPage (parent), mp_data (0)
{
setupUi (this);
@@ -52,22 +151,49 @@ MacroEditorSetupDialog::MacroEditorSetupDialog (QWidget *parent)
connect (background_color_button, SIGNAL (color_changed (QColor)), this, SLOT (color_changed (QColor)));
connect (font_sel, SIGNAL (currentFontChanged (const QFont &)), this, SLOT (update_font ()));
connect (font_size, SIGNAL (valueChanged (int)), this, SLOT (update_font ()));
+ connect (clear_el, SIGNAL (clicked ()), this, SLOT (clear_exception_list ()));
+}
+
+MacroEditorSetupPage::~MacroEditorSetupPage ()
+{
+ delete mp_data;
+ mp_data = 0;
}
void
-MacroEditorSetupDialog::color_changed (QColor)
+MacroEditorSetupPage::color_changed (QColor)
{
commit_attributes (styles_list->currentItem ());
}
void
-MacroEditorSetupDialog::cb_changed (int)
+MacroEditorSetupPage::cb_changed (int)
{
commit_attributes (styles_list->currentItem ());
}
+void
+MacroEditorSetupPage::clear_exception_list ()
+{
+ if (mp_data) {
+ mp_data->ignore_exceptions_list.clear ();
+ update_ignore_exception_list ();
+ }
+}
+
+void
+MacroEditorSetupPage::update_ignore_exception_list ()
+{
+ if (mp_data) {
+ exception_list->clear ();
+ for (std::set::const_iterator i = mp_data->ignore_exceptions_list.begin (); i != mp_data->ignore_exceptions_list.end (); ++i) {
+ exception_list->addItem (tl::to_qstring (*i));
+ }
+ }
+}
+
void
-MacroEditorSetupDialog::update_font ()
+MacroEditorSetupPage::update_font ()
{
QFont f;
f.setFamily (font_sel->currentFont().family ());
@@ -76,26 +202,30 @@ MacroEditorSetupDialog::update_font ()
styles_list->setFont (f);
}
-int
-MacroEditorSetupDialog::exec_dialog (MacroEditorSetupDialogData &data)
+void
+MacroEditorSetupPage::setup (PluginRoot *root)
{
- mp_data = &data;
+ delete mp_data;
+ mp_data = new MacroEditorSetupDialogData ();
+ mp_data->setup (root);
- tab_width->setValue (data.tab_width);
- indent->setValue (data.indent);
- save_all_cb->setChecked (data.save_all_on_run);
- stop_on_exception->setChecked (data.stop_on_exception);
- watch_files->setChecked (data.file_watcher_enabled);
+ update_ignore_exception_list ();
- if (data.font_size <= 0) {
- data.font_size = font ().pointSize ();
- data.font_family = "Monospace";
+ tab_width->setValue (mp_data->tab_width);
+ indent->setValue (mp_data->indent);
+ save_all_cb->setChecked (mp_data->save_all_on_run);
+ stop_on_exception->setChecked (mp_data->stop_on_exception);
+ watch_files->setChecked (mp_data->file_watcher_enabled);
+
+ if (mp_data->font_size <= 0) {
+ mp_data->font_size = font ().pointSize ();
+ mp_data->font_family = "Monospace";
}
QFont f;
- f.setFamily (tl::to_qstring (data.font_family));
+ f.setFamily (tl::to_qstring (mp_data->font_family));
font_sel->setCurrentFont (f);
- font_size->setValue (data.font_size);
+ font_size->setValue (mp_data->font_size);
styles_list->blockSignals (true);
@@ -103,18 +233,18 @@ MacroEditorSetupDialog::exec_dialog (MacroEditorSetupDialogData &data)
std::map basic_names;
- for (GenericSyntaxHighlighterAttributes::const_iterator a = data.basic_attributes.begin (); a != data.basic_attributes.end (); ++a) {
+ for (GenericSyntaxHighlighterAttributes::const_iterator a = mp_data->basic_attributes.begin (); a != mp_data->basic_attributes.end (); ++a) {
QListWidgetItem *item = new QListWidgetItem (styles_list);
QString n = tl::to_qstring (tl::to_string (QObject::tr ("(basic)")) + " ") + a->first;
item->setText (n);
item->setData (Qt::UserRole, -1);
item->setData (Qt::UserRole + 1, a->second);
basic_names.insert (std::make_pair (a->second, n));
- update_item (item, data.basic_attributes.format_for (a->second));
+ update_item (item, mp_data->basic_attributes.format_for (a->second));
}
int na = 0;
- for (std::vector >::const_iterator sa = data.specific_attributes.begin (); sa != data.specific_attributes.end (); ++sa, ++na) {
+ for (std::vector >::const_iterator sa = mp_data->specific_attributes.begin (); sa != mp_data->specific_attributes.end (); ++sa, ++na) {
QString l = tl::to_qstring ("(" + sa->first + ") ");
@@ -137,30 +267,32 @@ MacroEditorSetupDialog::exec_dialog (MacroEditorSetupDialogData &data)
update_attributes (styles_list->currentItem ());
update_font ();
+}
- int r = QDialog::exec ();
- if (r) {
-
- if (styles_list->currentItem ()) {
- commit_attributes (styles_list->currentItem ());
- }
-
- data.tab_width = tab_width->value ();
- data.indent = indent->value ();
- data.save_all_on_run = save_all_cb->isChecked ();
- data.stop_on_exception = stop_on_exception->isChecked ();
- data.file_watcher_enabled = watch_files->isChecked ();
-
- data.font_family = tl::to_string (font_sel->currentFont ().family ());
- data.font_size = font_size->value ();
-
+void
+MacroEditorSetupPage::commit (PluginRoot *root)
+{
+ if (styles_list->currentItem ()) {
+ commit_attributes (styles_list->currentItem ());
}
- return r;
+ if (mp_data) {
+
+ mp_data->tab_width = tab_width->value ();
+ mp_data->indent = indent->value ();
+ mp_data->save_all_on_run = save_all_cb->isChecked ();
+ mp_data->stop_on_exception = stop_on_exception->isChecked ();
+ mp_data->file_watcher_enabled = watch_files->isChecked ();
+
+ mp_data->font_family = tl::to_string (font_sel->currentFont ().family ());
+ mp_data->font_size = font_size->value ();
+
+ mp_data->commit (root);
+ }
}
void
-MacroEditorSetupDialog::current_attribute_changed (QListWidgetItem *current, QListWidgetItem *previous)
+MacroEditorSetupPage::current_attribute_changed (QListWidgetItem *current, QListWidgetItem *previous)
{
if (previous) {
commit_attributes (previous);
@@ -170,7 +302,7 @@ MacroEditorSetupDialog::current_attribute_changed (QListWidgetItem *current, QLi
}
void
-MacroEditorSetupDialog::commit_attributes (QListWidgetItem *to_item)
+MacroEditorSetupPage::commit_attributes (QListWidgetItem *to_item)
{
if (! to_item) {
return;
@@ -252,7 +384,7 @@ MacroEditorSetupDialog::commit_attributes (QListWidgetItem *to_item)
}
void
-MacroEditorSetupDialog::update_attributes (QListWidgetItem *from_item)
+MacroEditorSetupPage::update_attributes (QListWidgetItem *from_item)
{
if (from_item) {
diff --git a/src/lay/lay/layMacroEditorSetupDialog.h b/src/lay/lay/layMacroEditorSetupPage.h
similarity index 57%
rename from src/lay/lay/layMacroEditorSetupDialog.h
rename to src/lay/lay/layMacroEditorSetupPage.h
index 0f7d8b444..85f763ef8 100644
--- a/src/lay/lay/layMacroEditorSetupDialog.h
+++ b/src/lay/lay/layMacroEditorSetupPage.h
@@ -21,60 +21,43 @@
*/
-#ifndef HDR_layMacroEditorSetupDialog
-#define HDR_layMacroEditorSetupDialog
+#ifndef HDR_layMacroEditorSetupPage
+#define HDR_layMacroEditorSetupPage
-#include "layGenericSyntaxHighlighter.h"
-#include "lymMacro.h"
-#include "ui_MacroEditorSetupDialog.h"
-
-#include
-
-#include
+#include "layPlugin.h"
+#include "ui_MacroEditorSetupPage.h"
namespace lay
{
-struct MacroEditorSetupDialogData
-{
- MacroEditorSetupDialogData ()
- : basic_attributes (0), tab_width (8), indent (2), save_all_on_run (true), stop_on_exception (true), file_watcher_enabled (true), font_size (0)
- {
- }
-
- GenericSyntaxHighlighterAttributes basic_attributes;
- std::vector > specific_attributes;
- int tab_width;
- int indent;
- bool save_all_on_run;
- bool stop_on_exception;
- bool file_watcher_enabled;
- std::string font_family;
- int font_size;
-};
+struct MacroEditorSetupDialogData;
/**
* @brief The dialog for editing the properties of the debugger/editor
*/
-class MacroEditorSetupDialog
- : public QDialog, private Ui::MacroEditorSetupDialog
+class MacroEditorSetupPage
+ : public lay::ConfigPage, private Ui::MacroEditorSetupPage
{
Q_OBJECT
public:
- MacroEditorSetupDialog (QWidget *parent);
+ MacroEditorSetupPage (QWidget *parent);
+ ~MacroEditorSetupPage ();
- int exec_dialog (MacroEditorSetupDialogData &data);
+ virtual void setup (PluginRoot *root);
+ virtual void commit (PluginRoot *root);
protected slots:
void current_attribute_changed (QListWidgetItem *current, QListWidgetItem *previous);
void cb_changed (int n);
void color_changed (QColor c);
void update_font ();
+ void clear_exception_list ();
private:
void commit_attributes (QListWidgetItem *to_item);
void update_attributes (QListWidgetItem *from_item);
+ void update_ignore_exception_list ();
MacroEditorSetupDialogData *mp_data;
};
diff --git a/src/lay/lay/layMainWindow.cc b/src/lay/lay/layMainWindow.cc
index 37be91928..01d08facd 100644
--- a/src/lay/lay/layMainWindow.cc
+++ b/src/lay/lay/layMainWindow.cc
@@ -1318,19 +1318,6 @@ MainWindow::about_to_exec ()
return;
}
}
-
- edt::combine_mode_type cm = edt::CM_Add;
- config_get (edt::cfg_edit_combine_mode, cm, edt::CMConverter ());
- if (lay::ApplicationBase::instance ()->is_editable () && cm != edt::CM_Add) {
- lay::TipDialog td (QApplication::activeWindow (),
- tl::to_string (QObject::tr ("The background combination mode of the shape editor is set to some other mode than 'Add'.\n"
- "This can be confusing, because a shape may not be drawn as expected.\n\nTo switch back to normal mode, choose 'Add' for the background combination mode in the toolbar.")),
- "has-non-add-edit-combine-mode");
- if (td.exec_dialog ()) {
- // Don't bother the user with more dialogs.
- return;
- }
- }
}
void
diff --git a/src/unit_tests/unit_test_main.cc b/src/unit_tests/unit_test_main.cc
index 2459dbd20..3047d7b66 100644
--- a/src/unit_tests/unit_test_main.cc
+++ b/src/unit_tests/unit_test_main.cc
@@ -70,8 +70,22 @@ main (int argc, char **argv)
return ret;
}
+static bool
+run_test (tl::TestBase *t, bool editable, bool slow, int repeat)
+{
+ for (int i = 0; i < repeat; ++i) {
+ if (repeat > 1) {
+ ut::noctrl << "Repeat iteration " << i + 1 << " of " << repeat;
+ }
+ if (! t->do_test (editable, slow)) {
+ return false;
+ }
+ }
+ return true;
+}
+
static int
-run_tests (const std::vector &selected_tests, bool editable, bool non_editable, bool slow, lay::ApplicationBase &app, bool gsi_coverage, const std::vector &class_names_vector)
+run_tests (const std::vector &selected_tests, bool editable, bool non_editable, bool slow, int repeat, lay::ApplicationBase &app, bool gsi_coverage, const std::vector &class_names_vector)
{
std::set class_names;
class_names.insert (class_names_vector.begin (), class_names_vector.end ());
@@ -129,7 +143,7 @@ run_tests (const std::vector &selected_tests, bool editable, boo
tl::Timer timer;
timer.start();
- if (! (*t)->do_test (e != 0, slow)) {
+ if (! run_test (*t, e != 0, slow, repeat)) {
ut::ctrl << "";
@@ -414,6 +428,7 @@ main_cont (int &argc, char **argv)
bool verbose = false;
bool debug_mode = false;
bool continue_flag = false;
+ int repeat = 1;
tl::CommandLineOptions cmd;
cmd << tl::arg ("-a", &xml_format, "Provide XML output format (JUnit format)")
@@ -428,11 +443,12 @@ main_cont (int &argc, char **argv)
<< tl::arg ("-s", &slow, "Includes slow (long runner) tests")
<< tl::arg ("-v", &verbose, "Provides verbose output")
<< tl::arg ("-g", &gsi_coverage, "Produces a GSI test coverage statistics")
- << tl::arg ("*-gg=class", &class_names, "Produces a specific GDS coverage statistics"
+ << tl::arg ("-r=n", &repeat, "Repeat the tests n times each")
+ << tl::arg ("*-gg=class", &class_names, "Produces a specific GDS coverage statistics",
"With this specification, coverage will be printed for this specific class. "
"This option can be used multiple times to add more classes."
)
- << tl::arg ("-x=test", &exclude_test_list, "Exclude the following tests"
+ << tl::arg ("-x=test", &exclude_test_list, "Exclude the following tests",
"This option can be given multiple times or with a comma-separated list "
"of pattern. Test tests matching one of the exclude pattern "
"are not executed."
@@ -509,7 +525,7 @@ main_cont (int &argc, char **argv)
selected_tests = &tl::TestRegistrar::instance()->tests ();
}
- result = run_tests (*selected_tests, editable, non_editable, slow, app, gsi_coverage, class_names);
+ result = run_tests (*selected_tests, editable, non_editable, slow, repeat, app, gsi_coverage, class_names);
ut::ctrl << "";