diff --git a/src/lay/lay/layMainWindow.cc b/src/lay/lay/layMainWindow.cc index ef4ec5d3f..df4d4eda8 100644 --- a/src/lay/lay/layMainWindow.cc +++ b/src/lay/lay/layMainWindow.cc @@ -1160,8 +1160,7 @@ MainWindow::close_all () // try a smooth shutdown of the current view lay::LayoutView::set_current (0); - current_view_changed_event (); - // TODO: required? current_view_changed_event (int (view_index_org)); + current_view_changed (); for (unsigned int i = 0; i < mp_views.size (); ++i) { mp_views [i]->stop (); @@ -3231,8 +3230,7 @@ MainWindow::select_view (int index) } - current_view_changed_event (); - // TODO: required? current_view_changed_event (int (view_index_org)); + current_view_changed (); clear_current_pos (); edits_enabled_changed (); @@ -3613,6 +3611,7 @@ MainWindow::clone_current_view () // create a new view view = new lay::LayoutView (current_view (), &m_manager, lay::Application::instance ()->is_editable (), this, mp_view_stack); connect (view, SIGNAL (title_changed ()), this, SLOT (view_title_changed ())); + connect (view, SIGNAL (dirty_changed ()), this, SLOT (view_title_changed ())); connect (view, SIGNAL (edits_enabled_changed ()), this, SLOT (edits_enabled_changed ())); connect (view, SIGNAL (show_message (const std::string &, int)), this, SLOT (message (const std::string &, int))); connect (view, SIGNAL (current_pos_changed (double, double, bool)), this, SLOT (current_pos (double, double, bool))); @@ -3908,7 +3907,7 @@ MainWindow::close_view (int index) // last view closed mp_layer_toolbox->set_view (0); - current_view_changed_event (); + current_view_changed (); clear_current_pos (); edits_enabled_changed (); @@ -4217,6 +4216,7 @@ MainWindow::do_create_view () lay::LayoutView *view = new lay::LayoutView (&m_manager, lay::Application::instance ()->is_editable (), this, mp_view_stack); connect (view, SIGNAL (title_changed ()), this, SLOT (view_title_changed ())); + connect (view, SIGNAL (dirty_changed ()), this, SLOT (view_title_changed ())); connect (view, SIGNAL (edits_enabled_changed ()), this, SLOT (edits_enabled_changed ())); connect (view, SIGNAL (show_message (const std::string &, int)), this, SLOT (message (const std::string &, int))); connect (view, SIGNAL (current_pos_changed (double, double, bool)), this, SLOT (current_pos (double, double, bool))); @@ -4318,15 +4318,14 @@ MainWindow::create_or_load_layout (const std::string *filename, const db::LoadLa bool f = m_disable_tab_selected; m_disable_tab_selected = true; - int index = mp_tab_bar->insertTab (-1, tl::to_qstring (current_view ()->title ())); + int index = mp_tab_bar->insertTab (-1, QString ()); + update_tab_title (index); m_disable_tab_selected = f; view_created_event (index); select_view (index); - } else if (mode == 0) { - mp_tab_bar->setTabText (index_of (current_view ()), tl::to_qstring (current_view ()->title ())); - } else if (mode == 2) { - mp_tab_bar->setTabText (index_of (current_view ()), tl::to_qstring (current_view ()->title ())); + } else if (mode == 0 || mode == 2) { + update_tab_title (index_of (current_view ())); } update_dock_widget_state (); @@ -4346,16 +4345,74 @@ MainWindow::create_or_load_layout (const std::string *filename, const db::LoadLa return vw->cellview_ref (cv_index); } +void +MainWindow::update_tab_title (int i) +{ + std::string title; + + lay::LayoutView *v = view (i); + if (v) { + if (v->is_dirty ()) { + title += "[+] "; + } + title += v->title (); + } + + if (tl::to_string (mp_tab_bar->tabText (i)) != title) { + mp_tab_bar->setTabText (i, tl::to_qstring (title)); + } + + if (v) { + std::string files; + for (unsigned int cv = 0; cv < v->cellviews (); ++cv) { + if (! files.empty ()) { + files += "\n"; + } + if (! v->cellview (cv)->filename ().empty ()) { + files += v->cellview (cv)->filename (); + } else { + files += tl::to_string (tr ("(not saved)")); + } + } + if (tl::to_string (mp_tab_bar->tabToolTip (i)) != files) { + mp_tab_bar->setTabToolTip (i, tl::to_qstring (files)); + } + } +} + void MainWindow::view_title_changed () { - // transfer the current view's text into the tab bar - unsigned int tabs = mp_tab_bar->count (); - for (unsigned int i = 0; i < tabs && i < views (); ++i) { - if (tl::to_string (mp_tab_bar->tabText (i)) != view (i)->title ()) { - mp_tab_bar->setTabText (i, tl::to_qstring (view (i)->title ())); - } + int i = index_of (dynamic_cast (sender ())); + if (i >= 0) { + update_tab_title (i); } + + if (sender () == current_view ()) { + update_window_title (); + } +} + +void +MainWindow::update_window_title () +{ + if (current_view ()) { + std::string sep = " - "; + if (current_view ()->is_dirty ()) { + sep += "[+] "; + } + setWindowTitle (tl::to_qstring (lay::Application::instance ()->version () + sep + current_view ()->title ())); + } else { + setWindowTitle (tl::to_qstring (lay::Application::instance ()->version ())); + } +} + +void +MainWindow::current_view_changed () +{ + update_window_title (); + current_view_changed_event (); + // TODO: required? current_view_changed_event (int (view_index_org)); } double diff --git a/src/lay/lay/layMainWindow.h b/src/lay/lay/layMainWindow.h index 0b0f60101..f969c43ff 100644 --- a/src/lay/lay/layMainWindow.h +++ b/src/lay/lay/layMainWindow.h @@ -921,6 +921,9 @@ private: void close_view (int index); void interactive_close_view (int index, bool all_cellviews); void call_on_current_view (void (lay::LayoutView::*func) (), const std::string &op_desc); + void current_view_changed (); + void update_window_title (); + void update_tab_title (int i); bool can_close (); lay::CellViewRef create_or_load_layout (const std::string *filename, const db::LoadLayoutOptions *options, const std::string &tech, const int mode); diff --git a/src/laybasic/laybasic/layLayoutView.cc b/src/laybasic/laybasic/layLayoutView.cc index 49633cb9b..308b121e7 100644 --- a/src/laybasic/laybasic/layLayoutView.cc +++ b/src/laybasic/laybasic/layLayoutView.cc @@ -384,6 +384,7 @@ LayoutView::init (db::Manager *mgr, lay::PluginRoot *root, QWidget * /*parent*/) m_drop_small_cells_value = 10; m_drop_small_cells_cond = DSC_Max; m_draw_array_border_instances = false; + m_dirty = false; m_activated = true; m_animated = false; m_phase = 0; @@ -776,6 +777,12 @@ LayoutView::set_synchronous (bool s) m_synchronous = s; } +bool +LayoutView::is_dirty () const +{ + return m_dirty; +} + std::string LayoutView::title () const { @@ -784,11 +791,29 @@ LayoutView::title () const } else if (cellviews () == 0) { return tl::to_string (QObject::tr ("")); } else { - std::string t (cellview (0)->name ()); + + int cv_index = active_cellview_index (); + if (cv_index < 0 || cv_index >= int (cellviews ())) { + cv_index = 0; + } + + const lay::CellView &cv0 = cellview (cv_index); + + std::string t; + + t += cv0->name (); + if (cv0->layout ().is_valid_cell_index (cv0.cell_index ())) { + t += " ["; + t += cv0->layout ().cell_name (cv0.cell_index ()); + t += "]"; + } + if (cellviews () > 1) { t += " ..."; } + return t; + } } @@ -1897,12 +1922,7 @@ LayoutView::save_as (unsigned int index, const std::string &filename, tl::Output tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (QObject::tr ("Saving"))); cellview (index)->save_as (filename, om, options, update); - // because the file name for the cellviews has changed we issue that event: - cellview_changed_event (index); - - if (m_title.empty ()) { - emit title_changed (); - } + cellview_changed (index); } void @@ -3316,6 +3336,16 @@ LayoutView::box () const void LayoutView::timer () { + bool dirty = false; + for (std::list::const_iterator i = m_cellviews.begin (); i != m_cellviews.end () && ! dirty; ++i) { + dirty = (*i)->layout ().is_editable () && (*i)->is_dirty (); + } + + if (dirty != m_dirty) { + m_dirty = dirty; + emit dirty_changed (); + } + if (m_animated) { set_view_ops (); if (mp_control_panel) { @@ -3324,7 +3354,7 @@ LayoutView::timer () if (m_animated) { ++m_phase; } - } + } } bool @@ -4317,7 +4347,7 @@ LayoutView::select_cellviews_fit (const std::list &cvs) finish_cellviews_changed (); for (int index = 0; index < int (m_cellviews.size ()); ++index) { - cellview_changed_event (index); + cellview_changed (index); } update_content (); @@ -4331,8 +4361,25 @@ void LayoutView::active_cellview_changed (int index) { if (m_active_cellview_changed_event_enabled) { + active_cellview_changed_event (); active_cellview_changed_with_index_event (index); + + // Because the title reflects the active one, emit a title changed event + if (m_title.empty ()) { + emit title_changed (); + } + + } +} + +void +LayoutView::cellview_changed (unsigned int index) +{ + cellview_changed_event (index); + + if (m_title.empty ()) { + emit title_changed (); } } @@ -4376,7 +4423,7 @@ LayoutView::select_cell_fit (const cell_path_type &path, int index) redraw (); zoom_fit (); - cellview_changed_event (index); + cellview_changed (index); update_content (); @@ -4397,7 +4444,7 @@ LayoutView::select_cell_fit (cell_index_type cell_index, int index) redraw (); zoom_fit (); - cellview_changed_event (index); + cellview_changed (index); update_content (); @@ -4421,7 +4468,7 @@ LayoutView::select_cellviews (const std::list &cvs) cellviews_changed_event (); for (int index = 0; index < int (m_cellviews.size ()); ++index) { - cellview_changed_event (index); + cellview_changed (index); } update_content (); @@ -4444,7 +4491,7 @@ LayoutView::select_cellview (int index, const CellView &cv) *cellview_iter (index) = cv; redraw (); - cellview_changed_event (index); + cellview_changed (index); update_content (); @@ -4464,7 +4511,7 @@ LayoutView::select_cell (const cell_path_type &path, int index) set_active_cellview_index (index); redraw (); - cellview_changed_event (index); + cellview_changed (index); update_content (); @@ -4484,7 +4531,7 @@ LayoutView::select_cell (cell_index_type cell_index, int index) set_active_cellview_index (index); redraw (); - cellview_changed_event (index); + cellview_changed (index); update_content (); @@ -6161,7 +6208,7 @@ LayoutView::ascend (int index) store_state (); redraw (); - cellview_changed_event (index); + cellview_changed (index); update_content (); @@ -6186,7 +6233,7 @@ LayoutView::descend (const std::vector &path, int index) store_state (); redraw (); - cellview_changed_event (index); + cellview_changed (index); update_content (); diff --git a/src/laybasic/laybasic/layLayoutView.h b/src/laybasic/laybasic/layLayoutView.h index 1dfc40bb2..20479e56c 100644 --- a/src/laybasic/laybasic/layLayoutView.h +++ b/src/laybasic/laybasic/layLayoutView.h @@ -285,6 +285,13 @@ public: */ void reset_title (); + /** + * @brief The "dirty" flag indicates that one of the layout has been modified + * + * A signal is provided on a change of this flag (dirty_changed). + */ + bool is_dirty () const; + /** * @brief Fill the layer properties for a new layer * @@ -2386,13 +2393,6 @@ public slots: */ void select_cell_dispatch (const cell_path_type &path, int cellview_index); - /** - * @brief The active cellview has changed - * - * This signal is forwarded to the active_cellview_changed event - */ - void active_cellview_changed (int index); - /** * @brief Gets the full field box * @@ -2509,12 +2509,20 @@ public slots: void signal_plugin_enabled_changed (); void signal_apply_technology (lay::LayoutHandle *layout_handle); +private slots: + void active_cellview_changed (int index); + signals: /** * @brief This signal is emitted when the title changes */ void title_changed (); + /** + * @brief This signal is emitted when the "dirty" flag changes + */ + void dirty_changed (); + /** * @brief This signal is emitted when the view wants to show a message for the given time (of infinitely for ms == 0) */ @@ -2642,6 +2650,7 @@ private: bool m_dbu_coordinates; bool m_absolute_coordinates; + bool m_dirty; bool m_activated; bool m_animated; unsigned int m_phase; @@ -2709,6 +2718,7 @@ private: void update_event_handlers (); void viewport_changed (); + void cellview_changed (unsigned int index); bool configure (const std::string &name, const std::string &value);