X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Ffrontends%2Fqt4%2FGuiApplication.cpp;h=69e5f09a28b06979f2409e807f456a75494e25bd;hb=4e223167ff2872ee123c8354d486352c8a368102;hp=10aeaa62a1e0a07a50949bd9fceb44e3bd6842c5;hpb=9abb7db46800e554f57e865a3e768602ffd9d6f1;p=lyx.git diff --git a/src/frontends/qt4/GuiApplication.cpp b/src/frontends/qt4/GuiApplication.cpp index 10aeaa62a1..69e5f09a28 100644 --- a/src/frontends/qt4/GuiApplication.cpp +++ b/src/frontends/qt4/GuiApplication.cpp @@ -16,41 +16,42 @@ #include "qt_helpers.h" #include "GuiImage.h" +#include "GuiKeySymbol.h" #include "GuiView.h" #include "frontends/alert.h" #include "frontends/Application.h" -#include "frontends/NoGuiFontLoader.h" -#include "frontends/NoGuiFontMetrics.h" #include "frontends/FontLoader.h" #include "frontends/FontMetrics.h" -#include "support/ExceptionMessage.h" -#include "support/FileName.h" -#include "support/lstrings.h" -#include "support/os.h" -#include "support/Package.h" - #include "Buffer.h" #include "BufferList.h" #include "BufferView.h" -#include "support/debug.h" #include "Font.h" #include "FuncRequest.h" #include "FuncStatus.h" -#include "support/gettext.h" #include "LyX.h" #include "LyXFunc.h" #include "LyXRC.h" #include "Session.h" #include "version.h" +#include "support/debug.h" +#include "support/ExceptionMessage.h" +#include "support/FileName.h" +#include "support/ForkedCalls.h" +#include "support/gettext.h" +#include "support/lstrings.h" +#include "support/os.h" +#include "support/Package.h" + #include #include #include #include #include #include +#include #include #include #include @@ -72,6 +73,7 @@ #include using namespace std; +using namespace lyx::support; namespace lyx { @@ -120,6 +122,27 @@ public: } }; +class GlobalMenuBar : public QMenuBar +{ +public: + /// + GlobalMenuBar() : QMenuBar(0) {} + + /// + bool event(QEvent * e) + { + if (e->type() == QEvent::ShortcutOverride) { + // && activeWindow() == 0) { + QKeyEvent * ke = static_cast(e); + KeySymbol sym; + setKeySymbol(&sym, ke); + theLyXFunc().processKeySym(sym, q_key_state(ke->modifiers())); + e->accept(); + return true; + } + return false; + } +}; /////////////////////////////////////////////////////////////// // You can find more platform specific stuff @@ -127,22 +150,28 @@ public: /////////////////////////////////////////////////////////////// -using support::FileName; - 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); QCoreApplication::setOrganizationDomain("lyx.org"); QCoreApplication::setApplicationName(app_name + "-" + lyx_version); - // Qt bug? setQuitOnLastWindowClosed(true); does not work + // FIXME: quitOnLastWindowClosed is true by default. We should have a + // lyxrc setting for this in order to let the application stay resident. + // But then we need some kind of dock icon, at least on Windows. + /* + 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. @@ -174,6 +203,7 @@ GuiApplication::GuiApplication(int & argc, char ** argv) // This allows to translate the strings that appear in the LyX menu. addMenuTranslator(); #endif + connect(this, SIGNAL(lastWindowClosed()), this, SLOT(onLastWindowClosed())); using namespace lyx::graphics; @@ -199,6 +229,19 @@ GuiApplication::GuiApplication(int & argc, char ** argv) if (lyxrc.typewriter_font_name.empty()) lyxrc.typewriter_font_name = fromqstr(typewriterFontName()); + + general_timer_.setInterval(500); + connect(&general_timer_, SIGNAL(timeout()), + this, SLOT(handleRegularEvents())); + general_timer_.start(); + +#ifdef Q_WS_MACX + if (global_menubar_ == 0) { + // Create the global default menubar which is shown for the dialogs + // and if no GuiView is visible. + global_menubar_ = new GlobalMenuBar(); + } +#endif } @@ -245,9 +288,6 @@ bool GuiApplication::dispatch(FuncRequest const & cmd) // update bookmark pit of the current buffer before window close for (size_t i = 0; i < LyX::ref().session().bookmarks().size(); ++i) theLyXFunc().gotoBookmark(i+1, false, false); - // ask the user for saving changes or cancel quit - if (!current_view_->quitWriteAll()) - break; current_view_->close(); break; @@ -255,8 +295,8 @@ bool GuiApplication::dispatch(FuncRequest const & cmd) // quitting is triggered by the gui code // (leaving the event loop). current_view_->message(from_utf8(N_("Exiting."))); - if (current_view_->quitWriteAll()) - closeAllViews(); + if (closeAllViews()) + quit(); break; case LFUN_SCREEN_FONT_UPDATE: { @@ -276,6 +316,35 @@ bool GuiApplication::dispatch(FuncRequest const & cmd) break; } + case LFUN_BUFFER_NEW: + if (viewCount() == 0 + || (!lyxrc.open_buffers_in_tabs && current_view_->buffer() != 0)) + createView(); + current_view_->newDocument(to_utf8(cmd.argument()), false); + break; + + case LFUN_BUFFER_NEW_TEMPLATE: + if (viewCount() == 0 + || (!lyxrc.open_buffers_in_tabs && current_view_->buffer() != 0)) { + createView(); + current_view_->newDocument(to_utf8(cmd.argument()), true); + if (!current_view_->buffer()) + current_view_->close(); + } else + current_view_->newDocument(to_utf8(cmd.argument()), true); + break; + + case LFUN_FILE_OPEN: + if (viewCount() == 0 + || (!lyxrc.open_buffers_in_tabs && current_view_->buffer() != 0)) { + createView(); + current_view_->openDocument(to_utf8(cmd.argument())); + if (!current_view_->buffer()) + current_view_->close(); + } else + current_view_->openDocument(to_utf8(cmd.argument())); + break; + default: // Notify the caller that the action has not been dispatched. return false; @@ -307,15 +376,23 @@ static void updateIds(map const & stdmap, vector & ids) void GuiApplication::createView(QString const & geometry_arg) { + if (global_menubar_) + global_menubar_->releaseKeyboard(); + + // create new view updateIds(views_, view_ids_); int id = 0; while (views_.find(id) != views_.end()) id++; - views_[id] = new GuiView(id); - updateIds(views_, view_ids_); + GuiView * view = new GuiView(id); + + // copy the icon size from old view + if (viewCount() > 0) + view->setIconSize(current_view_->iconSize()); - GuiView * view = views_[id]; - theLyXFunc().setLyXView(view); + // register view + views_[id] = view; + updateIds(views_, view_ids_); view->show(); if (!geometry_arg.isEmpty()) { @@ -332,7 +409,7 @@ void GuiApplication::createView(QString const & geometry_arg) #endif } view->setFocus(); - + setActiveWindow(view); setCurrentView(*view); } @@ -370,6 +447,24 @@ void GuiApplication::execBatchCommands() } +void GuiApplication::restoreGuiSession() +{ + if (!lyxrc.load_session) + return; + + Session & session = LyX::ref().session(); + vector const & lastopened = session.lastOpened().getfiles(); + // do not add to the lastfile list since these files are restored from + // last session, and should be already there (regular files), or should + // not be added at all (help files). + for_each(lastopened.begin(), lastopened.end(), + bind(&GuiView::loadDocument, current_view_, _1, false)); + + // clear this list to save a few bytes of RAM + session.lastOpened().clear(); +} + + QString const GuiApplication::romanFontName() { QFont font; @@ -403,6 +498,12 @@ QString const GuiApplication::typewriterFontName() } +void GuiApplication::handleRegularEvents() +{ + ForkedCallsController::handleCompletedProcesses(); +} + + bool GuiApplication::event(QEvent * e) { switch(e->type()) { @@ -415,7 +516,7 @@ bool GuiApplication::event(QEvent * e) // So we acknowledge the event and delay the file opening // until LyX is ready. // FIXME UNICODE: FileName accept an utf8 encoded string. - LyX::ref().addFileToLoad(FileName(fromqstr(foe->file()))); + LyX::ref().addFileToLoad(fromqstr(foe->file())); else lyx::dispatch(FuncRequest(LFUN_FILE_OPEN, qstring_to_ucs4(foe->file()))); @@ -434,15 +535,33 @@ bool GuiApplication::notify(QObject * receiver, QEvent * event) try { return QApplication::notify(receiver, event); } - catch (support::ExceptionMessage const & e) { - if (e.type_ == support::ErrorException) { - Alert::error(e.title_, e.details_); + catch (ExceptionMessage const & e) { + switch(e.type_) { + case ErrorException: LyX::cref().emergencyCleanup(); - QApplication::exit(1); - } else if (e.type_ == support::WarningException) { - Alert::warning(e.title_, e.details_); + setQuitOnLastWindowClosed(false); + closeAllViews(); + Alert::error(e.title_, e.details_); +#ifndef NDEBUG + // Properly crash in debug mode in order to get a useful backtrace. + abort(); +#endif + // In release mode, try to exit gracefully. + this->exit(1); + + case BufferException: { + Buffer * buf = current_view_->buffer(); + docstring details = e.details_ + '\n'; + details += theBufferList().emergencyWrite(buf); + theBufferList().release(buf); + details += _("\nThe current document was closed."); + Alert::error(e.title_, details); return false; } + case WarningException: + Alert::warning(e.title_, e.details_); + return false; + }; } catch (exception const & e) { docstring s = _("LyX has caught an exception, it will now " @@ -450,15 +569,13 @@ bool GuiApplication::notify(QObject * receiver, QEvent * event) "\n\nException: "); s += from_ascii(e.what()); Alert::error(_("Software exception Detected"), s); - LyX::cref().emergencyCleanup(); - QApplication::exit(1); + LyX::cref().exit(1); } catch (...) { docstring s = _("LyX has caught some really weird exception, it will " "now attempt to save all unsaved documents and exit."); Alert::error(_("Software exception Detected"), s); - LyX::cref().emergencyCleanup(); - QApplication::exit(1); + LyX::cref().exit(1); } return false; @@ -483,7 +600,7 @@ bool GuiApplication::getRgbColor(ColorCode col, RGBColor & rgbcol) string const GuiApplication::hexName(ColorCode col) { - return support::ltrim(fromqstr(color_cache_.get(col).name()), "#"); + return ltrim(fromqstr(color_cache_.get(col).name()), "#"); } @@ -521,8 +638,9 @@ void GuiApplication::commitData(QSessionManager & sm) /// The default implementation sends a close event to all /// visible top level widgets when session managment allows /// interaction. - /// We are changing that to write all unsaved buffers... - if (sm.allowsInteraction() && !current_view_->quitWriteAll()) + /// We are changing that to close all wiew one by one. + /// FIXME: verify if the default implementation is enough now. + if (sm.allowsInteraction() && !closeAllViews()) sm.cancel(); } @@ -554,20 +672,14 @@ bool GuiApplication::unregisterView(int id) bool GuiApplication::closeAllViews() { updateIds(views_, view_ids_); - if (views_.empty()) { - // quit in CloseEvent will not be triggert - qApp->quit(); + if (views_.empty()) return true; - } map const cmap = views_; map::const_iterator it; for (it = cmap.begin(); it != cmap.end(); ++it) { - // TODO: return false when close event was ignored - // e.g. quitWriteAll()->'Cancel' - // maybe we need something like 'bool closeView()' - it->second->close(); - // unregisterd by the CloseEvent + if (!it->second->close()) + return false; } views_.clear(); @@ -606,6 +718,32 @@ Buffer const * GuiApplication::updateInset(Inset const * inset) const } +void GuiApplication::readMenus(Lexer & lex) +{ + menus().read(lex); +} + + +bool GuiApplication::searchMenu(FuncRequest const & func, + vector & names) const +{ + return menus().searchMenu(func, names); +} + + +void GuiApplication::initGlobalMenu() +{ + if (global_menubar_) + menus().fillMenuBar(global_menubar_, 0); +} + + +void GuiApplication::onLastWindowClosed() +{ + if (global_menubar_) + global_menubar_->grabKeyboard(); +} + //////////////////////////////////////////////////////////////////////// // X11 specific stuff goes here... #ifdef Q_WS_X11 @@ -652,11 +790,6 @@ bool GuiApplication::x11EventFilter(XEvent * xev) frontend::FontLoader & theFontLoader() { - static frontend::NoGuiFontLoader no_gui_font_loader; - - if (!use_gui) - return no_gui_font_loader; - BOOST_ASSERT(frontend::guiApp); return frontend::guiApp->fontLoader(); } @@ -670,11 +803,6 @@ frontend::FontMetrics const & theFontMetrics(Font const & f) frontend::FontMetrics const & theFontMetrics(FontInfo const & f) { - static frontend::NoGuiFontMetrics no_gui_font_metrics; - - if (!use_gui) - return no_gui_font_metrics; - BOOST_ASSERT(frontend::guiApp); return frontend::guiApp->fontLoader().metrics(f); }