Merge branch 'master' into development

This commit is contained in:
Thomas Ferreira de Lima 2018-03-12 09:32:15 -04:00
commit 5d0017ffa7
12 changed files with 574 additions and 284 deletions

View File

@ -1,46 +1,46 @@
0.25.1 (2018-02-23): 0.25.1 (2018-02-23):
* Enhancements: build compatibility with MacOS, Qt 5.9. * Enhancements: build compatibility with MacOS and Qt 5.9.
Qt 4.6+4.7 supported as well with restrictions: Qt 4.6 supported now as well with one restriction:
the package installation feature is not working. the package installation feature is not working.
* Bugfix: Package manager * Bugfixs: Package manager
- Remove button wasn't enabled if multiple packages were selected - Remove button wasn't enabled if multiple packages were selected
- A potential crash ob removing packages was fixed - A potential crash ob removing packages was fixed
* Enhancement: 64 bit coordinate support enabled on Windows builds * Enhancement: 64 bit coordinate support enabled on Windows builds
* Further bugfixes: See links * 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/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/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/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/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/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/39 (Action cannot be reassigned)
- https://github.com/klayoutmatthias/klayout/issues/40 (Crash in Python binding) - 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/41 (Polygon#touches? issue)
- https://github.com/klayoutmatthias/klayout/issues/42 (headless mode support with Qt5/-zz) - 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/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/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/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/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/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/53 (Unreadable 'about' text)
- https://github.com/klayoutmatthias/klayout/issues/59 (async download of package index and details)
- https://github.com/klayoutmatthias/klayout/issues/62 (QXmlSimpleReader#parse cannot be called) - 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/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/64 (Crash on exit)
- https://github.com/klayoutmatthias/klayout/issues/68 (OASIS reader issue with degenerated shapes) - 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/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/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/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/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/75 (Python PCell issue when parameters are called 'layer')
- https://github.com/klayoutmatthias/klayout/issues/79 (Replace function enabled also for read-only macros) - https://github.com/klayoutmatthias/klayout/issues/79 (Replace function enabled also for read-only macros)
* Further enhancements: see links * 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/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): 0.25 (2017-11-04):
* Enhancement: Menu customization * Enhancement: Menu customization

View File

