X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Ffrontends%2Fqt4%2FGuiAlert.cpp;h=ef4725c84accbc3173abefa5c174c34d99a12320;hb=b6eacd8d4f86734e8abef3335b190ce12a6a11b5;hp=ec904e96500fcdc218676f99fdf3634da34b5f41;hpb=ab3459c41088cd4d50f8e902c80f42094fe77e03;p=lyx.git diff --git a/src/frontends/qt4/GuiAlert.cpp b/src/frontends/qt4/GuiAlert.cpp index ec904e9650..ef4725c84a 100644 --- a/src/frontends/qt4/GuiAlert.cpp +++ b/src/frontends/qt4/GuiAlert.cpp @@ -4,6 +4,7 @@ * Licence details can be found in the file COPYING. * * \author John Levon + * \author Jürgen Spitzmüller * \author Abdelrazak Younes * * Full author contact details are available in file CREDITS. @@ -12,24 +13,35 @@ #include #include "alert.h" +#include "InGuiThread.h" #include "frontends/Application.h" #include "qt_helpers.h" -#include "support/debug.h" #include "LyX.h" // for lyx::use_gui -#include "ui_AskForTextUi.h" -#include "support/gettext.h" +#include "support/gettext.h" +#include "support/debug.h" #include "support/docstring.h" #include "support/lstrings.h" +#include "support/lassert.h" +#include "support/ProgressInterface.h" #include +#include #include #include #include +#include +#include #include +#include + + +// sync with GuiView.cpp +#define EXPORT_in_THREAD 1 + using namespace std; using namespace lyx::support; @@ -38,83 +50,48 @@ namespace lyx { namespace frontend { -static docstring const formatted(docstring const & text) +void noAppDialog(QString const & title, QString const & msg, QMessageBox::Icon mode) { - const int w = 80; - docstring sout; - - if (text.empty()) - return sout; - - size_t curpos = 0; - docstring line; - - while (true) { - size_t const nxtpos1 = text.find(' ', curpos); - size_t const nxtpos2 = text.find('\n', curpos); - size_t const nxtpos = min(nxtpos1, nxtpos2); - - docstring const word = - nxtpos == docstring::npos ? - text.substr(curpos) : - text.substr(curpos, nxtpos - curpos); - - bool const newline = (nxtpos2 != docstring::npos && - nxtpos2 < nxtpos1); - - docstring const line_plus_word = - line.empty() ? word : line + char_type(' ') + word; - - // FIXME: make w be size_t - if (int(line_plus_word.length()) >= w) { - sout += line + char_type('\n'); - if (newline) { - sout += word + char_type('\n'); - line.erase(); - } else { - line = word; - } - - } else if (newline) { - sout += line_plus_word + char_type('\n'); - line.erase(); - - } else { - if (!line.empty()) - line += char_type(' '); - line += word; - } - - if (nxtpos == docstring::npos) { - if (!line.empty()) - sout += line; - break; - } - - curpos = nxtpos + 1; + int argc = 1; + const char *argv[] = { "lyx", 0 }; + + QApplication app(argc, (char**)argv); + switch (mode) + { + case QMessageBox::Information: QMessageBox::information(0, title, msg); break; + case QMessageBox::Warning: QMessageBox::warning(0, title, msg); break; + case QMessageBox::Critical: QMessageBox::critical(0, title, msg); break; + default: break; } - - return sout; } namespace Alert { -int prompt(docstring const & title0, docstring const & question, + +docstring toPlainText(docstring const & msg) +{ + return qstring_to_ucs4(qtHtmlToPlainText(toqstr(msg))); +} + + +int doPrompt(docstring const & title0, docstring const & question, int default_button, int cancel_button, - docstring const & b1, docstring const & b2, docstring const & b3) + docstring const & b1, docstring const & b2, + docstring const & b3, docstring const & b4) { - lyxerr << "PROMPT" << title0 << "FOCUS: " << qApp->focusWidget() << endl; + //lyxerr << "PROMPT" << title0 << "FOCUS: " << qApp->focusWidget() << endl; if (!use_gui || lyxerr.debugging()) { - lyxerr << title0 << '\n' + lyxerr << toPlainText(title0) << '\n' << "----------------------------------------\n" - << question << endl; + << toPlainText(question) << endl; lyxerr << "Assuming answer is "; switch (default_button) { - case 0: lyxerr << b1 << endl; - case 1: lyxerr << b2 << endl; - case 2: lyxerr << b3 << endl; + case 0: lyxerr << b1 << endl; break; + case 1: lyxerr << b2 << endl; break; + case 2: lyxerr << b3 << endl; break; + case 3: lyxerr << b4 << endl; } if (!use_gui) return default_button; @@ -122,20 +99,37 @@ int prompt(docstring const & title0, docstring const & question, docstring const title = bformat(_("LyX: %1$s"), title0); - // For some reason, sometimes Qt uses an hourglass or watch cursor when + /// Long operation in progress prevents user from Ok-ing the error dialog + bool long_op = theApp()->longOperationStarted(); + if (long_op) + theApp()->stopLongOperation(); + + // For some reason, sometimes Qt uses a hourglass or watch cursor when // displaying the alert. Hence, we ask for the standard cursor shape. - // This call has no effect if the cursor has not been overridden. - qApp->changeOverrideCursor(Qt::ArrowCursor); + qApp->setOverrideCursor(Qt::ArrowCursor); // FIXME replace that with guiApp->currentView() - LYXERR0("FOCUS: " << qApp->focusWidget()); - int res = QMessageBox::information(qApp->focusWidget(), - toqstr(title), - toqstr(formatted(question)), - toqstr(b1), - toqstr(b2), - b3.empty() ? QString::null : toqstr(b3), - default_button, cancel_button); + //LYXERR0("FOCUS: " << qApp->focusWidget()); + QPushButton * b[4] = { 0, 0, 0, 0 }; + QMessageBox msg_box(QMessageBox::Information, + toqstr(title), toqstr(question), + QMessageBox::NoButton, qApp->focusWidget()); + b[0] = msg_box.addButton(b1.empty() ? "OK" : toqstr(b1), + QMessageBox::ActionRole); + if (!b2.empty()) + b[1] = msg_box.addButton(toqstr(b2), QMessageBox::ActionRole); + if (!b3.empty()) + b[2] = msg_box.addButton(toqstr(b3), QMessageBox::ActionRole); + if (!b4.empty()) + b[3] = msg_box.addButton(toqstr(b4), QMessageBox::ActionRole); + msg_box.setDefaultButton(b[default_button]); + msg_box.setEscapeButton(static_cast(b[cancel_button])); + int res = msg_box.exec(); + + qApp->restoreOverrideCursor(); + + if (long_op) + theApp()->startLongOperation(); // Qt bug: can return -1 on cancel or WM close, despite the docs. if (res == -1) @@ -143,12 +137,26 @@ int prompt(docstring const & title0, docstring const & question, return res; } +int prompt(docstring const & title0, docstring const & question, + int default_button, int cancel_button, + docstring const & b1, docstring const & b2, + docstring const & b3, docstring const & b4) +{ +#ifdef EXPORT_in_THREAD + return InGuiThread().call(&doPrompt, +#else + return doPrompt( +#endif + title0, question, default_button, + cancel_button, b1, b2, b3, b4); +} -void warning(docstring const & title0, docstring const & message) +void doWarning(docstring const & title0, docstring const & message, + bool const & askshowagain) { - lyxerr << "Warning: " << title0 << '\n' + lyxerr << "Warning: " << toPlainText(title0) << '\n' << "----------------------------------------\n" - << message << endl; + << toPlainText(message) << endl; if (!use_gui) return; @@ -156,68 +164,146 @@ void warning(docstring const & title0, docstring const & message) docstring const title = bformat(_("LyX: %1$s"), title0); if (theApp() == 0) { - int argc = 1; - char * argv[1]; - QApplication app(argc, argv); - QMessageBox::warning(0, - toqstr(title), - toqstr(formatted(message))); + noAppDialog(toqstr(title), toqstr(message), QMessageBox::Warning); return; } - QMessageBox::warning(qApp->focusWidget(), - toqstr(title), - toqstr(formatted(message))); + + /// Long operation in progress prevents user from Ok-ing the error dialog + bool long_op = theApp()->longOperationStarted(); + if (long_op) + theApp()->stopLongOperation(); + + // Don't use a hourglass cursor while displaying the alert + qApp->setOverrideCursor(Qt::ArrowCursor); + + if (!askshowagain) { + ProgressInterface::instance()->warning( + toqstr(title), + toqstr(message)); + } else { + ProgressInterface::instance()->toggleWarning( + toqstr(title), + toqstr(message), + toqstr(message)); + } + + qApp->restoreOverrideCursor(); + + if (long_op) + theApp()->startLongOperation(); } +void warning(docstring const & title0, docstring const & message, + bool const & askshowagain) +{ +#ifdef EXPORT_in_THREAD + InGuiThread().call(&doWarning, +#else + doWarning( +#endif + title0, message, askshowagain); +} -void error(docstring const & title0, docstring const & message) +void doError(docstring const & title0, docstring const & message, bool backtrace) { - lyxerr << "Error: " << title0 << '\n' + lyxerr << "Error: " << toPlainText(title0) << '\n' << "----------------------------------------\n" - << message << endl; + << toPlainText(message) << endl; + + QString details; + if (backtrace) + details = toqstr(printCallStack()); if (!use_gui) return; docstring const title = bformat(_("LyX: %1$s"), title0); + if (theApp() == 0) { - int argc = 1; - char * argv[1]; - QApplication app(argc, argv); - QMessageBox::critical(0, - toqstr(title), - toqstr(formatted(message))); + noAppDialog(toqstr(title), toqstr(message), QMessageBox::Critical); return; } - QMessageBox::critical(qApp->focusWidget(), - toqstr(title), - toqstr(formatted(message))); + + /// Long operation in progress prevents user from Ok-ing the error dialog + bool long_op = theApp()->longOperationStarted(); + if (long_op) + theApp()->stopLongOperation(); + + // Don't use a hourglass cursor while displaying the alert + qApp->setOverrideCursor(Qt::ArrowCursor); + + ProgressInterface::instance()->error( + toqstr(title), + toqstr(message), + details); + + qApp->restoreOverrideCursor(); + + if (long_op) + theApp()->startLongOperation(); } +void error(docstring const & title0, docstring const & message, bool backtrace) +{ +#ifdef EXPORT_in_THREAD + InGuiThread().call(&doError, +#else + doError( +#endif + title0, message, backtrace); +} -void information(docstring const & title0, docstring const & message) +void doInformation(docstring const & title0, docstring const & message) { if (!use_gui || lyxerr.debugging()) - lyxerr << title0 << '\n' + lyxerr << toPlainText(title0) << '\n' << "----------------------------------------\n" - << message << endl; + << toPlainText(message) << endl; if (!use_gui) return; docstring const title = bformat(_("LyX: %1$s"), title0); - QMessageBox::information(qApp->focusWidget(), - toqstr(title), - toqstr(formatted(message))); + + if (theApp() == 0) { + noAppDialog(toqstr(title), toqstr(message), QMessageBox::Information); + return; + } + + /// Long operation in progress prevents user from Ok-ing the error dialog + bool long_op = theApp()->longOperationStarted(); + if (long_op) + theApp()->stopLongOperation(); + + // Don't use a hourglass cursor while displaying the alert + qApp->setOverrideCursor(Qt::ArrowCursor); + + ProgressInterface::instance()->information( + toqstr(title), + toqstr(message)); + + qApp->restoreOverrideCursor(); + + if (long_op) + theApp()->startLongOperation(); } +void information(docstring const & title0, docstring const & message) +{ +#ifdef EXPORT_in_THREAD + InGuiThread().call(&doInformation, +#else + doInformation( +#endif + title0, message); +} -bool askForText(docstring & response, docstring const & msg, +bool doAskForText(docstring & response, docstring const & msg, docstring const & dflt) { if (!use_gui || lyxerr.debugging()) { lyxerr << "----------------------------------------\n" - << msg << '\n' + << toPlainText(msg) << '\n' << "Assuming answer is " << dflt << '\n' << "----------------------------------------" << endl; if (!use_gui) { @@ -228,6 +314,11 @@ bool askForText(docstring & response, docstring const & msg, docstring const title = bformat(_("LyX: %1$s"), msg); + /// Long operation in progress prevents user from Ok-ing the error dialog + bool long_op = theApp()->longOperationStarted(); + if (long_op) + theApp()->stopLongOperation(); + bool ok; QString text = QInputDialog::getText(qApp->focusWidget(), toqstr(title), @@ -235,7 +326,10 @@ bool askForText(docstring & response, docstring const & msg, QLineEdit::Normal, toqstr(dflt), &ok); - if (ok && !text.isEmpty()) { + if (long_op) + theApp()->startLongOperation(); + + if (ok) { response = qstring_to_ucs4(text); return true; } @@ -243,6 +337,16 @@ bool askForText(docstring & response, docstring const & msg, return false; } +bool askForText(docstring & response, docstring const & msg, + docstring const & dflt) +{ +#ifdef EXPORT_in_THREAD + return InGuiThread().call(&doAskForText, +#else + return doAskForText( +#endif + response, msg, dflt); +} } // namespace Alert } // namespace frontend