Merge branch 'master' into dvb

This commit is contained in:
Matthias Koefferlein 2019-11-06 01:13:24 +01:00
commit 118298780a
32 changed files with 120631 additions and 19900 deletions

View File

@ -28,6 +28,11 @@
#include <stdio.h>
// The system font to use
// NOTE: "Libration Mono" works only well for Ubuntu 16. The version from
// Ubuntu 18++ does not come with good hinting and is bad without AA.
static const char *font_name = "Liberation Mono";
/**
* @brief A small utility program to produce the fixed font definition file
* Run this binary and redirect the output to "laybasic/fixedFont.h".
@ -43,19 +48,34 @@ main (int argc, char *argv [])
std::string table;
int sz[] = { 9, 11, 13, 0 };
// 33% increments:
int sz[] = { 9, 11, 13, 16, 21, 27 };
const char *sz_name[] = { "Small", "Medium", "Large", "XLarge", "XXLarge", "XXXLarge" };
int resolutions = 6;
int font_sizes = int (sizeof (sz) / sizeof (sz[0]));
printf("\nconst int ff_resolutions = %d;\n", resolutions);
printf("const int ff_sizes = %d;\n", font_sizes);
printf("\nconst char *ff_size_name (int sz) {\n");
for (int s = 0; s < font_sizes; ++s) {
printf(" if (sz == %d) { return \"%s\"; }\n", s, sz_name [s]);
}
printf(" return \"\";\n}\n");
int os = 1;
for (int r = 1; r <= 6; ++r) {
for (int r = 1; r <= resolutions; ++r) {
for (int s = 0; sz[s] > 0; ++s) {
for (int s = 0; s < font_sizes; ++s) {
char b[1024];
sprintf (b, " FixedFont (ff%d_height, ff%d_line_height, ff%d_width, ff%d_first_char, sizeof (ff%d_data) / sizeof (uint32_t) / (ff%d_height * ff%d_stride), ff%d_data, ff%d_stride),\n", os, os, os, os, os, os, os, os, os);
table += b;
QFont f (QString::fromLatin1 ("Liberation Mono"), r * sz[s]);
QFont f (QString::fromLatin1 (font_name), r * sz[s]);
f.setStyleStrategy(QFont::StyleStrategy ((f.styleStrategy() & ~QFont::PreferAntialias) | QFont::NoAntialias));
QFontMetrics fm (f);

View File

@ -102,5 +102,6 @@ plugins.depends += lib rdb db
unit_tests.depends += plugins $$MAIN_DEPENDS
RESOURCES += \
plugins/tools/import/lay_plugin/layResources.qrc
plugins/tools/import/lay_plugin/layResources.qrc \
laybasic/laybasic/layResources.qrc

View File

@ -279,7 +279,7 @@
</font>
</property>
<property name="text">
<string>API version</string>
<string>API features</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@ -842,7 +842,7 @@
</font>
</property>
<property name="text">
<string>(API version required - i.e. &quot;0.25&quot;)</string>
<string>(API version and features - e.g. &quot;0.26; ruby 2.0&quot;)</string>
</property>
</widget>
</item>

View File

@ -602,7 +602,7 @@ overlaps = layer.size(0.2).raw.merged(2)</pre>
While the runset is executed, a log is written that lists the methods and their execution times.
The log is enabled using the <a href="/about/drc_ref_global.xml#verbose">verbose</a> function.
The <a href="/about/drc_ref_global.xml#log">log</a> and <a href="/about/drc_ref_global.xml#info">info</a> functions
allows enterin additional information into the log. "info" will enter the message if verbose mode is enabled.
allows entering additional information into the log. "info" will enter the message if verbose mode is enabled.
"log" will enter the message always. <a href="/about/drc_ref_global.xml#silent">silent</a> is equivalent to
"verbose(false)".
</p>
@ -618,7 +618,7 @@ overlaps = layer.size(0.2).raw.merged(2)</pre>
<pre>
...
drc_w = input(1, 0).width(0.2)
log("Number of width violations: #{drc_w.size}")
log("Number of width violations: #{drc_w.data.size}")
...
</pre>

View File

@ -119,7 +119,6 @@ SOURCES = \
layClipDialog.cc \
layCrashMessage.cc \
layFillDialog.cc \
layGenericSyntaxHighlighter.cc \
layGSIHelpProvider.cc \
layHelpDialog.cc \
layHelpProvider.cc \

View File

@ -113,7 +113,14 @@ MacroEditorHighlighters::highlighter_for_scheme (QObject *parent, const std::str
if (! scheme.empty ()) {
QResource res (tl::to_qstring (":/syntax/" + scheme + ".xml"));
QByteArray data = qUncompress (QByteArray ((const char *) res.data (), int (res.size ())));
QByteArray data;
if (res.isCompressed ()) {
data = qUncompress ((const unsigned char *)res.data (), (int)res.size ());
} else {
data = QByteArray ((const char *)res.data (), (int)res.size ());
}
QBuffer input (&data);
input.open (QIODevice::ReadOnly);
lay::GenericSyntaxHighlighter *hl = new GenericSyntaxHighlighter (parent, input, attributes);

View File

@ -305,6 +305,33 @@ SaltGrain::valid_name (const std::string &n)
return res == n;
}
bool
SaltGrain::valid_api_version (const std::string &v)
{
tl::Extractor ex (v.c_str ());
while (! ex.at_end ()) {
std::string feature;
ex.try_read_name (feature);
bool first = true;
while (! ex.at_end () && ! ex.test (";")) {
int n = 0;
if (! first && ! ex.test (".")) {
return false;
}
if (! ex.try_read (n)) {
return false;
}
first = false;
}
}
return true;
}
bool
SaltGrain::valid_version (const std::string &v)
{

View File

@ -198,6 +198,11 @@ public:
* The API version is the KLayout version required to run the grain's macros.
* A version string is of the form "x.y..." where x, y and other version
* components are integer numbers.
*
* The version string can also list other features such as ruby version etc.
* The components are separated with a semicolon.
* For example, "0.26; ruby; python 3.0" means: requires KLayout API 0.26,
* ruby (any version) any python (>= 3.0).
*/
const std::string &api_version () const
{
@ -433,6 +438,11 @@ public:
*/
static bool valid_version (const std::string &v);
/**
* @brief Gets a value indicating whether the given version string is a valid API version string
*/
static bool valid_api_version (const std::string &v);
/**
* @brief Checks whether the given string is a valid name
*/

View File

@ -252,7 +252,7 @@ SaltGrainDetailsTextWidget::details_text ()
stream << "<p>";
if (! g->api_version ().empty ()) {
stream << "<b>" << QObject::tr ("API version") << ":</b> " << tl::to_qstring (tl::escaped_to_html (g->api_version ())) << " ";
stream << "<b>" << QObject::tr ("API version and features") << ":</b> " << tl::to_qstring (tl::escaped_to_html (g->api_version ())) << " ";
}
stream << "</p>";

View File

@ -529,8 +529,8 @@ SaltGrainPropertiesDialog::accept ()
// API version
api_version_alert->clear ();
if (! m_grain.api_version ().empty () && ! SaltGrain::valid_version (m_grain.api_version ())) {
api_version_alert->error () << tr ("'%1' is not a valid API version string. An API version string needs to be numeric (like '0.25'').").arg (tl::to_qstring (m_grain.api_version ()));
if (! m_grain.api_version ().empty () && ! SaltGrain::valid_api_version (m_grain.api_version ())) {
api_version_alert->error () << tr ("'%1' is not a valid API version string. An API version string needs to be a semicolon-separated list of features with optional numeric versions (like '0.26' or 'ruby 2.0; python').").arg (tl::to_qstring (m_grain.api_version ()));
}
// doc URL

View File

@ -31,6 +31,9 @@
#include "tlString.h"
#include "tlExceptions.h"
#include "rba.h"
#include "pya.h"
#include <QTextDocument>
#include <QPainter>
#include <QDir>
@ -108,6 +111,176 @@ private:
lay::Salt *mp_salt;
};
// --------------------------------------------------------------------------------------
// SaltAPIVersionCheck
class SaltAPIVersionCheck
{
public:
struct APIFeature
{
APIFeature (const std::string &_name, const std::string &_version, const std::string &_description)
: name (_name), version (_version), description (_description)
{
// .. nothing yet ..
}
std::string name, version, description;
};
SaltAPIVersionCheck ();
bool check (const std::string &api_version);
const std::string &message () const
{
return m_message;
}
private:
std::vector<APIFeature> m_features;
std::string m_message;
void populate_features ();
const APIFeature *find_feature (const std::string &name) const;
std::string feature_list () const;
};
SaltAPIVersionCheck::SaltAPIVersionCheck ()
{
populate_features ();
}
bool
SaltAPIVersionCheck::check (const std::string &api_version)
{
tl::Extractor ex (api_version.c_str ());
bool any_not_available = false;
bool good = true;
m_message.clear ();
while (! ex.at_end ()) {
std::string fname;
ex.try_read_name (fname);
std::string v;
while (! ex.at_end () && ! ex.test (";")) {
int n = 0;
if (ex.try_read (n)) {
v += tl::to_string (n);
} else if (ex.test (".")) {
v += ".";
} else {
m_message = tl::to_string (tr ("API version string malformed - cannot check."));
return false;
}
}
const APIFeature *f = find_feature (fname);
if (!f) {
if (! m_message.empty ()) {
m_message += "\n";
}
m_message += tl::sprintf (tl::to_string (tr ("Feature %s not available.")), fname);
good = false;
any_not_available = true;
} else if (! f->version.empty () && ! v.empty () && SaltGrain::compare_versions (f->version, v) < 0) {
// shorten the version (Python reports "3.6.7 blabla...")
std::vector<std::string> fv = tl::split (f->version, " ");
tl_assert (! fv.empty ());
std::string fv_short = fv.front ();
if (fv.size () > 1) {
fv_short += " ...";
}
if (! m_message.empty ()) {
m_message += "\n";
}
m_message += tl::sprintf (tl::to_string (tr ("%s required with version %s or later (is %s).")), f->description, v, fv_short);
good = false;
}
}
if (any_not_available) {
m_message += tl::sprintf (tl::to_string (tr ("\nAvailable features are: %s.")), feature_list ());
}
return good;
}
std::string
SaltAPIVersionCheck::feature_list () const
{
std::string fl;
for (std::vector<APIFeature>::const_iterator f = m_features.begin (); f != m_features.end (); ++f) {
if (! fl.empty ()) {
fl += ", ";
}
fl += f->name;
}
return fl;
}
const SaltAPIVersionCheck::APIFeature *
SaltAPIVersionCheck::find_feature (const std::string &name) const
{
for (std::vector<APIFeature>::const_iterator f = m_features.begin (); f != m_features.end (); ++f) {
if (f->name == name) {
return f.operator-> ();
}
}
return 0;
}
void
SaltAPIVersionCheck::populate_features ()
{
m_features.push_back (APIFeature (std::string (), lay::Version::version (), "KLayout API"));
if (rba::RubyInterpreter::instance () && rba::RubyInterpreter::instance ()->available ()) {
std::string v = rba::RubyInterpreter::instance ()->version ();
m_features.push_back (APIFeature ("ruby", v, "Ruby"));
if (SaltGrain::compare_versions (v, "2") < 0) {
m_features.push_back (APIFeature ("ruby1", v, "Ruby 1"));
} else if (SaltGrain::compare_versions (v, "3") < 0) {
m_features.push_back (APIFeature ("ruby2", v, "Ruby 2"));
}
}
if (pya::PythonInterpreter::instance () && pya::PythonInterpreter::instance ()->available ()) {
std::string v = pya::PythonInterpreter::instance ()->version ();
m_features.push_back (APIFeature ("python", v, "Python"));
if (SaltGrain::compare_versions (v, "3") < 0) {
m_features.push_back (APIFeature ("python2", v, "Python 2"));
} else if (SaltGrain::compare_versions (v, "4") < 0) {
m_features.push_back (APIFeature ("python3", v, "Python 3"));
}
}
#if defined(HAVE_QTBINDINGS)
m_features.push_back (APIFeature ("qt_binding", std::string (), "Qt Binding for RBA or PYA"));
#endif
#if defined(HAVE_QT)
# if QT_VERSION >= 0x040000 && QT_VERSION < 0x050000
m_features.push_back (APIFeature ("qt4", std::string (), "Qt 4"));
# elif QT_VERSION >= 0x050000 && QT_VERSION < 0x060000
m_features.push_back (APIFeature ("qt5", std::string (), "Qt 5"));
# endif
#endif
#if defined(HAVE_64BIT_COORD)
m_features.push_back (APIFeature ("wide-coords", std::string (), "64 bit coordinates"));
#endif
}
// --------------------------------------------------------------------------------------
// SaltManager implementation
@ -790,6 +963,7 @@ SaltManagerDialog::update_models ()
}
SaltAPIVersionCheck svc;
SaltModel *mine_model;
mine_model = dynamic_cast <SaltModel *> (salt_mine_view_update->model ());
@ -817,8 +991,8 @@ SaltManagerDialog::update_models ()
// Establish a message indicating whether the API version does not match
for (Salt::flat_iterator g = m_salt_mine.begin_flat (); g != m_salt_mine.end_flat (); ++g) {
if (SaltGrain::compare_versions (lay::Version::version (), (*g)->api_version ()) < 0) {
mine_model->set_message ((*g)->name (), SaltModel::Warning, tl::to_string (tr ("This package requires a newer API (%1)").arg (tl::to_qstring ((*g)->api_version ()))));
if (! svc.check ((*g)->api_version ())) {
mine_model->set_message ((*g)->name (), SaltModel::Warning, svc.message ());
mine_model->set_enabled ((*g)->name (), false);
}
}
@ -848,8 +1022,8 @@ SaltManagerDialog::update_models ()
// Establish a message indicating whether the API version does not match
for (Salt::flat_iterator g = m_salt_mine.begin_flat (); g != m_salt_mine.end_flat (); ++g) {
if (SaltGrain::compare_versions (lay::Version::version (), (*g)->api_version ()) < 0) {
mine_model->set_message ((*g)->name (), SaltModel::Warning, tl::to_string (tr ("This package requires a newer API (%1)").arg (tl::to_qstring ((*g)->api_version ()))));
if (! svc.check ((*g)->api_version ())) {
mine_model->set_message ((*g)->name (), SaltModel::Warning, svc.message ());
mine_model->set_enabled ((*g)->name (), false);
}
}

View File

@ -1,10 +1,8 @@
<ui version="4.0" >
<author></author>
<comment></comment>
<exportmacro></exportmacro>
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SelectStippleForm</class>
<widget class="QDialog" name="SelectStippleForm" >
<property name="geometry" >
<widget class="QDialog" name="SelectStippleForm">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
@ -12,86 +10,102 @@
<height>374</height>
</rect>
</property>
<property name="windowTitle" >
<property name="windowTitle">
<string>Select Stipple Pattern</string>
</property>
<layout class="QVBoxLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing" >
<layout class="QVBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>9</number>
</property>
<property name="topMargin">
<number>9</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<item>
<widget class="QListWidget" name="stipple_items" >
<property name="sizePolicy" >
<sizepolicy>
<hsizetype>5</hsizetype>
<vsizetype>7</vsizetype>
<widget class="QListWidget" name="stipple_items">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="acceptDrops" >
<property name="acceptDrops">
<bool>true</bool>
</property>
<property name="showDropIndicator" stdset="0" >
<property name="showDropIndicator" stdset="0">
<bool>false</bool>
</property>
<property name="dragEnabled" >
<property name="dragEnabled">
<bool>false</bool>
</property>
<property name="alternatingRowColors" >
<property name="alternatingRowColors">
<bool>false</bool>
</property>
<property name="selectionMode" >
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="iconSize" >
<property name="iconSize">
<size>
<width>34</width>
<height>36</height>
</size>
</property>
<property name="movement" >
<property name="movement">
<enum>QListView::Static</enum>
</property>
<property name="viewMode" >
<property name="viewMode">
<enum>QListView::ListMode</enum>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line" >
<property name="orientation" >
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="frame5" >
<property name="frameShape" >
<widget class="QFrame" name="frame5">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow" >
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" >
<property name="margin" >
<layout class="QHBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="spacing" >
<number>6</number>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<spacer>
<property name="orientation" >
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType" >
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" >
<property name="sizeHint" stdset="0">
<size>
<width>81</width>
<height>31</height>
@ -100,21 +114,21 @@
</spacer>
</item>
<item>
<widget class="QPushButton" name="ok_button" >
<property name="text" >
<widget class="QPushButton" name="ok_button">
<property name="text">
<string>OK</string>
</property>
<property name="default" >
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="cancel_button" >
<property name="text" >
<widget class="QPushButton" name="cancel_button">
<property name="text">
<string>Cancel</string>
</property>
<property name="default" >
<property name="default">
<bool>true</bool>
</property>
</widget>
@ -124,11 +138,8 @@
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11" />
<pixmapfunction></pixmapfunction>
<resources>
<include location="layResources.qrc" />
</resources>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections>
<connection>
<sender>ok_button</sender>
@ -136,11 +147,11 @@
<receiver>SelectStippleForm</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel" >
<hint type="sourcelabel">
<x>182</x>
<y>334</y>
</hint>
<hint type="destinationlabel" >
<hint type="destinationlabel">
<x>163</x>
<y>178</y>
</hint>
@ -152,11 +163,11 @@
<receiver>SelectStippleForm</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel" >
<hint type="sourcelabel">
<x>275</x>
<y>334</y>
</hint>
<hint type="destinationlabel" >
<hint type="destinationlabel">
<x>163</x>
<y>178</y>
</hint>

View File

@ -1,179 +1,198 @@
<ui version="4.0" >
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>UserPropertiesForm</class>
<widget class="QDialog" name="UserPropertiesForm" >
<property name="geometry" >
<widget class="QDialog" name="UserPropertiesForm">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>424</width>
<height>305</height>
<height>428</height>
</rect>
</property>
<property name="windowTitle" >
<property name="windowTitle">
<string>User Properties</string>
</property>
<layout class="QGridLayout" >
<property name="margin" >
<layout class="QGridLayout">
<property name="leftMargin">
<number>9</number>
</property>
<property name="spacing" >
<number>0</number>
<property name="topMargin">
<number>9</number>
</property>
<item row="1" column="0" colspan="2" >
<spacer>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType" >
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" >
<size>
<width>332</width>
<height>16</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0" colspan="2" >
<widget class="QLabel" name="title_lbl" >
<property name="text" >
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<property name="spacing">
<number>6</number>
</property>
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="title_lbl">
<property name="text">
<string>User properties</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2" >
<widget class="QDialogButtonBox" name="buttonBox" >
<property name="orientation" >
<item row="4" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons" >
<set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="2" column="0" >
<widget class="QTreeWidget" name="prop_list" >
<property name="rootIsDecorated" >
<bool>false</bool>
</property>
<property name="allColumnsShowFocus" >
<bool>true</bool>
</property>
<column>
<property name="text" >
<string>Key</string>
</property>
</column>
<column>
<property name="text" >
<string>Value</string>
</property>
</column>
</widget>
</item>
<item row="2" column="1" >
<widget class="QFrame" name="edit_frame" >
<property name="frameShape" >
<item row="3" column="1">
<widget class="QFrame" name="edit_frame">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow" >
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QGridLayout" >
<property name="margin" >
<layout class="QGridLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="spacing" >
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="spacing">
<number>6</number>
</property>
<item row="3" column="2" >
<spacer>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" >
<size>
<width>61</width>
<height>114</height>
</size>
</property>
</spacer>
</item>
<item rowspan="4" row="0" column="0" >
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType" >
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" >
<size>
<width>6</width>
<height>201</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="1" colspan="2" >
<widget class="QPushButton" name="edit_pb" >
<property name="text" >
<string>Edit</string>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2" >
<widget class="QPushButton" name="add_pb" >
<property name="text" >
<string/>
</property>
<property name="icon" >
<iconset resource="layResources.qrc" >:/add.png</iconset>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2" >
<widget class="QPushButton" name="remove_pb" >
<property name="text" >
<string/>
</property>
<property name="icon" >
<iconset resource="layResources.qrc" >:/del.png</iconset>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="3" column="0" colspan="2" >
<spacer>
<property name="orientation" >
<enum>Qt::Vertical</enum>
<item row="1" column="0">
<widget class="QTabWidget" name="mode_tab">
<property name="currentIndex">
<number>0</number>
</property>
<property name="sizeType" >
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" >
<size>
<width>332</width>
<height>16</height>
</size>
</property>
</spacer>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Table</string>
</attribute>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1" rowspan="4">
<spacer name="spacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>6</width>
<height>201</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="add_pb">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../lay/lay/layResources.qrc">
<normaloff>:/add.png</normaloff>:/add.png</iconset>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="remove_pb">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../lay/lay/layResources.qrc">
<normaloff>:/del.png</normaloff>:/del.png</iconset>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QPushButton" name="edit_pb">
<property name="text">
<string>Edit</string>
</property>
</widget>
</item>
<item row="3" column="2">
<spacer name="spacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>61</width>
<height>211</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0" rowspan="4">
<widget class="QTreeWidget" name="prop_list">
<property name="rootIsDecorated">
<bool>false</bool>
</property>
<property name="allColumnsShowFocus">
<bool>true</bool>
</property>
<column>
<property name="text">
<string>Key</string>
</property>
</column>
<column>
<property name="text">
<string>Value</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>Text Editor</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTextEdit" name="text_edit"/>
</item>
<item>
<widget class="QLabel" name="help_label">
<property name="text">
<string>&lt;html&gt;Use the Variant Notation for key and value (&lt;a href=&quot;int:/about/variant_notation.xml&quot;&gt;See here for details&lt;/a&gt;)&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11" />
<layoutdefault spacing="6" margin="11"/>
<tabstops>
<tabstop>prop_list</tabstop>
<tabstop>add_pb</tabstop>
<tabstop>remove_pb</tabstop>
<tabstop>edit_pb</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources>
<include location="layResources.qrc" />
<include location="../../lay/lay/layResources.qrc"/>
</resources>
<connections>
<connection>
@ -182,11 +201,11 @@
<receiver>UserPropertiesForm</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel" >
<hint type="sourcelabel">
<x>211</x>
<y>282</y>
</hint>
<hint type="destinationlabel" >
<hint type="destinationlabel">
<x>211</x>
<y>152</y>
</hint>
@ -198,11 +217,11 @@
<receiver>UserPropertiesForm</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel" >
<hint type="sourcelabel">
<x>211</x>
<y>282</y>
</hint>
<hint type="destinationlabel" >
<hint type="destinationlabel">
<x>211</x>
<y>152</y>
</hint>

File diff suppressed because it is too large Load Diff

View File

@ -36,6 +36,7 @@
#include "layLayoutView.h"
#include "layCellTreeModel.h"
#include "layQtTools.h"
#include "layGenericSyntaxHighlighter.h"
#include "ui_LayerSourceDialog.h"
#include "ui_NewLayoutPropertiesDialog.h"
@ -55,6 +56,9 @@
#include "ui_UserPropertiesForm.h"
#include "ui_UserPropertiesEditForm.h"
#include <QResource>
#include <QBuffer>
namespace lay
{
@ -1012,17 +1016,38 @@ FlattenInstOptionsDialog::exec_dialog (int &levels, bool &prune)
// UserPropertiesForm implementation
UserPropertiesForm::UserPropertiesForm (QWidget *parent)
: QDialog (parent), m_editable (false)
: QDialog (parent), m_editable (false), mp_prep (0)
{
setObjectName (QString::fromUtf8 ("user_properties_form"));
mp_ui = new Ui::UserPropertiesForm ();
mp_ui->setupUi (this);
mp_ui->text_edit->setFont (QFont ("Monospace"));
mp_ui->text_edit->setAcceptRichText (false);
connect (mp_ui->add_pb, SIGNAL (clicked ()), this, SLOT (add ()));
connect (mp_ui->remove_pb, SIGNAL (clicked ()), this, SLOT (remove ()));
connect (mp_ui->edit_pb, SIGNAL (clicked ()), this, SLOT (edit ()));
connect (mp_ui->prop_list, SIGNAL (itemDoubleClicked (QTreeWidgetItem *, int)), this, SLOT (dbl_clicked (QTreeWidgetItem *, int)));
connect (mp_ui->mode_tab, SIGNAL (currentChanged (int)), this, SLOT (tab_changed (int)));
activate_help_links (mp_ui->help_label);
QResource res (tl::to_qstring (":/syntax/ur_text.xml"));
QByteArray data ((const char *) res.data (), int (res.size ()));
if (res.isCompressed ()) {
data = qUncompress (data);
}
QBuffer input (&data);
input.open (QIODevice::ReadOnly);
mp_hl_basic_attributes.reset (new GenericSyntaxHighlighterAttributes ());
mp_hl_attributes.reset (new GenericSyntaxHighlighterAttributes (mp_hl_basic_attributes.get ()));
lay::GenericSyntaxHighlighter *hl = new GenericSyntaxHighlighter (mp_ui->text_edit, input, mp_hl_attributes.get ());
input.close ();
hl->setDocument (mp_ui->text_edit->document ());
}
UserPropertiesForm::~UserPropertiesForm ()
@ -1031,35 +1056,12 @@ UserPropertiesForm::~UserPropertiesForm ()
mp_ui = 0;
}
bool
UserPropertiesForm::show (lay::LayoutView *view, unsigned int cv_index, db::properties_id_type &prop_id)
db::PropertiesRepository::properties_set
UserPropertiesForm::get_properties (int tab)
{
bool ret = false;
db::PropertiesRepository::properties_set props;
BEGIN_PROTECTED
const lay::CellView &cv = view->cellview (cv_index);
db::PropertiesRepository &prep = cv->layout ().properties_repository ();
m_editable = cv->layout ().is_editable ();
if (m_editable) {
mp_ui->edit_frame->show ();
} else {
mp_ui->edit_frame->hide ();
}
mp_ui->prop_list->clear ();
const db::PropertiesRepository::properties_set &props = prep.properties (prop_id);
for (db::PropertiesRepository::properties_set::const_iterator p = props.begin (); p != props.end (); ++p) {
QTreeWidgetItem *entry = new QTreeWidgetItem (mp_ui->prop_list);
entry->setText (0, tl::to_qstring (prep.prop_name (p->first).to_parsable_string ()));
entry->setText (1, tl::to_qstring (p->second.to_parsable_string ()));
}
if (exec ()) {
db::PropertiesRepository::properties_set props;
if (tab == 0) {
QTreeWidgetItemIterator it (mp_ui->prop_list);
while (*it) {
@ -1076,13 +1078,92 @@ BEGIN_PROTECTED
kex.read (k);
kex.expect_end ();
props.insert (std::make_pair (prep.prop_name_id (k), v));
props.insert (std::make_pair (mp_prep->prop_name_id (k), v));
++it;
}
prop_id = prep.properties_id (props);
} else {
std::string text = tl::to_string (mp_ui->text_edit->toPlainText ());
std::vector<std::string> lines = tl::split (text, "\n");
for (std::vector<std::string>::const_iterator l = lines.begin (); l != lines.end (); ++l) {
tl::Extractor ex (l->c_str ());
if (ex.at_end ()) {
// empty line
} else {
tl::Variant v, k;
ex.read (k);
ex.test (":");
ex.read (v);
ex.expect_end ();
props.insert (std::make_pair (mp_prep->prop_name_id (k), v));
}
}
}
return props;
}
void
UserPropertiesForm::set_properties (const db::PropertiesRepository::properties_set &props)
{
mp_ui->prop_list->clear ();
for (db::PropertiesRepository::properties_set::const_iterator p = props.begin (); p != props.end (); ++p) {
QTreeWidgetItem *entry = new QTreeWidgetItem (mp_ui->prop_list);
entry->setText (0, tl::to_qstring (mp_prep->prop_name (p->first).to_parsable_string ()));
entry->setText (1, tl::to_qstring (p->second.to_parsable_string ()));
}
std::string text;
for (db::PropertiesRepository::properties_set::const_iterator p = props.begin (); p != props.end (); ++p) {
text += mp_prep->prop_name (p->first).to_parsable_string ();
text += ": ";
text += p->second.to_parsable_string ();
text += "\n";
}
mp_ui->text_edit->setPlainText (tl::to_qstring (text));
}
bool
UserPropertiesForm::show (lay::LayoutView *view, unsigned int cv_index, db::properties_id_type &prop_id)
{
bool ret = false;
BEGIN_PROTECTED
const lay::CellView &cv = view->cellview (cv_index);
mp_prep = &cv->layout ().properties_repository ();
m_editable = cv->layout ().is_editable ();
if (m_editable) {
mp_ui->edit_frame->show ();
} else {
mp_ui->edit_frame->hide ();
}
mp_ui->text_edit->setReadOnly (! m_editable);
mp_ui->prop_list->clear ();
const db::PropertiesRepository::properties_set &props = mp_prep->properties (prop_id);
set_properties (props);
if (exec ()) {
if (m_editable) {
db::PropertiesRepository::properties_set props = get_properties (mp_ui->mode_tab->currentIndex ());
prop_id = mp_prep->properties_id (props);
}
ret = true;
@ -1090,6 +1171,8 @@ BEGIN_PROTECTED
ret = false;
}
mp_prep = 0;
END_PROTECTED
return ret;
@ -1144,6 +1227,50 @@ UserPropertiesForm::dbl_clicked (QTreeWidgetItem *, int)
edit ();
}
void
UserPropertiesForm::tab_changed (int tab_index)
{
if (! m_editable) {
return;
}
BEGIN_PROTECTED
int prev_tab = tab_index == 0 ? 1 : 0;
try {
// sync content
set_properties (get_properties (prev_tab));
} catch (...) {
mp_ui->mode_tab->blockSignals (true);
mp_ui->mode_tab->setCurrentIndex (prev_tab);
mp_ui->mode_tab->blockSignals (false);
throw;
}
END_PROTECTED
}
void
UserPropertiesForm::accept ()
{
BEGIN_PROTECTED
// Test for errors
if (m_editable) {
get_properties (mp_ui->mode_tab->currentIndex ());
}
QDialog::accept ();
END_PROTECTED
}
void
UserPropertiesForm::edit ()
{

View File

@ -27,9 +27,11 @@
#include "dbPoint.h"
#include "dbVector.h"
#include "dbTypes.h"
#include "dbPropertiesRepository.h"
#include "laybasicCommon.h"
#include <QDialog>
#include <memory>
class QTreeWidgetItem;
@ -39,6 +41,11 @@ namespace db
struct LayerProperties;
}
namespace lay
{
class GenericSyntaxHighlighterAttributes;
}
namespace Ui
{
class LayerSourceDialog;
@ -412,11 +419,17 @@ public slots:
void remove ();
void edit ();
void dbl_clicked (QTreeWidgetItem *, int);
void tab_changed (int);
private:
bool m_editable;
db::PropertiesRepository::properties_set get_properties (int tab);
void set_properties (const db::PropertiesRepository::properties_set &props);
void accept ();
bool m_editable;
db::PropertiesRepository *mp_prep;
Ui::UserPropertiesForm *mp_ui;
std::auto_ptr<lay::GenericSyntaxHighlighterAttributes> mp_hl_attributes, mp_hl_basic_attributes;
};
/**
@ -432,7 +445,6 @@ public:
bool show (QString &key, QString &value);
virtual void accept ();
private:
Ui::UserPropertiesEditForm *mp_ui;
};

View File

@ -37,18 +37,30 @@ FixedFont::FixedFont (unsigned int h, unsigned int lh, unsigned int w, unsigned
// .. nothing yet ..
}
int
FixedFont::font_sizes ()
{
return ff_sizes;
}
const char *
FixedFont::font_size_name (int sz)
{
return ff_size_name (sz);
}
void
FixedFont::set_default_font_size (int fs)
{
ms_default_font_size = std::min (2, std::max (0, fs));
ms_default_font_size = std::min (ff_sizes - 1, std::max (0, fs));
}
const FixedFont &
FixedFont::get_font (double resolution)
{
int fs = ms_default_font_size;
int od = std::max (1, std::min (int (sizeof (fonts) / sizeof (fonts [0])) / 3, int (1.0 / resolution + 0.5))) - 1;
return fonts [od * 3 + fs];
int od = std::max (1, std::min (ff_resolutions, int (1.0 / resolution + 0.5))) - 1;
return fonts [od * ff_sizes + fs];
}
}

View File

@ -27,10 +27,20 @@ public:
*/
static const FixedFont &get_font (double resolution);
/**
* @brief Gets the number of font sizes available
*/
static int font_sizes ();
/**
* @brief Gets the size description ("small", "large", ...)
*/
static const char *font_size_name (int sz);
/**
* @brief Set the default font size
*
* Allowed values are 0 (small), 1 (medium) or 2 (large)
* Allowed values are 0 (small), 1 (medium) or 2 (large) etc.
*/
static void set_default_font_size (int fs);

View File

@ -25,6 +25,7 @@
#define HDR_layGenericSyntaxHighlighter
#include "tlString.h"
#include "laybasicCommon.h"
#include <QSyntaxHighlighter>
#include <QString>
@ -40,7 +41,7 @@ namespace lay
/**
* @brief Specifies one element in the text block's user data
*/
struct SyntaxHighlighterElement
struct LAYBASIC_PUBLIC SyntaxHighlighterElement
{
public:
/**
@ -61,7 +62,7 @@ public:
*
* The user data will contain useful data for bracket detection and other things
*/
class SyntaxHighlighterUserData
class LAYBASIC_PUBLIC SyntaxHighlighterUserData
: public QTextBlockUserData
{
public:
@ -92,7 +93,7 @@ public:
* Rule implementations must implement this base class in order to plug into the
* generic syntax highlighter framework.
*/
class GenericSyntaxHighlighterRuleBase
class LAYBASIC_PUBLIC GenericSyntaxHighlighterRuleBase
{
public:
/**
@ -131,7 +132,7 @@ public:
/**
* @brief A specialization of GenericSyntaxHighlighterRuleBase which looks for a choice of strings
*/
class GenericSyntaxHighlighterRuleStringList
class LAYBASIC_PUBLIC GenericSyntaxHighlighterRuleStringList
: public GenericSyntaxHighlighterRuleBase
{
public:
@ -152,7 +153,7 @@ private:
*
* This object will forward the match request to the actual implementation.
*/
class GenericSyntaxHighlighterRule
class LAYBASIC_PUBLIC GenericSyntaxHighlighterRule
{
public:
/**
@ -319,7 +320,7 @@ private:
* Special context ID's are 0 (#stay), -n (#pop n times).
* A context is associated with an attribute, which is given by an integer ID.
*/
class GenericSyntaxHighlighterContext
class LAYBASIC_PUBLIC GenericSyntaxHighlighterContext
{
public:
enum {
@ -478,7 +479,7 @@ private:
/**
* @brief A collection of (named) contexts
*/
class GenericSyntaxHighlighterContexts
class LAYBASIC_PUBLIC GenericSyntaxHighlighterContexts
{
public:
GenericSyntaxHighlighterContexts ();
@ -579,7 +580,7 @@ enum def_style {
/**
* @brief A collection of attributes
*/
class GenericSyntaxHighlighterAttributes
class LAYBASIC_PUBLIC GenericSyntaxHighlighterAttributes
{
public:
typedef std::map<QString, int>::const_iterator const_iterator;
@ -672,7 +673,7 @@ private:
/**
* @brief The parser's state
*/
class GenericSyntaxHighlighterState
class LAYBASIC_PUBLIC GenericSyntaxHighlighterState
{
public:
GenericSyntaxHighlighterState (const GenericSyntaxHighlighterContexts *contexts);
@ -710,7 +711,7 @@ private:
/**
* @brief A generic syntax highlighter using "Kate"'s syntax highlight scripts
*/
class GenericSyntaxHighlighter
class LAYBASIC_PUBLIC GenericSyntaxHighlighter
: public QSyntaxHighlighter
{
public:

View File

@ -28,10 +28,10 @@
#include "tlException.h"
#include "tlExpression.h"
#include "tlAssert.h"
#include "tlInternational.h"
#include <algorithm>
namespace lay
{
@ -1870,8 +1870,14 @@ LayerPropertiesList::insert (const LayerPropertiesIterator &iter, const LayerPro
LayerPropertiesIterator parent = iter.parent ();
if (parent.is_null ()) {
if (iter.child_index () > m_layer_properties.size ()) {
throw tl::Exception (tl::to_string (tr ("Iterator is out of range in LayerPropertiesList::insert")));
}
ret = &*(m_layer_properties.insert (m_layer_properties.begin () + iter.child_index (), node));
} else {
if (iter.child_index () > size_t (parent->end_children () - parent->begin_children ())) {
throw tl::Exception (tl::to_string (tr ("Iterator is out of range in LayerPropertiesList::insert")));
}
ret = &(parent->insert_child (parent->begin_children () + iter.child_index (), node));
}
@ -1889,8 +1895,14 @@ LayerPropertiesList::erase (const LayerPropertiesIterator &iter)
std::pair <LayerPropertiesNode *, size_t> pp = iter.parent_obj ();
if (pp.first == 0) {
if (pp.second >= m_layer_properties.size ()) {
throw tl::Exception (tl::to_string (tr ("Iterator is out of range in LayerPropertiesList::erase")));
}
m_layer_properties.erase (m_layer_properties.begin () + pp.second);
} else {
if (pp.second >= size_t (pp.first->end_children () - pp.first->begin_children ())) {
throw tl::Exception (tl::to_string (tr ("Iterator is out of range in LayerPropertiesList::erase")));
}
pp.first->erase_child (pp.first->begin_children () + pp.second);
}
}

View File

@ -530,7 +530,6 @@ LCPStylePalette::LCPStylePalette (QWidget *parent, const char *name)
b->setMinimumSize (25, 16);
b->setAlignment (Qt::AlignCenter);
b->setLineWidth (1);
b->setSizePolicy (sp);
b->setText (QObject::tr ("0px"));
connect (b, SIGNAL (clicked (int)), this, SLOT (button_clicked (int)));
ll->addWidget (b);
@ -539,7 +538,6 @@ LCPStylePalette::LCPStylePalette (QWidget *parent, const char *name)
b->setMinimumSize (25, 16);
b->setAlignment (Qt::AlignCenter);
b->setLineWidth (1);
b->setSizePolicy (sp);
b->setText (QObject::tr ("1px"));
connect (b, SIGNAL (clicked (int)), this, SLOT (button_clicked (int)));
ll->addWidget (b);
@ -548,7 +546,6 @@ LCPStylePalette::LCPStylePalette (QWidget *parent, const char *name)
b->setMinimumSize (25, 16);
b->setAlignment (Qt::AlignCenter);
b->setLineWidth (1);
b->setSizePolicy (sp);
b->setText (QObject::tr ("2px"));
connect (b, SIGNAL (clicked (int)), this, SLOT (button_clicked (int)));
ll->addWidget (b);
@ -557,7 +554,6 @@ LCPStylePalette::LCPStylePalette (QWidget *parent, const char *name)
b->setMinimumSize (25, 16);
b->setAlignment (Qt::AlignCenter);
b->setLineWidth (1);
b->setSizePolicy (sp);
b->setText (QObject::tr ("3px"));
connect (b, SIGNAL (clicked (int)), this, SLOT (button_clicked (int)));
ll->addWidget (b);
@ -572,7 +568,6 @@ LCPStylePalette::LCPStylePalette (QWidget *parent, const char *name)
b->setMinimumSize (50, 16);
b->setAlignment (Qt::AlignCenter);
b->setLineWidth (1);
b->setSizePolicy (sp);
b->setText (QObject::tr ("No Cross"));
connect (b, SIGNAL (clicked (int)), this, SLOT (button_clicked (int)));
ll->addWidget (b);
@ -581,7 +576,6 @@ LCPStylePalette::LCPStylePalette (QWidget *parent, const char *name)
b->setMinimumSize (50, 16);
b->setAlignment (Qt::AlignCenter);
b->setLineWidth (1);
b->setSizePolicy (sp);
b->setText (QObject::tr ("Cross"));
connect (b, SIGNAL (clicked (int)), this, SLOT (button_clicked (int)));
ll->addWidget (b);
@ -596,7 +590,6 @@ LCPStylePalette::LCPStylePalette (QWidget *parent, const char *name)
b->setMinimumSize (50, 16);
b->setAlignment (Qt::AlignCenter);
b->setLineWidth (1);
b->setSizePolicy (sp);
b->setText (QObject::tr ("Simple"));
connect (b, SIGNAL (clicked (int)), this, SLOT (button_clicked (int)));
ll->addWidget (b);
@ -605,7 +598,6 @@ LCPStylePalette::LCPStylePalette (QWidget *parent, const char *name)
b->setMinimumSize (50, 16);
b->setAlignment (Qt::AlignCenter);
b->setLineWidth (1);
b->setSizePolicy (sp);
b->setText (QObject::tr ("Marked"));
connect (b, SIGNAL (clicked (int)), this, SLOT (button_clicked (int)));
ll->addWidget (b);

View File

@ -45,6 +45,8 @@
#include "layWidgets.h"
#include "layFileDialog.h"
#include "layFixedFont.h"
#include "dbHershey.h"
#include <QColorDialog>
@ -1424,6 +1426,11 @@ LayoutViewConfigPage7::LayoutViewConfigPage7 (QWidget *parent)
{
mp_ui = new Ui::LayoutViewConfigPage7 ();
mp_ui->setupUi (this);
mp_ui->default_font_size->clear ();
for (int i = 0; i < lay::FixedFont::font_sizes (); ++i) {
mp_ui->default_font_size->addItem (QString::fromUtf8 (lay::FixedFont::font_size_name (i)));
}
}
LayoutViewConfigPage7::~LayoutViewConfigPage7 ()

View File

@ -177,7 +177,8 @@ SOURCES = \
layNetlistCrossReferenceModel.cc \
layNetlistBrowserTreeModel.cc \
layLibrariesView.cc \
layBookmarksView.cc
layBookmarksView.cc \
layGenericSyntaxHighlighter.cc
HEADERS = \
gtf.h \
@ -275,7 +276,8 @@ HEADERS = \
layNetlistCrossReferenceModel.h \
layNetlistBrowserTreeModel.h \
layLibrariesView.h \
layBookmarksView.h
layBookmarksView.h \
layGenericSyntaxHighlighter.h
INCLUDEPATH += $$TL_INC $$GSI_INC $$DB_INC $$RDB_INC $$LYM_INC
DEPENDPATH += $$TL_INC $$GSI_INC $$DB_INC $$RDB_INC $$LYM_INC

View File

@ -44,5 +44,6 @@
<file>images/icon_device_bjt_32.png</file>
<file>images/icon_device_bjt_24.png</file>
<file>images/icon_device_bjt_16.png</file>
<file>syntax/ur_text.xml</file>
</qresource>
</RCC>

View File

@ -0,0 +1,89 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE language SYSTEM "language.dtd">
<language name="UserPropertiesTextFormat">
<highlighting>
<contexts>
<context name="Normal" attribute="Normal Text">
<DetectChar attribute="String" char="&quot;" context="Quoted Key String"/>
<DetectChar attribute="Raw String" char="'" context="Apostrophed Key String"/>
<RegExpr attribute="Float" String="##\s*\-?[0-9]([0-9]|_[0-9])*(\.[0-9]([0-9]|_[0-9])*)?([eE]\-?[1-9]([0-9]|_[0-9])*(\.[0-9]*)?)?" context="After Key"/>
<RegExpr attribute="Dec" String="#\s*\-?[1-9]([0-9]|_[0-9])*" context="After Key"/>
<RegExpr attribute="Symbol" String="[_A-Za-z0-9]+\b" context="After Key"/>
<RegExpr attribute="Error" String="[^\s]" context="Error"/>
</context>
<context name="After Key" attribute="Normal Text" fallthrough="true" fallthroughContext="Value" lineEndContext="Error">
<DetectChar attribute="Normal" char=":" context="Value"/>
<RegExpr attribute="Normal" String="\s+" context="#stay"/>
</context>
<context name="Value" attribute="Normal Text" fallthrough="true" fallthroughContext="Error" lineEndContext="Error">
<DetectChar attribute="String" char="&quot;" context="Quoted Value String"/>
<DetectChar attribute="Raw String" char="'" context="Apostrophed Value String"/>
<RegExpr attribute="Float" String="##\s*\-?[0-9]([0-9]|_[0-9])*(\.[0-9]([0-9]|_[0-9])*)?([eE]\-?[1-9]([0-9]|_[0-9])*(\.[0-9]*)?)?" context="After Value"/>
<RegExpr attribute="Dec" String="#\s*\-?[1-9]([0-9]|_[0-9])*" context="After Value"/>
<RegExpr attribute="Symbol" String="[_A-Za-z0-9]+\b" context="After Value"/>
<RegExpr attribute="Normal" String="\s+" context="Value"/>
</context>
<context name="After Value" attribute="Normal Text" fallthrough="true" fallthroughContext="Error" lineEndContext="Normal">
<RegExpr attribute="Normal" String="\s+" context="#stay"/>
</context>
<context name="Error" attribute="Error" lineEndContext="Normal">
</context>
<context name="Quoted Key String" attribute="String" lineEndContext="Error">
<StringDetect attribute="String" String="\\" context="#stay"/>
<RegExpr attribute="String" String="\\\&quot;" context="#stay"/>
<DetectChar char="&quot;" attribute="String" context="After Key"/>
</context>
<context name="Apostrophed Key String" attribute="Raw String" lineEndContext="Error">
<StringDetect attribute="String" String="\\" context="#stay"/>
<RegExpr attribute="String" String="\\\'" context="#stay"/>
<DetectChar char="'" attribute="Raw String" context="After Key"/>
</context>
<context name="Quoted Value String" attribute="String" lineEndContext="Error">
<StringDetect attribute="String" String="\\" context="#stay"/>
<RegExpr attribute="String" String="\\\&quot;" context="#stay"/>
<DetectChar char="&quot;" attribute="String" context="After Value"/>
</context>
<context name="Apostrophed Value String" attribute="Raw String" lineEndContext="Error">
<StringDetect attribute="String" String="\\" context="#stay"/>
<RegExpr attribute="String" String="\\\'" context="#stay"/>
<DetectChar char="'" attribute="Raw String" context="After Value"/>
</context>
</contexts>
<itemDatas>
<itemData name="Normal Text" defStyleNum="dsNormal"/>
<itemData name="Dec" defStyleNum="dsDecVal"/>
<itemData name="Float" defStyleNum="dsFloat"/>
<itemData name="Symbol" defStyleNum="dsString" color="#D40000"/>
<itemData name="String" defStyleNum="dsString"/>
<itemData name="Raw String" defStyleNum="dsString" color="#DD4A4A" selColor="#DD4A4A"/>
<!-- use these to mark errors and alerts things -->
<itemData name="Error" defStyleNum="dsAlert"/>
</itemDatas>
</highlighting>
</language>

View File

@ -451,7 +451,8 @@ static bool is_reserved_word (const std::string &name)
name == "def" ||
name == "for" ||
name == "lambda" ||
name == "try");
name == "try" ||
name == "None");
}
/**
@ -2641,7 +2642,7 @@ PythonModule::make_classes (const char *mod_name)
}
if (name != raw_name) {
add_python_doc (**c, mt, int (mid), tl::sprintf (tl::to_string (tr ("This method is available as method '%s' in Python")), name));
add_python_doc (**c, mt, int (mid), tl::sprintf (tl::to_string (tr ("This attribute is available as '%s' in Python")), name));
}
// create documentation
@ -2741,7 +2742,7 @@ PythonModule::make_classes (const char *mod_name)
} else if (tl::verbosity () >= 20) {
tl::warn << "Upper case method name encountered which cannot be used as a Python constant (more than one overload or at least one argument): " << (*c)->name () << "." << name;
add_python_doc (**c, mt, int (mid), tl::to_string (tr ("This method is not available for Python")));
add_python_doc (**c, mt, int (mid), tl::to_string (tr ("This attribute is not available for Python")));
}
} else {

View File

@ -160,7 +160,13 @@ rba_check_error ()
// parse the backtrace to get the line number
tl::BacktraceElement info;
if (! bt.empty ()) {
if (CLASS_OF (lasterr) == rb_eSyntaxError) {
// for syntax errors we try to parse the message
info = rba_split_bt_information (emsg.c_str (), emsg.size ());
if (info.line == 0 && ! bt.empty ()) {
info = bt.front ();
}
} else if (! bt.empty ()) {
// use the backtrace
info = bt.front ();
} else {

View File

@ -1023,6 +1023,15 @@ Extractor::read_word (std::string &value, const char *non_term)
return *this;
}
Extractor &
Extractor::read_name (std::string &value, const char *non_term)
{
if (! try_read_name (value, non_term)) {
error (tl::to_string (tr ("Expected a name string")));
}
return *this;
}
Extractor &
Extractor::read_word_or_quoted (std::string &value, const char *non_term)
{
@ -1227,6 +1236,31 @@ Extractor::try_read (bool &value)
return false;
}
bool
Extractor::try_read_name (std::string &string, const char *non_term)
{
if (! *skip ()) {
return false;
}
string.clear ();
// first character must not be a digit
if (*m_cp && (safe_isalpha (*m_cp) || strchr (non_term, *m_cp) != NULL)) {
string += *m_cp;
++m_cp;
} else {
return false;
}
while (*m_cp && (safe_isalnum (*m_cp) || strchr (non_term, *m_cp) != NULL)) {
string += *m_cp;
++m_cp;
}
return ! string.empty ();
}
bool
Extractor::try_read_word (std::string &string, const char *non_term)
{
@ -1235,10 +1269,12 @@ Extractor::try_read_word (std::string &string, const char *non_term)
}
string.clear ();
while (*m_cp && (safe_isalnum (*m_cp) || strchr (non_term, *m_cp) != NULL)) {
string += *m_cp;
++m_cp;
}
return ! string.empty ();
}

View File

@ -528,6 +528,13 @@ public:
*/
Extractor &read (std::string &value, const char *term = "");
/**
* @brief Read a name string
*
* Name strings are like words, but for the first character digits are not allowed.
*/
Extractor &read_name (std::string &value, const char *non_term = "_.$");
/**
* @brief Read a string consisting of "word" characters
*
@ -610,6 +617,13 @@ public:
*/
bool try_read (std::string &string, const char *term = "");
/**
* @brief Try to read a name string
*
* Name strings are like words, but for the first character digits are not allowed.
*/
bool try_read_name (std::string &value, const char *non_term = "_.$");
/**
* @brief Try to read a string consisting of "word" characters
*

View File

@ -312,23 +312,49 @@ TEST(8)
x = Extractor ("a_word!");
x.read_word (s);
EXPECT_EQ (s, "a_word");
x = Extractor ("a_word!");
s.clear ();
x.read_name (s);
EXPECT_EQ (s, "a_word");
EXPECT_EQ (x.test ("!"), true);
x = Extractor ("0_word!");
EXPECT_EQ (x.try_read_word (s), true);
x = Extractor ("0_word!");
EXPECT_EQ (x.try_read_name (s), false);
x = Extractor ("a_word!");
EXPECT_EQ (x.try_read_word (s), true);
EXPECT_EQ (s, "a_word");
EXPECT_EQ (x.test ("!"), true);
x = Extractor ("a_word!");
EXPECT_EQ (x.try_read_name (s), true);
EXPECT_EQ (s, "a_word");
EXPECT_EQ (x.test ("!"), true);
x = Extractor ("a_word!");
x.read_word (s, "_!");
EXPECT_EQ (s, "a_word!");
EXPECT_EQ (x.at_end (), true);
x = Extractor ("a_word!");
x.read_name (s, "_!");
EXPECT_EQ (s, "a_word!");
EXPECT_EQ (x.at_end (), true);
x = Extractor ("a_word!");
EXPECT_EQ (x.try_read_word (s, "_!"), true);
EXPECT_EQ (s, "a_word!");
EXPECT_EQ (x.at_end (), true);
x = Extractor ("a_word!");
EXPECT_EQ (x.try_read_name (s, "_!"), true);
EXPECT_EQ (s, "a_word!");
EXPECT_EQ (x.at_end (), true);
x = Extractor ("a_word!");
x.read_word_or_quoted (s);
EXPECT_EQ (s, "a_word");

View File

@ -2,7 +2,7 @@
# This script is sourced to define the main version parameters
# The main version
KLAYOUT_VERSION="0.26"
KLAYOUT_VERSION="0.26.1"
# The build date
KLAYOUT_VERSION_DATE=$(date "+%Y-%m-%d")