@ -883,20 +883,31 @@ struct JoinEdgesCluster
void finish () void finish ()
{ {
std::multimap<db::Point, iterator> objects_by_p1; 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) { for (iterator o = begin (); o != end (); ++o) {
if (o->first->p1 () != o->first->p2 ()) { if (o->first->p1 () != o->first->p2 ()) {
objects_by_p1.insert (std::make_pair (o->first->p1 (), o)); 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 ()); tl_assert (! objects_by_p1.empty ());
// Find the beginning of a new sequence // 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; iterator i = j->second;
// determine a sequence // determine a sequence
@ -906,12 +917,22 @@ struct JoinEdgesCluster
do { do {
// record the next point
pts.push_back (i->first->p2 ()); pts.push_back (i->first->p2 ());
std::multiset<db::Point>::iterator ip2 = p2.find (i->first->p2 ());
tl_assert (ip2 != p2.end ()); // remove the edge as it's taken
p2.erase (ip2); 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); 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 ()); j = objects_by_p1.find (i->first->p2 ());
if (j != objects_by_p1.end ()) { if (j != objects_by_p1.end ()) {
i = j->second; 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)"); 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; db::Edges e;
e.insert (db::Edge (db::Point (0, 0), db::Point (0, 200))); e.insert (db::Edge (db::Point (0, 0), db::Point (0, 200)));

View File

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

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>MacroEditorSetupDialog</class> <class>MacroEditorSetupPage</class>
<widget class="QDialog" name="MacroEditorSetupDialog"> <widget class="QWidget" name="MacroEditorSetupPage">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
@ -32,7 +32,7 @@
<item> <item>
<widget class="QTabWidget" name="tabWidget"> <widget class="QTabWidget" name="tabWidget">
<property name="currentIndex"> <property name="currentIndex">
<number>0</number> <number>3</number>
</property> </property>
<widget class="QWidget" name="tab_4"> <widget class="QWidget" name="tab_4">
<attribute name="title"> <attribute name="title">
@ -452,10 +452,71 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QCheckBox" name="stop_on_exception"> <widget class="QGroupBox" name="stop_on_exception">
<property name="text"> <property name="title">
<string>Ask whether to stop in debugger on exception</string> <string>As&amp;k whether to stop in debugger on exception</string>
</property> </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> </widget>
</item> </item>
<item> <item>
@ -475,16 +536,6 @@
</widget> </widget>
</widget> </widget>
</item> </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> </layout>
</widget> </widget>
<customwidgets> <customwidgets>
@ -495,38 +546,5 @@
</customwidget> </customwidget>
</customwidgets> </customwidgets>
<resources/> <resources/>
<connections> <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>
</ui> </ui>

View File

@ -20,7 +20,6 @@ HEADERS = \
layLogViewerDialog.h \ layLogViewerDialog.h \
layMacroEditorDialog.h \ layMacroEditorDialog.h \
layMacroEditorPage.h \ layMacroEditorPage.h \
layMacroEditorSetupDialog.h \
layMacroEditorTree.h \ layMacroEditorTree.h \
layMacroPropertiesDialog.h \ layMacroPropertiesDialog.h \
layMacroVariableView.h \ layMacroVariableView.h \
@ -57,7 +56,8 @@ HEADERS = \
layLibraryController.h \ layLibraryController.h \
layFontController.h \ layFontController.h \
layNativePlugin.h \ layNativePlugin.h \
laySystemPaths.h laySystemPaths.h \
layMacroEditorSetupPage.h
FORMS = \ FORMS = \
ClipDialog.ui \ ClipDialog.ui \
@ -69,7 +69,6 @@ FORMS = \
LayoutStatistics.ui \ LayoutStatistics.ui \
LogViewerDialog.ui \ LogViewerDialog.ui \
MacroEditorDialog.ui \ MacroEditorDialog.ui \
MacroEditorSetupDialog.ui \
MacroPropertiesDialog.ui \ MacroPropertiesDialog.ui \
MacroTemplateSelectionDialog.ui \ MacroTemplateSelectionDialog.ui \
MainConfigPage.ui \ MainConfigPage.ui \
@ -106,7 +105,8 @@ FORMS = \
SaltGrainPropertiesDialog.ui \ SaltGrainPropertiesDialog.ui \
SaltGrainTemplateSelectionDialog.ui \ SaltGrainTemplateSelectionDialog.ui \
SaltManagerInstallConfirmationDialog.ui \ SaltManagerInstallConfirmationDialog.ui \
CustomizeMenuConfigPage.ui CustomizeMenuConfigPage.ui \
MacroEditorSetupPage.ui
SOURCES = \ SOURCES = \
gsiDeclLayApplication.cc \ gsiDeclLayApplication.cc \
@ -125,7 +125,6 @@ SOURCES = \
layLogViewerDialog.cc \ layLogViewerDialog.cc \
layMacroEditorDialog.cc \ layMacroEditorDialog.cc \
layMacroEditorPage.cc \ layMacroEditorPage.cc \
layMacroEditorSetupDialog.cc \
layMacroEditorTree.cc \ layMacroEditorTree.cc \
layMacroPropertiesDialog.cc \ layMacroPropertiesDialog.cc \
layMacroVariableView.cc \ layMacroVariableView.cc \
@ -161,7 +160,8 @@ SOURCES = \
layLibraryController.cc \ layLibraryController.cc \
layFontController.cc \ layFontController.cc \
layNativePlugin.cc \ layNativePlugin.cc \
laySystemPaths.cc laySystemPaths.cc \
layMacroEditorSetupPage.cc
RESOURCES = layBuildInMacros.qrc \ RESOURCES = layBuildInMacros.qrc \
layHelpResources.qrc \ layHelpResources.qrc \

View File

@ -22,10 +22,11 @@
#include "ui_MacroTemplateSelectionDialog.h" #include "ui_MacroTemplateSelectionDialog.h"
#include "layConfigurationDialog.h"
#include "layMacroController.h" #include "layMacroController.h"
#include "layMacroEditorTree.h" #include "layMacroEditorTree.h"
#include "layMacroEditorDialog.h" #include "layMacroEditorDialog.h"
#include "layMacroEditorSetupDialog.h" #include "layMacroEditorSetupPage.h"
#include "layMacroPropertiesDialog.h" #include "layMacroPropertiesDialog.h"
#include "layFileDialog.h" #include "layFileDialog.h"
#include "layMainWindow.h" #include "layMainWindow.h"
@ -58,6 +59,9 @@
#include <QHeaderView> #include <QHeaderView>
#include <QResource> #include <QResource>
namespace lay
{
const std::string cfg_macro_editor_styles ("macro-editor-styles"); 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_save_all_on_run ("macro-editor-save-all-on-run");
const std::string cfg_macro_editor_stop_on_exception ("macro-editor-stop-on-exception"); 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_active_macro ("macro-editor-active-macro");
const std::string cfg_macro_editor_watch_expressions ("macro-editor-watch-expressions"); const std::string cfg_macro_editor_watch_expressions ("macro-editor-watch-expressions");
const std::string cfg_macro_editor_debugging_enabled ("macro-editor-debugging-enabled"); const std::string cfg_macro_editor_debugging_enabled ("macro-editor-debugging-enabled");
const std::string cfg_macro_editor_ignore_exception_list ("macro-editor-ignore-exception-list");
namespace lay
{
// ----------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------
// Implementation of the macro template selection dialog // Implementation of the macro template selection dialog
@ -225,8 +227,10 @@ public:
static lay::MacroEditorDialog *s_macro_editor_instance = 0; 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), : QDialog (0 /*show as individual top widget*/, Qt::Window),
lay::Plugin (mw, true),
mp_plugin_root (mw),
mp_root (root), mp_root (root),
m_first_show (true), m_in_processing (false), m_debugging_on (true), m_first_show (true), m_in_processing (false), m_debugging_on (true),
mp_run_macro (0), mp_run_macro (0),
@ -245,6 +249,7 @@ MacroEditorDialog::MacroEditorDialog (QWidget * /*parent*/, lym::MacroCollection
m_eval_context (-1), m_eval_context (-1),
m_process_events_interval (0.0), m_process_events_interval (0.0),
m_window_closed (true), m_window_closed (true),
m_needs_update (true),
m_ntab (8), m_ntab (8),
m_nindent (2), m_nindent (2),
m_save_all_on_run (false), m_save_all_on_run (false),
@ -598,6 +603,8 @@ MacroEditorDialog::MacroEditorDialog (QWidget * /*parent*/, lym::MacroCollection
if (! s_macro_editor_instance) { if (! s_macro_editor_instance) {
s_macro_editor_instance = this; s_macro_editor_instance = this;
} }
config_setup ();
} }
MacroEditorDialog::~MacroEditorDialog () MacroEditorDialog::~MacroEditorDialog ()
@ -716,6 +723,113 @@ MacroEditorDialog::current_macro_tree ()
return t; 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 void
MacroEditorDialog::showEvent (QShowEvent *) MacroEditorDialog::showEvent (QShowEvent *)
{ {
@ -726,29 +840,19 @@ MacroEditorDialog::showEvent (QShowEvent *)
m_window_closed = false; m_window_closed = false;
// read configuration // read debugger environment from configuration
std::string styles;
if (MainWindow::instance ()->config_get (cfg_macro_editor_styles, styles)) { mp_plugin_root->config_get (cfg_macro_editor_debugging_enabled, m_debugging_on);
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);
std::string ws; 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); lay::restore_dialog_state (this, ws);
input_field->clear (); input_field->clear ();
try { try {
std::string hi; 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 ()); tl::Extractor ex (hi.c_str ());
while (! ex.at_end ()) { while (! ex.at_end ()) {
std::string h; std::string h;
@ -770,7 +874,7 @@ MacroEditorDialog::showEvent (QShowEvent *)
} }
std::string ci; 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") { if (ci == "ruby") {
pythonLangSel->setChecked (false); pythonLangSel->setChecked (false);
rubyLangSel->setChecked (true); rubyLangSel->setChecked (true);
@ -784,7 +888,7 @@ MacroEditorDialog::showEvent (QShowEvent *)
m_watch_expressions.clear (); m_watch_expressions.clear ();
std::string we; 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 ()); tl::Extractor ex (we.c_str ());
while (! ex.at_end ()) { while (! ex.at_end ()) {
@ -806,7 +910,7 @@ MacroEditorDialog::showEvent (QShowEvent *)
try { try {
std::string om; 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 ()); tl::Extractor ex (om.c_str ());
while (! ex.at_end ()) { while (! ex.at_end ()) {
std::string h; std::string h;
@ -818,7 +922,7 @@ MacroEditorDialog::showEvent (QShowEvent *)
} catch (...) { } } catch (...) { }
std::string am; 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 ()) { if (! am.empty ()) {
lym::Macro *macro = mp_root->find_macro (am); lym::Macro *macro = mp_root->find_macro (am);
if (macro) { if (macro) {
@ -829,7 +933,7 @@ MacroEditorDialog::showEvent (QShowEvent *)
dbgOn->setChecked (m_debugging_on); dbgOn->setChecked (m_debugging_on);
std::string cm; 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 ()) { if (! cm.empty ()) {
// this will make that macro the current one // this will make that macro the current one
editor_for_file (cm); editor_for_file (cm);
@ -866,10 +970,10 @@ void
MacroEditorDialog::closeEvent (QCloseEvent *) MacroEditorDialog::closeEvent (QCloseEvent *)
{ {
// save the debugging enabled state // 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 // 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) // save the console history (at maximum the last 200 entries)
std::string hi; std::string hi;
@ -879,7 +983,7 @@ MacroEditorDialog::closeEvent (QCloseEvent *)
} }
hi += tl::to_quoted_string (tl::to_string (input_field->itemText (i))); 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 // save the open macro list
std::string om; std::string om;
@ -892,7 +996,7 @@ MacroEditorDialog::closeEvent (QCloseEvent *)
om += tl::to_quoted_string (page->macro ()->path ()); 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 // save the watch expressions
std::string we; std::string we;
@ -908,15 +1012,15 @@ MacroEditorDialog::closeEvent (QCloseEvent *)
we += ":"; we += ":";
we += tl::to_quoted_string (i->second); 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 // 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 // save the current macro
MacroEditorPage *page = dynamic_cast<MacroEditorPage *> (tabWidget->currentWidget ()); MacroEditorPage *page = dynamic_cast<MacroEditorPage *> (tabWidget->currentWidget ());
std::string cm = page && page->macro () ? page->macro ()->path () : std::string (); 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 // save the current interpreter in the console
std::string ci; std::string ci;
@ -925,7 +1029,7 @@ MacroEditorDialog::closeEvent (QCloseEvent *)
} else if (pythonLangSel->isChecked ()) { } else if (pythonLangSel->isChecked ()) {
ci = "python"; 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 // stop execution when the window is closed
m_in_exec = false; m_in_exec = false;
@ -1914,73 +2018,9 @@ MacroEditorDialog::setup_button_clicked ()
return; return;
} }
// fill data lay::ConfigurationDialog config_dialog (this, mp_plugin_root, "MacroEditor");
if (config_dialog.exec ()) {
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 ();
refresh_file_watcher (); refresh_file_watcher ();
} }
} }
@ -2253,12 +2293,12 @@ MacroEditorDialog::ensure_writeable_collection_selected ()
} }
static std::vector<std::pair<std::string, std::string> > 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::vector <std::pair<std::string, std::string> > paths;
std::string mp; std::string mp;
MainWindow::instance ()->config_get (cfg_custom_macro_paths, mp); root->config_get (cfg_custom_macro_paths, mp);
try { try {
@ -2281,7 +2321,7 @@ get_custom_paths ()
} }
static void 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; std::string mp;
@ -2295,7 +2335,7 @@ set_custom_paths (const std::vector<std::pair<std::string, std::string> > &paths
mp += p->second; mp += p->second;
} }
MainWindow::instance ()->config_set (cfg_custom_macro_paths, mp); root->config_set (cfg_custom_macro_paths, mp);
} }
void void
@ -2494,7 +2534,7 @@ BEGIN_PROTECTED
std::string cat = current_macro_tree ()->category (); 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 ()); std::string new_path = tl::to_string (QFileInfo (new_dir).absoluteFilePath ());
paths.push_back (std::make_pair (new_path, cat)); 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"))); 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 (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) { 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"))); 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; bool found = false;
@ -2560,7 +2600,7 @@ BEGIN_PROTECTED
mp_root->erase (collection); mp_root->erase (collection);
// save the new paths // save the new paths
set_custom_paths (paths); set_custom_paths (mp_plugin_root, paths);
END_PROTECTED END_PROTECTED
} }
@ -2809,10 +2849,34 @@ MacroEditorDialog::exception_thrown (gsi::Interpreter *interpreter, size_t file_
return; return;
} }
if (QMessageBox::critical (this, QObject::tr ("Exception Caught"), std::string p;
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"))), if (file_id > 0 && file_id <= m_file_to_widget.size () && m_file_to_widget [file_id - 1].first) {
QMessageBox::Cancel, QMessageBox::Ok) == QMessageBox::Ok) { 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; 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); write_str (emsg.c_str (), OS_stderr);
@ -3399,6 +3463,12 @@ class MacroEditorPluginDeclaration
: public lay::PluginDeclaration : public lay::PluginDeclaration
{ {
public: 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 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, "")); options.push_back (std::pair<std::string, std::string> (cfg_macro_editor_styles, ""));

