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.

This commit is contained in:
Matthias Koefferlein 2025-12-03 22:11:54 +01:00
parent fc4a8b92b0
commit 389a0996fd
8 changed files with 93 additions and 30 deletions

View File

@ -328,6 +328,12 @@ set_menu_items_hidden (lay::MainWindow *mw, const std::map<std::string, bool> &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<lay::MainWindow> decl_MainWindow (QT_EXTERNAL_BASE (QMainWindow) "lay", "MainWindow",
// Dispatcher interface and convenience functions
@ -475,15 +481,36 @@ Class<lay::MainWindow> 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"

View File

@ -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)));

View File

@ -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<int, std::string> m_messages;
std::unique_ptr<QPrinter> mp_printer;
std::vector<QString> m_changed_files;
std::string m_title;

View File

@ -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.

View File

@ -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

View File

@ -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);
}
}

View File

@ -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

View File

@ -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);
}