mirror of
https://github.com/KLayout/klayout.git
synced 2026-08-22 05:57:41 +02:00
WIP: Library controller plus a bugfix
The bug was that a crash happened when a package was deleted. Essentially that was an effect of too many message boxes asking to run autorun macros (also a bug - solved by deferred execution of the macro update). This is solved by putting the salt model into a "under construction" state while the model is not updated yet.
This commit is contained in:
+4
-2
@@ -57,7 +57,8 @@ HEADERS = \
|
|||||||
laySaltDownloadManager.h \
|
laySaltDownloadManager.h \
|
||||||
laySaltModel.h \
|
laySaltModel.h \
|
||||||
laySaltController.h \
|
laySaltController.h \
|
||||||
laySignalHandler.h
|
laySignalHandler.h \
|
||||||
|
layLibraryController.h
|
||||||
|
|
||||||
FORMS = \
|
FORMS = \
|
||||||
ClipDialog.ui \
|
ClipDialog.ui \
|
||||||
@@ -160,7 +161,8 @@ SOURCES = \
|
|||||||
laySaltDownloadManager.cc \
|
laySaltDownloadManager.cc \
|
||||||
laySaltModel.cc \
|
laySaltModel.cc \
|
||||||
laySaltController.cc \
|
laySaltController.cc \
|
||||||
laySignalHandler.cc
|
laySignalHandler.cc \
|
||||||
|
layLibraryController.cc
|
||||||
|
|
||||||
RESOURCES = layBuildInMacros.qrc \
|
RESOURCES = layBuildInMacros.qrc \
|
||||||
layHelpResources.qrc \
|
layHelpResources.qrc \
|
||||||
|
|||||||
@@ -1055,48 +1055,6 @@ Application::run ()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// scan for libraries
|
|
||||||
for (std::vector <std::string>::const_iterator p = m_klayout_path.begin (); p != m_klayout_path.end (); ++p) {
|
|
||||||
|
|
||||||
QDir lp = QDir (tl::to_qstring (*p)).filePath (tl::to_qstring ("libraries"));
|
|
||||||
|
|
||||||
QStringList name_filters;
|
|
||||||
name_filters << QString::fromUtf8 ("*");
|
|
||||||
|
|
||||||
QStringList libs = lp.entryList (name_filters, QDir::Files);
|
|
||||||
for (QStringList::const_iterator im = libs.begin (); im != libs.end (); ++im) {
|
|
||||||
|
|
||||||
std::string filename = tl::to_string (*im);
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
std::auto_ptr<db::Library> lib (new db::Library ());
|
|
||||||
lib->set_description (filename);
|
|
||||||
lib->set_name (tl::to_string (QFileInfo (*im).baseName ()));
|
|
||||||
|
|
||||||
tl::log << "Reading library '" << filename << "'";
|
|
||||||
tl::InputStream stream (tl::to_string (lp.filePath (*im)));
|
|
||||||
db::Reader reader (stream);
|
|
||||||
reader.read (lib->layout ());
|
|
||||||
|
|
||||||
// Use the libname if there is one
|
|
||||||
for (db::Layout::meta_info_iterator m = lib->layout ().begin_meta (); m != lib->layout ().end_meta (); ++m) {
|
|
||||||
if (m->name == "libname" && ! m->value.empty ()) {
|
|
||||||
lib->set_name (m->value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
db::LibraryManager::instance ().register_lib (lib.release ());
|
|
||||||
|
|
||||||
} catch (tl::Exception &ex) {
|
|
||||||
tl::error << ex.msg ();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// run all autorun macros
|
// run all autorun macros
|
||||||
lay::MacroCollection::root ().autorun ();
|
lay::MacroCollection::root ().autorun ();
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,261 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
KLayout Layout Viewer
|
||||||
|
Copyright (C) 2006-2017 Matthias Koefferlein
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "layLibraryController.h"
|
||||||
|
#include "layApplication.h"
|
||||||
|
#include "laySaltController.h"
|
||||||
|
#include "layConfig.h"
|
||||||
|
#include "layMainWindow.h"
|
||||||
|
#include "layQtTools.h"
|
||||||
|
#include "dbLibraryManager.h"
|
||||||
|
#include "dbLibrary.h"
|
||||||
|
#include "dbReader.h"
|
||||||
|
#include "tlLog.h"
|
||||||
|
#include "tlStream.h"
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
|
||||||
|
namespace lay
|
||||||
|
{
|
||||||
|
|
||||||
|
LibraryController::LibraryController ()
|
||||||
|
: m_file_watcher (0),
|
||||||
|
dm_sync_files (this, &LibraryController::sync_files)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LibraryController::initialize (lay::PluginRoot * /*root*/)
|
||||||
|
{
|
||||||
|
// NOTE: we initialize the libraries in the stage once to have them available for the autorun
|
||||||
|
// macros. We'll do that later again in order to pull in the libraries from the packages.
|
||||||
|
sync_files ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LibraryController::initialized (lay::PluginRoot * /*root*/)
|
||||||
|
{
|
||||||
|
if (lay::SaltController::instance ()) {
|
||||||
|
connect (lay::SaltController::instance (), SIGNAL (salt_changed ()), this, SLOT (sync_with_external_sources ()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! m_file_watcher) {
|
||||||
|
m_file_watcher = new tl::FileSystemWatcher (this);
|
||||||
|
connect (m_file_watcher, SIGNAL (fileChanged (const QString &)), this, SLOT (file_watcher_triggered ()));
|
||||||
|
connect (m_file_watcher, SIGNAL (fileRemoved (const QString &)), this, SLOT (file_watcher_triggered ()));
|
||||||
|
}
|
||||||
|
|
||||||
|
sync_files ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LibraryController::uninitialize (lay::PluginRoot * /*root*/)
|
||||||
|
{
|
||||||
|
if (m_file_watcher) {
|
||||||
|
disconnect (m_file_watcher, SIGNAL (fileChanged (const QString &)), this, SLOT (file_watcher_triggered ()));
|
||||||
|
disconnect (m_file_watcher, SIGNAL (fileRemoved (const QString &)), this, SLOT (file_watcher_triggered ()));
|
||||||
|
delete m_file_watcher;
|
||||||
|
m_file_watcher = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lay::SaltController::instance ()) {
|
||||||
|
disconnect (lay::SaltController::instance (), SIGNAL (salt_changed ()), this, SLOT (sync_with_external_sources ()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LibraryController::get_options (std::vector < std::pair<std::string, std::string> > & /*options*/) const
|
||||||
|
{
|
||||||
|
// .. nothing yet ..
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LibraryController::get_menu_entries (std::vector<lay::MenuEntry> & /*menu_entries*/) const
|
||||||
|
{
|
||||||
|
// .. nothing yet ..
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
LibraryController::configure (const std::string & /*name*/, const std::string & /*value*/)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LibraryController::config_finalize()
|
||||||
|
{
|
||||||
|
// .. nothing yet ..
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
LibraryController::can_exit (lay::PluginRoot * /*root*/) const
|
||||||
|
{
|
||||||
|
// .. nothing yet ..
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LibraryController::sync_files ()
|
||||||
|
{
|
||||||
|
if (! m_file_watcher) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_file_watcher->clear ();
|
||||||
|
m_file_watcher->enable (false);
|
||||||
|
|
||||||
|
std::map<std::string, std::pair<std::string, QDateTime> > new_lib_files;
|
||||||
|
|
||||||
|
std::vector<std::string> paths = lay::Application::instance ()->klayout_path ();
|
||||||
|
|
||||||
|
// add the salt grains as potential sources for library definitions
|
||||||
|
|
||||||
|
lay::SaltController *sc = lay::SaltController::instance ();
|
||||||
|
if (sc) {
|
||||||
|
for (lay::Salt::flat_iterator g = sc->salt ().begin_flat (); g != sc->salt ().end_flat (); ++g) {
|
||||||
|
paths.push_back ((*g)->path ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// scan for libraries
|
||||||
|
|
||||||
|
for (std::vector <std::string>::const_iterator p = paths.begin (); p != paths.end (); ++p) {
|
||||||
|
|
||||||
|
QDir lp = QDir (tl::to_qstring (*p)).filePath (tl::to_qstring ("libraries"));
|
||||||
|
m_file_watcher->add_file (tl::to_string (lp.absolutePath ()));
|
||||||
|
|
||||||
|
QStringList name_filters;
|
||||||
|
name_filters << QString::fromUtf8 ("*");
|
||||||
|
|
||||||
|
QStringList libs = lp.entryList (name_filters, QDir::Files);
|
||||||
|
for (QStringList::const_iterator im = libs.begin (); im != libs.end (); ++im) {
|
||||||
|
|
||||||
|
std::string filename = tl::to_string (*im);
|
||||||
|
std::string lib_path = tl::to_string (lp.absoluteFilePath (*im));
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
QFileInfo fi (tl::to_qstring (lib_path));
|
||||||
|
|
||||||
|
bool needs_load = false;
|
||||||
|
std::map<std::string, std::pair<std::string, QDateTime> >::iterator ll = m_lib_files.find (lib_path);
|
||||||
|
if (ll == m_lib_files.end ()) {
|
||||||
|
needs_load = true;
|
||||||
|
} else {
|
||||||
|
if (fi.lastModified () > ll->second.second) {
|
||||||
|
needs_load = true;
|
||||||
|
} else {
|
||||||
|
new_lib_files.insert (*ll);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needs_load) {
|
||||||
|
|
||||||
|
std::auto_ptr<db::Library> lib (new db::Library ());
|
||||||
|
lib->set_description (filename);
|
||||||
|
lib->set_name (tl::to_string (QFileInfo (*im).baseName ()));
|
||||||
|
|
||||||
|
tl::log << "Reading library '" << filename << "'";
|
||||||
|
tl::InputStream stream (lib_path);
|
||||||
|
db::Reader reader (stream);
|
||||||
|
reader.read (lib->layout ());
|
||||||
|
|
||||||
|
// Use the libname if there is one
|
||||||
|
for (db::Layout::meta_info_iterator m = lib->layout ().begin_meta (); m != lib->layout ().end_meta (); ++m) {
|
||||||
|
if (m->name == "libname" && ! m->value.empty ()) {
|
||||||
|
lib->set_name (m->value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
new_lib_files.insert (std::make_pair (lib_path, std::make_pair (lib->get_name (), fi.lastModified ())));
|
||||||
|
|
||||||
|
db::LibraryManager::instance ().register_lib (lib.release ());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (tl::Exception &ex) {
|
||||||
|
tl::error << ex.msg ();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
m_file_watcher->enable (true);
|
||||||
|
|
||||||
|
// remove libraries which are no longer present
|
||||||
|
|
||||||
|
std::set<std::string> new_names;
|
||||||
|
|
||||||
|
for (std::map<std::string, std::pair<std::string, QDateTime> >::const_iterator lf = new_lib_files.begin (); lf != new_lib_files.end (); ++lf) {
|
||||||
|
new_names.insert (lf->second.first);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::map<std::string, std::pair<std::string, QDateTime> >::const_iterator lf = m_lib_files.begin (); lf != m_lib_files.end (); ++lf) {
|
||||||
|
if (new_names.find (lf->second.first) == new_names.end ()) {
|
||||||
|
try {
|
||||||
|
std::pair<bool, db::lib_id_type> li = db::LibraryManager::instance ().lib_by_name (lf->second.first);
|
||||||
|
if (li.first) {
|
||||||
|
db::LibraryManager::instance ().delete_lib (db::LibraryManager::instance ().lib (li.second));
|
||||||
|
}
|
||||||
|
} catch (...) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// establish the new libraries
|
||||||
|
|
||||||
|
m_lib_files = new_lib_files;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LibraryController::sync_with_external_sources ()
|
||||||
|
{
|
||||||
|
tl::log << tl::to_string (tr ("Package updates - updating libraries"));
|
||||||
|
dm_sync_files ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LibraryController::file_watcher_triggered ()
|
||||||
|
{
|
||||||
|
tl::log << tl::to_string (tr ("Detected file system change in libraries - updating"));
|
||||||
|
dm_sync_files ();
|
||||||
|
}
|
||||||
|
|
||||||
|
LibraryController *
|
||||||
|
LibraryController::instance ()
|
||||||
|
{
|
||||||
|
for (tl::Registrar<lay::PluginDeclaration>::iterator cls = tl::Registrar<lay::PluginDeclaration>::begin (); cls != tl::Registrar<lay::PluginDeclaration>::end (); ++cls) {
|
||||||
|
LibraryController *sc = dynamic_cast <LibraryController *> (cls.operator-> ());
|
||||||
|
if (sc) {
|
||||||
|
return sc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The singleton instance of the library controller
|
||||||
|
static tl::RegisteredClass<lay::PluginDeclaration> salt_controller_decl (new lay::LibraryController (), 150, "LibraryController");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,132 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
KLayout Layout Viewer
|
||||||
|
Copyright (C) 2006-2017 Matthias Koefferlein
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef HDR_layLibraryController
|
||||||
|
#define HDR_layLibraryController
|
||||||
|
|
||||||
|
#include "layCommon.h"
|
||||||
|
#include "layPlugin.h"
|
||||||
|
#include "tlFileSystemWatcher.h"
|
||||||
|
#include "tlDeferredExecution.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
namespace lay
|
||||||
|
{
|
||||||
|
|
||||||
|
class LibraryManagerDialog;
|
||||||
|
class MainWindow;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A controller for the libraries
|
||||||
|
*
|
||||||
|
* This object is a singleton that acts as a controller
|
||||||
|
* for the library management. The controller is responsible
|
||||||
|
* to managing the libraries and notifying library consumers
|
||||||
|
* of changes.
|
||||||
|
*
|
||||||
|
* By making the controller a PluginDeclaration it will receive
|
||||||
|
* initialization and configuration calls.
|
||||||
|
*/
|
||||||
|
class LibraryController
|
||||||
|
: public lay::PluginDeclaration, public tl::Object
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Default constructor
|
||||||
|
*/
|
||||||
|
LibraryController ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reimplementation of the PluginDeclaration interface
|
||||||
|
*/
|
||||||
|
virtual void initialize (lay::PluginRoot *root);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reimplementation of the PluginDeclaration interface
|
||||||
|
*/
|
||||||
|
virtual void initialized (lay::PluginRoot *root);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reimplementation of the PluginDeclaration interface
|
||||||
|
*/
|
||||||
|
virtual void uninitialize (lay::PluginRoot *root);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reimplementation of the PluginDeclaration interface
|
||||||
|
*/
|
||||||
|
void get_options (std::vector < std::pair<std::string, std::string> > &options) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reimplementation of the PluginDeclaration interface
|
||||||
|
*/
|
||||||
|
void get_menu_entries (std::vector<lay::MenuEntry> &menu_entries) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reimplementation of the PluginDeclaration interface
|
||||||
|
*/
|
||||||
|
bool configure (const std::string &key, const std::string &value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reimplementation of the PluginDeclaration interface
|
||||||
|
*/
|
||||||
|
void config_finalize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reimplementation of the PluginDeclaration interface
|
||||||
|
*/
|
||||||
|
bool can_exit (lay::PluginRoot *root) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the singleton instance for this object
|
||||||
|
*/
|
||||||
|
static LibraryController *instance ();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
/**
|
||||||
|
* @brief Called when the file watcher detects a change in the file system
|
||||||
|
*/
|
||||||
|
void file_watcher_triggered ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Called when the salt (packages) has changed
|
||||||
|
*/
|
||||||
|
void sync_with_external_sources ();
|
||||||
|
|
||||||
|
private:
|
||||||
|
tl::FileSystemWatcher *m_file_watcher;
|
||||||
|
tl::DeferredMethod<LibraryController> dm_sync_files;
|
||||||
|
std::map<std::string, std::pair<std::string, QDateTime> > m_lib_files;
|
||||||
|
|
||||||
|
void sync_files ();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -40,6 +40,7 @@ namespace lay
|
|||||||
MacroController::MacroController ()
|
MacroController::MacroController ()
|
||||||
: mp_macro_editor (0), mp_mw (0), m_no_implicit_macros (false), m_file_watcher (0),
|
: mp_macro_editor (0), mp_mw (0), m_no_implicit_macros (false), m_file_watcher (0),
|
||||||
dm_do_update_menu_with_macros (this, &MacroController::do_update_menu_with_macros),
|
dm_do_update_menu_with_macros (this, &MacroController::do_update_menu_with_macros),
|
||||||
|
dm_do_sync_with_external_sources (this, &MacroController::do_sync_with_external_sources),
|
||||||
dm_sync_file_watcher (this, &MacroController::sync_file_watcher),
|
dm_sync_file_watcher (this, &MacroController::sync_file_watcher),
|
||||||
dm_sync_files (this, &MacroController::sync_files)
|
dm_sync_files (this, &MacroController::sync_files)
|
||||||
{
|
{
|
||||||
@@ -288,7 +289,7 @@ MacroController::enable_implicit_macros (bool enable)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MacroController::sync_implicit_macros (bool check_autorun)
|
MacroController::sync_implicit_macros (bool ask_before_autorun)
|
||||||
{
|
{
|
||||||
if (m_no_implicit_macros) {
|
if (m_no_implicit_macros) {
|
||||||
return;
|
return;
|
||||||
@@ -427,7 +428,7 @@ MacroController::sync_implicit_macros (bool check_autorun)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_autorun) {
|
{
|
||||||
|
|
||||||
// This prevents the message dialog below to issue deferred methods
|
// This prevents the message dialog below to issue deferred methods
|
||||||
tl::NoDeferredMethods silent;
|
tl::NoDeferredMethods silent;
|
||||||
@@ -438,7 +439,7 @@ MacroController::sync_implicit_macros (bool check_autorun)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (has_autorun) {
|
if (has_autorun) {
|
||||||
if (QMessageBox::question (mp_mw, QObject::tr ("Run Macros"), QObject::tr ("Some macros associated with new items are 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 (! ask_before_autorun || QMessageBox::question (mp_mw, QObject::tr ("Run Macros"), QObject::tr ("Some macros associated with new items are configured to run automatically.\n\nChoose 'Yes' to run these macros now. Choose 'No' to not run them."), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
|
||||||
for (std::vector<lay::MacroCollection *>::const_iterator m = new_folders.begin (); m != new_folders.end (); ++m) {
|
for (std::vector<lay::MacroCollection *>::const_iterator m = new_folders.begin (); m != new_folders.end (); ++m) {
|
||||||
(*m)->autorun ();
|
(*m)->autorun ();
|
||||||
}
|
}
|
||||||
@@ -547,6 +548,12 @@ MacroController::add_macro_items_to_menu (lay::MacroCollection &collection, int
|
|||||||
|
|
||||||
void
|
void
|
||||||
MacroController::sync_with_external_sources ()
|
MacroController::sync_with_external_sources ()
|
||||||
|
{
|
||||||
|
dm_do_sync_with_external_sources ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MacroController::do_sync_with_external_sources ()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
sync_implicit_macros (true);
|
sync_implicit_macros (true);
|
||||||
|
|||||||
@@ -220,12 +220,14 @@ private:
|
|||||||
std::vector<ExternalPathDescriptor> m_external_paths;
|
std::vector<ExternalPathDescriptor> m_external_paths;
|
||||||
tl::FileSystemWatcher *m_file_watcher;
|
tl::FileSystemWatcher *m_file_watcher;
|
||||||
tl::DeferredMethod<MacroController> dm_do_update_menu_with_macros;
|
tl::DeferredMethod<MacroController> dm_do_update_menu_with_macros;
|
||||||
|
tl::DeferredMethod<MacroController> dm_do_sync_with_external_sources;
|
||||||
tl::DeferredMethod<MacroController> dm_sync_file_watcher;
|
tl::DeferredMethod<MacroController> dm_sync_file_watcher;
|
||||||
tl::DeferredMethod<MacroController> dm_sync_files;
|
tl::DeferredMethod<MacroController> dm_sync_files;
|
||||||
|
|
||||||
void sync_implicit_macros (bool check_autorun);
|
void sync_implicit_macros (bool ask_before_autorun);
|
||||||
void add_macro_items_to_menu (lay::MacroCollection &collection, int &n, std::set<std::string> &groups, const lay::Technology *tech, std::vector<std::pair<std::string, std::string> > *key_bindings);
|
void add_macro_items_to_menu (lay::MacroCollection &collection, int &n, std::set<std::string> &groups, const lay::Technology *tech, std::vector<std::pair<std::string, std::string> > *key_bindings);
|
||||||
void do_update_menu_with_macros ();
|
void do_update_menu_with_macros ();
|
||||||
|
void do_sync_with_external_sources ();
|
||||||
void sync_file_watcher ();
|
void sync_file_watcher ();
|
||||||
void sync_files ();
|
void sync_files ();
|
||||||
};
|
};
|
||||||
|
|||||||
+11
-10
@@ -49,6 +49,7 @@ Salt::Salt (const Salt &other)
|
|||||||
Salt &Salt::operator= (const Salt &other)
|
Salt &Salt::operator= (const Salt &other)
|
||||||
{
|
{
|
||||||
if (this != &other) {
|
if (this != &other) {
|
||||||
|
emit collections_about_to_change ();
|
||||||
m_root = other.m_root;
|
m_root = other.m_root;
|
||||||
invalidate ();
|
invalidate ();
|
||||||
}
|
}
|
||||||
@@ -97,6 +98,7 @@ Salt::add_location (const std::string &path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
lay::SaltGrains gg = lay::SaltGrains::from_path (path);
|
lay::SaltGrains gg = lay::SaltGrains::from_path (path);
|
||||||
|
emit collections_about_to_change ();
|
||||||
m_root.add_collection (gg);
|
m_root.add_collection (gg);
|
||||||
invalidate ();
|
invalidate ();
|
||||||
}
|
}
|
||||||
@@ -107,6 +109,7 @@ Salt::remove_location (const std::string &path)
|
|||||||
QFileInfo fi (tl::to_qstring (path));
|
QFileInfo fi (tl::to_qstring (path));
|
||||||
for (lay::SaltGrains::collection_iterator g = m_root.begin_collections (); g != m_root.end_collections (); ++g) {
|
for (lay::SaltGrains::collection_iterator g = m_root.begin_collections (); g != m_root.end_collections (); ++g) {
|
||||||
if (QFileInfo (tl::to_qstring (g->path ())) == fi) {
|
if (QFileInfo (tl::to_qstring (g->path ())) == fi) {
|
||||||
|
emit collections_about_to_change ();
|
||||||
m_root.remove_collection (g, false);
|
m_root.remove_collection (g, false);
|
||||||
invalidate ();
|
invalidate ();
|
||||||
return;
|
return;
|
||||||
@@ -122,6 +125,7 @@ Salt::refresh ()
|
|||||||
new_root.add_collection (lay::SaltGrains::from_path (g->path ()));
|
new_root.add_collection (lay::SaltGrains::from_path (g->path ()));
|
||||||
}
|
}
|
||||||
if (new_root != m_root) {
|
if (new_root != m_root) {
|
||||||
|
emit collections_about_to_change ();
|
||||||
m_root = new_root;
|
m_root = new_root;
|
||||||
invalidate ();
|
invalidate ();
|
||||||
}
|
}
|
||||||
@@ -208,21 +212,18 @@ bool remove_from_collection (SaltGrains &collection, const std::string &name)
|
|||||||
bool
|
bool
|
||||||
Salt::remove_grain (const SaltGrain &grain)
|
Salt::remove_grain (const SaltGrain &grain)
|
||||||
{
|
{
|
||||||
|
emit collections_about_to_change ();
|
||||||
|
|
||||||
tl::info << QObject::tr ("Removing package '%1' ..").arg (tl::to_qstring (grain.name ()));
|
tl::info << QObject::tr ("Removing package '%1' ..").arg (tl::to_qstring (grain.name ()));
|
||||||
if (remove_from_collection (m_root, grain.name ())) {
|
bool res = remove_from_collection (m_root, grain.name ());
|
||||||
|
if (res) {
|
||||||
tl::info << QObject::tr ("Package '%1' removed.").arg (tl::to_qstring (grain.name ()));
|
tl::info << QObject::tr ("Package '%1' removed.").arg (tl::to_qstring (grain.name ()));
|
||||||
|
|
||||||
// NOTE: this is a bit brute force .. we could as well try to insert the new grain into the existing structure
|
|
||||||
refresh ();
|
|
||||||
|
|
||||||
invalidate ();
|
|
||||||
return true;
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
tl::warn << QObject::tr ("Failed to remove package '%1'.").arg (tl::to_qstring (grain.name ()));
|
tl::warn << QObject::tr ("Failed to remove package '%1'.").arg (tl::to_qstring (grain.name ()));
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
invalidate ();
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
|
|||||||
@@ -186,6 +186,11 @@ public:
|
|||||||
bool create_grain (const SaltGrain &templ, SaltGrain &target);
|
bool create_grain (const SaltGrain &templ, SaltGrain &target);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
/**
|
||||||
|
* @brief A signal triggered before one of the collections changed
|
||||||
|
*/
|
||||||
|
void collections_about_to_change ();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A signal triggered when one of the collections changed
|
* @brief A signal triggered when one of the collections changed
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -137,7 +137,9 @@ SaltManagerDialog::SaltManagerDialog (QWidget *parent, lay::Salt *salt, lay::Sal
|
|||||||
connect (mode_tab, SIGNAL (currentChanged (int)), this, SLOT (mode_changed ()));
|
connect (mode_tab, SIGNAL (currentChanged (int)), this, SLOT (mode_changed ()));
|
||||||
|
|
||||||
connect (mp_salt, SIGNAL (collections_changed ()), this, SLOT (salt_changed ()));
|
connect (mp_salt, SIGNAL (collections_changed ()), this, SLOT (salt_changed ()));
|
||||||
|
connect (mp_salt, SIGNAL (collections_about_to_change ()), this, SLOT (salt_about_to_change ()));
|
||||||
connect (mp_salt_mine, SIGNAL (collections_changed ()), this, SLOT (salt_mine_changed ()));
|
connect (mp_salt_mine, SIGNAL (collections_changed ()), this, SLOT (salt_mine_changed ()));
|
||||||
|
connect (mp_salt_mine, SIGNAL (collections_about_to_change ()), this, SLOT (salt_mine_about_to_change ()));
|
||||||
|
|
||||||
update_models ();
|
update_models ();
|
||||||
|
|
||||||
@@ -407,12 +409,28 @@ BEGIN_PROTECTED
|
|||||||
END_PROTECTED
|
END_PROTECTED
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SaltManagerDialog::salt_about_to_change ()
|
||||||
|
{
|
||||||
|
SaltModel *model = dynamic_cast <SaltModel *> (salt_view->model ());
|
||||||
|
tl_assert (model != 0);
|
||||||
|
model->begin_update ();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SaltManagerDialog::salt_changed ()
|
SaltManagerDialog::salt_changed ()
|
||||||
{
|
{
|
||||||
dm_update_models ();
|
dm_update_models ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SaltManagerDialog::salt_mine_about_to_change ()
|
||||||
|
{
|
||||||
|
SaltModel *mine_model = dynamic_cast <SaltModel *> (salt_mine_view->model ());
|
||||||
|
tl_assert (mine_model != 0);
|
||||||
|
mine_model->begin_update ();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SaltManagerDialog::salt_mine_changed ()
|
SaltManagerDialog::salt_mine_changed ()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -51,11 +51,21 @@ public:
|
|||||||
SaltManagerDialog (QWidget *parent, lay::Salt *salt, lay::Salt *salt_mine);
|
SaltManagerDialog (QWidget *parent, lay::Salt *salt, lay::Salt *salt_mine);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
/**
|
||||||
|
* @brief Called when the list of packages (grains) is about to change
|
||||||
|
*/
|
||||||
|
void salt_about_to_change ();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Called when the list of packages (grains) has changed
|
* @brief Called when the list of packages (grains) has changed
|
||||||
*/
|
*/
|
||||||
void salt_changed ();
|
void salt_changed ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Called when the repository (salt mine) is about to change
|
||||||
|
*/
|
||||||
|
void salt_mine_about_to_change ();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Called when the repository (salt mine) has changed
|
* @brief Called when the repository (salt mine) has changed
|
||||||
*/
|
*/
|
||||||
|
|||||||
+17
-5
@@ -96,7 +96,7 @@ SaltItemDelegate::sizeHint (const QStyleOptionViewItem &option, const QModelInde
|
|||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
SaltModel::SaltModel (QObject *parent, lay::Salt *salt)
|
SaltModel::SaltModel (QObject *parent, lay::Salt *salt)
|
||||||
: QAbstractItemModel (parent), mp_salt (salt)
|
: QAbstractItemModel (parent), mp_salt (salt), m_in_update (false)
|
||||||
{
|
{
|
||||||
create_ordered_list ();
|
create_ordered_list ();
|
||||||
}
|
}
|
||||||
@@ -221,7 +221,7 @@ SaltModel::index (int row, int column, const QModelIndex &parent) const
|
|||||||
if (parent.isValid ()) {
|
if (parent.isValid ()) {
|
||||||
return QModelIndex ();
|
return QModelIndex ();
|
||||||
} else {
|
} else {
|
||||||
return createIndex (row, column, m_ordered_grains [row]);
|
return createIndex (row, column);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,8 +250,8 @@ SaltModel::rowCount (const QModelIndex &parent) const
|
|||||||
SaltGrain *
|
SaltGrain *
|
||||||
SaltModel::grain_from_index (const QModelIndex &index) const
|
SaltModel::grain_from_index (const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
if (index.isValid ()) {
|
if (index.isValid () && index.row () >= 0 && index.row () < int (m_ordered_grains.size ())) {
|
||||||
return static_cast<SaltGrain *> (index.internalPointer ());
|
return m_ordered_grains [index.row ()];
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -362,11 +362,23 @@ SaltModel::clear_messages ()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SaltModel::begin_update ()
|
||||||
|
{
|
||||||
|
if (! m_in_update) {
|
||||||
|
m_ordered_grains.clear ();
|
||||||
|
beginResetModel ();
|
||||||
|
m_in_update = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SaltModel::update ()
|
SaltModel::update ()
|
||||||
{
|
{
|
||||||
|
begin_update ();
|
||||||
create_ordered_list ();
|
create_ordered_list ();
|
||||||
reset ();
|
endResetModel ();
|
||||||
|
m_in_update = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -98,6 +98,13 @@ public:
|
|||||||
*/
|
*/
|
||||||
SaltGrain *grain_from_index (const QModelIndex &index) const;
|
SaltGrain *grain_from_index (const QModelIndex &index) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Marks the model as "under construction"
|
||||||
|
* This method can be called (multiple times) before update to mark the model
|
||||||
|
* as being under construction. update() will end this state.
|
||||||
|
*/
|
||||||
|
void begin_update ();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Updates the model
|
* @brief Updates the model
|
||||||
* Needs to be called when the salt has changed.
|
* Needs to be called when the salt has changed.
|
||||||
@@ -169,6 +176,7 @@ public:
|
|||||||
std::map<std::string, std::pair<Severity, std::string> > m_messages;
|
std::map<std::string, std::pair<Severity, std::string> > m_messages;
|
||||||
std::map<std::string, int> m_display_order;
|
std::map<std::string, int> m_display_order;
|
||||||
std::vector<SaltGrain *> m_ordered_grains;
|
std::vector<SaltGrain *> m_ordered_grains;
|
||||||
|
bool m_in_update;
|
||||||
|
|
||||||
bool is_marked (const std::string &name) const;
|
bool is_marked (const std::string &name) const;
|
||||||
bool is_enabled (const std::string &name) const;
|
bool is_enabled (const std::string &name) const;
|
||||||
|
|||||||
Reference in New Issue
Block a user