/* 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_layMainWindow #define HDR_layMainWindow #include "layCommon.h" #include #include #include #include #include #include #include #include "dbManager.h" #include "dbLoadLayoutOptions.h" #include "layAbstractMenu.h" #include "layAbstractMenuProvider.h" #include "layMacro.h" #include "layLayoutView.h" #include "layPlugin.h" #include "layProgress.h" #include "layTextProgress.h" #include "layTechnology.h" #include "tlException.h" #include "tlDeferredExecution.h" #include "tlObjectCollection.h" #include "gsi.h" class QTabBar; class QToolBar; class QLabel; class QAction; class QMenu; class QStackedWidget; class QDockWidget; class QAction; namespace Ui { class HelpAboutDialog; } namespace lay { class SettingsForm; class ViewWidgetStack; class ControlWidgetStack; class ProgressReporter; class ProgressWidget; class ProgressDialog; class FileDialog; class AbstractMenu; class SaveLayoutAsOptionsDialog; class SaveLayoutOptionsDialog; class LoadLayoutOptionsDialog; class LogViewerDialog; class CellView; class Navigator; class LayerToolbox; class MainWindow; class HelpDialog; /** * @brief A dialog for showing the "help about" dialog */ class LAY_PUBLIC HelpAboutDialog : public QDialog { public: HelpAboutDialog (QWidget *parent); ~HelpAboutDialog (); private: Ui::HelpAboutDialog *mp_ui; }; class TextProgressDelegate : public lay::TextProgress { public: TextProgressDelegate (MainWindow *mw, int verbosity); virtual void set_progress_can_cancel (bool f); virtual void set_progress_text (const std::string &text); virtual void set_progress_value (double v, const std::string &value); virtual void show_progress_bar (bool show); private: MainWindow *mp_mw; }; class LAY_PUBLIC MainWindow : public QMainWindow, public lay::AbstractMenuProvider, public lay::PluginRoot { Q_OBJECT public: /** * @brief The (only) instance of the main window */ static MainWindow *instance (); /** * @brief Constructor */ MainWindow (QApplication *app = 0, const char *name = "main_window"); /** * @brief Destructor */ ~MainWindow (); /** * @brief Implementation of the AbstractMenuProvider interface */ QWidget *menu_parent_widget () { return this; } /** * @brief Get the main menu abstraction object */ AbstractMenu *menu () { return mp_menu; } /** * @brief Close all views */ void close_all (); /** * @brief Create a new view * * @return The index of the newly created view */ int create_view (); /** * @brief Startup behaviour immediately before the application is executed. * * This method will be called shortly the before the application is executed. * It is supposed to perform some startup procedure, i.e. displaying tip-of-the-day * windows. */ void about_to_exec (); /** * @brief Display a technology message */ void tech_message (const std::string &s); /** * @brief Save the session to a file */ void save_session (const std::string &fn); /** * @brief Restore the session from a file */ void restore_session (const std::string &fn); /** * @brief Reload the given cellview into the current view * * The cellview is given by index in the current view's cellview list. */ void reload_layout (unsigned int cv_index); /** * @brief Load a (new) file into the layout * * The mode param controls how to open the file: * 0 = replace current view, 1 = create new view, 2 = add to current view */ lay::CellViewRef load_layout (const std::string &filename, int mode = 0) { return load_layout (filename, m_initial_technology, mode); } /** * @brief Load a (new) file into the layout and associate it with the given technology * * The mode param controls how to open the file: * 0 = replace current view, 1 = create new view, 2 = add to current view */ lay::CellViewRef load_layout (const std::string &filename, const std::string &technology, int mode = 0) { return load_layout (filename, lay::Technologies::instance ()->technology_by_name (technology)->load_layout_options (), technology, mode); } /** * @brief Load a (new) file into the layout using the given options * * The mode param controls how to open the file: * 0 = replace current view, 1 = create new view, 2 = add to current view */ lay::CellViewRef load_layout (const std::string &filename, const db::LoadLayoutOptions &options, int mode = 0) { return load_layout (filename, options, m_initial_technology, mode); } /** * @brief Load a (new) file into the layout using the given options and technology * * The mode param controls how to open the file: * 0 = replace current view, 1 = create new view, 2 = add to current view */ lay::CellViewRef load_layout (const std::string &filename, const db::LoadLayoutOptions &options, const std::string &technology, int mode = 0); /** * @brief Create new, empty layout * * The mode param controls how to create the layout * 0 = replace current view, 1 = create new view, 2 = add to current view */ lay::CellViewRef create_layout (int mode = 0) { return create_layout (m_initial_technology, mode); } /** * @brief Create new, empty layout and associate it with the given technology * * The mode param controls how to create the layout * 0 = replace current view, 1 = create new view, 2 = add to current view */ lay::CellViewRef create_layout (const std::string &technology, int mode = 0); /** * @brief Clone the current view */ void clone_current_view (); /** * @brief Determine whether a given layer properties file is a single-layout file * * @return True, if the file contains definitions of a single layout only. */ bool is_single_cv_layer_properties_file (const std::string &fn); /** * @brief Load a layer definition file * * This version will load the layer properties file "as it is". No mapping of cellview index * is performed. Only adding of missing layers is supported. * The file name can be an empty string. * * @param fn The name of the .lyp file to load. * @param all_views Apply the .lyp file to all views. If false, load the layer properties for the current view. * @param add_default Add the missing layers for each view. */ void load_layer_properties (const std::string &fn, bool all_views, bool add_default); /** * @brief Load a layer definition file for a specific cv * * This version will load the layer properties file and apply it to the given cv. The cv_index * parameter will denote the cv index to which to apply the layer properties file. It is assumed * that the .lyp file will contain definitions for a single layout only. This definition is * mapped to the specified cv_index after all definitions for this layout have been removed * from the layer properties list. * "cv_index" can be -1. In that case, the layer properties file will be loaded multiple times, * once for each cv present. * * @param fn The name of the .lyp file to load. * @param cv_index See above * @param all_views Apply the .lyp file to all views. If false, load the layer properties for the current view. * @param add_default Add the missing layers for each view. */ void load_layer_properties (const std::string &fn, int cv_index, bool all_views, bool add_default); /** * @brief Grid accessor: get the grid value * * This is the version delivering a double value in micron. */ double grid_micron () const; /** * @brief Hierarchy level selection setter */ void set_hier_levels (std::pair l); /** * @brief Hierarchy level selection setter */ void set_min_hier_levels (int l) { set_hier_levels (std::pair (l, get_max_hier_levels ())); } /** * @brief Hierarchy level selection setter */ void set_max_hier_levels (int l) { set_hier_levels (std::pair (get_min_hier_levels (), l)); } /** * @brief Hierarchy level selection getter */ std::pair get_hier_levels () const; /** * @brief Hierarchy level selection getter */ int get_min_hier_levels () const { return get_hier_levels ().first; } /** * @brief Hierarchy level selection getter */ int get_max_hier_levels () const { return get_hier_levels ().second; } /** * @brief Return true, if there is a "last" display state */ bool has_last_display_state (); /** * @brief Return true, if there is a "next" display state */ bool has_next_display_state (); /** * @brief Get the global manager object */ db::Manager &manager () { return m_manager; } /** * @brief Implementation of the lay::ProgressBar interface: set the flag indicating whether we can cancel the operation */ bool set_progress_can_cancel(bool f); /** * @brief Implementation of the lay::ProgressBar interface: set the text to display */ bool set_progress_text (const std::string &text); /** * @brief Implementation of the lay::ProgressBar interface: set the value to display */ bool set_progress_value (double v, const std::string &value); /** * @brief Implementation of the lay::ProgressBar interface: Make the progress widget visible or invisible */ bool show_progress_bar (bool show); /** * @brief Implementation of the PluginRoot interface */ bool configure (const std::string &name, const std::string &value); /** * @brief Implementation of the PluginRoot interface */ void config_finalize (); /** * @brief Tell, if exit was called * * This method returns true if exit () has been called. This state is never reset. * The main purpose is to detect "exit ()" calls before the event loop is executed. */ bool exited () { return m_exited; } /** * @brief Enter or leave busy state * * In busy state, the main window will not try to ask for saving changes etc. * Instead, it will ask whether to shut down the application anyway. * The intention of the busy state is to implement a special behavior while inside a processEvent * loop. */ void enter_busy_mode (bool bm) { m_busy = bm; } /** * @brief Enable synchronous mode or disable it * * In synchronous mode, the program waits until the drawing has finished. * If this mode is disabled, drawing is done in the background thread. * Synchronous mode is mainly intended for automation purposes. */ void set_synchronous (bool sync_mode); /** * @brief Tell the state of the synchronous mode flag */ bool synchronous () const { return m_synchronous; } /** * @brief Returns true, if the edit functions of the current view are enabled */ bool edits_enabled () const; /** * @brief Retrieve index of the given view * * @return the current view's index or -1 if no index is available */ int index_of (const lay::LayoutView *view) const; /** * @brief Retrieve view with the given index */ lay::LayoutView *view (int index); /** * @brief Retrieve current the current view (const mode) */ const lay::LayoutView *view (int index) const; /** * @brief Gets the current view * * This is just a convience method. It's equivalent to lay::LayoutView::current (). */ lay::LayoutView *current_view () const; /** * @brief Gets the index of the current view */ int current_view_index () const; /** * @brief Return the number of number of views */ unsigned int views () const { return (unsigned int) mp_views.size (); } /** * @brief Select the view with the given index */ void select_view (int index); /** * @brief Select the given mode * * @param The index of the mode to select */ void select_mode (int m); /** * @brief Get the instance of the assistant */ lay::HelpDialog *assistant () const { return mp_assistant; } /** * @brief Show the assistant with the given URL */ void show_assistant_url (const std::string &url, bool modal = false); /** * @brief Show the assistant with the given topic */ void show_assistant_topic (const std::string &s, bool modal = false); /** * @brief Show the macro editor * * The category can be given to specify the category to show. If empty, the current category * is shown. * "add" can be true, to create a new macro initially. */ void show_macro_editor (const std::string &cat = std::string (), bool add = false); /** * @brief Reimplementation of the plugin interface: handle a generic menu request */ void menu_activated (const std::string &symbol); /** * @brief Get the action for a slot */ lay::Action &action_for_slot (const char *slot); /** * @brief Create a configuration action with the given title, parameter name and value * * The action will be owned by the main window but can be deleted to remove the action from the main window. */ lay::Action *create_config_action (const std::string &title, const std::string &cname, const std::string &cvalue); /** * @brief Create a configuration action with the given parameter name and value * * The action will be owned by the main window but can be deleted to remove the action from the main window. * This version is provided for applications, where the title is set later. */ lay::Action *create_config_action (const std::string &cname, const std::string &cvalue); /** * @brief Register a configuration action with the given name */ void register_config_action (const std::string &name, lay::ConfigureAction *action); /** * @brief Unregister a configuration action with the given name */ void unregister_config_action (const std::string &name, lay::ConfigureAction *action); /** * @brief Open a new layout in mode 'mode' * * If mode is 2, the layout is opened in the current view in addition to the existing ones. * If mode is 1, the layout is opened in a new view. If mode is 0, the layout is opened in * the current view deleting the existing ones. */ void open (int mode); /** * @brief An event indicating that the current view has changed * This event is fired if the current view was changed. * The current view's reference is updated if the event is issued. */ tl::Event current_view_changed_event; /** * @brief An event indicating that a view was closed * If a view is closed, this event is triggered. When the signal is sent, * the view still points to the view being closed which is still valid. * The integer parameter will receive the index of the view about to be closed. */ tl::event view_closed_event; /** * @brief An event indicating that a new view is created * If a new view is created, this event will be triggered. * The integer parameter will receive the index of the view that was created. */ tl::event view_created_event; /** * @brief Add an entry to the MRU list with the initial technology */ void add_mru (const std::string &fn); /** * @brief Add an entry to the MRU list */ void add_mru (const std::string &fn, const std::string &tech); /** * @brief Get the technology used for loading or creating layouts */ const std::string &initial_technology () { return m_initial_technology; } /** * @brief Set the initial technology used for loading or creating layouts */ void set_initial_technology (const std::string &tech) { m_initial_technology = tech; } /** * @brief Reimplementation of the dragEnterEvent event handler */ void dragEnterEvent(QDragEnterEvent *event); /** * @brief Reimplementation of the dropEvent event handler */ void dropEvent(QDropEvent *event); signals: void closed (); public slots: /** * @brief Display the current position */ void current_pos (double x, double y, bool dbu_units); /** * @brief Clear the current position */ void clear_current_pos (); /** * @brief Display a status message next to the coordinates */ void message (const std::string &s, int ms); /** * @brief Clears the current message */ void clear_message (); /** * @brief Called when one of the built-in modes (i.e. select, move) is selected */ void intrinsic_mode_triggered (); void update_action_states (); void cancel (); void redraw (); void exit (); void close_current_view (); void tab_close_requested (int); void enable_all (); void disable_all (); void goto_bookmark (); void open_recent (); void view_selected (int index); void view_title_changed (); // menu callbacks for main window void cm_select_all (); void cm_unselect_all (); void cm_undo (); void cm_redo (); void cm_delete (); void cm_show_properties (); void cm_copy (); void cm_paste (); void cm_duplicate (); void cm_cut (); void cm_zoom_fit_sel (); void cm_zoom_fit (); void cm_zoom_in (); void cm_zoom_out (); void cm_pan_up (); void cm_pan_down (); void cm_pan_left (); void cm_pan_right (); void cm_save_session (); void cm_restore_session (); void cm_setup (); void cm_save_as (); void cm_save_all (); void cm_save (); void cm_reload (); void cm_close (); void cm_close_all (); void cm_clone (); void cm_layout_props (); void cm_layout_stats (); void cm_inc_max_hier (); void cm_dec_max_hier (); void cm_max_hier (); void cm_max_hier_0 (); void cm_max_hier_1 (); void cm_last_display_state (); void cm_next_display_state (); void cm_cancel (); void cm_redraw (); void cm_screenshot (); void cm_save_layer_props (); void cm_load_layer_props (); void cm_save_bookmarks (); void cm_load_bookmarks (); void cm_select_cell (); void cm_select_current_cell (); void cm_print (); void cm_exit (); void cm_view_log (); void cm_bookmark_view (); void cm_manage_bookmarks (); void cm_goto_position (); void cm_show_all_tips (); void cm_help_about (); void cm_help_about_qt (); void cm_macro_editor (); void cm_new_drc_script (); void cm_edit_drc_scripts (); void cm_technologies (); void cm_open_too (); void cm_open_new_view (); void cm_open (); void cm_pull_in (); void cm_reader_options (); void cm_writer_options (); void cm_new_layout (); void cm_new_panel (); void cm_adjust_origin (); void cm_new_cell (); void cm_new_layer (); void cm_clear_layer (); void cm_delete_layer (); void cm_edit_layer (); void cm_copy_layer (); void cm_lay_convert_to_static (); void cm_lay_flip_x (); void cm_lay_flip_y (); void cm_lay_rot_cw (); void cm_lay_rot_ccw (); void cm_lay_free_rot (); void cm_lay_scale (); void cm_lay_move (); void cm_sel_flip_x (); void cm_sel_flip_y (); void cm_sel_rot_cw (); void cm_sel_rot_ccw (); void cm_sel_free_rot (); void cm_sel_scale (); void cm_sel_move (); void cm_sel_move_to (); void cm_show_assistant (); // forwarded to the current view: layer list context menu void cm_lv_new_tab (); void cm_lv_remove_tab (); void cm_lv_rename_tab (); void cm_lv_make_valid (); void cm_lv_make_invalid (); void cm_lv_hide (); void cm_lv_hide_all (); void cm_lv_show (); void cm_lv_show_all (); void cm_lv_show_only (); void cm_lv_rename (); void cm_lv_select_all (); void cm_lv_delete (); void cm_lv_insert (); void cm_lv_group (); void cm_lv_ungroup (); void cm_lv_source (); void cm_lv_sort_by_name (); void cm_lv_sort_by_ild (); void cm_lv_sort_by_idl (); void cm_lv_sort_by_ldi (); void cm_lv_sort_by_dli (); void cm_lv_regroup_by_index (); void cm_lv_regroup_by_datatype (); void cm_lv_regroup_by_layer (); void cm_lv_regroup_flatten (); void cm_lv_expand_all (); void cm_lv_add_missing (); void cm_lv_remove_unused (); void cm_lv_copy (); void cm_lv_cut (); void cm_lv_paste (); // forwarded to the current view: cell list context menu void cm_cell_user_properties (); void cm_cell_delete (); void cm_cell_replace (); void cm_cell_rename (); void cm_cell_flatten (); void cm_cell_convert_to_static (); void cm_cell_copy (); void cm_cell_cut (); void cm_cell_paste (); void cm_cell_select (); void cm_open_current_cell (); void cm_save_current_cell_as (); void cm_cell_hide (); void cm_cell_show (); void cm_cell_show_all (); // forwarded to the navigator void cm_navigator_freeze (); void cm_navigator_close (); /** * @brief shows the given URL as a model help window * Intended as a connection target for QLabel linkVisisted signals. */ void show_help (const QString &url); /** * @brief visibility of one of the dock widgets changed */ void dock_widget_visibility_changed (bool visible); protected slots: void menu_changed (); void message_timer (); void bookmark_menu_show (); void file_menu_show (); void edits_enabled_changed (); void file_changed_timer (); void file_changed (const QString &path); void file_removed (const QString &path); protected: void update_content (); void do_update_menu (); private: TextProgressDelegate m_text_progress; // Main menu AbstractMenu *mp_menu; QMenu *mp_goto_bookmark_menu; QTabBar *mp_tab_bar; QToolBar *mp_tool_bar; QDockWidget *mp_navigator_dock_widget; lay::Navigator *mp_navigator; QDockWidget *mp_hp_dock_widget, *mp_lp_dock_widget; ControlWidgetStack *mp_hp_stack, *mp_lp_stack; bool m_hp_visible, m_lp_visible, m_navigator_visible, m_layer_toolbox_visible; QDockWidget *mp_layer_toolbox_dock_widget; lay::LayerToolbox *mp_layer_toolbox; ViewWidgetStack *mp_view_stack; lay::FileDialog *mp_bookmarks_fdia; lay::FileDialog *mp_session_fdia; lay::FileDialog *mp_lprops_fdia; lay::FileDialog *mp_screenshot_fdia; lay::FileDialog *mp_layout_fdia; lay::SaveLayoutAsOptionsDialog *mp_layout_save_as_options; lay::SaveLayoutOptionsDialog *mp_layout_save_options; lay::LoadLayoutOptionsDialog *mp_layout_load_options; lay::LogViewerDialog *mp_log_viewer_dialog; int m_mode; SettingsForm *mp_setup_form; std::vector mp_views; int m_open_mode; std::vector > m_mru; QStatusBar *mp_status_bar; QStackedWidget *mp_main_stack_widget; ProgressWidget *mp_progress_widget; tl::shared_ptr mp_progress_dialog; QFrame *mp_cp_frame; QFrame *mp_main_frame; QLabel *mp_cpx_label, *mp_cpy_label; QLabel *mp_msg_label; QLabel *mp_tech_status_label; bool m_disable_tab_selected; bool m_exited; tl::DeferredMethod dm_do_update_menu; QTimer m_message_timer; QTimer m_file_changed_timer; QTimer m_menu_update_timer; std::string m_config_window_state; std::string m_initial_technology; double m_grid_micron; std::vector m_default_grids; bool m_default_grids_updated; std::vector m_default_grid_actions; std::vector > m_key_bindings; double m_new_cell_window_size; bool m_new_layout_current_panel; std::string m_new_cell_cell_name; bool m_synchronized_views; bool m_synchronous; bool m_busy; QApplication *mp_app; lay::HelpDialog *mp_assistant; std::string m_current_session; std::string m_message; std::auto_ptr mp_printer; std::vector m_changed_files; std::map m_actions_for_slot; std::map > m_configuration_actions; tl::shared_collection m_ca_collection; // the object manager (undo/redo mechanism and others) db::Manager m_manager; lay::ProgressReporter *mp_pr; void init_menu (); void closeEvent (QCloseEvent *event); void resizeEvent (QResizeEvent *event); void format_message (); int dirty_files (std::string &dirty_files); 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); bool can_close (); lay::CellViewRef create_or_load_layout (const std::string *filename, const db::LoadLayoutOptions *options, const std::string &tech, const int mode); int do_create_view (); void do_save (bool as); void do_close (); void save_state_to_config (); void update_dock_widget_state (); void read_dock_widget_state (); virtual void plugin_registered (lay::PluginDeclaration *cls); virtual void plugin_removed (lay::PluginDeclaration *cls); void libraries_changed (); void apply_key_bindings (); }; } namespace tl { template <> struct type_traits : public type_traits { typedef tl::false_tag has_copy_constructor; typedef tl::false_tag has_default_constructor; }; } #endif