Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Kazunari Sekigawa 2018-03-12 21:41:03 +09:00
commit 38b2e7828c
26 changed files with 857 additions and 310 deletions

View File

@ -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

1
macbuild/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*.pyc

View File

@ -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]

View File

@ -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

View File

@ -18,6 +18,21 @@
<string>APPL</string>
<key>CFBundleVersion</key>
<string>${VERSION}</string>
<key>CFBundleShortVersionString</key>
<string>${VERSION}</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>gds</string>
</array>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleTypeIconFile</key>
<string>${ICONFILE}</string>
</dict>
</array>
<key>CFBundleSignature</key>
<string>????</string>
<key>NSPrincipalClass</key>

View File

@ -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
--

View File

@ -0,0 +1,4 @@
[Paths]
Plugins = ../PlugIns
Imports = ../Resources/qml
Qml2Imports = ../Resources/qml

View File

@ -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>] : type=['Qt4MacPorts', 'Qt5MacPorts'] | qt5macports \n"
Usage += " [-r|--ruby <type>] : type=['nil', 'Sys', 'Src24', 'MP24'] | sys \n"
Usage += " [-p|--python <type>] : type=['nil', 'Sys', 'Ana27', 'Ana36', 'MP36'] | sys \n"
Usage += " [-q|--qt <type>] : type=['Qt4MacPorts', 'Qt5MacPorts', 'Qt5Custom'] | qt5macports \n"
Usage += " [-r|--ruby <type>] : type=['nil', 'Sys', 'Src24', 'MP24', 'B25'] | sys \n"
Usage += " [-p|--python <type>] : 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>] : 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 }

View File

@ -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,
}
#-----------------------------------------------------

BIN
macbuild/build4mac_env.pyc Normal file

Binary file not shown.

View File

@ -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:
#-----------------------------------------------------------

BIN
macbuild/build4mac_util.pyc Normal file

Binary file not shown.

View File

@ -883,20 +883,31 @@ struct JoinEdgesCluster
void finish ()
{
std::multimap<db::Point, iterator> objects_by_p1;
std::multiset<db::Point> p2;
std::multimap<db::Point, iterator> 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<db::Point, iterator>::iterator j = objects_by_p1.begin ();
std::multimap<db::Point, iterator>::iterator j0 = objects_by_p1.begin ();
std::multimap<db::Point, iterator>::iterator j = j0;
do {
std::multimap<db::Point, iterator>::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<db::Point>::iterator ip2 = p2.find (i->first->p2 ());
tl_assert (ip2 != p2.end ());
p2.erase (ip2);
// remove the edge as it's taken
std::multimap<db::Point, iterator>::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;

View File

@ -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)));

View File

@ -7,7 +7,7 @@
<epilog/>
<doc/>
<autorun>true</autorun>
<autorun-early>false</autorun-early>
<autorun-early>true</autorun-early>
<shortcut/>
<show-in-menu>false</show-in-menu>
<group-name/>

View File

@ -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

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MacroEditorSetupDialog</class>
<widget class="QDialog" name="MacroEditorSetupDialog">
<class>MacroEditorSetupPage</class>
<widget class="QWidget" name="MacroEditorSetupPage">
<property name="geometry">
<rect>
<x>0</x>
@ -32,7 +32,7 @@
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
<number>3</number>
</property>
<widget class="QWidget" name="tab_4">
<attribute name="title">
@ -452,10 +452,71 @@
</widget>
</item>
<item>
<widget class="QCheckBox" name="stop_on_exception">
<property name="text">
<string>Ask whether to stop in debugger on exception</string>
<widget class="QGroupBox" name="stop_on_exception">
<property name="title">
<string>As&amp;k whether to stop in debugger on exception</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="1">
<widget class="QLabel" name="label_11">
<property name="text">
<string>Don't stop inside these files:</string>
</property>
<property name="alignment">
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QPushButton" name="clear_el">
<property name="text">
<string>Clear List</string>
</property>
</widget>
</item>
<item row="1" column="0">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>32</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="2">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1" colspan="3">
<widget class="QListWidget" name="exception_list">
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
@ -475,16 +536,6 @@
</widget>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
@ -495,38 +546,5 @@
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>MacroEditorSetupDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>MacroEditorSetupDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
<connections/>
</ui>

View File

@ -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 \

View File

@ -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<QFileOpenEvent *>(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 ()
{

View File

@ -28,6 +28,9 @@
#include <QApplication>
#include <QEventLoop>
#ifdef __APPLE__
# include <QEvent>
#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 ();

View File

@ -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 <QHeaderView>
#include <QResource>
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<MacroEditorPage *> (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<MacroEditorPage *> (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<std::string, GenericSyntaxHighlighterAttributes> >::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<MacroEditorPage *> (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<std::pair<std::string, std::string> >
get_custom_paths ()
get_custom_paths (lay::PluginRoot *root)
{
std::vector <std::pair<std::string, std::string> > 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<std::pair<std::string, std::string> > &paths)
set_custom_paths (lay::PluginRoot *root, const std::vector<std::pair<std::string, std::string> > &paths)
{
std::string mp;
@ -2295,7 +2335,7 @@ set_custom_paths (const std::vector<std::pair<std::string, std::string> > &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 <std::pair<std::string, std::string> > paths = get_custom_paths ();
std::vector <std::pair<std::string, std::string> > 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 <std::pair <std::string, std::string> > paths = get_custom_paths ();
std::vector <std::pair <std::string, std::string> > 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<std::string>::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<std::string, std::string> > &options) const
{
options.push_back (std::pair<std::string, std::string> (cfg_macro_editor_styles, ""));

View File

@ -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<std::string> m_ignore_exception_list;
bool m_file_watcher_enabled;
std::string m_font_family;
int m_font_size;

View File

@ -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 <vector>
#include <cstdio>
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 <std::pair <std::string, GenericSyntaxHighlighterAttributes> > 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 <std::string> 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<std::string, GenericSyntaxHighlighterAttributes> >::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<std::string>::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<std::string>::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 <int, QString> 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 <std::pair <std::string, GenericSyntaxHighlighterAttributes> >::const_iterator sa = data.specific_attributes.begin (); sa != data.specific_attributes.end (); ++sa, ++na) {
for (std::vector <std::pair <std::string, GenericSyntaxHighlighterAttributes> >::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) {

View File

@ -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 <QDialog>
#include <vector>
#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 <std::pair <std::string, GenericSyntaxHighlighterAttributes> > 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;
};

View File

@ -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

View File

@ -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<tl::TestBase *> &selected_tests, bool editable, bool non_editable, bool slow, lay::ApplicationBase &app, bool gsi_coverage, const std::vector<std::string> &class_names_vector)
run_tests (const std::vector<tl::TestBase *> &selected_tests, bool editable, bool non_editable, bool slow, int repeat, lay::ApplicationBase &app, bool gsi_coverage, const std::vector<std::string> &class_names_vector)
{
std::set<std::string> class_names;
class_names.insert (class_names_vector.begin (), class_names_vector.end ());
@ -129,7 +143,7 @@ run_tests (const std::vector<tl::TestBase *> &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 << "</system-out>";
@ -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 << "</testsuites>";