mirror of https://github.com/KLayout/klayout.git
Reworked lym::MacroCollection for not using Qt (too much)
This commit is contained in:
parent
89547a6fde
commit
8e21dab345
|
|
@ -30,7 +30,7 @@ class RCFile(object):
|
|||
file.write(f"\n// Resource file {self.path} as {self.alias}\n")
|
||||
file.write( "namespace {\n")
|
||||
file.write( "\n")
|
||||
file.write(f" class {cls}\n")
|
||||
file.write(f" struct {cls}\n")
|
||||
file.write( " {\n")
|
||||
file.write(f" {cls}() {cb}\n")
|
||||
file.write(f" static bool compressed = {compressed};\n")
|
||||
|
|
@ -49,10 +49,10 @@ class RCFile(object):
|
|||
file.write( " m_id = tl::register_resource(name, compressed, data, sizeof(data) / sizeof(data[0]));\n")
|
||||
file.write( " }\n")
|
||||
file.write(f" ~{cls}() {cb}\n")
|
||||
file.write( " tl::unregister_resource(m_id)\n")
|
||||
file.write( " tl::unregister_resource(m_id);\n")
|
||||
file.write( " }\n")
|
||||
file.write( " tl::resource_id_type m_id;\n")
|
||||
file.write(f" {bc} resource_instance{index}\n")
|
||||
file.write(f" {bc} resource_instance{index};\n")
|
||||
file.write( "\n")
|
||||
file.write( "}\n")
|
||||
|
||||
|
|
|
|||
|
|
@ -83,6 +83,8 @@ BD_PUBLIC int strmrun (int argc, char *argv[])
|
|||
python.define_variable (v->first, v->second);
|
||||
}
|
||||
|
||||
// @@@ ... add Python and Ruby built-in macro collections, autorun-early and autorun ...
|
||||
|
||||
std::string script = tl::absolute_file_path (data.script);
|
||||
|
||||
lym::Macro macro;
|
||||
|
|
|
|||
|
|
@ -2685,7 +2685,7 @@ CODE
|
|||
end
|
||||
|
||||
def _process_events
|
||||
if RBA::Application.instance
|
||||
if RBA.constants.member?(:Application) && RBA::Application.instance
|
||||
RBA::Application.instance.process_events
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ module DRC
|
|||
|
||||
# Installs the home menu entries (needs to be done on autorun, not autorun-early)
|
||||
|
||||
if RBA::Application::instance && RBA::Application::instance.main_window
|
||||
if RBA.constants.member?(:Application) && RBA::Application::instance && RBA::Application::instance.main_window
|
||||
|
||||
cat = "drc"
|
||||
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ module DRC
|
|||
create_template(":/drc-templates/drc.lym")
|
||||
|
||||
# if available, create a menu branch
|
||||
if RBA::Application::instance && RBA::Application::instance.main_window
|
||||
if RBA.constants.member?(:Application) && RBA::Application::instance && RBA::Application::instance.main_window
|
||||
mw = RBA::Application::instance.main_window
|
||||
mw.menu.insert_menu("tools_menu.verification_group+", "drc", "DRC")
|
||||
end
|
||||
|
|
@ -160,7 +160,7 @@ module DRC
|
|||
DRCPlainTextInterpreter::new(drc_recipe)
|
||||
|
||||
# Creates a new macro category
|
||||
if RBA::Application::instance
|
||||
if RBA.constants.member?(:Application) && RBA::Application::instance
|
||||
RBA::Application::instance.add_macro_category("drc", "DRC", [ "drc" ])
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -66,6 +66,18 @@ Class<lay::LayoutView> decl_LayoutView (decl_LayoutViewBase, "lay", "LayoutView"
|
|||
"\n"
|
||||
"This event has been introduced in version 0.28."
|
||||
) +
|
||||
gsi::method ("current", &lay::LayoutView::current,
|
||||
"@brief Returns the current view\n"
|
||||
"The current view is the one that is made current by using \\current=.\n"
|
||||
"\n"
|
||||
"This variation has been introduced for the non-Qt case in version 0.28."
|
||||
) +
|
||||
gsi::method ("current=", &lay::LayoutView::set_current, gsi::arg ("view"),
|
||||
"@brief Sets the current view\n"
|
||||
"See \\current for details.\n"
|
||||
"\n"
|
||||
"This method has been introduced for the non-Qt case in version 0.28."
|
||||
) +
|
||||
gsi::method ("timer", static_cast<void (lay::LayoutView::*) ()> (&lay::LayoutView::timer),
|
||||
"@brief A callback required to be called regularily in the non-Qt case.\n"
|
||||
"\n"
|
||||
|
|
@ -84,12 +96,36 @@ Class<lay::LayoutView> decl_LayoutView (decl_LayoutViewBase, "lay", "LayoutView"
|
|||
"This object controls these aspects of the view and controls the appearance of the data. "
|
||||
);
|
||||
|
||||
static lay::CellViewRef get_active_cellview_ref ()
|
||||
{
|
||||
lay::LayoutView *view = 0; // @@@ lay::LayoutView::current ();
|
||||
if (! view) {
|
||||
return lay::CellViewRef ();
|
||||
}
|
||||
if (view->active_cellview_index () >= 0) {
|
||||
return view->active_cellview_ref ();
|
||||
} else {
|
||||
return lay::CellViewRef ();
|
||||
}
|
||||
}
|
||||
|
||||
static lay::LayoutView *get_view (lay::CellViewRef *cv)
|
||||
{
|
||||
return cv->view ()->ui ();
|
||||
}
|
||||
|
||||
static ClassExt<lay::CellViewRef> extdecl_CellView (
|
||||
method ("active", &get_active_cellview_ref,
|
||||
"@brief Gets the active CellView\n"
|
||||
"The active CellView is the one that is selected in the current layout view. This method is "
|
||||
"equivalent to\n"
|
||||
"@code\n"
|
||||
"RBA::LayoutView::current.active_cellview\n"
|
||||
"@/code\n"
|
||||
"If no CellView is active, this method returns nil.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.23."
|
||||
) +
|
||||
method_ext ("view", &get_view,
|
||||
"@brief Gets the view the cellview resides in\n"
|
||||
"This reference will be nil if the cellview is not a valid one.\n"
|
||||
|
|
|
|||
|
|
@ -59,6 +59,18 @@ LayoutView::timer ()
|
|||
}
|
||||
}
|
||||
|
||||
static tl::weak_ptr<lay::LayoutView> s_current_view;
|
||||
|
||||
LayoutView *LayoutView::current ()
|
||||
{
|
||||
return s_current_view.get ();
|
||||
}
|
||||
|
||||
void LayoutView::set_current (LayoutView *view)
|
||||
{
|
||||
s_current_view.reset (view);
|
||||
}
|
||||
|
||||
} // namespace lay
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -66,6 +66,16 @@ public:
|
|||
*/
|
||||
void timer ();
|
||||
|
||||
/**
|
||||
* @brief Gets the current view
|
||||
*/
|
||||
static LayoutView *current ();
|
||||
|
||||
/**
|
||||
* @brief Sets the current view
|
||||
*/
|
||||
static void set_current (LayoutView *view);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Gets the LayoutView interface
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ module LVS
|
|||
|
||||
# Installs the home menu entries (needs to be done on autorun, not autorun-early)
|
||||
|
||||
if RBA::Application::instance && RBA::Application::instance.main_window
|
||||
if RBA.constants.member?(:Application) && RBA::Application::instance && RBA::Application::instance.main_window
|
||||
|
||||
cat = "lvs"
|
||||
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ module LVS
|
|||
create_template(":/lvs-templates/lvs.lym")
|
||||
|
||||
# if available, create a menu branch
|
||||
if RBA::Application::instance && RBA::Application::instance.main_window
|
||||
if RBA.constants.member?(:Application) && RBA::Application::instance && RBA::Application::instance.main_window
|
||||
mw = RBA::Application::instance.main_window
|
||||
mw.menu.insert_menu("tools_menu.verification_group+", "lvs", "LVS")
|
||||
end
|
||||
|
|
@ -160,7 +160,7 @@ module LVS
|
|||
LVSPlainTextInterpreter::new(lvs_recipe)
|
||||
|
||||
# Creates a new macro category
|
||||
if RBA::Application::instance
|
||||
if RBA.constants.member?(:Application) && RBA::Application::instance
|
||||
RBA::Application::instance.add_macro_category("lvs", "LVS", [ "lvs" ])
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ HEADERS = \
|
|||
lvsCommon.h \
|
||||
lvsForceLink.h \
|
||||
|
||||
!equals(HAVE_QT, "0") {
|
||||
!equals(HAVE_QT, "0") || !equals(HAVE_PYTHON, "0") {
|
||||
RESOURCES = \
|
||||
lvsResources.qrc
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,8 +23,6 @@
|
|||
|
||||
#include "lymMacroCollection.h"
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
|
||||
#include "lymMacroInterpreter.h"
|
||||
#include "tlExceptions.h"
|
||||
#include "gsiDecl.h"
|
||||
|
|
@ -38,14 +36,15 @@
|
|||
#include "tlGlobPattern.h"
|
||||
#include "tlInclude.h"
|
||||
#include "tlProgress.h"
|
||||
#include "tlFileUtils.h"
|
||||
#include "tlResources.h"
|
||||
|
||||
#include "rba.h"
|
||||
#include "pya.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
#include <QUrl>
|
||||
#include <QResource>
|
||||
#if defined(HAVE_QT)
|
||||
# include <QResource>
|
||||
#endif
|
||||
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
|
|
@ -90,20 +89,26 @@ void MacroCollection::begin_changes ()
|
|||
if (mp_parent) {
|
||||
mp_parent->begin_changes ();
|
||||
} else {
|
||||
#if defined(HAVE_QT)
|
||||
emit about_to_change ();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void MacroCollection::on_menu_needs_update ()
|
||||
{
|
||||
#if defined(HAVE_QT)
|
||||
emit menu_needs_update ();
|
||||
#endif
|
||||
}
|
||||
|
||||
void MacroCollection::on_changed ()
|
||||
{
|
||||
// Note: it is very important that each on_changed occurs after exactly one begin_changes.
|
||||
// (See #459 for example)
|
||||
#if defined(HAVE_QT)
|
||||
emit changed ();
|
||||
#endif
|
||||
on_macro_collection_changed (this);
|
||||
}
|
||||
|
||||
|
|
@ -112,13 +117,17 @@ void MacroCollection::on_macro_collection_changed (MacroCollection *mc)
|
|||
if (mp_parent) {
|
||||
mp_parent->on_macro_collection_changed (mc);
|
||||
} else {
|
||||
#if defined(HAVE_QT)
|
||||
emit macro_collection_changed (mc);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void MacroCollection::on_child_deleted (MacroCollection *mc)
|
||||
{
|
||||
#if defined(HAVE_QT)
|
||||
emit child_deleted (mc);
|
||||
#endif
|
||||
on_macro_collection_deleted (mc);
|
||||
}
|
||||
|
||||
|
|
@ -127,13 +136,17 @@ void MacroCollection::on_macro_collection_deleted (MacroCollection *mc)
|
|||
if (mp_parent) {
|
||||
mp_parent->on_macro_collection_deleted (mc);
|
||||
} else {
|
||||
#if defined(HAVE_QT)
|
||||
emit macro_collection_deleted (mc);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void MacroCollection::on_macro_deleted_here (Macro *macro)
|
||||
{
|
||||
#if defined(HAVE_QT)
|
||||
emit macro_deleted_here (macro);
|
||||
#endif
|
||||
on_macro_deleted (macro);
|
||||
}
|
||||
|
||||
|
|
@ -142,7 +155,9 @@ void MacroCollection::on_macro_deleted (Macro *macro)
|
|||
if (mp_parent) {
|
||||
mp_parent->on_macro_deleted (macro);
|
||||
} else {
|
||||
#if defined(HAVE_QT)
|
||||
emit macro_deleted (macro);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -151,7 +166,9 @@ void MacroCollection::on_macro_changed (Macro *macro)
|
|||
if (mp_parent) {
|
||||
mp_parent->on_macro_changed (macro);
|
||||
} else {
|
||||
#if defined(HAVE_QT)
|
||||
emit macro_changed (macro);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -215,7 +232,7 @@ std::string MacroCollection::path () const
|
|||
if (m_virtual_mode) {
|
||||
return m_path;
|
||||
} else if (mp_parent) {
|
||||
return tl::to_string (QFileInfo (QDir (tl::to_qstring (mp_parent->path ())), tl::to_qstring (m_path)).filePath ());
|
||||
return tl::combine_path (mp_parent->path (), m_path);
|
||||
} else {
|
||||
return m_path;
|
||||
}
|
||||
|
|
@ -245,64 +262,62 @@ MacroCollection::make_readonly (bool f)
|
|||
}
|
||||
|
||||
MacroCollection *
|
||||
MacroCollection::add_folder (const std::string &description, const std::string &path, const std::string &cat, bool readonly, bool force_create)
|
||||
MacroCollection::add_folder (const std::string &description, const std::string &p, const std::string &cat, bool readonly, bool force_create)
|
||||
{
|
||||
if (! path.empty () && path[0] == ':') {
|
||||
if (! p.empty () && p[0] == ':') {
|
||||
|
||||
readonly = true;
|
||||
|
||||
} else {
|
||||
|
||||
QFileInfo file_info (tl::to_qstring (path));
|
||||
std::string fp = p;
|
||||
if (! tl::is_absolute (fp)) {
|
||||
fp = tl::combine_path (path (), fp);
|
||||
}
|
||||
|
||||
if (! file_info.exists ()) {
|
||||
if (! tl::file_exists (fp)) {
|
||||
|
||||
// Try to create the folder since it does not exist yet or skip that one
|
||||
if (! force_create) {
|
||||
|
||||
if (tl::verbosity () >= 20) {
|
||||
tl::log << "Folder does not exist - skipping: " << path;
|
||||
tl::log << "Folder does not exist - skipping: " << fp;
|
||||
}
|
||||
return 0;
|
||||
|
||||
} else {
|
||||
|
||||
if (tl::verbosity () >= 20) {
|
||||
tl::log << "Folder does not exist yet - trying to create it: " << path;
|
||||
tl::log << "Folder does not exist yet - trying to create it: " << fp;
|
||||
}
|
||||
if (! QDir::root ().mkpath (file_info.absoluteFilePath ())) {
|
||||
if (! tl::mkpath (fp)) {
|
||||
if (tl::verbosity () >= 10) {
|
||||
tl::error << "Unable to create folder path: " << path;
|
||||
tl::error << "Unable to create folder path: " << fp;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
file_info.refresh ();
|
||||
|
||||
}
|
||||
|
||||
if (! file_info.isDir ()) {
|
||||
if (! tl::is_dir (fp)) {
|
||||
if (tl::verbosity () >= 10) {
|
||||
tl::error << "Folder is not a directory: " << path;
|
||||
tl::error << "Folder is not a directory: " << fp;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
QString cp = file_info.canonicalFilePath ();
|
||||
if (cp.isEmpty ()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (child_iterator f = m_folders.begin (); f != m_folders.end (); ++f) {
|
||||
// skip, if that folder is in the collection already
|
||||
if (QFileInfo (tl::to_qstring (f->first)).canonicalFilePath () == cp) {
|
||||
if (f->second->path () == fp) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (! readonly && ! file_info.isWritable ()) {
|
||||
if (! readonly && ! tl::is_writable (fp)) {
|
||||
readonly = true;
|
||||
if (tl::verbosity () >= 20) {
|
||||
tl::log << "Folder is read-only: " << path;
|
||||
tl::log << "Folder is read-only: " << fp;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -310,12 +325,12 @@ MacroCollection::add_folder (const std::string &description, const std::string &
|
|||
|
||||
begin_changes ();
|
||||
|
||||
MacroCollection *mc = m_folders.insert (std::make_pair (path, new MacroCollection ())).first->second;
|
||||
mc->set_name (path);
|
||||
MacroCollection *mc = m_folders.insert (std::make_pair (p, new MacroCollection ())).first->second;
|
||||
mc->set_name (p);
|
||||
mc->set_description (description);
|
||||
mc->set_category (cat);
|
||||
mc->set_readonly (readonly);
|
||||
mc->scan (path);
|
||||
mc->scan ();
|
||||
mc->set_parent (this);
|
||||
|
||||
on_changed ();
|
||||
|
|
@ -327,10 +342,11 @@ MacroCollection::add_folder (const std::string &description, const std::string &
|
|||
void MacroCollection::rescan ()
|
||||
{
|
||||
for (std::map <std::string, MacroCollection *>::const_iterator m = m_folders.begin (); m != m_folders.end (); ++m) {
|
||||
m->second->scan (m->first);
|
||||
m->second->scan ();
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
namespace {
|
||||
|
||||
/**
|
||||
|
|
@ -345,168 +361,85 @@ namespace {
|
|||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
void MacroCollection::scan (const std::string &path)
|
||||
void MacroCollection::scan ()
|
||||
{
|
||||
std::string p = path ();
|
||||
|
||||
if (tl::verbosity () >= 20) {
|
||||
tl::info << "Scanning macro path " << path << " (readonly=" << m_readonly << ")";
|
||||
tl::info << "Scanning macro path " << p << " (readonly=" << m_readonly << ")";
|
||||
}
|
||||
|
||||
if (! path.empty () && path[0] == ':') {
|
||||
if (! p.empty () && p[0] == ':') {
|
||||
|
||||
ResourceWithChildren res (tl::to_qstring (path));
|
||||
#if defined(HAVE_QT)
|
||||
|
||||
ResourceWithChildren res (tl::to_qstring (p));
|
||||
QStringList children = res.children ();
|
||||
children.sort ();
|
||||
|
||||
for (QStringList::const_iterator c = children.begin (); c != children.end (); ++c) {
|
||||
for (auto c = children.begin (); c != children.end (); ++c) {
|
||||
|
||||
std::string url = path + "/" + tl::to_string (*c);
|
||||
std::string url = p + "/" + tl::to_string (*c);
|
||||
QResource res (tl::to_qstring (url));
|
||||
if (res.size () > 0) {
|
||||
|
||||
QByteArray data;
|
||||
#if QT_VERSION >= 0x60000
|
||||
if (res.compressionAlgorithm () == QResource::ZlibCompression) {
|
||||
#else
|
||||
if (res.isCompressed ()) {
|
||||
#endif
|
||||
data = qUncompress ((const unsigned char *)res.data (), (int)res.size ());
|
||||
} else {
|
||||
data = QByteArray ((const char *)res.data (), (int)res.size ());
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
Macro::Format format = Macro::NoFormat;
|
||||
Macro::Interpreter interpreter = Macro::None;
|
||||
std::string dsl_name;
|
||||
bool autorun = false;
|
||||
|
||||
if (Macro::format_from_suffix (tl::to_string (*c), interpreter, dsl_name, autorun, format)) {
|
||||
|
||||
std::string n = tl::to_string (QFileInfo (*c).baseName ());
|
||||
|
||||
iterator mm = m_macros.find (n);
|
||||
bool found = false;
|
||||
while (mm != m_macros.end () && mm->first == n && ! found) {
|
||||
if ((interpreter == Macro::None || mm->second->interpreter () == interpreter) &&
|
||||
(dsl_name.empty () || mm->second->dsl_interpreter () == dsl_name) &&
|
||||
mm->second->format () == format) {
|
||||
found = true;
|
||||
}
|
||||
++mm;
|
||||
}
|
||||
if (! found) {
|
||||
Macro *m = m_macros.insert (std::make_pair (n, new Macro ()))->second;
|
||||
m->set_interpreter (interpreter);
|
||||
m->set_autorun_default (autorun);
|
||||
m->set_autorun (autorun);
|
||||
m->set_dsl_interpreter (dsl_name);
|
||||
m->set_format (format);
|
||||
m->set_name (n);
|
||||
m->load_from_string (std::string (data.constData (), data.size ()), url);
|
||||
m->set_readonly (m_readonly);
|
||||
m->reset_modified ();
|
||||
m->set_is_file ();
|
||||
m->set_parent (this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} catch (tl::Exception &ex) {
|
||||
tl::error << "Reading " << url << ": " << ex.msg ();
|
||||
}
|
||||
|
||||
create_entry (url);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
std::vector<std::string> res = tl::find_resources (std::string (p, 1) + "/*");
|
||||
for (auto c = res.begin (); c != res.end (); ++c) {
|
||||
create_entry (":" + *c);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} else {
|
||||
|
||||
QDir dir (tl::to_qstring (path));
|
||||
QStringList filters;
|
||||
filters << QString::fromUtf8 ("*.lym");
|
||||
filters << QString::fromUtf8 ("*.txt");
|
||||
std::set<std::string> suffixes;
|
||||
suffixes.insert ("lym");
|
||||
suffixes.insert ("txt");
|
||||
// TODO: should be either *.rb or *.python, depending on the category.
|
||||
// Right now we rely on the folders not containing foreign files.
|
||||
filters << QString::fromUtf8 ("*.rb");
|
||||
filters << QString::fromUtf8 ("*.py");
|
||||
suffixes.insert ("rb");
|
||||
suffixes.insert ("py");
|
||||
|
||||
// add the suffixes in the DSL interpreter declarations
|
||||
for (tl::Registrar<lym::MacroInterpreter>::iterator cls = tl::Registrar<lym::MacroInterpreter>::begin (); cls != tl::Registrar<lym::MacroInterpreter>::end (); ++cls) {
|
||||
if (! cls->suffix ().empty ()) {
|
||||
filters << tl::to_qstring ("*." + cls->suffix ());
|
||||
suffixes.insert (cls->suffix ());
|
||||
}
|
||||
}
|
||||
|
||||
QStringList files = dir.entryList (filters, QDir::Files);
|
||||
for (QStringList::ConstIterator f = files.begin (); f != files.end (); ++f) {
|
||||
|
||||
std::unique_ptr<lym::Macro> new_macro;
|
||||
|
||||
try {
|
||||
|
||||
std::string n = tl::to_string (QFileInfo (*f).completeBaseName ());
|
||||
std::string mp = tl::to_string (dir.absoluteFilePath (*f));
|
||||
|
||||
Macro::Format format = Macro::NoFormat;
|
||||
Macro::Interpreter interpreter = Macro::None;
|
||||
std::string dsl_name;
|
||||
bool autorun = false;
|
||||
|
||||
if (Macro::format_from_suffix (tl::to_string (*f), interpreter, dsl_name, autorun, format)) {
|
||||
|
||||
iterator mm = m_macros.find (n);
|
||||
bool found = false;
|
||||
while (mm != m_macros.end () && mm->first == n && ! found) {
|
||||
if ((interpreter == Macro::None || mm->second->interpreter () == interpreter) &&
|
||||
(dsl_name.empty () || mm->second->dsl_interpreter () == dsl_name) &&
|
||||
mm->second->format () == format) {
|
||||
found = true;
|
||||
}
|
||||
++mm;
|
||||
}
|
||||
if (! found) {
|
||||
Macro *m = new Macro ();
|
||||
new_macro.reset (m);
|
||||
m->set_format (format);
|
||||
m->set_autorun_default (autorun);
|
||||
m->set_autorun (autorun);
|
||||
m->set_interpreter (interpreter);
|
||||
m->set_dsl_interpreter (dsl_name);
|
||||
m->set_name (n);
|
||||
m->load_from (mp);
|
||||
m->reset_modified ();
|
||||
m->set_readonly (m_readonly);
|
||||
m->set_parent (this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (new_macro.get ()) {
|
||||
m_macros.insert (std::make_pair (n, new_macro.release ()));
|
||||
}
|
||||
|
||||
} catch (tl::Exception &ex) {
|
||||
tl::error << "Reading " << tl::to_string (*f) << " in " << path << ": " << ex.msg ();
|
||||
std::vector<std::string> files = tl::dir_entries (p, true /*with_files*/, false /*with_dirs*/, true /*without_dotfiles*/);
|
||||
for (auto f = files.begin (); f != files.end (); ++f) {
|
||||
if (suffixes.find (tl::extension (*f)) != suffixes.end ()) {
|
||||
create_entry (tl::combine_path (p, *f));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
QStringList folders = dir.entryList (QDir::Dirs | QDir::NoDotAndDotDot);
|
||||
for (QStringList::ConstIterator f = folders.begin (); f != folders.end (); ++f) {
|
||||
std::vector<std::string> dirs = tl::dir_entries (p, false /*with_files*/, true /*with_dirs*/, true /*without_dotfiles*/);
|
||||
for (auto f = files.begin (); f != files.end (); ++f) {
|
||||
|
||||
std::string fp = tl::combine_path (p, *f);
|
||||
if (! tl::is_dir (fp)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
std::string n = tl::to_string (*f);
|
||||
MacroCollection *&mc = m_folders.insert (std::make_pair (n, (MacroCollection *) 0)).first->second;
|
||||
MacroCollection *&mc = m_folders.insert (std::make_pair (*f, (MacroCollection *) 0)).first->second;
|
||||
if (! mc) {
|
||||
mc = new MacroCollection ();
|
||||
mc->set_name (n);
|
||||
mc->set_name (*f);
|
||||
mc->set_virtual_mode (NotVirtual);
|
||||
bool ro = (m_readonly || ! QFileInfo (dir.filePath (*f)).isWritable ());
|
||||
bool ro = (m_readonly || ! tl::is_writable (fp));
|
||||
mc->set_readonly (ro);
|
||||
mc->scan (tl::to_string (dir.filePath (*f)));
|
||||
mc->scan ();
|
||||
mc->set_parent (this);
|
||||
}
|
||||
|
||||
|
|
@ -519,6 +452,59 @@ void MacroCollection::scan (const std::string &path)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
MacroCollection::create_entry (const std::string &path)
|
||||
{
|
||||
try {
|
||||
|
||||
std::string n = tl::complete_basename (path);
|
||||
|
||||
Macro::Format format = Macro::NoFormat;
|
||||
Macro::Interpreter interpreter = Macro::None;
|
||||
std::string dsl_name;
|
||||
bool autorun = false;
|
||||
|
||||
std::unique_ptr<lym::Macro> new_macro;
|
||||
|
||||
if (Macro::format_from_suffix (path, interpreter, dsl_name, autorun, format)) {
|
||||
|
||||
iterator mm = m_macros.find (n);
|
||||
bool found = false;
|
||||
while (mm != m_macros.end () && mm->first == n && ! found) {
|
||||
if ((interpreter == Macro::None || mm->second->interpreter () == interpreter) &&
|
||||
(dsl_name.empty () || mm->second->dsl_interpreter () == dsl_name) &&
|
||||
mm->second->format () == format) {
|
||||
found = true;
|
||||
}
|
||||
++mm;
|
||||
}
|
||||
if (! found) {
|
||||
Macro *m = new Macro ();
|
||||
new_macro.reset (m);
|
||||
m->set_interpreter (interpreter);
|
||||
m->set_autorun_default (autorun);
|
||||
m->set_autorun (autorun);
|
||||
m->set_dsl_interpreter (dsl_name);
|
||||
m->set_format (format);
|
||||
m->set_name (n);
|
||||
m->load_from (path);
|
||||
m->set_readonly (m_readonly);
|
||||
m->reset_modified ();
|
||||
m->set_is_file ();
|
||||
m->set_parent (this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (new_macro.get ()) {
|
||||
m_macros.insert (std::make_pair (n, new_macro.release ()));
|
||||
}
|
||||
|
||||
} catch (tl::Exception &ex) {
|
||||
tl::error << "Reading " << path << ": " << ex.msg ();
|
||||
}
|
||||
}
|
||||
|
||||
void MacroCollection::clear ()
|
||||
{
|
||||
begin_changes ();
|
||||
|
|
@ -594,9 +580,8 @@ bool MacroCollection::rename (const std::string &n)
|
|||
if (tl::verbosity () >= 20) {
|
||||
tl::info << "Renaming macro folder " << path () << " to " << n;
|
||||
}
|
||||
QFile f (tl::to_qstring (path ()));
|
||||
begin_changes ();
|
||||
if (! f.rename (QFileInfo (QDir (tl::to_qstring (mp_parent->path ())), tl::to_qstring (n)).filePath ())) {
|
||||
if (! tl::rename_file (path (), n)) {
|
||||
on_changed ();
|
||||
return false;
|
||||
} else {
|
||||
|
|
@ -621,7 +606,7 @@ lym::MacroCollection *MacroCollection::create_folder (const char *prefix, bool m
|
|||
++n;
|
||||
} while (true);
|
||||
|
||||
if (mkdir && ! QDir (tl::to_qstring (path ())).mkdir (tl::to_qstring (name))) {
|
||||
if (mkdir && ! tl::mkpath (tl::combine_path (path (), name))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -673,8 +658,8 @@ void MacroCollection::add_unspecific (lym::Macro *m)
|
|||
|
||||
bool MacroCollection::add (lym::Macro *m)
|
||||
{
|
||||
QDir d (tl::to_qstring (path ()));
|
||||
QDir dd = QFileInfo (tl::to_qstring (m->path ())).dir ();
|
||||
std::string d = tl::normalize_path (path ());
|
||||
std::string dd = tl::normalize_path (m->dir ());
|
||||
|
||||
if (d == dd) {
|
||||
|
||||
|
|
@ -694,21 +679,26 @@ bool MacroCollection::add (lym::Macro *m)
|
|||
|
||||
// try to detect new child folders. If that is the case, create that folder and add
|
||||
// the macro there.
|
||||
QDir dm (tl::to_qstring (m->dir ()));
|
||||
std::string dm = tl::normalize_path (m->dir ());
|
||||
while (true) {
|
||||
|
||||
std::string folder_name = tl::to_string (dm.dirName ());
|
||||
if (! dm.cdUp ()) {
|
||||
std::string folder_name = tl::filename (dm);
|
||||
dm = tl::dirname (dm);
|
||||
if (dm.empty () || dm == ".") {
|
||||
break;
|
||||
}
|
||||
|
||||
if (dm == d) {
|
||||
|
||||
begin_changes ();
|
||||
lym::MacroCollection *mc = m_folders.insert (std::make_pair (folder_name, new MacroCollection ())).first->second;
|
||||
mc->set_virtual_mode (NotVirtual);
|
||||
mc->set_name (folder_name);
|
||||
mc->set_parent (this);
|
||||
on_changed ();
|
||||
|
||||
return mc->add (m);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -723,7 +713,7 @@ bool MacroCollection::del ()
|
|||
if (tl::verbosity () >= 20) {
|
||||
tl::info << "Deleting macro folder " << path ();
|
||||
}
|
||||
return QDir ().rmdir (tl::to_qstring (path ()));
|
||||
return tl::rm_dir_recursive (path ());
|
||||
}
|
||||
|
||||
void MacroCollection::rename_macro (Macro *macro, const std::string &new_name)
|
||||
|
|
@ -984,4 +974,3 @@ void MacroCollection::dump (int l)
|
|||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -27,13 +27,13 @@
|
|||
#include "lymCommon.h"
|
||||
#include "lymMacro.h"
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include <QObject>
|
||||
#if defined(HAVE_QT)
|
||||
# include <QObject>
|
||||
#endif
|
||||
|
||||
namespace lym
|
||||
{
|
||||
|
|
@ -45,9 +45,13 @@ namespace lym
|
|||
* a folder containing *.lym, *.rb or other script files.
|
||||
*/
|
||||
class LYM_PUBLIC MacroCollection
|
||||
#if defined(HAVE_QT)
|
||||
: public QObject
|
||||
#endif
|
||||
{
|
||||
#if defined(HAVE_QT)
|
||||
Q_OBJECT
|
||||
#endif
|
||||
|
||||
public:
|
||||
typedef std::multimap <std::string, Macro *>::iterator iterator;
|
||||
|
|
@ -334,6 +338,11 @@ public:
|
|||
|
||||
/**
|
||||
* @brief Gets the begin iterator of the folders
|
||||
*
|
||||
* The iterator will deliver a pair of a string and a MacroCollection object.
|
||||
* The string is the absolute path of the child folder. Child folders do not
|
||||
* necessarily live inside the directory of the parent folder. Specifically for
|
||||
* the root folder, children with any kind of paths may be present.
|
||||
*/
|
||||
child_iterator begin_children ()
|
||||
{
|
||||
|
|
@ -382,6 +391,7 @@ public:
|
|||
* @brief Gets a folder by name
|
||||
*
|
||||
* If no folder with that name exists, this method will return 0.
|
||||
* The name is either relative to the folders path or it is an absolute path.
|
||||
*/
|
||||
MacroCollection *folder_by_name (const std::string &name);
|
||||
|
||||
|
|
@ -389,6 +399,7 @@ public:
|
|||
* @brief Gets a folder by name
|
||||
*
|
||||
* If no folder with that name exists, this method will return 0.
|
||||
* The name is either relative to the folders path or it is an absolute path.
|
||||
*/
|
||||
const MacroCollection *folder_by_name (const std::string &name) const;
|
||||
|
||||
|
|
@ -445,6 +456,7 @@ public:
|
|||
*/
|
||||
void dump (int l = 0);
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
signals:
|
||||
/**
|
||||
* @brief This signal is sent when the collection changes
|
||||
|
|
@ -496,6 +508,7 @@ signals:
|
|||
* @brief This signal is emitted from the collection root if the menu needs to be updated
|
||||
*/
|
||||
void menu_needs_update ();
|
||||
#endif
|
||||
|
||||
private:
|
||||
friend class Macro;
|
||||
|
|
@ -518,10 +531,8 @@ private:
|
|||
void on_changed ();
|
||||
void on_menu_needs_update ();
|
||||
|
||||
/**
|
||||
* @brief Scans a folder creating the macro collection
|
||||
*/
|
||||
void scan (const std::string &path);
|
||||
void scan ();
|
||||
void create_entry (const std::string &path);
|
||||
|
||||
void rename_macro (Macro *macro, const std::string &new_name);
|
||||
|
||||
|
|
@ -551,44 +562,5 @@ private:
|
|||
|
||||
}
|
||||
|
||||
#else // without QT:
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace lym
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Dummy implementation for Qt-less builds.
|
||||
*
|
||||
* This dummy implementation does not provide any services but acts as a dummy anchor
|
||||
* for lym::Macro.
|
||||
*
|
||||
* Without Qt, the MacroCollection does not make much sense as there is no
|
||||
* application specific file system without an Application object.
|
||||
*/
|
||||
class LYM_PUBLIC MacroCollection
|
||||
{
|
||||
public:
|
||||
MacroCollection ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
std::string path () const
|
||||
{
|
||||
return std::string ();
|
||||
}
|
||||
|
||||
void rename_macro (lym::Macro *, const std::string &)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -314,6 +314,17 @@ std::string basename (const std::string &s)
|
|||
}
|
||||
}
|
||||
|
||||
std::string complete_basename (const std::string &s)
|
||||
{
|
||||
std::vector<std::string> fnp = split_filename (filename (s));
|
||||
if (fnp.size () > 0) {
|
||||
fnp.pop_back ();
|
||||
return tl::join (fnp, ".");
|
||||
} else {
|
||||
return std::string ();
|
||||
}
|
||||
}
|
||||
|
||||
std::string extension (const std::string &s)
|
||||
{
|
||||
std::vector<std::string> fnp = split_filename (filename (s));
|
||||
|
|
|
|||
|
|
@ -85,6 +85,12 @@ std::string TL_PUBLIC filename (const std::string &s);
|
|||
*/
|
||||
std::string TL_PUBLIC basename (const std::string &s);
|
||||
|
||||
/**
|
||||
* @brief Gets the basename for a given file path (file name without the last extensions)
|
||||
* This will strip all extensions (i.e. "archive.tar.gz" will become "archive.tar").
|
||||
*/
|
||||
std::string TL_PUBLIC complete_basename (const std::string &s);
|
||||
|
||||
/**
|
||||
* @brief Gets the complete extension for a given file path
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
*/
|
||||
|
||||
#include "tlResources.h"
|
||||
#include "tlGlobPattern.h"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
|
@ -35,17 +36,21 @@ class ResourceDict
|
|||
public:
|
||||
struct DictEntry
|
||||
{
|
||||
std::string name;
|
||||
const unsigned char *data;
|
||||
size_t data_size;
|
||||
bool compressed;
|
||||
};
|
||||
|
||||
typedef std::vector<DictEntry>::const_iterator iterator;
|
||||
|
||||
ResourceDict () { }
|
||||
|
||||
resource_id_type add (const char *name, bool compressed, const unsigned char *data, size_t data_size)
|
||||
{
|
||||
m_dict[std::string (name)] = m_entries.size ();
|
||||
m_entries.push_back (DictEntry ());
|
||||
m_entries.back ().name = name;
|
||||
m_entries.back ().data = data;
|
||||
m_entries.back ().data_size = data_size;
|
||||
m_entries.back ().compressed = compressed;
|
||||
|
|
@ -55,6 +60,7 @@ public:
|
|||
void remove (resource_id_type id)
|
||||
{
|
||||
if (id < m_entries.size ()) {
|
||||
m_entries [id].name.clear ();
|
||||
m_entries [id].data = 0;
|
||||
m_entries [id].data_size = 0;
|
||||
}
|
||||
|
|
@ -70,6 +76,16 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
iterator begin ()
|
||||
{
|
||||
return m_entries.begin ();
|
||||
}
|
||||
|
||||
iterator end ()
|
||||
{
|
||||
return m_entries.end ();
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<std::string, resource_id_type> m_dict;
|
||||
std::vector<DictEntry> m_entries;
|
||||
|
|
@ -94,15 +110,15 @@ void unregister_resource (size_t id)
|
|||
}
|
||||
}
|
||||
|
||||
tl::InputStream *get_resource (const char *name)
|
||||
std::pair<tl::InputStreamBase *, bool> get_resource_reader (const char *name)
|
||||
{
|
||||
if (! ms_dict) {
|
||||
return 0;
|
||||
return std::pair<tl::InputStreamBase *, bool> (0, false);
|
||||
}
|
||||
|
||||
ResourceDict::DictEntry *entry = ms_dict->entry (name);
|
||||
if (! entry || ! entry->data) {
|
||||
return 0;
|
||||
return std::pair<tl::InputStreamBase *, bool> (0, false);
|
||||
}
|
||||
|
||||
if (entry->compressed) {
|
||||
|
|
@ -111,16 +127,48 @@ tl::InputStream *get_resource (const char *name)
|
|||
|
||||
// NOTE: zlib compression (used in pyqrc) adds two bytes header before the data block and
|
||||
// 4 bytes after (CRC32)
|
||||
auto stream = new tl::InputStream (new tl::InputMemoryStream ((const char *) entry->data + 2, entry->data_size - 6));
|
||||
stream->inflate ();
|
||||
return stream;
|
||||
return std::make_pair (new tl::InputMemoryStream ((const char *) entry->data + 2, entry->data_size - 6), true);
|
||||
|
||||
} else {
|
||||
|
||||
// raw data
|
||||
return new tl::InputStream (new tl::InputMemoryStream ((const char *) entry->data, entry->data_size));
|
||||
return std::make_pair (new tl::InputMemoryStream ((const char *) entry->data, entry->data_size), false);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
tl::InputStream *get_resource (const char *name)
|
||||
{
|
||||
std::pair<tl::InputStreamBase *, bool> rr = get_resource_reader (name);
|
||||
if (! rr.first) {
|
||||
return 0;
|
||||
} else {
|
||||
auto stream = new tl::InputStream (rr.first);
|
||||
if (rr.second) {
|
||||
stream->inflate ();
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string>
|
||||
find_resources (const std::string &pattern)
|
||||
{
|
||||
if (! ms_dict) {
|
||||
return std::vector<std::string> ();
|
||||
}
|
||||
|
||||
std::vector<std::string> res;
|
||||
tl::GlobPattern p (pattern);
|
||||
|
||||
for (ResourceDict::iterator i = ms_dict->begin (); i != ms_dict->end (); ++i) {
|
||||
if (i->data && p.match (i->name)) {
|
||||
res.push_back (i->name);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,6 +68,24 @@ TL_PUBLIC void unregister_resource (size_t id);
|
|||
*/
|
||||
TL_PUBLIC tl::InputStream *get_resource (const char *name);
|
||||
|
||||
/**
|
||||
* @brief Gets the resource data as a stream reader delegate plus compressed flag
|
||||
*
|
||||
* @param name The resource name
|
||||
* @return A pair of reader delegate and a flag indicating whether the stream is compressed.
|
||||
* If the resource is not found, the reade delegate is 0.
|
||||
* It is the responsibility of the called to delete the reader delegate.
|
||||
*/
|
||||
TL_PUBLIC std::pair<tl::InputStreamBase *, bool> get_resource_reader (const char *name);
|
||||
|
||||
/**
|
||||
* @brief Get resource names matching a glob pattern
|
||||
*
|
||||
* For example, find_resources("/group/*") will find resources below "group".
|
||||
* "*" also matches "/", so resources from subgroups will be listed too.
|
||||
*/
|
||||
TL_PUBLIC std::vector<std::string> find_resources (const std::string &pattern);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -166,6 +166,8 @@ InputStream::InputStream (const std::string &abstract_path)
|
|||
m_blen = 0;
|
||||
mp_buffer = 0;
|
||||
|
||||
bool needs_inflate = false;
|
||||
|
||||
tl::Extractor ex (abstract_path.c_str ());
|
||||
|
||||
if (ex.test (":")) {
|
||||
|
|
@ -197,13 +199,13 @@ InputStream::InputStream (const std::string &abstract_path)
|
|||
|
||||
#else
|
||||
|
||||
tl::InputStream *stream = tl::get_resource (ex.get ());
|
||||
if (! stream) {
|
||||
std::pair<tl::InputStreamBase *, bool> rr = tl::get_resource_reader (ex.get ());
|
||||
if (! rr.first) {
|
||||
throw tl::Exception (tl::to_string (tr ("Resource not found: ")) + abstract_path);
|
||||
}
|
||||
|
||||
swap (*stream);
|
||||
delete stream;
|
||||
mp_delegate = rr.first;
|
||||
needs_inflate = rr.second;
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -236,6 +238,10 @@ InputStream::InputStream (const std::string &abstract_path)
|
|||
}
|
||||
|
||||
m_owns_delegate = true;
|
||||
|
||||
if (needs_inflate) {
|
||||
inflate ();
|
||||
}
|
||||
}
|
||||
|
||||
InputStream::~InputStream ()
|
||||
|
|
@ -279,19 +285,6 @@ std::string InputStream::absolute_path (const std::string &abstract_path)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
InputStream::swap (InputStream &other)
|
||||
{
|
||||
std::swap (m_pos, other.m_pos);
|
||||
std::swap (mp_buffer, other.mp_buffer);
|
||||
std::swap (m_bcap, other.m_bcap);
|
||||
std::swap (m_blen, other.m_blen);
|
||||
std::swap (mp_bptr, other.mp_bptr);
|
||||
std::swap (mp_delegate, other.mp_delegate);
|
||||
std::swap (m_owns_delegate, other.m_owns_delegate);
|
||||
std::swap (mp_inflate, other.mp_inflate);
|
||||
}
|
||||
|
||||
const char *
|
||||
InputStream::get (size_t n, bool bypass_inflate)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -540,11 +540,6 @@ public:
|
|||
return mp_delegate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Swaps two streams
|
||||
*/
|
||||
void swap (InputStream &other);
|
||||
|
||||
protected:
|
||||
void reset_pos ()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "tlCommandLineParser.h"
|
||||
#include "tlFileUtils.h"
|
||||
#include "tlGlobPattern.h"
|
||||
#include "lymMacroCollection.h"
|
||||
#include "rba.h"
|
||||
#include "pya.h"
|
||||
#include "gsiDecl.h"
|
||||
|
|
@ -66,9 +67,9 @@
|
|||
// (some in non-Qt case)
|
||||
#include "libForceLink.h"
|
||||
#include "rdbForceLink.h"
|
||||
#if defined(HAVE_RUBY) && defined(HAVE_QT)
|
||||
#include "drcForceLink.h"
|
||||
#include "lvsForceLink.h"
|
||||
#if defined(HAVE_RUBY)
|
||||
# include "drcForceLink.h"
|
||||
# include "lvsForceLink.h"
|
||||
#endif
|
||||
|
||||
static int main_cont (int &argc, char **argv);
|
||||
|
|
@ -530,6 +531,13 @@ main_cont (int &argc, char **argv)
|
|||
python_interpreter.reset (new pya::PythonInterpreter ());
|
||||
python_interpreter->push_console (&console);
|
||||
|
||||
lym::MacroCollection &lym_root = lym::MacroCollection::root ();
|
||||
lym_root.add_folder (tl::to_string (tr ("Built-In")), ":/built-in-macros", "macros", true);
|
||||
lym_root.add_folder (tl::to_string (tr ("Built-In")), ":/built-in-pymacros", "pymacros", true);
|
||||
|
||||
lym_root.autorun_early ();
|
||||
lym_root.autorun ();
|
||||
|
||||
#endif
|
||||
|
||||
bool editable = false, non_editable = false;
|
||||
|
|
|
|||
|
|
@ -29,13 +29,11 @@ equals(HAVE_PYTHON, "1") {
|
|||
LIBS += -lklayout_pyastub
|
||||
}
|
||||
|
||||
!equals(HAVE_QT, "0") {
|
||||
equals(HAVE_RUBY, "1") {
|
||||
# DRC is only available with Ruby
|
||||
INCLUDEPATH += $$DRC_INC $$LVS_INC
|
||||
DEPENDPATH += $$DRC_INC $$LVS_INC
|
||||
LIBS += -lklayout_drc -lklayout_lvs
|
||||
}
|
||||
equals(HAVE_RUBY, "1") {
|
||||
# DRC is only available with Ruby
|
||||
INCLUDEPATH += $$DRC_INC $$LVS_INC
|
||||
DEPENDPATH += $$DRC_INC $$LVS_INC
|
||||
LIBS += -lklayout_drc -lklayout_lvs
|
||||
}
|
||||
|
||||
msvc {
|
||||
|
|
|
|||
Loading…
Reference in New Issue