From 43bb55b1ae7b556eb5b2523410c8c21f7e6a7d29 Mon Sep 17 00:00:00 2001
From: Stefan Schimanski <sts@lyx.org>
Date: Wed, 12 Mar 2008 22:20:21 +0100
Subject: [PATCH] * on Mac keep the GuiView with id 0 hidden in memory.
 * bind the global menubar action to the GuiView with id 0
 * reuse the GuiView with id 0 when opening a new window

---
 src/frontends/qt4/GuiApplication.cpp |   34 +++++++++++++++++++++++++---------
 src/frontends/qt4/GuiApplication.h   |    7 ++++++-
 src/frontends/qt4/GuiView.cpp        |   31 +++++++++++++++++++++++++++++++
 src/frontends/qt4/GuiView.h          |    2 ++
 src/frontends/qt4/GuiWorkArea.cpp    |    4 +++-
 src/frontends/qt4/GuiWorkArea.h      |    2 ++
 src/frontends/qt4/Menus.cpp          |   15 +++++++++------
 src/frontends/qt4/Menus.h            |    4 ++--
 8 files changed, 80 insertions(+), 19 deletions(-)

diff --git a/src/frontends/qt4/GuiApplication.cpp b/src/frontends/qt4/GuiApplication.cpp
index e76f726..edf15fd 100644
--- a/src/frontends/qt4/GuiApplication.cpp
+++ b/src/frontends/qt4/GuiApplication.cpp
@@ -132,7 +132,7 @@ GuiApplication * guiApp;
 
 
 GuiApplication::GuiApplication(int & argc, char ** argv)
-	: QApplication(argc, argv), Application(), current_view_(0)
+	: QApplication(argc, argv), Application(), current_view_(0), global_menubar_(0)
 {
 	QString app_name = "LyX";
 	QCoreApplication::setOrganizationName(app_name);
@@ -146,7 +146,10 @@ GuiApplication::GuiApplication(int & argc, char ** argv)
 	if (lyxrc.quit_on_last_window_closed)
 		setQuitOnLastWindowClosed(false);
 	*/
-
+#ifdef Q_WS_MAC
+	setQuitOnLastWindowClosed(false);
+#endif
+	
 #ifdef Q_WS_X11
 	// doubleClickInterval() is 400 ms on X11 which is just too long.
 	// On Windows and Mac OS X, the operating system's value is used.
@@ -175,8 +178,6 @@ GuiApplication::GuiApplication(int & argc, char ** argv)
 			<< fromqstr(language_name));
 
 #ifdef Q_WS_MACX
-	// all windows in a Mac application share the same menu bar.
-	QMenuBar *menuBar = new QMenuBar(0);
 	// This allows to translate the strings that appear in the LyX menu.
 	addMenuTranslator();
 #endif
@@ -315,12 +316,18 @@ static void updateIds(map<int, GuiView *> const & stdmap, vector<int> & ids)
 
 void GuiApplication::createView(QString const & geometry_arg)
 {
-	updateIds(views_, view_ids_);
 	int id = 0;
-	while (views_.find(id) != views_.end())
-		id++;
-	views_[id] = new GuiView(id);
-	updateIds(views_, view_ids_);
+
+	// can we recover the initial view which was just hidden?
+	map<int, GuiView *>::iterator it = views_.find(0);
+	if (it == views_.end() || it->second->isVisible()) {
+		// create new view
+		updateIds(views_, view_ids_);
+		while (views_.find(id) != views_.end())
+			id++;
+		views_[id] = new GuiView(id);
+		updateIds(views_, view_ids_);
+	}
 
 	GuiView * view  = views_[id];
 	theLyXFunc().setLyXView(view);
@@ -342,6 +349,15 @@ void GuiApplication::createView(QString const & geometry_arg)
 	view->setFocus();
 
 	setCurrentView(*view);
+	
+#ifdef Q_WS_MACX
+	// If this is the first view, create the global default menubar which
+	// is shown for the dialogs and if no GuiView is visible.
+	if (global_menubar_ == 0) {
+		global_menubar_ = new QMenuBar(0);
+		menus().fillMenuBar(view, global_menubar_);
+	}
+#endif
 }
 
 
