X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Ffrontends%2Fqt4%2FGuiApplication.cpp;h=4656e63a69f5855ce8593e043a099075055a19ab;hb=28896d1bddcfcd358c863603334c0a013fb601ea;hp=c53331fb29e645ed5b2d1eb852d491f00d60abed;hpb=545d7bb4314df420c615a2e551396d47965625b1;p=lyx.git diff --git a/src/frontends/qt4/GuiApplication.cpp b/src/frontends/qt4/GuiApplication.cpp index c53331fb29..4656e63a69 100644 --- a/src/frontends/qt4/GuiApplication.cpp +++ b/src/frontends/qt4/GuiApplication.cpp @@ -104,6 +104,9 @@ #include #include #include +#if QT_VERSION >= 0x040400 +#include +#endif #include #ifdef Q_WS_X11 @@ -121,7 +124,7 @@ #include #endif // Q_WS_WIN -#include +#include "support/bind.h" #include #include @@ -159,7 +162,11 @@ frontend::Application * createApplication(int & argc, char * argv[]) } } #endif - return new frontend::GuiApplication(argc, argv); + frontend::GuiApplication * guiApp = new frontend::GuiApplication(argc, argv); + // I'd rather do that in the constructor, but I do not think that + // the palette is accessible there. + guiApp->colorCache().setPalette(guiApp->palette()); + return guiApp; } namespace frontend { @@ -260,7 +267,11 @@ PngMap sorted_png_map[] = { { "nvDash", "nvdash2" }, { "textrm \\AA", "textrm_AA"}, { "textrm \\O", "textrm_O"}, - { "vDash", "vdash2" } + { "vDash", "vdash2" }, + { "varPhi", "varphi2" }, + { "varPi", "varpi2" }, + { "varSigma", "varsigma2" }, + { "varTheta", "vartheta2" } }; size_t const nr_sorted_png_map = sizeof(sorted_png_map) / sizeof(PngMap); @@ -310,7 +321,7 @@ QString iconName(FuncRequest const & f, bool unknown) QString name1; QString name2; QString path; - switch (f.action) { + switch (f.action()) { case LFUN_MATH_INSERT: if (!f.argument().empty()) { path = "math/"; @@ -350,7 +361,7 @@ QString iconName(FuncRequest const & f, bool unknown) } } default: - name2 = toqstr(lyxaction.getActionName(f.action)); + name2 = toqstr(lyxaction.getActionName(f.action())); name1 = name2; if (!f.argument().empty()) { @@ -362,11 +373,11 @@ QString iconName(FuncRequest const & f, bool unknown) FileName fname = libFileSearch("images/" + path, name1, "png"); if (fname.exists()) - return toqstr(fname.absFilename()); + return toqstr(fname.absFileName()); fname = libFileSearch("images/" + path, name2, "png"); if (fname.exists()) - return toqstr(fname.absFilename()); + return toqstr(fname.absFileName()); path = ":/images/" + path; QDir res(path); @@ -387,13 +398,13 @@ QString iconName(FuncRequest const & f, bool unknown) << " or filename " << "\"" << name2 << "\"" << " for command \"" - << lyxaction.getActionName(f.action) + << lyxaction.getActionName(f.action()) << '(' << to_utf8(f.argument()) << ")\""); if (unknown) { fname = libFileSearch(QString("images/"), "unknown", "png"); if (fname.exists()) - return toqstr(fname.absFilename()); + return toqstr(fname.absFileName()); return QString(":/images/unknown.png"); } @@ -404,7 +415,7 @@ QPixmap getPixmap(QString const & path, QString const & name, QString const & ex { QPixmap pixmap; FileName fname = libFileSearch(path, name, ext); - QString path1 = toqstr(fname.absFilename()); + QString path1 = toqstr(fname.absFileName()); QString path2 = ":/" + path + name + "." + ext; if (pixmap.load(path1)) { @@ -779,7 +790,6 @@ GuiApplication::GuiApplication(int & argc, char ** argv) // FIXME: Do we need a lyxrc setting for this on Mac? This behaviour // seems to be the default case for applications like LyX. setQuitOnLastWindowClosed(false); - // This allows to translate the strings that appear in the LyX menu. /// A translator suitable for the entries in the LyX menu. /// Only needed with Qt/Mac. @@ -820,6 +830,13 @@ GuiApplication::GuiApplication(int & argc, char ** argv) connect(&d->general_timer_, SIGNAL(timeout()), this, SLOT(handleRegularEvents())); d->general_timer_.start(); + +#if QT_VERSION >= 0x040400 + // maxThreadCount() defaults in general to 2 on single or dual-processor. + // This is clearly not enough in a time where we use threads for + // document preview and/or export. 20 should be OK. + QThreadPool::globalInstance()->setMaxThreadCount(20); +#endif } @@ -844,27 +861,82 @@ docstring GuiApplication::iconName(FuncRequest const & f, bool unknown) FuncStatus GuiApplication::getStatus(FuncRequest const & cmd) const { - FuncStatus flag; + FuncStatus status; - if (cmd.action == LFUN_NOACTION) { - flag.message(from_utf8(N_("Nothing to do"))); - flag.setEnabled(false); - return flag; + BufferView * bv = 0; + BufferView * doc_bv = 0; + + if (cmd.action() == LFUN_NOACTION) { + status.message(from_utf8(N_("Nothing to do"))); + status.setEnabled(false); } - if (cmd.action == LFUN_UNKNOWN_ACTION) { - flag.unknown(true); - flag.setEnabled(false); - flag.message(from_utf8(N_("Unknown action"))); - return flag; + else if (cmd.action() == LFUN_UNKNOWN_ACTION) { + status.setUnknown(true); + status.message(from_utf8(N_("Unknown action"))); + status.setEnabled(false); + } + + // Does the GuiApplication know something? + else if (getStatus(cmd, status)) { } + + // If we do not have a GuiView, then other functions are disabled + else if (!current_view_) + status.setEnabled(false); + + // Does the GuiView know something? + else if (current_view_->getStatus(cmd, status)) { } + + // In LyX/Mac, when a dialog is open, the menus of the + // application can still be accessed without giving focus to + // the main window. In this case, we want to disable the menu + // entries that are buffer or view-related. + //FIXME: Abdel (09/02/10) This has very bad effect on Linux, don't know why... + /* + else if (cmd.origin() == FuncRequest::MENU && !current_view_->hasFocus()) + status.setEnabled(false); + */ + + // If we do not have a BufferView, then other functions are disabled + else if (!(bv = current_view_->currentBufferView())) + status.setEnabled(false); + + // Does the current BufferView know something? + else if (bv->getStatus(cmd, status)) { } + + // Does the current Buffer know something? + else if (bv->buffer().getStatus(cmd, status)) { } + + // If we do not have a document BufferView, different from the + // current BufferView, then other functions are disabled + else if (!(doc_bv = current_view_->documentBufferView()) || doc_bv == bv) + status.setEnabled(false); + + // Does the document Buffer know something? + else if (doc_bv->buffer().getStatus(cmd, status)) { } + + else { + LYXERR(Debug::ACTION, "LFUN not handled in getStatus(): " << cmd); + status.message(from_utf8(N_("Command not handled"))); + status.setEnabled(false); } + + // the default error message if we disable the command + if (!status.enabled() && status.message().empty()) + status.message(from_utf8(N_("Command disabled"))); + + return status; +} + +bool GuiApplication::getStatus(FuncRequest const & cmd, FuncStatus & flag) const +{ // I would really like to avoid having this switch and rather try to // encode this in the function itself. // -- And I'd rather let an inset decide which LFUNs it is willing // to handle (Andre') bool enable = true; - switch (cmd.action) { + switch (cmd.action()) { // This could be used for the no-GUI version. The GUI version is handled in // GuiView::getStatus(). See above. @@ -893,7 +965,7 @@ FuncStatus GuiApplication::getStatus(FuncRequest const & cmd) const // argument contains ';'-terminated commands string const firstcmd = token(to_utf8(cmd.argument()), ';', 0); FuncRequest func(lyxaction.lookupFunc(firstcmd)); - func.origin = cmd.origin; + func.setOrigin(cmd.origin()); flag = getStatus(func); break; } @@ -906,7 +978,7 @@ FuncStatus GuiApplication::getStatus(FuncRequest const & cmd) const string first; arg = split(arg, first, ';'); FuncRequest func(lyxaction.lookupFunc(first)); - func.origin = cmd.origin; + func.setOrigin(cmd.origin()); flag = getStatus(func); // if this one is enabled, the whole thing is if (flag.enabled()) @@ -919,7 +991,7 @@ FuncStatus GuiApplication::getStatus(FuncRequest const & cmd) const FuncRequest func; string name = to_utf8(cmd.argument()); if (theTopLevelCmdDef().lock(name, func)) { - func.origin = cmd.origin; + func.setOrigin(cmd.origin()); flag = getStatus(func); theTopLevelCmdDef().release(name); } else { @@ -964,63 +1036,23 @@ FuncStatus GuiApplication::getStatus(FuncRequest const & cmd) const break; default: - // Does the view know something? - if (!current_view_) { - enable = false; - break; - } - - if (current_view_->getStatus(cmd, flag)) - break; - - // In LyX/Mac, when a dialog is open, the menus of the - // application can still be accessed without giving focus to - // the main window. In this case, we want to disable the menu - // entries that are buffer or view-related. - //FIXME: Abdel (09/02/10) This has very bad effect on Linux, don't know why... - /* - if (cmd.origin == FuncRequest::MENU && !current_view_->hasFocus()) { - enable = false; - break; - } - */ - - BufferView * bv = current_view_->currentBufferView(); - BufferView * doc_bv = current_view_->documentBufferView(); - // If we do not have a BufferView, then other functions are disabled - if (!bv) { - enable = false; - break; - } - // try the BufferView - bool decided = bv->getStatus(cmd, flag); - if (!decided) - // try the Buffer - decided = bv->buffer().getStatus(cmd, flag); - if (!decided && doc_bv) - // try the Document Buffer - decided = doc_bv->buffer().getStatus(cmd, flag); + return false; } if (!enable) flag.setEnabled(false); - - // the default error message if we disable the command - if (!flag.enabled() && flag.message().empty()) - flag.message(from_utf8(N_("Command disabled"))); - - return flag; + return true; } /// make a post-dispatch status message static docstring makeDispatchMessage(docstring const & msg, FuncRequest const & cmd) { - const bool verbose = (cmd.origin == FuncRequest::MENU - || cmd.origin == FuncRequest::TOOLBAR - || cmd.origin == FuncRequest::COMMANDBUFFER); + const bool verbose = (cmd.origin() == FuncRequest::MENU + || cmd.origin() == FuncRequest::TOOLBAR + || cmd.origin() == FuncRequest::COMMANDBUFFER); - if (cmd.action == LFUN_SELF_INSERT || !verbose) { + if (cmd.action() == LFUN_SELF_INSERT || !verbose) { LYXERR(Debug::ACTION, "dispatch msg is " << msg); return msg; } @@ -1029,12 +1061,12 @@ static docstring makeDispatchMessage(docstring const & msg, if (!dispatch_msg.empty()) dispatch_msg += ' '; - docstring comname = from_utf8(lyxaction.getActionName(cmd.action)); + docstring comname = from_utf8(lyxaction.getActionName(cmd.action())); bool argsadded = false; if (!cmd.argument().empty()) { - if (cmd.action != LFUN_UNKNOWN_ACTION) { + if (cmd.action() != LFUN_UNKNOWN_ACTION) { comname += ' ' + cmd.argument(); argsadded = true; } @@ -1063,8 +1095,8 @@ void GuiApplication::dispatch(FuncRequest const & cmd) DispatchResult dr; // redraw the screen at the end (first of the two drawing steps). - //This is done unless explicitly requested otherwise - dr.update(Update::FitCursor); + // This is done unless explicitly requested otherwise + dr.screenUpdate(Update::FitCursor); dispatch(cmd, dr); if (!current_view_) @@ -1072,11 +1104,32 @@ void GuiApplication::dispatch(FuncRequest const & cmd) BufferView * bv = current_view_->currentBufferView(); if (bv) { + Cursor & cursor = bv->cursor(); + Buffer & buf = bv->buffer(); + + // FIXME + // This check out to be done somewhere else. It got moved here + // from TextMetrics.cpp, where it definitely didn't need to be. + // Actually, this test ought not to be done at all, since the + // whole InsetBibitem business is a mess. But that is a different + // story. + if (cursor.inTexted()) { + int const moveCursor = cursor.paragraph().checkBiblio(buf); + if (moveCursor > 0) + cursor.posForward(); + else if (moveCursor < 0 && cursor.pos() >= -moveCursor) + cursor.posBackward(); + + if (moveCursor != 0 || dr.needBufferUpdate()) { + cursor.clearBufferUpdate(); + buf.updateBuffer(); + } + } // BufferView::update() updates the ViewMetricsInfo and // also initializes the position cache for all insets in // (at least partially) visible top-level paragraphs. // We will redraw the screen only if needed. - bv->processUpdateFlags(dr.update()); + bv->processUpdateFlags(dr.screenUpdate()); // Do we have a selection? theSelection().haveSelection(bv->cursor().selection()); @@ -1084,21 +1137,23 @@ void GuiApplication::dispatch(FuncRequest const & cmd) // update gui current_view_->restartCursor(); } - // Some messages may already be translated, so we cannot use _() - current_view_->message(makeDispatchMessage( - translateIfPossible(dr.message()), cmd)); + if (dr.needMessageUpdate()) { + // Some messages may already be translated, so we cannot use _() + current_view_->message(makeDispatchMessage( + translateIfPossible(dr.message()), cmd)); + } } -void GuiApplication::gotoBookmark(unsigned int idx, bool openFile, bool switchToBuffer) +void GuiApplication::gotoBookmark(unsigned int idx, bool openFile, + bool switchToBuffer) { - GuiView * lv = current_view_; - LASSERT(lv, /**/); if (!theSession().bookmarks().isValid(idx)) return; - BookmarksSection::Bookmark const & bm = theSession().bookmarks().bookmark(idx); + BookmarksSection::Bookmark const & bm = + theSession().bookmarks().bookmark(idx); LASSERT(!bm.filename.empty(), /**/); - string const file = bm.filename.absFilename(); + string const file = bm.filename.absFileName(); // if the file is not opened, open it. if (!theBufferList().exists(bm.filename)) { if (openFile) @@ -1118,16 +1173,18 @@ void GuiApplication::gotoBookmark(unsigned int idx, bool openFile, bool switchTo dispatch(FuncRequest(LFUN_BOOKMARK_SAVE, "0")); // if the current buffer is not that one, switch to it. - if (!lv->documentBufferView() - || lv->documentBufferView()->buffer().fileName() != tmp.filename) { - if (!switchToBuffer) + BufferView * doc_bv = current_view_->documentBufferView(); + if (!doc_bv || doc_bv->buffer().fileName() != tmp.filename) { + if (switchToBuffer) { + dispatch(FuncRequest(LFUN_BUFFER_SWITCH, file)); + doc_bv = current_view_->documentBufferView(); + } else return; - dispatch(FuncRequest(LFUN_BUFFER_SWITCH, file)); } // moveToPosition try paragraph id first and then paragraph (pit, pos). - if (!lv->documentBufferView()->moveToPosition( - tmp.bottom_pit, tmp.bottom_pos, tmp.top_id, tmp.top_pos)) + if (!doc_bv->moveToPosition( + tmp.bottom_pit, tmp.bottom_pos, tmp.top_id, tmp.top_pos)) return; // bm changed @@ -1135,7 +1192,7 @@ void GuiApplication::gotoBookmark(unsigned int idx, bool openFile, bool switchTo return; // Cursor jump succeeded! - Cursor const & cur = lv->documentBufferView()->cursor(); + Cursor const & cur = doc_bv->cursor(); pit_type new_pit = cur.pit(); pos_type new_pos = cur.pos(); int new_id = cur.paragraph().id(); @@ -1151,11 +1208,11 @@ void GuiApplication::gotoBookmark(unsigned int idx, bool openFile, bool switchTo // This function runs "configure" and then rereads lyx.defaults to // reconfigure the automatic settings. -static void reconfigure(GuiView * lv, string const & option) +void GuiApplication::reconfigure(string const & option) { // emit message signal. - if (lv) - lv->message(_("Running configure...")); + if (current_view_) + current_view_->message(_("Running configure...")); // Run configure in user lyx directory PathChanger p(package().user_support()); @@ -1165,8 +1222,8 @@ static void reconfigure(GuiView * lv, string const & option) int ret = one.startscript(Systemcall::Wait, configure_command); p.pop(); // emit message signal. - if (lv) - lv->message(_("Reloading configuration...")); + if (current_view_) + current_view_->message(_("Reloading configuration...")); lyxrc.read(libFileSearch(QString(), "lyxrc.defaults")); // Re-read packages.lst LaTeXFeatures::getAvailable(); @@ -1178,7 +1235,6 @@ static void reconfigure(GuiView * lv, string const & option) "not be able to work properly.\n" "Please reconfigure again if needed.")); else - Alert::information(_("System reconfigured"), _("The system has been reconfigured.\n" "You need to restart LyX to make use of any\n" @@ -1186,11 +1242,10 @@ static void reconfigure(GuiView * lv, string const & option) } - void GuiApplication::dispatch(FuncRequest const & cmd, DispatchResult & dr) { string const argument = to_utf8(cmd.argument()); - FuncCode const action = cmd.action; + FuncCode const action = cmd.action(); LYXERR(Debug::ACTION, "cmd: " << cmd); @@ -1208,14 +1263,15 @@ void GuiApplication::dispatch(FuncRequest const & cmd, DispatchResult & dr) dr.setMessage(flag.message()); dr.setError(true); dr.dispatched(false); - dr.update(Update::None); + dr.screenUpdate(Update::None); + dr.clearBufferUpdate(); return; }; // Assumes that the action will be dispatched. dr.dispatched(true); - switch (cmd.action) { + switch (cmd.action()) { case LFUN_WINDOW_NEW: createView(toqstr(cmd.argument())); @@ -1228,7 +1284,7 @@ void GuiApplication::dispatch(FuncRequest const & cmd, DispatchResult & dr) // clear the last opened list, because // maybe this will end the session theSession().lastOpened().clear(); - current_view_->close(); + current_view_->closeScheduled(); break; case LFUN_LYX_QUIT: @@ -1278,11 +1334,11 @@ void GuiApplication::dispatch(FuncRequest const & cmd, DispatchResult & dr) } break; - case LFUN_FILE_OPEN: + case LFUN_FILE_OPEN: { // FIXME: create a new method shared with LFUN_HELP_OPEN. - if (d->views_.empty() - || (!lyxrc.open_buffers_in_tabs && current_view_->documentBufferView() != 0)) { - string const fname = to_utf8(cmd.argument()); + string const fname = to_utf8(cmd.argument()); + if (d->views_.empty() || (!lyxrc.open_buffers_in_tabs + && current_view_->documentBufferView() != 0)) { // We want the ui session to be saved per document and not per // window number. The filename crc is a good enough identifier. boost::crc_32_type crc; @@ -1292,8 +1348,9 @@ void GuiApplication::dispatch(FuncRequest const & cmd, DispatchResult & dr) if (current_view_ && !current_view_->documentBufferView()) current_view_->close(); } else - current_view_->openDocument(to_utf8(cmd.argument())); + current_view_->openDocument(fname); break; + } case LFUN_HELP_OPEN: { // FIXME: create a new method shared with LFUN_FILE_OPEN. @@ -1314,16 +1371,15 @@ void GuiApplication::dispatch(FuncRequest const & cmd, DispatchResult & dr) break; } current_view_->message(bformat(_("Opening help file %1$s..."), - makeDisplayPath(fname.absFilename()))); + makeDisplayPath(fname.absFileName()))); Buffer * buf = current_view_->loadDocument(fname, false); - if (buf) { - current_view_->setBuffer(buf); + #ifndef DEVEL_VERSION + if (buf) buf->setReadonly(true); +#else + (void) buf; #endif - buf->updateBuffer(); - buf->errors("Parse"); - } break; } @@ -1331,7 +1387,8 @@ void GuiApplication::dispatch(FuncRequest const & cmd, DispatchResult & dr) string lyx_name; string const x11_name = split(to_utf8(cmd.argument()), lyx_name, ' '); if (lyx_name.empty() || x11_name.empty()) { - current_view_->message( + if (current_view_) + current_view_->message( _("Syntax: set-color ")); break; } @@ -1392,7 +1449,7 @@ void GuiApplication::dispatch(FuncRequest const & cmd, DispatchResult & dr) GuiView * gv = currentView(); if (gv && gv->currentBufferView()) // cancel any selection - lyx::dispatch(FuncRequest(LFUN_MARK_OFF)); + processFuncRequest(FuncRequest(LFUN_MARK_OFF)); dr.setMessage(from_ascii(N_("Cancel"))); break; } @@ -1404,15 +1461,14 @@ void GuiApplication::dispatch(FuncRequest const & cmd, DispatchResult & dr) // --- Menus ----------------------------------------------- case LFUN_RECONFIGURE: // argument is any additional parameter to the configure.py command - reconfigure(currentView(), to_utf8(cmd.argument())); + reconfigure(to_utf8(cmd.argument())); break; // --- lyxserver commands ---------------------------- case LFUN_SERVER_GET_FILENAME: { - GuiView * lv = currentView(); - LASSERT(lv && lv->documentBufferView(), return); + LASSERT(current_view_ && current_view_->documentBufferView(), return); docstring const fname = from_utf8( - lv->documentBufferView()->buffer().absFileName()); + current_view_->documentBufferView()->buffer().absFileName()); dr.setMessage(fname); LYXERR(Debug::INFO, "FNAME[" << fname << ']'); break; @@ -1453,7 +1509,7 @@ void GuiApplication::dispatch(FuncRequest const & cmd, DispatchResult & dr) string first; arg = split(arg, first, ';'); FuncRequest func(lyxaction.lookupFunc(first)); - func.origin = cmd.origin; + func.setOrigin(cmd.origin()); dispatch(func); } // the buffer may have been closed by one action @@ -1469,8 +1525,8 @@ void GuiApplication::dispatch(FuncRequest const & cmd, DispatchResult & dr) string first; arg = split(arg, first, ';'); FuncRequest func(lyxaction.lookupFunc(first)); - func.origin = cmd.origin; - FuncStatus stat = getStatus(func); + func.setOrigin(cmd.origin()); + FuncStatus const stat = getStatus(func); if (stat.enabled()) { dispatch(func); break; @@ -1482,11 +1538,11 @@ void GuiApplication::dispatch(FuncRequest const & cmd, DispatchResult & dr) case LFUN_CALL: { FuncRequest func; if (theTopLevelCmdDef().lock(argument, func)) { - func.origin = cmd.origin; + func.setOrigin(cmd.origin()); dispatch(func); theTopLevelCmdDef().release(argument); } else { - if (func.action == LFUN_UNKNOWN_ACTION) { + if (func.action() == LFUN_UNKNOWN_ACTION) { // unknown command definition lyxerr << "Warning: unknown command definition `" << argument << "'" @@ -1503,11 +1559,11 @@ void GuiApplication::dispatch(FuncRequest const & cmd, DispatchResult & dr) case LFUN_PREFERENCES_SAVE: lyxrc.write(support::makeAbsPath("preferences", - package().user_support().absFilename()), false); + package().user_support().absFileName()), false); break; case LFUN_BUFFER_SAVE_AS_DEFAULT: { - string const fname = addName(addPath(package().user_support().absFilename(), + string const fname = addName(addPath(package().user_support().absFileName(), "templates/"), "defaults.lyx"); Buffer defaults(fname); @@ -1536,7 +1592,7 @@ void GuiApplication::dispatch(FuncRequest const & cmd, DispatchResult & dr) case LFUN_BOOKMARK_GOTO: // go to bookmark, open unopened file and switch to buffer if necessary gotoBookmark(convert(to_utf8(cmd.argument())), true, true); - dr.update(Update::FitCursor); + dr.screenUpdate(Update::Force | Update::FitCursor); break; case LFUN_BOOKMARK_CLEAR: @@ -1548,89 +1604,91 @@ void GuiApplication::dispatch(FuncRequest const & cmd, DispatchResult & dr) break; default: - // Notify the caller that the action has not been dispatched. - dr.dispatched(false); - break; - } - - // The action has been dispatched in this method, nothing more to do. - if (dr.dispatched()) - return; - - GuiView * lv = current_view_; - - // Everything below is only for active window - if (lv == 0) - return; - - // Let the current GuiView dispatch its own actions. - lv->dispatch(cmd, dr); - if (dr.dispatched() && lv ) - return; - - BufferView * bv = lv->currentBufferView(); - LASSERT(bv, /**/); - - // Let the current BufferView dispatch its own actions. - bv->dispatch(cmd, dr); - if (dr.dispatched()) - return; + // Everything below is only for active window + if (current_view_ == 0) + break; + + // Let the current GuiView dispatch its own actions. + current_view_->dispatch(cmd, dr); - BufferView * doc_bv = lv->documentBufferView(); - // Try with the document BufferView dispatch if any. - if (doc_bv) { - doc_bv->dispatch(cmd, dr); if (dr.dispatched()) - return; - } + break; - // OK, so try the current Buffer itself... - bv->buffer().dispatch(cmd, dr); - if (dr.dispatched()) - return; + BufferView * bv = current_view_->currentBufferView(); + LASSERT(bv, /**/); + + // Avoid a screen redraw in the middle of a dispatch operation just + // because a warning or an error was displayed. + current_view_->setBusy(true); - // and with the document Buffer. - if (doc_bv) { - doc_bv->buffer().dispatch(cmd, dr); + // Let the current BufferView dispatch its own actions. + bv->dispatch(cmd, dr); if (dr.dispatched()) - return; - } - - // Let the current Cursor dispatch its own actions. - Cursor old = bv->cursor(); - bv->cursor().dispatch(cmd); - - // notify insets we just left - if (bv->cursor() != old) { - old.fixIfBroken(); - bool badcursor = notifyCursorLeavesOrEnters(old, bv->cursor()); - if (badcursor) - bv->cursor().fixIfBroken(); - } + break; + + BufferView * doc_bv = current_view_->documentBufferView(); + // Try with the document BufferView dispatch if any. + if (doc_bv) { + doc_bv->dispatch(cmd, dr); + if (dr.dispatched()) + break; + } + + // OK, so try the current Buffer itself... + bv->buffer().dispatch(cmd, dr); + if (dr.dispatched()) + break; + + // and with the document Buffer. + if (doc_bv) { + doc_bv->buffer().dispatch(cmd, dr); + if (dr.dispatched()) + break; + } + + // Let the current Cursor dispatch its own actions. + Cursor old = bv->cursor(); + bv->cursor().dispatch(cmd); + + // notify insets we just left + // FIXME: move this code to Cursor::dispatch + if (bv->cursor() != old) { + old.beginUndoGroup(); + old.fixIfBroken(); + bool badcursor = notifyCursorLeavesOrEnters(old, bv->cursor()); + if (badcursor) { + bv->cursor().fixIfBroken(); + bv->fixInlineCompletionPos(); + } + old.endUndoGroup(); + } + + // update completion. We do it here and not in + // processKeySym to avoid another redraw just for a + // changed inline completion + if (cmd.origin() == FuncRequest::KEYBOARD) { + if (cmd.action() == LFUN_SELF_INSERT + || (cmd.action() == LFUN_ERT_INSERT && bv->cursor().inMathed())) + current_view_->updateCompletion(bv->cursor(), true, true); + else if (cmd.action() == LFUN_CHAR_DELETE_BACKWARD) + current_view_->updateCompletion(bv->cursor(), false, true); + else + current_view_->updateCompletion(bv->cursor(), false, false); + } + + dr = bv->cursor().result(); - // update completion. We do it here and not in - // processKeySym to avoid another redraw just for a - // changed inline completion - if (cmd.origin == FuncRequest::KEYBOARD) { - if (cmd.action == LFUN_SELF_INSERT - || (cmd.action == LFUN_ERT_INSERT && bv->cursor().inMathed())) - lv->updateCompletion(bv->cursor(), true, true); - else if (cmd.action == LFUN_CHAR_DELETE_BACKWARD) - lv->updateCompletion(bv->cursor(), false, true); - else - lv->updateCompletion(bv->cursor(), false, false); + current_view_->setBusy(false); } - - dr = bv->cursor().result(); - + // if we executed a mutating lfun, mark the buffer as dirty - Buffer * doc_buffer = (lv && lv->documentBufferView()) - ? &(lv->documentBufferView()->buffer()) : 0; + Buffer * doc_buffer = (current_view_ && current_view_->documentBufferView()) + ? &(current_view_->documentBufferView()->buffer()) : 0; if (doc_buffer && theBufferList().isLoaded(doc_buffer) && flag.enabled() && !lyxaction.funcHasFlag(action, LyXAction::NoBuffer) && !lyxaction.funcHasFlag(action, LyXAction::ReadOnly)) - lv->currentBufferView()->buffer().markDirty(); + current_view_->currentBufferView()->buffer().markDirty(); } @@ -1666,7 +1724,6 @@ void GuiApplication::handleKeyFunc(FuncCode action) d->keyseq.clear(); // copied verbatim from do_accent_char bv->cursor().resetAnchor(); - bv->processUpdateFlags(Update::FitCursor); } @@ -1674,19 +1731,18 @@ void GuiApplication::processKeySym(KeySymbol const & keysym, KeyModifier state) { LYXERR(Debug::KEY, "KeySym is " << keysym.getSymbolName()); - GuiView * lv = currentView(); - // Do nothing if we have nothing (JMarc) if (!keysym.isOK()) { LYXERR(Debug::KEY, "Empty kbd action (probably composing)"); - lv->restartCursor(); + if (current_view_) + current_view_->restartCursor(); return; } if (keysym.isModifier()) { LYXERR(Debug::KEY, "isModifier true"); - if (lv) - lv->restartCursor(); + if (current_view_) + current_view_->restartCursor(); return; } @@ -1697,44 +1753,44 @@ void GuiApplication::processKeySym(KeySymbol const & keysym, KeyModifier state) d->cancel_meta_seq.reset(); FuncRequest func = d->cancel_meta_seq.addkey(keysym, state); - LYXERR(Debug::KEY, "action first set to [" << func.action << ']'); + LYXERR(Debug::KEY, "action first set to [" << func.action() << ']'); // When not cancel or meta-fake, do the normal lookup. // Note how the meta_fake Mod1 bit is OR-ed in and reset afterwards. // Mostly, meta_fake_bit = NoModifier. RVDK_PATCH_5. - if ((func.action != LFUN_CANCEL) && (func.action != LFUN_META_PREFIX)) { + if ((func.action() != LFUN_CANCEL) && (func.action() != LFUN_META_PREFIX)) { // remove Caps Lock and Mod2 as a modifiers func = d->keyseq.addkey(keysym, (state | d->meta_fake_bit)); - LYXERR(Debug::KEY, "action now set to [" << func.action << ']'); + LYXERR(Debug::KEY, "action now set to [" << func.action() << ']'); } // Dont remove this unless you know what you are doing. d->meta_fake_bit = NoModifier; // Can this happen now ? - if (func.action == LFUN_NOACTION) + if (func.action() == LFUN_NOACTION) func = FuncRequest(LFUN_COMMAND_PREFIX); - LYXERR(Debug::KEY, " Key [action=" << func.action << "][" + LYXERR(Debug::KEY, " Key [action=" << func.action() << "][" << d->keyseq.print(KeySequence::Portable) << ']'); // already here we know if it any point in going further // why not return already here if action == -1 and // num_bytes == 0? (Lgb) - if (d->keyseq.length() > 1) - lv->message(d->keyseq.print(KeySequence::ForGui)); + if (d->keyseq.length() > 1 && current_view_) + current_view_->message(d->keyseq.print(KeySequence::ForGui)); // Maybe user can only reach the key via holding down shift. // Let's see. But only if shift is the only modifier - if (func.action == LFUN_UNKNOWN_ACTION && state == ShiftModifier) { + if (func.action() == LFUN_UNKNOWN_ACTION && state == ShiftModifier) { LYXERR(Debug::KEY, "Trying without shift"); func = d->keyseq.addkey(keysym, NoModifier); - LYXERR(Debug::KEY, "Action now " << func.action); + LYXERR(Debug::KEY, "Action now " << func.action()); } - if (func.action == LFUN_UNKNOWN_ACTION) { + if (func.action() == LFUN_UNKNOWN_ACTION) { // Hmm, we didn't match any of the keysequences. See // if it's normal insertable text not already covered // by a binding @@ -1744,31 +1800,57 @@ void GuiApplication::processKeySym(KeySymbol const & keysym, KeyModifier state) FuncRequest::KEYBOARD); } else { LYXERR(Debug::KEY, "Unknown, !isText() - giving up"); - lv->message(_("Unknown function.")); - lv->restartCursor(); + if (current_view_) { + current_view_->message(_("Unknown function.")); + current_view_->restartCursor(); + } return; } } - if (func.action == LFUN_SELF_INSERT) { + if (func.action() == LFUN_SELF_INSERT) { if (encoded_last_key != 0) { docstring const arg(1, encoded_last_key); - lyx::dispatch(FuncRequest(LFUN_SELF_INSERT, arg, + processFuncRequest(FuncRequest(LFUN_SELF_INSERT, arg, FuncRequest::KEYBOARD)); LYXERR(Debug::KEY, "SelfInsert arg[`" << to_utf8(arg) << "']"); } - } else { - lyx::dispatch(func); - if (!lv) - return; + } else + processFuncRequest(func); +} + + +void GuiApplication::processFuncRequest(FuncRequest const & func) +{ + lyx::dispatch(func); +} + + +void GuiApplication::processFuncRequestAsync(FuncRequest const & func) +{ + addToFuncRequestQueue(func); + processFuncRequestQueueAsync(); +} + + +void GuiApplication::processFuncRequestQueue() +{ + while (!d->func_request_queue_.empty()) { + processFuncRequest(d->func_request_queue_.front()); + d->func_request_queue_.pop(); } } -void GuiApplication::dispatchDelayed(FuncRequest const & func) +void GuiApplication::processFuncRequestQueueAsync() +{ + QTimer::singleShot(0, this, SLOT(slotProcessFuncRequestQueue())); +} + + +void GuiApplication::addToFuncRequestQueue(FuncRequest const & func) { d->func_request_queue_.push(func); - QTimer::singleShot(0, this, SLOT(processFuncRequestQueue())); } @@ -1793,7 +1875,7 @@ void GuiApplication::resetGui() gv->resetDialogs(); } - lyx::dispatch(FuncRequest(LFUN_SCREEN_FONT_UPDATE)); + processFuncRequest(FuncRequest(LFUN_SCREEN_FONT_UPDATE)); } @@ -1953,15 +2035,6 @@ void GuiApplication::setGuiLanguage() } -void GuiApplication::processFuncRequestQueue() -{ - while (!d->func_request_queue_.empty()) { - lyx::dispatch(d->func_request_queue_.back()); - d->func_request_queue_.pop(); - } -} - - void GuiApplication::execBatchCommands() { setGuiLanguage(); @@ -1972,6 +2045,9 @@ void GuiApplication::execBatchCommands() return; #ifdef Q_WS_MACX +#if QT_VERSION > 0x040600 + setAttribute(Qt::AA_MacDontSwapCtrlAndMeta,lyxrc.mac_dontswap_ctrl_meta); +#endif // Create the global default menubar which is shown for the dialogs // and if no GuiView is visible. // This must be done after the session was recovered to know the "last files". @@ -2039,7 +2115,7 @@ void GuiApplication::restoreGuiSession() if (d->views_.empty() || (!lyxrc.open_buffers_in_tabs && current_view_->documentBufferView() != 0)) { boost::crc_32_type crc; - string const & fname = file_name.absFilename(); + string const & fname = file_name.absFileName(); crc = for_each(fname.begin(), fname.end(), crc); createView(crc.checksum()); } @@ -2108,7 +2184,8 @@ bool GuiApplication::event(QEvent * e) // commands are not executed here yet and the gui is not ready // therefore. QFileOpenEvent * foe = static_cast(e); - dispatchDelayed(FuncRequest(LFUN_FILE_OPEN, qstring_to_ucs4(foe->file()))); + FuncRequest const fr(LFUN_FILE_OPEN, qstring_to_ucs4(foe->file())); + processFuncRequestAsync(fr); e->accept(); return true; } @@ -2223,8 +2300,13 @@ void GuiApplication::commitData(QSessionManager & sm) /// interaction. /// 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(); + #ifdef QT_NO_SESSIONMANAGER + #warning Qt is compiled without session manager + (void) sm; + #else + if (sm.allowsInteraction() && !closeAllViews()) + sm.cancel(); + #endif } @@ -2248,7 +2330,7 @@ bool GuiApplication::closeAllViews() QList views = d->views_.values(); foreach (GuiView * view, views) { - if (!view->close()) + if (!view->closeScheduled()) return false; } @@ -2330,7 +2412,7 @@ bool GuiApplication::readUIFile(QString const & name, bool include) // Ensure that a file is read only once (prevents include loops) static QStringList uifiles; - QString const uifile = toqstr(ui_path.absFilename()); + QString const uifile = toqstr(ui_path.absFileName()); if (uifiles.contains(uifile)) { if (!include) { // We are reading again the top uifile so reset the safeguard: