From 389a0996fdb40ddeb8d97bcf14382933f009cfa7 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Wed, 3 Dec 2025 22:11:54 +0100 Subject: [PATCH] Messages can have priorities now. The net tracer uses higher-priority messages to make the 'click on second/first point' message more persistent. The have infinite lifetime now. --- src/lay/lay/gsiDeclLayMainWindow.cc | 31 +++++++++- src/lay/lay/layMainWindow.cc | 59 +++++++++++++++---- src/lay/lay/layMainWindow.h | 7 ++- src/laybasic/laybasic/layLayoutViewBase.cc | 4 +- src/laybasic/laybasic/layLayoutViewBase.h | 2 +- src/layview/layview/layLayoutView_qt.cc | 4 +- src/layview/layview/layLayoutView_qt.h | 6 +- .../lay_plugin/layNetTracerDialog.cc | 10 ++-- 8 files changed, 93 insertions(+), 30 deletions(-) diff --git a/src/lay/lay/gsiDeclLayMainWindow.cc b/src/lay/lay/gsiDeclLayMainWindow.cc index 9bb58226d..4339aa8bf 100644 --- a/src/lay/lay/gsiDeclLayMainWindow.cc +++ b/src/lay/lay/gsiDeclLayMainWindow.cc @@ -328,6 +328,12 @@ set_menu_items_hidden (lay::MainWindow *mw, const std::map &h mw->dispatcher ()->config_set (lay::cfg_menu_items_hidden, lay::pack_menu_items_hidden (hv)); } +static void +clear_message (lay::MainWindow *mw, int priority) +{ + mw->message (std::string (), 0, priority); +} + Class decl_MainWindow (QT_EXTERNAL_BASE (QMainWindow) "lay", "MainWindow", // Dispatcher interface and convenience functions @@ -475,15 +481,36 @@ Class decl_MainWindow (QT_EXTERNAL_BASE (QMainWindow) "lay", "M "\n" "This method has been added in version 0.24." ) + - gsi::method ("message", &lay::MainWindow::message, gsi::arg ("message"), gsi::arg ("time", -1, "infinite"), + gsi::method_ext ("clear_message", &clear_message, gsi::arg ("priority", -1, "all priorities"), + "@brief Clears the message\n" + "When calling this method with a priority, it will clear the message in the given priority slot, thus " + "unhiding the messages with lower priority. This is equivalent to calling \\message with an empty string.\n" + "\n" + "When calling without a priority, all messages in all priority slots will be cleared.\n" + "\n" + "This method has been added in version 0.30.6." + ) + + gsi::method ("message", &lay::MainWindow::message, gsi::arg ("message"), gsi::arg ("time", -1, "infinite"), gsi::arg ("priority", 0), "@brief Displays a message in the status bar\n" "\n" "@param message The message to display\n" "@param time The time how long to display the message in ms. A negative value means 'infinitely'.\n" + "@param priority The priority of the message. Higher-priority messages have precendence over lower-priority ones.\n" "\n" "This given message is shown in the status bar for the given time.\n" + "If a priority is given, higher-priority messages have precedence over lower-priority ones.\n" + "Placing an empty message clears a message with a given priority and unhides messages with lower " + "priority. Standard messages like selection descriptions have priority 0, which is the lowest priority.\n" "\n" - "This method has been added in version 0.18. The 'time' parameter was made optional in version 0.28.10." + "Messages generated during modal actions (e.g. 'Click on first point') by convention should have priority 10 " + "and should be tied to the active state of a plugin. This ensures there is only one such message.\n" + "Higher-priority messages must be cleared (set to empty string) explicitly to unhide lower-priority messages " + "when the indicated action is finished.\n" + "\n" + "\\clear_message is a convenience method that will clear messages.\n" + "\n" + "This method has been added in version 0.18. The 'time' parameter was made optional in version 0.28.10.\n" + "The 'priority' argument has been added in version 0.30.6." ) + gsi::method ("resize", (void (lay::MainWindow::*)(int, int)) &lay::MainWindow::resize, gsi::arg ("width"), gsi::arg ("height"), "@brief Resizes the window\n" diff --git a/src/lay/lay/layMainWindow.cc b/src/lay/lay/layMainWindow.cc index b54499056..e787d0dcd 100644 --- a/src/lay/lay/layMainWindow.cc +++ b/src/lay/lay/layMainWindow.cc @@ -186,6 +186,7 @@ MainWindow::MainWindow (QApplication *app, const char *name, bool undo_enabled) m_synchronous (false), m_busy (false), mp_app (app), + m_message_timer_priority (-1), m_manager (undo_enabled) { setAnimated (false); @@ -823,10 +824,15 @@ static int fm_width (const QFontMetrics &fm, const QString &s) void MainWindow::format_message () { + std::string msg; + if (! m_messages.empty ()) { + msg = (--m_messages.end ())->second; + } + QFontMetrics fm (mp_msg_label->font ()); std::string full_message; - for (const char *c = m_message.c_str (); *c; ++c) { + for (const char *c = msg.c_str (); *c; ++c) { if (*c == '\\' && (c[1] == '(' || c[1] == ')')) { ++c; } else { @@ -847,7 +853,7 @@ MainWindow::format_message () short_message.clear (); - for (const char *c = m_message.c_str (); *c; ++c) { + for (const char *c = msg.c_str (); *c; ++c) { if (*c == '\\' && c[1] == '(') { if (nsection++ < ndrop) { in_drop = true; @@ -875,24 +881,53 @@ MainWindow::format_message () } void -MainWindow::message (const std::string &s, int ms) +MainWindow::message (const std::string &s, int ms, int priority) { - m_message = s; + if (s.empty () && priority < 0) { + + m_messages.clear (); + + } else if (s.empty ()) { + + m_messages.erase (priority); + + } else { + + // simulate timeout of previous message timer + if (m_message_timer_priority >= 0) { + m_messages.erase (m_message_timer_priority); + } + + m_messages[priority] = s; + + if (ms >= 0) { + m_message_timer_priority = priority; + m_message_timer.start (ms); + } else { + m_message_timer_priority = -1; + } + + } + format_message (); - m_message_timer.start (ms); } void -MainWindow::clear_message () +MainWindow::clear_messages () { - m_message.clear (); - m_message_timer.start (0); + m_message_timer.stop (); + m_message_timer_priority = -1; + m_messages.clear (); + format_message (); } void MainWindow::message_timer () { - m_message.clear (); + if (m_message_timer_priority >= 0) { + m_messages.erase (m_message_timer_priority); + } + m_message_timer_priority = -1; format_message (); } @@ -2457,7 +2492,7 @@ MainWindow::select_view (int index) update_editor_options_dock (); clear_current_pos (); edits_enabled_changed (); - clear_message (); + clear_messages (); menu_needs_update (); m_disable_tab_selected = dis; @@ -2984,7 +3019,7 @@ MainWindow::close_view (int index) clear_current_pos (); edits_enabled_changed (); menu_needs_update (); - clear_message (); + clear_messages (); update_dock_widget_state (); @@ -3469,7 +3504,7 @@ MainWindow::add_view (lay::LayoutViewWidget *view) connect (view, SIGNAL (dirty_changed (lay::LayoutView *)), this, SLOT (view_title_changed (lay::LayoutView *))); connect (view, SIGNAL (edits_enabled_changed ()), this, SLOT (edits_enabled_changed ())); connect (view, SIGNAL (menu_needs_update ()), this, SLOT (menu_needs_update ())); - connect (view, SIGNAL (show_message (const std::string &, int)), this, SLOT (message (const std::string &, int))); + connect (view, SIGNAL (show_message (const std::string &, int, int)), this, SLOT (message (const std::string &, int, int))); connect (view, SIGNAL (current_pos_changed (double, double, bool)), this, SLOT (current_pos (double, double, bool))); connect (view, SIGNAL (clear_current_pos ()), this, SLOT (clear_current_pos ())); connect (view, SIGNAL (mode_change (int)), this, SLOT (select_mode (int))); diff --git a/src/lay/lay/layMainWindow.h b/src/lay/lay/layMainWindow.h index 737e24efc..0aab28d1a 100644 --- a/src/lay/lay/layMainWindow.h +++ b/src/lay/lay/layMainWindow.h @@ -649,12 +649,12 @@ public slots: /** * @brief Displays a status message next to the coordinates */ - void message (const std::string &s, int ms); + void message (const std::string &s, int ms, int); /** * @brief Clears the current message */ - void clear_message (); + void clear_messages (); /** * @brief Selects the given mode @@ -789,7 +789,8 @@ private: QApplication *mp_app; lay::HelpDialog *mp_assistant; std::string m_current_session; - std::string m_message; + int m_message_timer_priority; + std::map m_messages; std::unique_ptr mp_printer; std::vector m_changed_files; std::string m_title; diff --git a/src/laybasic/laybasic/layLayoutViewBase.cc b/src/laybasic/laybasic/layLayoutViewBase.cc index c0a5b7879..b357fb073 100644 --- a/src/laybasic/laybasic/layLayoutViewBase.cc +++ b/src/laybasic/laybasic/layLayoutViewBase.cc @@ -693,7 +693,7 @@ LayoutViewBase::set_synchronous (bool s) } void -LayoutViewBase::message (const std::string & /*s*/, int /*timeout*/) +LayoutViewBase::message (const std::string & /*s*/, int /*timeout*/, int /*priority*/) { // .. nothing yet .. } @@ -4156,7 +4156,7 @@ void LayoutViewBase::cancel_edits () { // clear any messages - message (); + message (std::string (), 0, -1); // the move service takes a special role here as it manages the // transaction for the collective move operation. diff --git a/src/laybasic/laybasic/layLayoutViewBase.h b/src/laybasic/laybasic/layLayoutViewBase.h index b0ad6d28e..4d64b410f 100644 --- a/src/laybasic/laybasic/layLayoutViewBase.h +++ b/src/laybasic/laybasic/layLayoutViewBase.h @@ -293,7 +293,7 @@ public: /** * @brief Display a status message */ - virtual void message (const std::string &s = "", int timeout = 10); + virtual void message (const std::string &s = "", int timeout = 10, int priority = 0); /** * @brief Sets the keyboard focus to the view diff --git a/src/layview/layview/layLayoutView_qt.cc b/src/layview/layview/layLayoutView_qt.cc index 55cad6857..4fcc1b810 100644 --- a/src/layview/layview/layLayoutView_qt.cc +++ b/src/layview/layview/layLayoutView_qt.cc @@ -1577,10 +1577,10 @@ LayoutView::signal_selection_changed () } void -LayoutView::message (const std::string &s, int timeout) +LayoutView::message (const std::string &s, int timeout, int priority) { if (mp_widget) { - mp_widget->emit_show_message (s, timeout * 1000); + mp_widget->emit_show_message (s, timeout * 1000, priority); } } diff --git a/src/layview/layview/layLayoutView_qt.h b/src/layview/layview/layLayoutView_qt.h index 837146a9a..26b18593c 100644 --- a/src/layview/layview/layLayoutView_qt.h +++ b/src/layview/layview/layLayoutView_qt.h @@ -182,7 +182,7 @@ public: /** * @brief Displays a status message */ - void message (const std::string &s = "", int timeout = 10); + virtual void message (const std::string &s = "", int timeout = 10, int priority = 0); /** * @brief Sets the keyboard focus to the view @@ -832,7 +832,7 @@ public: void emit_title_changed (lay::LayoutView *view) { emit title_changed (view); } void emit_dirty_changed (lay::LayoutView *view) { emit dirty_changed (view); } - void emit_show_message (const std::string &s, int ms) { emit show_message (s, ms); } + void emit_show_message (const std::string &s, int ms, int priority) { emit show_message (s, ms, priority); } void emit_current_pos_changed (double x, double y, bool dbu_units) { emit current_pos_changed (x, y, dbu_units); } void emit_clear_current_pos () { emit clear_current_pos (); } void emit_edits_enabled_changed () { emit edits_enabled_changed (); } @@ -885,7 +885,7 @@ signals: /** * @brief This signal is emitted when the view wants to show a message for the given time (of infinitely for ms == 0) */ - void show_message (const std::string &s, int ms); + void show_message (const std::string &s, int ms, int priority); /** * @brief This signal is emitted when the view wants to indicate a mouse position change diff --git a/src/plugins/tools/net_tracer/lay_plugin/layNetTracerDialog.cc b/src/plugins/tools/net_tracer/lay_plugin/layNetTracerDialog.cc index f7b0011bf..68b49a361 100644 --- a/src/plugins/tools/net_tracer/lay_plugin/layNetTracerDialog.cc +++ b/src/plugins/tools/net_tracer/lay_plugin/layNetTracerDialog.cc @@ -207,7 +207,7 @@ NetTracerDialog::drag_cancel () { if (m_mouse_state > 0) { - view ()->message (); + view ()->message (std::string (), 0, 10); ui ()->ungrab_mouse (this); set_cursor (lay::Cursor::none); @@ -241,7 +241,7 @@ NetTracerDialog::mouse_click_event (const db::DPoint &p, unsigned int buttons, b m_mouse_first_point = p; m_mouse_state = 3; - view ()->message (tl::to_string (QObject::tr ("Click on the second point in the net"))); + view ()->message (tl::to_string (QObject::tr ("Click on the second point in the net")), -1 /*infinitely*/, 10); } else { @@ -1264,7 +1264,7 @@ BEGIN_PROTECTED commit (); net_list->setCurrentItem (0); m_mouse_state = 2; - view ()->message (tl::to_string (QObject::tr ("Click on the first point in the net"))); + view ()->message (tl::to_string (QObject::tr ("Click on the first point in the net")), -1 /*infinitely*/, 10); ui ()->grab_mouse (this, false); END_PROTECTED } @@ -1276,7 +1276,7 @@ BEGIN_PROTECTED commit (); net_list->setCurrentItem (0); m_mouse_state = 1; - view ()->message (tl::to_string (QObject::tr ("Click on a point in the net"))); + view ()->message (tl::to_string (QObject::tr ("Click on a point in the net")), -1 /*infinitely*/, 10); ui ()->grab_mouse (this, false); END_PROTECTED } @@ -1299,7 +1299,7 @@ NetTracerDialog::release_mouse () add_pb->setChecked (false); add2_pb->setChecked (false); m_mouse_state = 0; - view ()->message (); + view ()->message (std::string (), 0, 10); ui ()->ungrab_mouse (this); set_cursor (lay::Cursor::none); }