diff --git a/src/frontends/qt4/GuiApplication.h b/src/frontends/qt4/GuiApplication.h
index f9a770a..4a049ad 100644
--- a/src/frontends/qt4/GuiApplication.h
+++ b/src/frontends/qt4/GuiApplication.h
@@ -87,7 +87,7 @@ public:
 
 	/// Create the main window with given geometry settings.
 	/// \param geometry_arg: only for Windows platform.
-	void createView(QString const & geometry_arg);
+	void createView(QString const & geometry_arg = QString());
 	///
 	GuiView const * currentView() const { return current_view_; }
 	///
@@ -121,6 +121,9 @@ public:
 	///
 	virtual Buffer const * updateInset(Inset const * inset) const;
 
+	///
+	QMenuBar * globalMenuBar() const { return global_menubar_; }
+
 private Q_SLOTS:
 	///
 	void execBatchCommands();
@@ -171,6 +174,8 @@ public:
 	/// This LyXView is the one receiving Clipboard and Selection
 	/// events
 	GuiView * current_view_;
+	///
+	QMenuBar * global_menubar_;
 }; // GuiApplication
 
 extern GuiApplication * guiApp;
diff --git a/src/frontends/qt4/GuiView.cpp b/src/frontends/qt4/GuiView.cpp
index 9ade138..88cc71f 100644
--- a/src/frontends/qt4/GuiView.cpp
+++ b/src/frontends/qt4/GuiView.cpp
@@ -402,6 +402,15 @@ void GuiView::closeEvent(QCloseEvent * close_event)
 		}
 	}
 
+#ifdef Q_WS_MAC
+	// hide if it is the initial view
+	if (id_ == 0) {
+		hide();
+		close_event->ignore();
+		return;
+	}
+#endif
+	
 	// Make sure that no LFUN use this close to be closed View.
 	theLyXFunc().setLyXView(0);
 
@@ -534,6 +543,22 @@ void GuiView::on_currentWorkAreaChanged(GuiWorkArea * wa)
 }
 
 
+void GuiView::on_lastWorkAreaRemoved()
+{
+#ifdef Q_WS_MAC
+	// On Mac close the view if there is no Tab open anymore,
+	// but only if no splitter is visible
+	if (d.splitter_->count() == 1) {
+		TabWorkArea * twa = qobject_cast<TabWorkArea *>(d.splitter_->widget(0));
+		if (twa && twa->count() == 0) {
+			// close the view, as no tab is open anymore
+			QTimer::singleShot(0, this, SLOT(close()));
+		}
+	}
+#endif
+}
+
+
 void GuiView::updateStatusBar()
 {
 	// let the user see the explicit message
@@ -704,6 +729,9 @@ GuiWorkArea * GuiView::workArea(Buffer & buffer)
 
 GuiWorkArea * GuiView::addWorkArea(Buffer & buffer)
 {
+	if (isHidden())
+		show();
+
 	// Automatically create a TabWorkArea if there are none yet.
 	TabWorkArea * tab_widget = d.splitter_->count() 
 		? d.currentTabWorkArea() : addTabWorkArea();
@@ -716,6 +744,9 @@ TabWorkArea * GuiView::addTabWorkArea()
 	TabWorkArea * twa = new TabWorkArea;
 	QObject::connect(twa, SIGNAL(currentWorkAreaChanged(GuiWorkArea *)),
 		this, SLOT(on_currentWorkAreaChanged(GuiWorkArea *)));
+	QObject::connect(twa, SIGNAL(lastWorkAreaRemoved()),
+			 this, SLOT(on_lastWorkAreaRemoved()));
+
 	d.splitter_->addWidget(twa);
 	d.stack_widget_->setCurrentWidget(d.splitter_);
 	return twa;
diff --git a/src/frontends/qt4/GuiView.h b/src/frontends/qt4/GuiView.h
index de64048..4ccc9a9 100644
--- a/src/frontends/qt4/GuiView.h
+++ b/src/frontends/qt4/GuiView.h
@@ -151,6 +151,8 @@ private Q_SLOTS:
 
 	///
 	void on_currentWorkAreaChanged(GuiWorkArea *);
+	///
+	void on_lastWorkAreaRemoved();
 
 	/// slots to change the icon size
 	void smallSizedIcons();
diff --git a/src/frontends/qt4/GuiWorkArea.cpp b/src/frontends/qt4/GuiWorkArea.cpp
index ec398fe..2ff482f 100644
--- a/src/frontends/qt4/GuiWorkArea.cpp
+++ b/src/frontends/qt4/GuiWorkArea.cpp
@@ -1324,7 +1324,9 @@ bool TabWorkArea::removeWorkArea(GuiWorkArea * work_area)
 		else
 			// Hide tabbar if there's only one tab.
 			showBar(count() > 1);
-	}
+	} else
+		lastWorkAreaRemoved();
+
 	return true;
 }
 
