Issue 984 (#987)

* WIP: first attempt to fix issue-983

* WIP: bugfixes

* Fixed a problem with displaying empty cell dimensions, one warning

* Another fix: don't allow proxy cells to be selected in the instance properties dialog. This creates a confusing behaviour

* Fixed a few flaws in the cell selection scheme on the instance properties dialog.

* Early warning when trying to build a recursive hierarchy.

* Another fix: avoid too much undo in case of errors thrown during 'apply' followed by 'cancel'

* First attempt to fix issue 984

* Fixed issue-983 solution

* Fixed the modification status of PCell parameters for 'apply to all'
This commit is contained in:
Matthias Köfferlein 2022-02-08 19:07:04 +01:00 committed by GitHub
parent 285a5e9fca
commit d764adb101
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 197 additions and 17 deletions

View File

@ -1317,6 +1317,20 @@ GuiApplication::notify (QObject *receiver, QEvent *e)
return ret;
}
void
GuiApplication::enter_busy_mode (bool bm)
{
if (mp_mw) {
mp_mw->enter_busy_mode (bm);
}
}
bool
GuiApplication::is_busy () const
{
return mp_mw && mp_mw->is_busy ();
}
void
GuiApplication::force_update_app_menu ()
{
@ -1484,18 +1498,19 @@ GuiApplication::setup ()
void
GuiApplication::process_events_impl (QEventLoop::ProcessEventsFlags flags, bool silent)
{
// prevent recursive process_events
if (is_busy ()) {
return;
}
if (mp_mw) {
// prevent recursive process_events
if (mp_mw->is_busy ()) {
return;
}
lay::BusySection busy;
if (silent) {
tl::DeferredMethodScheduler::enable (false);
}
mp_mw->enter_busy_mode (true);
try {
#if QT_VERSION < 0x050000
QApplication::syncX ();
@ -1507,7 +1522,6 @@ GuiApplication::process_events_impl (QEventLoop::ProcessEventsFlags flags, bool
} catch (...) {
// ignore exceptions
}
mp_mw->enter_busy_mode (false);
if (silent) {
tl::DeferredMethodScheduler::enable (true);

View File

@ -25,6 +25,7 @@
#define HDR_layApplication
#include "layCommon.h"
#include "layBusy.h"
#include <QApplication>
#include <QEventLoop>
@ -366,7 +367,7 @@ private:
* @brief The GUI-enabled application class
*/
class LAY_PUBLIC GuiApplication
: public QApplication, public ApplicationBase
: public QApplication, public ApplicationBase, public lay::BusyMode
{
public:
GuiApplication (int &argc, char **argv);
@ -408,6 +409,19 @@ public:
return mp_mw;
}
/**
* @brief Enters busy mode (true) or leaves it (false)
*
* Use lay::BusySection to declare a section in "busy" mode. In busy mode, some features are disabled to
* prevent recursion in processing of events.
*/
virtual void enter_busy_mode (bool bm);
/**
* @brief Gets a value indicating whether busy mode is enabled
*/
virtual bool is_busy () const;
/**
* @brief Forces update of the application menu
* This function is used for work around a MacOS issue.

View File

@ -234,7 +234,7 @@ MacroEditorDialog::MacroEditorDialog (lay::Dispatcher *pr, lym::MacroCollection
lay::Plugin (pr, true),
mp_plugin_root (pr),
mp_root (root),
m_first_show (true), m_in_processing (false), m_debugging_on (true),
m_first_show (true), m_debugging_on (true),
mp_run_macro (0),
md_update_console_text (this, &MacroEditorDialog::update_console_text),
md_search_edited (this, &MacroEditorDialog::do_search_edited),
@ -1075,12 +1075,10 @@ void
MacroEditorDialog::process_events (QEventLoop::ProcessEventsFlags flags)
{
if (lay::ApplicationBase::instance ()) {
// disable execution of deferred methods to avoid undesired execution of
// NOTE: we disable execution of deferred methods to avoid undesired execution of
// code while we are inside a Ruby callback through the silent mode
bool last_processing = m_in_processing;
m_in_processing = true;
// NOTE: process_events will set BusySection::is_busy
lay::ApplicationBase::instance ()->process_events (flags, true /*silent*/);
m_in_processing = last_processing;
}
}
@ -1430,7 +1428,7 @@ MacroEditorDialog::eventFilter (QObject *obj, QEvent *event)
return false;
}
if (m_in_processing && (m_in_breakpoint || m_in_exec) && (dynamic_cast <QInputEvent *> (event) != 0 || dynamic_cast <QPaintEvent *> (event) != 0)) {
if (lay::BusySection::is_busy () && (m_in_breakpoint || m_in_exec) && (dynamic_cast <QInputEvent *> (event) != 0 || dynamic_cast <QPaintEvent *> (event) != 0)) {
// In breakpoint or execution mode and while processing the events from the debugger,
// ignore all input or paint events targeted to widgets which are not children of this or the assistant dialog.
@ -1447,7 +1445,7 @@ MacroEditorDialog::eventFilter (QObject *obj, QEvent *event)
return true;
}
} else if (! m_in_processing && m_in_exec) {
} else if (! lay::BusySection::is_busy () && m_in_exec) {
// While no explicit event processing is in progress and we are executing, this is an indication that
// "real" events are processed. In that case, we can postpone excplit processing. This avoids interference
@ -3032,7 +3030,7 @@ MacroEditorDialog::exception_thrown (gsi::Interpreter *interpreter, size_t file_
}
// avoid recursive breakpoints and exception catches from the console while in a breakpoint or exception stop
if (m_in_processing) {
if (lay::BusySection::is_busy ()) {
return;
}
@ -3126,7 +3124,7 @@ MacroEditorDialog::trace (gsi::Interpreter *interpreter, size_t file_id, int lin
}
// avoid recursive breakpoints and exception catches from the console while in a breakpoint or exception stop
if (m_in_processing) {
if (lay::BusySection::is_busy ()) {
return;
}

View File

@ -301,7 +301,6 @@ private:
lay::Dispatcher *mp_plugin_root;
lym::MacroCollection *mp_root;
bool m_first_show;
bool m_in_processing;
bool m_debugging_on;
lym::Macro *mp_run_macro;
std::vector<lym::Macro *> m_macro_templates;

View File

@ -0,0 +1,82 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2022 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 "layBusy.h"
#include "tlThreads.h"
namespace lay
{
tl::Mutex s_lock;
BusyMode *sp_busy_mode = 0;
// ----------------------------------------------------------------------------------------------------------
BusyMode::BusyMode ()
{
tl::MutexLocker locker (&s_lock);
if (sp_busy_mode == 0) {
sp_busy_mode = this;
}
}
BusyMode::~BusyMode ()
{
tl::MutexLocker locker (&s_lock);
if (sp_busy_mode == this) {
sp_busy_mode = 0;
}
}
// ----------------------------------------------------------------------------------------------------------
BusySection::BusySection ()
{
tl::MutexLocker locker (&s_lock);
mp_busy_mode = sp_busy_mode;
m_previous_mode = false;
if (mp_busy_mode) {
m_previous_mode = mp_busy_mode->is_busy ();
mp_busy_mode->enter_busy_mode (true);
}
}
BusySection::~BusySection ()
{
tl::MutexLocker locker (&s_lock);
if (sp_busy_mode == mp_busy_mode && mp_busy_mode) {
mp_busy_mode->enter_busy_mode (m_previous_mode);
}
mp_busy_mode = 0;
}
bool
BusySection::is_busy ()
{
tl::MutexLocker locker (&s_lock);
return sp_busy_mode && sp_busy_mode->is_busy ();
}
// ----------------------------------------------------------------------------------------------------------
}

View File

@ -0,0 +1,65 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2022 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_layBusy
#define HDR_layBusy
#include "laybasicCommon.h"
namespace lay
{
/**
* @brief An interface providing the "busy" methods
*
* There must be one provider implementing this interface.
*/
class LAYBASIC_PUBLIC BusyMode
{
public:
BusyMode ();
virtual ~BusyMode ();
virtual bool is_busy () const = 0;
virtual void enter_busy_mode (bool bm) = 0;
};
/**
* @brief A RAII implementation of the busy mode setter
*/
class LAYBASIC_PUBLIC BusySection
{
public:
BusySection ();
~BusySection ();
static bool is_busy ();
private:
bool m_previous_mode;
BusyMode *mp_busy_mode;
};
}
#endif

View File

@ -42,6 +42,7 @@
#include "dbClipboard.h"
#include "dbClipboardData.h"
#include "layBusy.h"
#include "layHierarchyControlPanel.h"
#include "layCellTreeModel.h"
#include "layLayoutView.h"
@ -146,6 +147,8 @@ HCPCellTreeWidget::startDrag (Qt::DropActions supportedActions)
return;
}
lay::BusySection busy_section; // issue 984
QDrag *drag = new QDrag (this);
drag->setMimeData(data);
QPixmap px (1, 1);

View File

@ -44,6 +44,7 @@
#include "dbClipboardData.h"
#include "dbLibraryManager.h"
#include "dbLibrary.h"
#include "layBusy.h"
#include "layLibrariesView.h"
#include "layCellTreeModel.h"
#include "layLayoutView.h"
@ -136,6 +137,8 @@ LibraryTreeWidget::startDrag (Qt::DropActions supportedActions)
return;
}
lay::BusySection busy_section; // issue 984
QDrag *drag = new QDrag (this);
drag->setMimeData(data);
QPixmap px (1, 1);

View File

@ -102,6 +102,7 @@ SOURCES = \
layBrowserDialog.cc \
layBrowserPanel.cc \
layBrowseShapesForm.cc \
layBusy.cc \
layCanvasPlane.cc \
layCellSelectionForm.cc \
layCellTreeModel.cc \
@ -208,6 +209,7 @@ HEADERS = \
layBrowser.h \
layBrowserPanel.h \
layBrowseShapesForm.h \
layBusy.h \
layCanvasPlane.h \
layCellSelectionForm.h \
layCellTreeModel.h \