]> git.lyx.org Git - lyx.git/blobdiff - src/frontends/qt4/GuiAlert.cpp
Make the InsetInfo dialog a bit less esoteric.
[lyx.git] / src / frontends / qt4 / GuiAlert.cpp
index 70bca4151e83df79e3eb8161710f0b1c6a990f26..ef4725c84accbc3173abefa5c174c34d99a12320 100644 (file)
 #include <config.h>
 
 #include "alert.h"
-
+#include "InGuiThread.h"
 
 #include "frontends/Application.h"
 
 #include "qt_helpers.h"
 #include "LyX.h" // for lyx::use_gui
-#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 <QApplication>
 #include <iomanip>
 #include <iostream>
 
+
+// sync with GuiView.cpp
+#define EXPORT_in_THREAD 1
+
+
 using namespace std;
 using namespace lyx::support;
 
@@ -44,68 +50,6 @@ namespace lyx {
 namespace frontend {
 
 
-
-
-static docstring const formatted(docstring const & text)
-{
-       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;
-       }
-
-       return sout;
-}
-
-
 void noAppDialog(QString const & title, QString const & msg, QMessageBox::Icon mode)
 {
        int argc = 1;
@@ -124,22 +68,29 @@ void noAppDialog(QString const & title, QString const & msg, QMessageBox::Icon m
 
 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 & b4)
 {
        //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)
@@ -148,6 +99,11 @@ int prompt(docstring const & title0, docstring const & question,
 
        docstring const title = bformat(_("LyX: %1$s"), title0);
 
+       /// 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.
        qApp->setOverrideCursor(Qt::ArrowCursor);
@@ -156,7 +112,7 @@ int prompt(docstring const & title0, docstring const & question,
        //LYXERR0("FOCUS: " << qApp->focusWidget());
        QPushButton * b[4] = { 0, 0, 0, 0 };
        QMessageBox msg_box(QMessageBox::Information,
-                       toqstr(title), toqstr(formatted(question)),
+                       toqstr(title), toqstr(question),
                        QMessageBox::NoButton, qApp->focusWidget());
        b[0] = msg_box.addButton(b1.empty() ? "OK" : toqstr(b1),
                                        QMessageBox::ActionRole);
@@ -172,19 +128,35 @@ int prompt(docstring const & title0, docstring const & question,
 
        qApp->restoreOverrideCursor();
 
+       if (long_op)
+               theApp()->startLongOperation();
+
        // Qt bug: can return -1 on cancel or WM close, despite the docs.
        if (res == -1)
                res = cancel_button;
        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<int>().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;
@@ -192,33 +164,55 @@ void warning(docstring const & title0, docstring const & message,
        docstring const title = bformat(_("LyX: %1$s"), title0);
 
        if (theApp() == 0) {
-               noAppDialog(toqstr(title), toqstr(formatted(message)), QMessageBox::Warning);
+               noAppDialog(toqstr(title), toqstr(message), QMessageBox::Warning);
                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);
 
        if (!askshowagain) {
                ProgressInterface::instance()->warning(
                                toqstr(title),
-                               toqstr(formatted(message)));
+                               toqstr(message));
        } else {
                ProgressInterface::instance()->toggleWarning(
                                toqstr(title),
                                toqstr(message),
-                               toqstr(formatted(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<void>().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;
@@ -226,27 +220,45 @@ void error(docstring const & title0, docstring const & message)
        docstring const title = bformat(_("LyX: %1$s"), title0);
 
        if (theApp() == 0) {
-               noAppDialog(toqstr(title), toqstr(formatted(message)), QMessageBox::Critical);
+               noAppDialog(toqstr(title), toqstr(message), QMessageBox::Critical);
                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()->error(
                toqstr(title),
-               toqstr(formatted(message)));
+               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<void>().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;
@@ -254,27 +266,44 @@ void information(docstring const & title0, docstring const & message)
        docstring const title = bformat(_("LyX: %1$s"), title0);
 
        if (theApp() == 0) {
-               noAppDialog(toqstr(title), toqstr(formatted(message)), QMessageBox::Information);
+               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(formatted(message)));
+               toqstr(message));
 
        qApp->restoreOverrideCursor();
+
+       if (long_op)
+               theApp()->startLongOperation();
 }
 
+void information(docstring const & title0, docstring const & message)
+{
+#ifdef EXPORT_in_THREAD
+       InGuiThread<void>().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) {
@@ -285,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),
@@ -292,6 +326,9 @@ bool askForText(docstring & response, docstring const & msg,
                QLineEdit::Normal,
                toqstr(dflt), &ok);
 
+       if (long_op)
+               theApp()->startLongOperation();
+
        if (ok) {
                response = qstring_to_ucs4(text);
                return true;
@@ -300,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<bool>().call(&doAskForText,
+#else
+       return doAskForText(
+#endif
+                               response, msg, dflt);
+}
 
 } // namespace Alert
 } // namespace frontend