Further refactoring - more functionality for GUI/non-GUI application classes.

This commit is contained in:
Matthias Koefferlein 2017-12-26 00:03:40 +01:00
parent bbb1514184
commit 9906565013
2 changed files with 305 additions and 176 deletions

View File

@ -225,6 +225,8 @@ ApplicationBase::ApplicationBase ()
m_write_config_file (true),
m_gtf_replay_rate (0),
m_gtf_replay_stop (-1),
m_gtf_record (),
m_gtf_save_incremental (false),
m_no_macros (false),
m_same_view (false),
m_sync_mode (false),
@ -233,12 +235,7 @@ ApplicationBase::ApplicationBase ()
m_editable (false),
m_enable_undo (true),
mp_ruby_interpreter (0),
mp_python_interpreter (0),
mp_mw (0),
mp_pr (0),
mp_pb (0),
mp_plugin_root (0),
mp_recorder (0)
mp_python_interpreter (0)
{
// nothing yet - see init
}
@ -256,8 +253,6 @@ ApplicationBase::init_app (int &argc, char **argv, bool non_ui_mode)
tl::set_ui_exception_handlers (ui_exception_handler_tl, ui_exception_handler_std, ui_exception_handler_def);
}
mp_dm_scheduler.reset (new tl::DeferredMethodScheduler ());
// initialize the system codecs (Hint: this must be done after the QApplication is initialized because
// it will call setlocale)
tl::initialize_codecs ();
@ -284,9 +279,6 @@ ApplicationBase::init_app (int &argc, char **argv, bool non_ui_mode)
tl_assert (ms_instance == 0);
ms_instance = this;
std::string gtf_record;
bool gtf_save_incremental = false;
// get and create the klayout appdata folder if required
m_appdata_path = lay::get_appdata_path ();
@ -491,11 +483,11 @@ ApplicationBase::init_app (int &argc, char **argv, bool non_ui_mode)
} else if (a == "-gr" && (i + 1) < argc) {
gtf_record = args [++i];
m_gtf_record = args [++i];
} else if (a == "-gi") {
gtf_save_incremental = true;
m_gtf_save_incremental = true;
} else if (a == "-gp" && (i + 1) < argc) {
@ -795,11 +787,10 @@ ApplicationBase::init_app (int &argc, char **argv, bool non_ui_mode)
db::set_default_editable_mode (m_editable);
db::enable_transactions (m_enable_undo);
if (qapp_gui () && ! gtf_record.empty ()) {
// since the recorder tracks QAction connections etc., it must be instantiated before every other
if (! m_gtf_record.empty ()) {
// since the recorder tracks QAction connections etc., it must be instantiated before every other
// object performing a gtf::action_connect for example
mp_recorder = new gtf::Recorder (qapp_gui (), gtf_record);
mp_recorder->save_incremental (gtf_save_incremental);
prepare_recording (m_gtf_record, m_gtf_save_incremental);
}
tl::Eval::set_global_var ("appdata_path", tl::Variant (m_appdata_path));
@ -822,16 +813,8 @@ ApplicationBase::init_app (int &argc, char **argv, bool non_ui_mode)
// suffixes through the MacroInterpreter interface.
lym::MacroCollection::root ().rescan ();
if (qapp_gui ()) {
mp_mw = new lay::MainWindow (qapp_gui (), "main_window");
QObject::connect (mp_mw, SIGNAL (closed ()), qapp_gui (), SLOT (quit ()));
mp_plugin_root = mp_mw;
} else {
mp_pr = new lay::ProgressReporter ();
mp_pb = new TextProgress (10 /*verbosity level*/);
mp_pr->set_progress_bar (mp_pb);
mp_plugin_root = new lay::PluginRoot ();
}
// creates the main window or plugin root as required
setup ();
// initialize the plugins for the first time
if (tl::verbosity () >= 20) {
@ -842,11 +825,11 @@ ApplicationBase::init_app (int &argc, char **argv, bool non_ui_mode)
if (tl::verbosity () >= 20) {
tl::info << " " << cls.current_name () << " [" << cls.current_position () << "]";
}
pd->initialize (mp_plugin_root);
pd->initialize (plugin_root ());
}
// establish the configuration
mp_plugin_root->config_setup ();
plugin_root ()->config_setup ();
// Some info output
if (tl::verbosity () >= 20) {
@ -868,11 +851,8 @@ ApplicationBase::~ApplicationBase ()
{
tl::set_ui_exception_handlers (0, 0, 0);
if (! ms_instance) {
return;
}
shutdown ();
// check whether shutdown was called
tl_assert (ms_instance == 0);
}
std::vector<std::string>
@ -933,26 +913,28 @@ ApplicationBase::exit (int result)
if (! result) {
finish ();
}
// uninitialize the plugins
for (tl::Registrar<lay::PluginDeclaration>::iterator cls = tl::Registrar<lay::PluginDeclaration>::begin (); cls != tl::Registrar<lay::PluginDeclaration>::end (); ++cls) {
lay::PluginDeclaration *pd = const_cast<lay::PluginDeclaration *> (&*cls);
pd->uninitialize (plugin_root ());
}
shutdown ();
::exit (result);
}
void
ApplicationBase::finish ()
{
// save the recorded test events
if (mp_mw && mp_recorder && mp_recorder->recording ()) {
mp_recorder->stop ();
mp_recorder->save ();
}
if (mp_plugin_root && m_write_config_file) {
if (plugin_root () && m_write_config_file) {
if (! m_config_file_to_write.empty ()) {
if (tl::verbosity () >= 20) {
tl::info << tl::to_string (QObject::tr ("Updating configuration file ")) << m_config_file_to_write;
}
mp_plugin_root->write_config (m_config_file_to_write);
plugin_root ()->write_config (m_config_file_to_write);
}
if (! m_config_file_to_delete.empty () && m_config_file_to_delete != m_config_file_to_write) {
if (tl::verbosity () >= 20) {
@ -964,48 +946,21 @@ ApplicationBase::finish ()
}
}
void
ApplicationBase::prepare_recording (const std::string & /*gtf_record*/, bool /*gtf_record_incremental*/)
{
// the base class does nothing
}
void
ApplicationBase::start_recording ()
{
// the base class does nothing
}
void
ApplicationBase::shutdown ()
{
// uninitialize the plugins
for (tl::Registrar<lay::PluginDeclaration>::iterator cls = tl::Registrar<lay::PluginDeclaration>::begin (); cls != tl::Registrar<lay::PluginDeclaration>::end (); ++cls) {
lay::PluginDeclaration *pd = const_cast<lay::PluginDeclaration *> (&*cls);
pd->uninitialize (mp_plugin_root);
}
if (mp_mw) {
delete mp_mw;
mp_mw = 0;
mp_plugin_root = 0;
} else if (mp_plugin_root) {
delete mp_plugin_root;
mp_plugin_root = 0;
}
// delete all other top level widgets for safety - we don't want Ruby clean them up for us
QWidgetList tl_widgets;
if (qapp_gui ()) {
tl_widgets = qapp_gui ()->topLevelWidgets ();
}
for (QWidgetList::iterator w = tl_widgets.begin (); w != tl_widgets.end (); ++w) {
delete *w;
}
if (mp_pr) {
delete mp_pr;
mp_pr = 0;
}
if (mp_pb) {
delete mp_pb;
mp_pb = 0;
}
if (mp_recorder) {
delete mp_recorder;
mp_recorder = 0;
}
if (mp_ruby_interpreter) {
delete mp_ruby_interpreter;
mp_ruby_interpreter = 0;
@ -1080,25 +1035,24 @@ ApplicationBase::usage ()
int
ApplicationBase::run ()
{
lay::MainWindow *mw = main_window ();
gtf::Player player (0);
if (mp_mw) {
if (mw) {
mp_mw->set_synchronous (m_sync_mode);
(mw)->set_synchronous (m_sync_mode);
if (! m_no_gui) {
mp_mw->setWindowTitle (tl::to_qstring (version ()));
mp_mw->resize (800, 600);
mp_mw->show ();
(mw)->setWindowTitle (tl::to_qstring (version ()));
(mw)->resize (800, 600);
(mw)->show ();
}
if (! m_gtf_replay.empty ()) {
player.load (m_gtf_replay);
}
if (mp_recorder) {
mp_recorder->start ();
}
start_recording ();
}
@ -1108,7 +1062,7 @@ ApplicationBase::run ()
for (std::vector <std::string>::const_iterator c = m_config_files.begin (); c != m_config_files.end (); ++c) {
BEGIN_PROTECTED_CLEANUP
mp_plugin_root->read_config (*c);
plugin_root ()->read_config (*c);
// if the last config was read successfully no reset will happen:
config_failed = false;
END_PROTECTED_CLEANUP {
@ -1153,7 +1107,7 @@ ApplicationBase::run ()
// Run plugin and macro specific initializations
autorun ();
if (mp_mw) {
if (mw) {
for (std::vector <std::pair<file_type, std::pair<std::string, std::string> > >::const_iterator f = m_files.begin (); f != m_files.end (); ++f) {
@ -1162,29 +1116,29 @@ ApplicationBase::run ()
std::string filename = f->second.first;
if (f->first != layout_file_with_tech) {
mp_mw->add_mru (f->second.first);
mp_mw->load_layout (f->second.first, m_same_view ? 2 /*same view*/ : 1 /*new view*/);
mw->add_mru (f->second.first);
mw->load_layout (f->second.first, m_same_view ? 2 /*same view*/ : 1 /*new view*/);
} else {
mp_mw->add_mru (f->second.first, f->second.second);
mp_mw->load_layout (f->second.first, f->second.second, m_same_view ? 2 /*same view*/ : 1 /*new view*/);
mw->add_mru (f->second.first, f->second.second);
mw->load_layout (f->second.first, f->second.second, m_same_view ? 2 /*same view*/ : 1 /*new view*/);
}
// Make the first one loaded the active one.
if (mp_mw->current_view ()) {
mp_mw->current_view ()->set_active_cellview_index (0);
if (mw->current_view ()) {
mw->current_view ()->set_active_cellview_index (0);
}
} else {
if (mp_mw->current_view () == 0) {
mp_mw->create_view ();
if (mw->current_view () == 0) {
mw->create_view ();
}
if (mp_mw->current_view () != 0) {
if (mw->current_view () != 0) {
std::auto_ptr <rdb::Database> db (new rdb::Database ());
db->load (f->second.first);
int rdb_index = mp_mw->current_view ()->add_rdb (db.release ());
mp_mw->current_view ()->open_rdb_browser (rdb_index, mp_mw->current_view ()->active_cellview_index ());
int rdb_index = mw->current_view ()->add_rdb (db.release ());
mw->current_view ()->open_rdb_browser (rdb_index, mw->current_view ()->active_cellview_index ());
}
}
@ -1192,23 +1146,23 @@ ApplicationBase::run ()
if (! m_layer_props_file.empty ()) {
if (m_lyp_map_all_cvs && mp_mw->is_single_cv_layer_properties_file (m_layer_props_file)) {
mp_mw->load_layer_properties (m_layer_props_file, -1, true /*all views*/, m_lyp_add_default);
if (m_lyp_map_all_cvs && mw->is_single_cv_layer_properties_file (m_layer_props_file)) {
mw->load_layer_properties (m_layer_props_file, -1, true /*all views*/, m_lyp_add_default);
} else {
mp_mw->load_layer_properties (m_layer_props_file, true /*all views*/, m_lyp_add_default);
mw->load_layer_properties (m_layer_props_file, true /*all views*/, m_lyp_add_default);
}
tl::log << "Layer properties loaded '" << m_layer_props_file << "'";
// because the layer may carry transformations, we need to refit the cellviews.
for (unsigned int v = 0; v != mp_mw->views (); ++v) {
mp_mw->view (v)->zoom_fit ();
for (unsigned int v = 0; v != mw->views (); ++v) {
mw->view (v)->zoom_fit ();
}
}
if (! m_session_file.empty ()) {
mp_mw->restore_session (m_session_file);
mw->restore_session (m_session_file);
tl::log << "Session restored '" << m_session_file << "'";
}
@ -1219,20 +1173,20 @@ ApplicationBase::run ()
// Give the plugins a change to do some last-minute initialisation and checks
for (tl::Registrar<lay::PluginDeclaration>::iterator cls = tl::Registrar<lay::PluginDeclaration>::begin (); cls != tl::Registrar<lay::PluginDeclaration>::end (); ++cls) {
lay::PluginDeclaration *pd = const_cast<lay::PluginDeclaration *> (&*cls);
pd->initialized (mp_mw);
pd->initialized (mw);
}
if (! m_no_gui && m_gtf_replay.empty () && ! mp_recorder) {
if (! m_no_gui && m_gtf_replay.empty () && m_gtf_record.empty ()) {
// Show initial tip window if required
mp_mw->about_to_exec ();
mw->about_to_exec ();
}
} else if (mp_plugin_root) {
} else if (plugin_root ()) {
// Give the plugins a change to do some last-minute initialisation and checks
for (tl::Registrar<lay::PluginDeclaration>::iterator cls = tl::Registrar<lay::PluginDeclaration>::begin (); cls != tl::Registrar<lay::PluginDeclaration>::end (); ++cls) {
lay::PluginDeclaration *pd = const_cast<lay::PluginDeclaration *> (&*cls);
pd->initialized (mp_plugin_root);
pd->initialized (plugin_root ());
}
}
@ -1299,37 +1253,15 @@ dump_children (QObject *obj, int level = 0)
}
void
ApplicationBase::process_events (QEventLoop::ProcessEventsFlags flags, bool silent)
ApplicationBase::process_events (QEventLoop::ProcessEventsFlags /*flags*/, bool /*silent*/)
{
if (mp_mw) {
if (silent) {
mp_dm_scheduler->enable (false);
}
#if QT_VERSION < 0x050000
QApplication::syncX ();
#endif
mp_mw->enter_busy_mode (true);
try {
QApplication::processEvents (flags);
} catch (...) {
// ignore exceptions
}
mp_mw->enter_busy_mode (false);
if (silent) {
mp_dm_scheduler->enable (true);
}
}
// The base class implementation does nothing ..
}
bool
ApplicationBase::write_config (const std::string &config_file)
{
return mp_plugin_root ? mp_plugin_root->write_config (config_file) : 0;
return plugin_root () ? plugin_root ()->write_config (config_file) : 0;
}
void
@ -1346,38 +1278,38 @@ ApplicationBase::reset_config ()
void
ApplicationBase::clear_config ()
{
if (mp_plugin_root) {
mp_plugin_root->clear_config ();
if (plugin_root ()) {
plugin_root ()->clear_config ();
}
}
bool
ApplicationBase::read_config (const std::string &config_file)
{
return mp_plugin_root ? mp_plugin_root->read_config (config_file) : true;
return plugin_root () ? plugin_root ()->read_config (config_file) : true;
}
void
ApplicationBase::set_config (const std::string &name, const std::string &value)
{
if (mp_plugin_root) {
mp_plugin_root->config_set (name, value);
if (plugin_root ()) {
plugin_root ()->config_set (name, value);
}
}
void
ApplicationBase::config_end ()
{
if (mp_plugin_root) {
mp_plugin_root->config_end ();
if (plugin_root ()) {
plugin_root ()->config_end ();
}
}
std::string
ApplicationBase::get_config (const std::string &name) const
{
if (mp_plugin_root) {
return mp_plugin_root->config_get (name);
if (plugin_root ()) {
return plugin_root ()->config_get (name);
} else {
return std::string ();
}
@ -1387,8 +1319,8 @@ std::vector<std::string>
ApplicationBase::get_config_names () const
{
std::vector<std::string> names;
if (mp_plugin_root) {
mp_plugin_root->get_config_names (names);
if (plugin_root ()) {
plugin_root ()->get_config_names (names);
}
return names;
}
@ -1405,7 +1337,9 @@ ApplicationBase::special_app_flag (const std::string &name)
// GuiApplication implementation
GuiApplication::GuiApplication (int &argc, char **argv)
: QApplication (argc, argv), ApplicationBase ()
: QApplication (argc, argv), ApplicationBase (),
mp_mw (0),
mp_recorder (0)
{
// install a special style proxy to overcome the issue of black-on-black tree expanders
setStyle (new lay::BackgroundAwareTreeStyle (0));
@ -1415,9 +1349,24 @@ GuiApplication::GuiApplication (int &argc, char **argv)
setAttribute (Qt::AA_DontShowIconsInMenus, false);
#endif
// only a GUI-enabled application runs an event loop and can have a deferred
// method scheduler therefore.
mp_dm_scheduler.reset (new tl::DeferredMethodScheduler ());
init_app (argc, argv, false);
}
GuiApplication::~GuiApplication ()
{
// uninitialize the plugins
for (tl::Registrar<lay::PluginDeclaration>::iterator cls = tl::Registrar<lay::PluginDeclaration>::begin (); cls != tl::Registrar<lay::PluginDeclaration>::end (); ++cls) {
lay::PluginDeclaration *pd = const_cast<lay::PluginDeclaration *> (&*cls);
pd->uninitialize (plugin_root ());
}
shutdown ();
}
bool
GuiApplication::notify (QObject *receiver, QEvent *e)
{
@ -1469,15 +1418,125 @@ GuiApplication::exec ()
return QApplication::exec ();
}
void
GuiApplication::shutdown ()
{
if (mp_mw) {
delete mp_mw;
mp_mw = 0;
}
// delete all other top level widgets for safety - we don't want Ruby clean them up for us
QWidgetList tl_widgets = topLevelWidgets ();
for (QWidgetList::iterator w = tl_widgets.begin (); w != tl_widgets.end (); ++w) {
delete *w;
}
if (mp_recorder) {
delete mp_recorder;
mp_recorder = 0;
}
ApplicationBase::shutdown ();
}
void
GuiApplication::finish ()
{
// save the recorded test events
if (mp_recorder && mp_recorder->recording ()) {
mp_recorder->stop ();
mp_recorder->save ();
}
ApplicationBase::finish ();
}
void
GuiApplication::prepare_recording (const std::string &gtf_record, bool gtf_save_incremental)
{
tl_assert (mp_recorder == 0);
// since the recorder tracks QAction connections etc., it must be instantiated before every other
// object performing a gtf::action_connect for example
mp_recorder = new gtf::Recorder (this, gtf_record);
mp_recorder->save_incremental (gtf_save_incremental);
}
void
GuiApplication::start_recording ()
{
if (mp_recorder) {
mp_recorder->start ();
}
}
lay::PluginRoot *
GuiApplication::plugin_root () const
{
return mp_mw;
}
void
GuiApplication::setup ()
{
tl_assert (mp_mw == 0);
mp_mw = new lay::MainWindow (this, "main_window");
QObject::connect (mp_mw, SIGNAL (closed ()), this, SLOT (quit ()));
}
void
GuiApplication::process_events (QEventLoop::ProcessEventsFlags flags, bool silent)
{
if (mp_mw) {
if (silent) {
mp_dm_scheduler->enable (false);
}
#if QT_VERSION < 0x050000
QApplication::syncX ();
#endif
mp_mw->enter_busy_mode (true);
try {
QApplication::processEvents (flags);
} catch (...) {
// ignore exceptions
}
mp_mw->enter_busy_mode (false);
if (silent) {
mp_dm_scheduler->enable (true);
}
}
}
// --------------------------------------------------------------------------------
// NonGuiApplication implementation
NonGuiApplication::NonGuiApplication (int &argc, char **argv)
: QCoreApplication (argc, argv), ApplicationBase ()
: QCoreApplication (argc, argv), ApplicationBase (),
mp_pr (0),
mp_pb (0),
mp_plugin_root (0)
{
init_app (argc, argv, true);
}
NonGuiApplication::~NonGuiApplication ()
{
// uninitialize the plugins
for (tl::Registrar<lay::PluginDeclaration>::iterator cls = tl::Registrar<lay::PluginDeclaration>::begin (); cls != tl::Registrar<lay::PluginDeclaration>::end (); ++cls) {
lay::PluginDeclaration *pd = const_cast<lay::PluginDeclaration *> (&*cls);
pd->uninitialize (plugin_root ());
}
shutdown ();
}
int
NonGuiApplication::exec ()
{
@ -1485,5 +1544,35 @@ NonGuiApplication::exec ()
return 0;
}
void
NonGuiApplication::shutdown ()
{
if (mp_plugin_root) {
delete mp_plugin_root;
mp_plugin_root = 0;
}
if (mp_pr) {
delete mp_pr;
mp_pr = 0;
}
if (mp_pb) {
delete mp_pb;
mp_pb = 0;
}
ApplicationBase::shutdown ();
}
void
NonGuiApplication::setup ()
{
mp_pr = new lay::ProgressReporter ();
mp_pb = new TextProgress (10 /*verbosity level*/);
mp_pr->set_progress_bar (mp_pb);
mp_plugin_root = new lay::PluginRoot ();
}
}

View File

@ -128,14 +128,12 @@ public:
std::string usage ();
/**
* @brief Return the main window's reference
* @brief Returns the main window's reference
*
* If the application has not been initialized properly, this pointer is 0.
* If the application has not been initialized properly or does not support GUI,
* this pointer is 0.
*/
MainWindow *main_window () const
{
return mp_mw;
}
virtual MainWindow *main_window () const = 0;
/**
* @brief Runs plugin and macro specific initializations
@ -164,7 +162,7 @@ public:
* handling for the "close application window" case and a "silent" mode. In that mode, processing
* of deferred methods is disabled.
*/
void process_events (QEventLoop::ProcessEventsFlags flags, bool silent = false);
virtual void process_events (QEventLoop::ProcessEventsFlags flags, bool silent = false);
/**
* @brief A shortcut for the default process_events
@ -325,11 +323,6 @@ public:
return m_native_plugins;
}
/**
* @brief Gets the QCoreApplication object
*/
virtual QCoreApplication *qapp () { return 0; }
/**
* @brief Gets the QApplication object
* This method will return non-null only if a GUI-enabled application is present.
@ -338,10 +331,14 @@ public:
protected:
void init_app (int &argc, char **argv, bool non_ui_mode);
virtual void setup () = 0;
virtual void shutdown ();
virtual void prepare_recording (const std::string &gtf_record, bool gtf_record_incremental);
virtual void start_recording ();
virtual lay::PluginRoot *plugin_root () const = 0;
virtual void finish ();
private:
void shutdown ();
void finish ();
std::vector<std::string> scan_global_modules ();
enum file_type {
@ -366,10 +363,11 @@ private:
std::vector<std::string> m_klayout_path;
std::string m_inst_path;
std::string m_appdata_path;
std::vector< std::pair<std::string, std::string> > m_macro_categories;
bool m_write_config_file;
std::vector< std::pair<std::string, std::string> > m_variables;
int m_gtf_replay_rate, m_gtf_replay_stop;
std::string m_gtf_record;
bool m_gtf_save_incremental;
bool m_no_macros;
bool m_same_view;
bool m_sync_mode;
@ -377,16 +375,10 @@ private:
bool m_vo_mode;
bool m_editable;
bool m_enable_undo;
std::auto_ptr<tl::DeferredMethodScheduler> mp_dm_scheduler;
// HINT: the ruby interpreter must be destroyed before MainWindow
// in order to maintain a valid MainWindow reference for ruby scripts and Ruby's GC all the time.
gsi::Interpreter *mp_ruby_interpreter;
gsi::Interpreter *mp_python_interpreter;
MainWindow *mp_mw;
lay::ProgressReporter *mp_pr;
lay::ProgressBar *mp_pb;
lay::PluginRoot *mp_plugin_root;
gtf::Recorder *mp_recorder;
std::vector<PluginDescriptor> m_native_plugins;
};
@ -398,9 +390,9 @@ class LAY_PUBLIC GuiApplication
{
public:
GuiApplication (int &argc, char **argv);
~GuiApplication ();
QApplication *qapp_gui () { return this; }
QCoreApplication *qapp () { return this; }
/**
* @brief Reimplementation of notify from QApplication
@ -427,6 +419,33 @@ public:
{
ApplicationBase::exit (result);
}
/**
* @brief Returns the main window's reference
*/
virtual MainWindow *main_window () const
{
return mp_mw;
}
/**
* @brief Reimplementation of ApplicationBase interface
*/
virtual void process_events (QEventLoop::ProcessEventsFlags flags, bool silent);
protected:
virtual void setup ();
virtual void shutdown ();
virtual void finish ();
virtual void prepare_recording (const std::string &gtf_record, bool gtf_save_incremental);
virtual void start_recording ();
virtual lay::PluginRoot *plugin_root () const;
private:
MainWindow *mp_mw;
gtf::Recorder *mp_recorder;
std::auto_ptr<tl::DeferredMethodScheduler> mp_dm_scheduler;
};
/**
@ -437,9 +456,7 @@ class LAY_PUBLIC NonGuiApplication
{
public:
NonGuiApplication (int &argc, char **argv);
QApplication *qapp_gui () { return 0; }
QCoreApplication *qapp () { return this; }
~NonGuiApplication ();
/**
* @brief Gets the application instance, cast to this class
@ -461,6 +478,29 @@ public:
{
ApplicationBase::exit (result);
}
/**
* @brief Returns the main window's reference
* This incarnation returns 0 since no GUI is supported.
*/
virtual MainWindow *main_window () const
{
return 0;
}
protected:
virtual void setup ();
virtual void shutdown ();
virtual lay::PluginRoot *plugin_root () const
{
return mp_plugin_root;
}
private:
lay::ProgressReporter *mp_pr;
lay::ProgressBar *mp_pb;
lay::PluginRoot *mp_plugin_root;
};
} // namespace lay