diff --git a/src/frontends/qt4/GuiWorkArea.h b/src/frontends/qt4/GuiWorkArea.h
index 6c80867..8e1a0aa 100644
--- a/src/frontends/qt4/GuiWorkArea.h
+++ b/src/frontends/qt4/GuiWorkArea.h
@@ -258,6 +258,8 @@ public:
 Q_SIGNALS:
 	///
 	void currentWorkAreaChanged(GuiWorkArea *);
+	///
+	void lastWorkAreaRemoved();
 
 public Q_SLOTS:
 	///
diff --git a/src/frontends/qt4/Menus.cpp b/src/frontends/qt4/Menus.cpp
index 27b2f98..b456494 100644
--- a/src/frontends/qt4/Menus.cpp
+++ b/src/frontends/qt4/Menus.cpp
@@ -1170,7 +1170,7 @@ struct Menus::Impl {
 		    Buffer const *) const;
 
 	/// Initialize specific MACOS X menubar
-	void macxMenuBarInit(GuiView * view);
+	void macxMenuBarInit(GuiView * view, QMenuBar * qmb);
 
 	/// Mac special menu.
 	/** This defines a menu whose entries list the FuncRequests
@@ -1211,7 +1211,7 @@ struct Menus::Impl {
   that this menubar will be used also when one of LyX' dialogs has
   focus. (JMarc)
 */
-void Menus::Impl::macxMenuBarInit(GuiView * view)
+void Menus::Impl::macxMenuBarInit(GuiView * view, QMenuBar * qmb)
 {
 	// The Mac menubar initialisation must be done only once!
 	static bool done = false;
@@ -1260,7 +1260,7 @@ void Menus::Impl::macxMenuBarInit(GuiView * view)
 
 	// add the entries to a QMenu that will eventually be empty
 	// and therefore invisible.
-	QMenu * qMenu = view->menuBar()->addMenu("special");
+	QMenu * qMenu = qmb->addMenu("special");
 	MenuDefinition::const_iterator cit = specialmenu_.begin();
 	MenuDefinition::const_iterator end = specialmenu_.end();
 	for (size_t i = 0 ; cit != end ; ++cit, ++i) {
@@ -1464,14 +1464,17 @@ bool Menus::searchMenu(FuncRequest const & func,
 }
 
 
-void Menus::fillMenuBar(GuiView * view)
+void Menus::fillMenuBar(GuiView * view, QMenuBar * qmb)
 {
+	if (qmb == 0)
+		qmb = view->menuBar();
+	
 	// Clear all menubar contents before filling it.
-	view->menuBar()->clear();
+	qmb->clear();
 	
 #ifdef Q_WS_MACX
 	// setup special mac specific menu item
-	d->macxMenuBarInit(view);
+	d->macxMenuBarInit(view, qmb);
 #endif
 
 	LYXERR(Debug::GUI, "populating menu bar" << fromqstr(d->menubar_.name()));
diff --git a/src/frontends/qt4/Menus.h b/src/frontends/qt4/Menus.h
index 80de0da..4281d47 100644
--- a/src/frontends/qt4/Menus.h
+++ b/src/frontends/qt4/Menus.h
@@ -62,8 +62,8 @@ public:
 	///
 	bool searchMenu(FuncRequest const & func,
 		std::vector<docstring> & names) const;
-	///
-	void fillMenuBar(GuiView * view);
+	/// Uses the view's menubar if \c qmb is 0.
+	void fillMenuBar(GuiView * view, QMenuBar * qmb = 0);
 
 	/// \return a top-level submenu given its name.
 	Menu * menu(QString const & name, GuiView & view);
-- 
1.5.3.7