View File

@ -29,6 +29,7 @@
#include "ui_MacroEditorDialog.h" #include "ui_MacroEditorDialog.h"
#include "layMacroEditorPage.h" #include "layMacroEditorPage.h"
#include "layMacroController.h" #include "layMacroController.h"
#include "layPlugin.h"
#include "tlDeferredExecution.h" #include "tlDeferredExecution.h"
#include "tlTimer.h" #include "tlTimer.h"
#include "tlFileSystemWatcher.h" #include "tlFileSystemWatcher.h"
@ -50,11 +51,34 @@ class QTreeWidgetItem;
namespace lay 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 MacroEditorTree;
class BrowserPanel; class BrowserPanel;
class MainWindow;
class MacroEditorDialog 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 Q_OBJECT
@ -74,7 +98,7 @@ public:
/** /**
* @brief Constructor * @brief Constructor
*/ */
MacroEditorDialog (QWidget *parent, lym::MacroCollection *root); MacroEditorDialog (lay::MainWindow *parent, lym::MacroCollection *root);
/** /**
* @brief Destructor * @brief Destructor
@ -262,7 +286,10 @@ private:
lym::Macro *new_macro (); lym::Macro *new_macro ();
void do_search_edited (); void do_search_edited ();
void select_trace (size_t index); 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; lym::MacroCollection *mp_root;
bool m_first_show; bool m_first_show;
bool m_in_processing; bool m_in_processing;
@ -294,10 +321,13 @@ private:
double m_process_events_interval; double m_process_events_interval;
tl::Clock m_last_process_events; tl::Clock m_last_process_events;
bool m_window_closed; bool m_window_closed;
bool m_needs_update;
std::string m_styles;
int m_ntab; int m_ntab;
int m_nindent; int m_nindent;
bool m_save_all_on_run; bool m_save_all_on_run;
bool m_stop_on_exception; bool m_stop_on_exception;
std::set<std::string> m_ignore_exception_list;
bool m_file_watcher_enabled; bool m_file_watcher_enabled;
std::string m_font_family; std::string m_font_family;
int m_font_size; 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 "tlString.h"
#include <vector>
#include <cstdio> #include <cstdio>
namespace lay 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 static void
update_item (QListWidgetItem *item, QTextCharFormat format) update_item (QListWidgetItem *item, QTextCharFormat format)
{ {
@ -38,8 +137,8 @@ update_item (QListWidgetItem *item, QTextCharFormat format)
item->setData (Qt::BackgroundRole, format.background ()); item->setData (Qt::BackgroundRole, format.background ());
} }
MacroEditorSetupDialog::MacroEditorSetupDialog (QWidget *parent) MacroEditorSetupPage::MacroEditorSetupPage (QWidget *parent)
: QDialog (parent), mp_data (0) : lay::ConfigPage (parent), mp_data (0)
{ {
setupUi (this); setupUi (this);
@ -52,22 +151,49 @@ MacroEditorSetupDialog::MacroEditorSetupDialog (QWidget *parent)
connect (background_color_button, SIGNAL (color_changed (QColor)), this, SLOT (color_changed (QColor))); 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_sel, SIGNAL (currentFontChanged (const QFont &)), this, SLOT (update_font ()));
connect (font_size, SIGNAL (valueChanged (int)), 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 void
MacroEditorSetupDialog::color_changed (QColor) MacroEditorSetupPage::color_changed (QColor)
{ {
commit_attributes (styles_list->currentItem ()); commit_attributes (styles_list->currentItem ());
} }
void void
MacroEditorSetupDialog::cb_changed (int) MacroEditorSetupPage::cb_changed (int)
{ {
commit_attributes (styles_list->currentItem ()); 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 void
MacroEditorSetupDialog::update_font () MacroEditorSetupPage::update_font ()
{ {
QFont f; QFont f;
f.setFamily (font_sel->currentFont().family ()); f.setFamily (font_sel->currentFont().family ());
@ -76,26 +202,30 @@ MacroEditorSetupDialog::update_font ()
styles_list->setFont (f); styles_list->setFont (f);
} }
int void
MacroEditorSetupDialog::exec_dialog (MacroEditorSetupDialogData &data) MacroEditorSetupPage::setup (PluginRoot *root)
{ {
mp_data = &data; delete mp_data;
mp_data = new MacroEditorSetupDialogData ();
mp_data->setup (root);
tab_width->setValue (data.tab_width); update_ignore_exception_list ();
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);
if (data.font_size <= 0) { tab_width->setValue (mp_data->tab_width);
data.font_size = font ().pointSize (); indent->setValue (mp_data->indent);
data.font_family = "Monospace"; 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; QFont f;
f.setFamily (tl::to_qstring (data.font_family)); f.setFamily (tl::to_qstring (mp_data->font_family));
font_sel->setCurrentFont (f); font_sel->setCurrentFont (f);
font_size->setValue (data.font_size); font_size->setValue (mp_data->font_size);
styles_list->blockSignals (true); styles_list->blockSignals (true);
@ -103,18 +233,18 @@ MacroEditorSetupDialog::exec_dialog (MacroEditorSetupDialogData &data)
std::map <int, QString> basic_names; 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); QListWidgetItem *item = new QListWidgetItem (styles_list);
QString n = tl::to_qstring (tl::to_string (QObject::tr ("(basic)")) + " ") + a->first; QString n = tl::to_qstring (tl::to_string (QObject::tr ("(basic)")) + " ") + a->first;
item->setText (n); item->setText (n);
item->setData (Qt::UserRole, -1); item->setData (Qt::UserRole, -1);
item->setData (Qt::UserRole + 1, a->second); item->setData (Qt::UserRole + 1, a->second);
basic_names.insert (std::make_pair (a->second, n)); 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; 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 + ") "); QString l = tl::to_qstring ("(" + sa->first + ") ");
@ -137,30 +267,32 @@ MacroEditorSetupDialog::exec_dialog (MacroEditorSetupDialogData &data)
update_attributes (styles_list->currentItem ()); update_attributes (styles_list->currentItem ());
update_font (); update_font ();
}
int r = QDialog::exec (); void
if (r) { MacroEditorSetupPage::commit (PluginRoot *root)
{
if (styles_list->currentItem ()) { if (styles_list->currentItem ()) {
commit_attributes (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 ();
} }
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 void
MacroEditorSetupDialog::current_attribute_changed (QListWidgetItem *current, QListWidgetItem *previous) MacroEditorSetupPage::current_attribute_changed (QListWidgetItem *current, QListWidgetItem *previous)
{ {
if (previous) { if (previous) {
commit_attributes (previous); commit_attributes (previous);
@ -170,7 +302,7 @@ MacroEditorSetupDialog::current_attribute_changed (QListWidgetItem *current, QLi
} }
void void
MacroEditorSetupDialog::commit_attributes (QListWidgetItem *to_item) MacroEditorSetupPage::commit_attributes (QListWidgetItem *to_item)
{ {
if (! to_item) { if (! to_item) {
return; return;
@ -252,7 +384,7 @@ MacroEditorSetupDialog::commit_attributes (QListWidgetItem *to_item)
} }
void void
MacroEditorSetupDialog::update_attributes (QListWidgetItem *from_item) MacroEditorSetupPage::update_attributes (QListWidgetItem *from_item)
{ {
if (from_item) { if (from_item) {

View File

@ -21,60 +21,43 @@
*/ */
#ifndef HDR_layMacroEditorSetupDialog #ifndef HDR_layMacroEditorSetupPage
#define HDR_layMacroEditorSetupDialog #define HDR_layMacroEditorSetupPage
#include "layGenericSyntaxHighlighter.h" #include "layPlugin.h"
#include "lymMacro.h" #include "ui_MacroEditorSetupPage.h"
#include "ui_MacroEditorSetupDialog.h"
#include <QDialog>
#include <vector>
namespace lay namespace lay
{ {
struct MacroEditorSetupDialogData 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;
};
/** /**
* @brief The dialog for editing the properties of the debugger/editor * @brief The dialog for editing the properties of the debugger/editor
*/ */
class MacroEditorSetupDialog class MacroEditorSetupPage
: public QDialog, private Ui::MacroEditorSetupDialog : public lay::ConfigPage, private Ui::MacroEditorSetupPage
{ {
Q_OBJECT Q_OBJECT
public: 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: protected slots:
void current_attribute_changed (QListWidgetItem *current, QListWidgetItem *previous); void current_attribute_changed (QListWidgetItem *current, QListWidgetItem *previous);
void cb_changed (int n); void cb_changed (int n);
void color_changed (QColor c); void color_changed (QColor c);
void update_font (); void update_font ();
void clear_exception_list ();
private: private:
void commit_attributes (QListWidgetItem *to_item); void commit_attributes (QListWidgetItem *to_item);
void update_attributes (QListWidgetItem *from_item); void update_attributes (QListWidgetItem *from_item);
void update_ignore_exception_list ();
MacroEditorSetupDialogData *mp_data; MacroEditorSetupDialogData *mp_data;
}; };

View File

@ -1318,19 +1318,6 @@ MainWindow::about_to_exec ()
return; 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 void

View File

@ -70,8 +70,22 @@ main (int argc, char **argv)
return ret; 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 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; std::set<std::string> class_names;
class_names.insert (class_names_vector.begin (), class_names_vector.end ()); 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; tl::Timer timer;
timer.start(); timer.start();
if (! (*t)->do_test (e != 0, slow)) { if (! run_test (*t, e != 0, slow, repeat)) {
ut::ctrl << "</system-out>"; ut::ctrl << "</system-out>";
@ -414,6 +428,7 @@ main_cont (int &argc, char **argv)
bool verbose = false; bool verbose = false;
bool debug_mode = false; bool debug_mode = false;
bool continue_flag = false; bool continue_flag = false;
int repeat = 1;
tl::CommandLineOptions cmd; tl::CommandLineOptions cmd;
cmd << tl::arg ("-a", &xml_format, "Provide XML output format (JUnit format)") 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 ("-s", &slow, "Includes slow (long runner) tests")
<< tl::arg ("-v", &verbose, "Provides verbose output") << tl::arg ("-v", &verbose, "Provides verbose output")
<< tl::arg ("-g", &gsi_coverage, "Produces a GSI test coverage statistics") << 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. " "With this specification, coverage will be printed for this specific class. "
"This option can be used multiple times to add more classes." "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 " "This option can be given multiple times or with a comma-separated list "
"of pattern. Test tests matching one of the exclude pattern " "of pattern. Test tests matching one of the exclude pattern "
"are not executed." "are not executed."
@ -509,7 +525,7 @@ main_cont (int &argc, char **argv)
selected_tests = &tl::TestRegistrar::instance()->tests (); 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>"; ut::ctrl << "</testsuites>";