Georg Baum wrote:
Abdelrazak Younes wrote:
Georg Baum wrote:
Abdelrazak Younes wrote:
OK. The fix is simple. As you know the Application instance is not
created when the export command-line feature is requested. This patch
fixes the crash and goes in soon.
So it is not possible to use the server in commandline mode? I am not
sure whether this is good.
Why would you want to use the server in command-line mode? Please don't
mix command-line and console mode (as Lars correctly pointed out
recently).
IIRC console mode was a hypothetical text frontend? With command line mode I
meant that LyX is started with a command line argument, either an explicit
command line option like export or an lfun (or lfun sequence).
We have the same understanding then but I would like to distinguish
three modes:
"command-line" = some tasks and exit
"server only" = no gui at all but a lyx server listening to connections.
"gui" = gui + server.
Command-line is for doing one or more tasks and then exit.
Not necessarily exit. Why should I not be able to start up a server session
with a commandline flag that then waits for client connections and
terminates when told by the client?
In theory this is possible. But right now, the lyx server and server
socket depends on Qt functionalities. It is thus not possible to start
the server without loading the GUI.
Right now the server depends on the frontend. If there is a need to have
a LyX server that could work without a frontend (not even a console
frontend) then that is another running mode, a server mode. I can
provide this functionality if needed.
I don't think that from a logical PoV it makes sense to connect the server
to the frontend. The server is IMHO completely independant from the
frontend.
Agreed but see above and below for a solution.
Others already pointed out that putting everything into a single global
variable might not always be the best solution. In this case it looks to me
like the connection of server and Application is artificial.
Indeed, and this is because the methods registerSocketCallback() and
unregisterSocketCallback() depends on Qt functionality. But it is
possible to create a minimal application without any GUI in it using
QtCore only. The attached patch goes toward this direction.
As you can see, I have transfered all singletons from Application to
LyX::Singletons.
I still have problems with keysym but it's working fine already.
Abdel.
Index: format.C
===================================================================
--- format.C (revision 15361)
+++ format.C (working copy)
@@ -312,7 +312,7 @@
command = subst(command, token_from, quoteName(filename));
command = subst(command, token_path, quoteName(onlyPath(filename)));
- command = subst(command, token_socket,
quoteName(theApp->socket().address()));
+ command = subst(command, token_socket,
quoteName(theLyXServerSocket().address()));
lyxerr[Debug::FILES] << "Executing command: " << command << std::endl;
buffer.message(_("Executing command: ") + lyx::from_utf8(command));
@@ -371,7 +371,7 @@
command = subst(command, token_from, quoteName(filename));
command = subst(command, token_path, quoteName(onlyPath(filename)));
- command = subst(command, token_socket,
quoteName(theApp->socket().address()));
+ command = subst(command, token_socket,
quoteName(theLyXServerSocket().address()));
lyxerr[Debug::FILES] << "Executing command: " << command << std::endl;
buffer.message(_("Executing command: ") + lyx::from_utf8(command));
Index: frontends/Application.C
===================================================================
--- frontends/Application.C (revision 15361)
+++ frontends/Application.C (working copy)
@@ -20,16 +20,12 @@
#include "frontends/LyXView.h"
#include "frontends/WorkArea.h"
-#include "bufferlist.h"
#include "funcrequest.h"
#include "FuncStatus.h"
#include "lyx_main.h"
-#include "LyXAction.h"
#include "lyxfont.h"
#include "lyxfunc.h"
#include "lyxrc.h"
-#include "lyxserver.h"
-#include "lyxsocket.h"
#include "support/lstrings.h"
#include "support/os.h"
@@ -43,60 +39,12 @@
namespace lyx {
namespace frontend {
-/// The main application class private implementation.
-struct Application_pimpl
-{
- /// our function handler
- boost::scoped_ptr<LyXFunc> lyxfunc_;
- ///
- boost::scoped_ptr<LyXServer> lyx_server_;
- ///
- boost::scoped_ptr<LyXServerSocket> lyx_socket_;
-};
-
Application::Application(int &, char **)
{
- pimpl_ = new Application_pimpl;
}
-LyXFunc & Application::lyxFunc()
-{
- return *pimpl_->lyxfunc_.get();
-}
-
-
-LyXFunc const & Application::lyxFunc() const
-{
- return *pimpl_->lyxfunc_.get();
-}
-
-
-LyXServer & Application::server()
-{
- return *pimpl_->lyx_server_.get();
-}
-
-
-LyXServer const & Application::server() const
-{
- return *pimpl_->lyx_server_.get();
-}
-
-
-LyXServerSocket & Application::socket()
-{
- return *pimpl_->lyx_socket_.get();
-}
-
-
-LyXServerSocket const & Application::socket() const
-{
- return *pimpl_->lyx_socket_.get();
-}
-
-
void Application::setBufferView(BufferView * buffer_view)
{
buffer_view_ = buffer_view;
@@ -117,7 +65,7 @@
int view_id = gui().newView();
LyXView & view = gui().view(view_id);
- pimpl_->lyxfunc_.reset(new LyXFunc(&view));
+ theLyXFunc().setLyXView(&view);
// FIXME: for now we assume that there is only one LyXView with id = 0.
/*int workArea_id_ =*/ gui().newWorkArea(width, height, 0);
@@ -132,42 +80,13 @@
int Application::start(std::string const & batch)
{
- pimpl_->lyx_server_.reset(new LyXServer(pimpl_->lyxfunc_.get(),
lyxrc.lyxpipes));
- pimpl_->lyx_socket_.reset(new LyXServerSocket(pimpl_->lyxfunc_.get(),
- lyx::support::os::internal_path(package().temp_dir() +
"/lyxsocket")));
-
- // handle the batch commands the user asked for
- if (!batch.empty()) {
- pimpl_->lyxfunc_->dispatch(lyxaction.lookupFunc(batch));
- }
-
return exec();
}
} // namespace frontend
-
-
-FuncStatus getStatus(FuncRequest const & action)
-{
- return theApp->lyxFunc().getStatus(action);
-}
-
-
-void dispatch(FuncRequest const & action)
-{
- theApp->lyxFunc().dispatch(action);
-}
-
} // namespace lyx
-LyXFunc & theLyXFunc()
-{
- BOOST_ASSERT(theApp);
- return theApp->lyxFunc();
-}
-
-
lyx::frontend::FontLoader & theFontLoader()
{
static lyx::frontend::NoGuiFontLoader no_gui_font_loader;
Index: frontends/Application.h
===================================================================
--- frontends/Application.h (revision 15361)
+++ frontends/Application.h (working copy)
@@ -15,11 +15,7 @@
#include <string>
-class BufferList;
class BufferView;
-class LyXFunc;
-class LyXServer;
-class LyXServerSocket;
class LyXView;
class LColor_color;
@@ -29,7 +25,6 @@
namespace frontend {
-struct Application_pimpl;
class Clipboard;
class FontLoader;
class Gui;
@@ -116,16 +111,6 @@
*/
virtual void unregisterSocketCallback(int fd) = 0;
- ///
- LyXFunc & lyxFunc();
- LyXFunc const & lyxFunc() const;
- ///
- LyXServer & server();
- LyXServer const & server() const;
- ///
- LyXServerSocket & socket();
- LyXServerSocket const & socket() const;
-
/// Create the main window with given geometry settings.
LyXView & createView(unsigned int width, unsigned int height,
int posx, int posy, bool maximize);
@@ -139,10 +124,6 @@
/// FIXME: \todo use Gui::currentView() in the future
BufferView * buffer_view_;
-private:
- /// Application private implementation.
- Application_pimpl * pimpl_;
-
}; // Application
} // namespace frontend
Index: lyx_main.C
===================================================================
--- lyx_main.C (revision 15361)
+++ lyx_main.C (working copy)
@@ -31,10 +31,12 @@
#include "session.h"
#include "LColor.h"
#include "lyx_cb.h"
+#include "LyXAction.h"
#include "lyxfunc.h"
#include "lyxlex.h"
#include "lyxrc.h"
#include "lyxserver.h"
+#include "lyxsocket.h"
#include "lyxtextclasslist.h"
#include "MenuBackend.h"
#include "mover.h"
@@ -107,8 +109,9 @@
*/
bool use_gui = true;
-}
+} // namespace lyx
+
namespace {
// Filled with the command line arguments "foo" of "-sysdir foo" or
@@ -139,8 +142,27 @@
} // namespace anon
+/// The main application class private implementation.
+struct LyX::Singletons
+{
+ /// our function handler
+ LyXFunc lyxfunc_;
+ ///
+ BufferList buffer_list_;
+ /// lyx session, containing lastfiles, lastfilepos, and lastopened
+ boost::scoped_ptr<lyx::Session> session_;
+ ///
+ boost::scoped_ptr<LyXServer> lyx_server_;
+ ///
+ boost::scoped_ptr<LyXServerSocket> lyx_socket_;
+ ///
+ boost::scoped_ptr<lyx::frontend::Application> application_;
+};
+
+
boost::scoped_ptr<LyX> LyX::singleton_;
+
int LyX::exec(int & argc, char * argv[])
{
BOOST_ASSERT(!singleton_.get());
@@ -167,45 +189,87 @@
}
-BufferList & theBufferList()
-{
- return LyX::ref().bufferList();
-}
-
-
LyX::LyX()
: first_start(false), geometryOption_(false)
{
- buffer_list_.reset(new BufferList);
+ pimpl_.reset(new Singletons);
}
BufferList & LyX::bufferList()
{
- return *buffer_list_.get();
+ return pimpl_->buffer_list_;
}
BufferList const & LyX::bufferList() const
{
- return *buffer_list_.get();
+ return pimpl_->buffer_list_;
}
lyx::Session & LyX::session()
{
- BOOST_ASSERT(session_.get());
- return *session_.get();
+ BOOST_ASSERT(pimpl_->session_.get());
+ return *pimpl_->session_.get();
}
lyx::Session const & LyX::session() const
{
- BOOST_ASSERT(session_.get());
- return *session_.get();
+ BOOST_ASSERT(pimpl_->session_.get());
+ return *pimpl_->session_.get();
}
+LyXFunc & LyX::lyxFunc()
+{
+ return pimpl_->lyxfunc_;
+}
+
+
+LyXFunc const & LyX::lyxFunc() const
+{
+ return pimpl_->lyxfunc_;
+}
+
+
+LyXServer & LyX::server()
+{
+ return *pimpl_->lyx_server_.get();
+}
+
+
+LyXServer const & LyX::server() const
+{
+ return *pimpl_->lyx_server_.get();
+}
+
+
+LyXServerSocket & LyX::socket()
+{
+ return *pimpl_->lyx_socket_.get();
+}
+
+
+LyXServerSocket const & LyX::socket() const
+{
+ return *pimpl_->lyx_socket_.get();
+}
+
+
+lyx::frontend::Application & LyX::application()
+{
+ return *pimpl_->application_.get();
+}
+
+
+lyx::frontend::Application const & LyX::application() const
+{
+ return *pimpl_->application_.get();
+}
+
+
void LyX::addLyXView(LyXView * lyxview)
{
views_.push_back(lyxview);
@@ -243,20 +307,36 @@
if (exit_status)
return exit_status;
-
+
if (lyx::use_gui) {
// Force adding of font path _before_ Application is initialized
lyx::support::addFontResources();
- application_.reset(lyx::createApplication(argc, argv));
+ pimpl_->application_.reset(lyx::createApplication(argc, argv));
initGuiFont();
// FIXME: this global pointer should probably go.
- theApp = application_.get();
+ theApp = pimpl_->application_.get();
restoreGuiSession(files);
// Start the real execution loop.
- exit_status = application_->start(batch_command);
+
+ // FIXME
+ /* Create a CoreApplication class that will provide the main
event loop and
+ * the socket callback registering. With Qt4, only QtCore
library would be needed.
+ * When this done, a lyx::server_mode could be created and the
following two
+ * line would be moved out from here.
+ */
+ pimpl_->lyx_server_.reset(new LyXServer(&pimpl_->lyxfunc_,
lyxrc.lyxpipes));
+ pimpl_->lyx_socket_.reset(new
LyXServerSocket(&pimpl_->lyxfunc_,
+ lyx::support::os::internal_path(package().temp_dir() +
"/lyxsocket")));
+
+ // handle the batch commands the user asked for
+ if (!batch_command.empty()) {
+
pimpl_->lyxfunc_.dispatch(lyxaction.lookupFunc(batch_command));
+ }
+
+ exit_status = pimpl_->application_->start(batch_command);
// Kill the application object before exiting. This avoid crash
// on exit on Linux.
- application_.reset();
+ pimpl_->application_.reset();
// Restore original font resources after Application is
destroyed.
lyx::support::restoreFontResources();
}
@@ -276,7 +356,7 @@
quitting = true;
// close buffers first
- buffer_list_->closeAll();
+ pimpl_->buffer_list_.closeAll();
// do any other cleanup procedures now
lyxerr[Debug::INFO] << "Deleting tmp dir " << package().temp_dir() <<
endl;
@@ -292,8 +372,8 @@
void LyX::earlyExit(int status)
{
- BOOST_ASSERT(application_.get());
- // LyX::application_ is not initialised at this
+ BOOST_ASSERT(pimpl_->application_.get());
+ // LyX::pimpl_::application_ is not initialised at this
// point so it's safe to just exit after some cleanup.
prepareExit();
exit(status);
@@ -305,16 +385,16 @@
lyxerr[Debug::INFO] << "Running QuitLyX." << endl;
if (lyx::use_gui) {
- if (!noask && !buffer_list_->quitWriteAll())
+ if (!noask && !pimpl_->buffer_list_.quitWriteAll())
return;
- session_->writeFile();
+ pimpl_->session_->writeFile();
}
prepareExit();
if (lyx::use_gui) {
- application_->exit(0);
+ pimpl_->application_->exit(0);
}
}
@@ -366,7 +446,7 @@
if (b)
last_loaded = b;
} else {
- Buffer * buf = buffer_list_->newBuffer(s,
false);
+ Buffer * buf =
pimpl_->buffer_list_.newBuffer(s, false);
if (loadLyXFile(buf, s)) {
last_loaded = buf;
ErrorList const & el =
buf->errorList("Parse");
@@ -375,7 +455,7 @@
boost::bind(&LyX::printError, this, _1));
}
else
- buffer_list_->release(buf);
+ pimpl_->buffer_list_.release(buf);
}
}
@@ -434,7 +514,7 @@
height = 0;
}
// create the main window
- LyXView * view = &application_->createView(width, height, posx, posy,
maximize);
+ LyXView * view = &pimpl_->application_->createView(width, height, posx,
posy, maximize);
ref().addLyXView(view);
// load files
@@ -443,7 +523,7 @@
// if a file is specified, I assume that user wants to edit *that* file
if (files.empty() && lyxrc.load_session) {
- vector<string> const & lastopened = session_->lastOpenedFiles();
+ vector<string> const & lastopened =
pimpl_->session_->lastOpenedFiles();
// do not add to the lastfile list since these files are
restored from
// last seesion, and should be already there (regular files),
or should
// not be added at all (help files).
@@ -451,7 +531,7 @@
bind(&LyXView::loadLyXFile, view, _1, false));
}
// clear this list to save a few bytes of RAM
- session_->clearLastOpenedFiles();
+ pimpl_->session_->clearLastOpenedFiles();
}
@@ -565,14 +645,14 @@
void LyX::initGuiFont()
{
if (lyxrc.roman_font_name.empty())
- lyxrc.roman_font_name = application_->romanFontName();
+ lyxrc.roman_font_name = pimpl_->application_->romanFontName();
if (lyxrc.sans_font_name.empty())
- lyxrc.sans_font_name = application_->sansFontName();
+ lyxrc.sans_font_name = pimpl_->application_->sansFontName();
if (lyxrc.typewriter_font_name.empty())
lyxrc.typewriter_font_name
- = application_->typewriterFontName();
+ = pimpl_->application_->typewriterFontName();
}
@@ -691,7 +771,7 @@
}
lyxerr[Debug::INIT] << "Reading session information '.lyx/session'..."
<< endl;
- session_.reset(new lyx::Session(lyxrc.num_lastfiles));
+ pimpl_->session_.reset(new lyx::Session(lyxrc.num_lastfiles));
return true;
}
@@ -755,9 +835,9 @@
// contain documents etc. which might be helpful on
// a crash
- buffer_list_->emergencyWriteAll();
+ pimpl_->buffer_list_.emergencyWriteAll();
if (lyx::use_gui)
- application_->server().emergencyCleanup();
+ pimpl_->lyx_server_->emergencyCleanup();
}
@@ -1150,3 +1230,43 @@
batch_command = batch;
}
+
+namespace lyx {
+
+FuncStatus getStatus(FuncRequest const & action)
+{
+ return LyX::ref().lyxFunc().getStatus(action);
+}
+
+
+void dispatch(FuncRequest const & action)
+{
+ LyX::ref().lyxFunc().dispatch(action);
+}
+
+} // namespace lyx
+
+
+BufferList & theBufferList()
+{
+ return LyX::ref().bufferList();
+}
+
+
+LyXFunc & theLyXFunc()
+{
+ return LyX::ref().lyxFunc();
+}
+
+
+LyXServer & theLyXServer()
+{
+ BOOST_ASSERT(theApp);
+ return LyX::ref().server();
+}
+
+LyXServerSocket & theLyXServerSocket()
+{
+ BOOST_ASSERT(theApp);
+ return LyX::ref().socket();
+}
\ No newline at end of file
Index: lyx_main.h
===================================================================
--- lyx_main.h (revision 15361)
+++ lyx_main.h (working copy)
@@ -26,9 +26,13 @@
class BufferList;
class ErrorItem;
class InsetBase;
+class LyXFunc;
+class LyXServer;
+class LyXServerSocket;
class LyXView;
class kb_keymap;
+
namespace lyx {
extern bool use_gui;
class Session;
@@ -74,7 +78,20 @@
///
lyx::Session & session();
lyx::Session const & session() const;
+ ///
+ LyXFunc & lyxFunc();
+ LyXFunc const & lyxFunc() const;
+ ///
+ LyXServer & server();
+ LyXServer const & server() const;
+ ///
+ LyXServerSocket & socket();
+ LyXServerSocket const & socket() const;
+ ///
+ lyx::frontend::Application & application();
+ lyx::frontend::Application const & application() const;
+
void addLyXView(LyXView * lyxview);
/** redraw \c inset in all the BufferViews in which it is currently
@@ -139,19 +156,15 @@
/// the parsed command line batch command if any
std::string batch_command;
+ /// Use the Pimpl idiom to hide the internals.
+ struct Singletons;
+ boost::scoped_ptr<Singletons> pimpl_;
///
- boost::scoped_ptr<BufferList> buffer_list_;
- /// lyx session, containing lastfiles, lastfilepos, and lastopened
- boost::scoped_ptr<lyx::Session> session_;
- ///
typedef std::list<LyXView *> ViewList;
ViewList views_;
///
bool geometryOption_;
-
- ///
- boost::scoped_ptr<lyx::frontend::Application> application_;
};
#endif // LYX_MAIN_H
Index: lyxfunc.C
===================================================================
--- lyxfunc.C (revision 15361)
+++ lyxfunc.C (working copy)
@@ -1121,7 +1121,7 @@
case LFUN_SERVER_NOTIFY:
dispatch_buffer = lyx::from_utf8(keyseq.print());
-
theApp->server().notifyClient(lyx::to_utf8(dispatch_buffer));
+
theLyXServer().notifyClient(lyx::to_utf8(dispatch_buffer));
break;
case LFUN_SERVER_GOTO_FILE_ROW: {
Index: lyxserver.h
===================================================================
--- lyxserver.h (revision 15361)
+++ lyxserver.h (working copy)
@@ -140,6 +140,9 @@
LyXComm pipes;
};
+/// Implementation is in lyx_main.C
+extern LyXServer & theLyXServer();
+
#endif /* _LYXSERVER_H_ */
/* === End of File: lyxserver.h ========================================== */
Index: lyxsocket.h
===================================================================
--- lyxsocket.h (revision 15361)
+++ lyxsocket.h (working copy)
@@ -89,4 +89,7 @@
std::string buffer_;
};
+/// Implementation is in lyx_main.C
+extern LyXServerSocket & theLyXServerSocket();
+
#endif // LYXSOCKET_H