diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index fdc40a316b..8568d5c631 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -16,6 +16,7 @@ files: |
src/Mod/Surface|
src/Mod/Start|
src/Mod/Test|
+ src/Mod/Tux|
src/Mod/Web
)
exclude: |
diff --git a/src/FCConfig.h b/src/FCConfig.h
index 9ddce84b52..a075b010ea 100644
--- a/src/FCConfig.h
+++ b/src/FCConfig.h
@@ -51,16 +51,7 @@
# if HAVE_CONFIG_H
# include
# endif // HAVE_CONFIG_H
-//# define HAVE_INT8_T
-//# define HAVE_UINT8_T
-//# define HAVE_INT16_T
-//# define HAVE_UINT16_T
-//# define HAVE_INT32_T
-//# define HAVE_UINT32_T
-//# define HAVE_INT64_T
-//# define HAVE_UINT64_T
-//# define HAVE_INTPTR_T
-//# define HAVE_UINTPTR_T
+
# endif
#elif defined(__MWERKS__) && defined(__INTEL__)
# ifndef FC_OS_WIN32
@@ -93,26 +84,7 @@
# define HAVE_INTPTR_T
# define HAVE_UINTPTR_T
#endif
-//#elif defined(sun) || defined(__sun) || defined(__sun__)
-//# if defined(__SVR4)
-//# define _FC_OS_SOLARIS
-//# else
-//# define _FC_OS_SUN_
-//# endif
-//#elif defined(hpux) || defined(__hpux) || defined(__hpux__)
-//# define FC_OS_HPUX_
-//#elif defined(__FreeBSD__)
-//# define FC_OS_FREEBSD
-//#elif defined(__NetBSD__)
-//# define FC_OS_NETBSD
-//#elif defined(__OpenBSD__)
-//# define FC_OS_OPENBSD
-//#elif defined(sgi) || defined(__sgi)
-//# define FC_OS_IRIX
-//#elif defined(_AIX)
-//# define FC_OS_AIX
-//#elif defined(__GNU__)
-//# define FC_OS_GNU
+
#else
# error "FreeCAD is not ported to this OS yet. For help see www.freecad.org"
#endif
@@ -203,7 +175,6 @@ typedef unsigned __int64 uint64_t;
#ifdef FC_OS_LINUX
# define LIN
# define LININTEL
-//# define NO_CXX_EXCEPTION
#endif
#define CSFDB
@@ -263,14 +234,6 @@ typedef unsigned __int64 uint64_t;
# endif
#endif
-//**************************************************************************
-// SoQt
-#if defined (FC_OS_WIN32) || defined(FC_OS_CYGWIN)
-# ifndef SOQT_DLL
-# define SOQT_DLL
-# endif
-#endif
-
//**************************************************************************
// Quarter
#if defined (FC_OS_WIN32) || defined(FC_OS_CYGWIN)
@@ -281,15 +244,13 @@ typedef unsigned __int64 uint64_t;
# endif
#endif
-// stops inclusion of the QT 3 header through the SoQT header...
-//#define __Qt3All__
-
//**************************************************************************
// Boost
#ifndef BOOST_SIGNALS_NO_DEPRECATION_WARNING
#define BOOST_SIGNALS_NO_DEPRECATION_WARNING
#endif
+
//**************************************************************************
// Exception handling
@@ -314,15 +275,12 @@ typedef unsigned __int64 uint64_t;
// point at which warnings of overly long specifiers disabled (needed for VC6)
#ifdef _MSC_VER
# pragma warning( disable : 4251 )
-//# pragma warning( disable : 4503 )
-//# pragma warning( disable : 4786 ) // specifier longer then 255 chars
-//# pragma warning( disable : 4290 ) // not implemented throw specification
# pragma warning( disable : 4996 ) // suppress deprecated warning for e.g. open()
#if defined(WIN64) || defined(_WIN64) || defined(__WIN64__)
# pragma warning( disable : 4244 )
# pragma warning( disable : 4267 )
#endif
-//# define _PreComp_ // use precompiled header
+
#endif
#endif //FC_CONFIG_H
diff --git a/src/Gui/3Dconnexion/GuiNativeEventLinuxX11.cpp b/src/Gui/3Dconnexion/GuiNativeEventLinuxX11.cpp
index 2ef1c983ff..f6bd8a955f 100644
--- a/src/Gui/3Dconnexion/GuiNativeEventLinuxX11.cpp
+++ b/src/Gui/3Dconnexion/GuiNativeEventLinuxX11.cpp
@@ -33,23 +33,22 @@
#include
#include
-#if QT_VERSION >= 0x050000
- #include "GuiRawInputEventFilter.h"
- #undef Bool
- #undef CursorShape
- #undef Expose
- #undef KeyPress
- #undef KeyRelease
- #undef FocusIn
- #undef FocusOut
- #undef FontChange
- #undef None
- #undef Status
- #undef Unsorted
- #undef False
- #undef True
- #undef Complex
-#endif // #if QT_VERSION >= 0x050000
+#include "GuiRawInputEventFilter.h"
+#undef Bool
+#undef CursorShape
+#undef Expose
+#undef KeyPress
+#undef KeyRelease
+#undef FocusIn
+#undef FocusOut
+#undef FontChange
+#undef None
+#undef Status
+#undef Unsorted
+#undef False
+#undef True
+#undef Complex
+
Gui::GuiNativeEvent::GuiNativeEvent(Gui::GUIApplicationNativeEventAware *app)
: GuiAbstractNativeEvent(app)
@@ -66,26 +65,19 @@ Gui::GuiNativeEvent::~GuiNativeEvent()
void Gui::GuiNativeEvent::initSpaceball(QMainWindow *window)
{
-#if QT_VERSION >= 0x050200
if (!QX11Info::isPlatformX11()) {
Base::Console().Log("Application is not running on X11\n");
return;
}
-#endif
if (spnav_x11_open(QX11Info::display(), window->winId()) == -1) {
Base::Console().Log("Couldn't connect to spacenav daemon on X11. Please ignore if you don't have a spacemouse.\n");
} else {
Base::Console().Log("Connected to spacenav daemon on X11\n");
mainApp->setSpaceballPresent(true);
-
-#if QT_VERSION >= 0x050000
mainApp->installNativeEventFilter(new Gui::RawInputEventFilter(&xcbEventFilter));
-#endif // #if QT_VERSION >= 0x050000
}
}
-#if QT_VERSION >= 0x050000
-
bool Gui::GuiNativeEvent::xcbEventFilter(void *xcb_void, long* result)
{
Q_UNUSED(result);
@@ -151,117 +143,4 @@ bool Gui::GuiNativeEvent::xcbEventFilter(void *xcb_void, long* result)
} // end switch (navEvent.type) {
}
-#else // if QT_VERSION >= 0x050000
-
-bool Gui::GuiNativeEvent::x11EventFilter(XEvent *event)
-{
- /*
- First we check if we have a motion flush event:
- - If there are unprocessed motion events we are in a flooding situation.
- In that case we wait with generating a Spaceball event.
- - A motion event counter of 0 indicates that FreeCAD is ready to process
- the event. A Spaceball event, using the saved motion data, is posted.
- */
- static Display* display = QX11Info::display();
- static Atom motion_flush_event = XInternAtom(display, "FCMotionFlushEvent", false);
- static int nMotionEvents = 0;
-
- if (event->type == ClientMessage)
- {
- Atom message_type = event->xclient.message_type;
-
- if (message_type == motion_flush_event)
- {
- nMotionEvents--;
- if (nMotionEvents == 0)
- {
- mainApp->postMotionEvent(motionDataArray);
- }
-
- return true;
- } // XEvent: motion_flush_event
- } // XEvent: ClientMessage
-
- /*
- From here on we deal with spacenav events only:
- - motion: The event data is saved and a self addressed flush event
- is sent through the window system (XEvent).
- In the case of an event flooding, the motion data is added up.
- - button: A Spaceball event is posted (QInputEvent).
- */
- spnav_event navEvent;
- if (!spnav_x11_event(event, &navEvent))
- return false;
-
- if (navEvent.type == SPNAV_EVENT_MOTION)
- {
- /*
- If the motion data of the preceding event has not been processed
- through posting an Spaceball event (flooding situation),
- the motion data provided by the incoming event is added to the saved data.
- */
- int dx, dy, dz, drx, dry, drz;
-
- if (nMotionEvents == 0)
- {
- dx = 0;
- dy = 0;
- dz = 0;
- drx = 0;
- dry = 0;
- drz = 0;
- }
- else
- {
- dx = motionDataArray[0];
- dy = motionDataArray[1];
- dz = motionDataArray[2];
- drx = motionDataArray[3];
- dry = motionDataArray[4];
- drz = motionDataArray[5];
- }
-
- motionDataArray[0] = -navEvent.motion.x;
- motionDataArray[1] = -navEvent.motion.z;
- motionDataArray[2] = -navEvent.motion.y;
- motionDataArray[3] = -navEvent.motion.rx;
- motionDataArray[4] = -navEvent.motion.rz;
- motionDataArray[5] = -navEvent.motion.ry;
-
- motionDataArray[0] += dx;
- motionDataArray[1] += dy;
- motionDataArray[2] += dz;
- motionDataArray[3] += drx;
- motionDataArray[4] += dry;
- motionDataArray[5] += drz;
-
- /*
- Send a self addressed flush event through the window system. This will
- trigger a Spaceball event if FreeCAD is ready to do so.
- */
- nMotionEvents++;
- XClientMessageEvent flushEvent;
-
- flushEvent.display = display;
- flushEvent.window = event->xclient.window;
- flushEvent.type = ClientMessage;
- flushEvent.format = 8;
- flushEvent.message_type = motion_flush_event;
-
- XSendEvent (display, flushEvent.window, False, 0, (XEvent*)&flushEvent); // siehe spnavd, False, 0
-
- return true;
- }
-
- if (navEvent.type == SPNAV_EVENT_BUTTON)
- {
- mainApp->postButtonEvent(navEvent.button.bnum, navEvent.button.press);
- return true;
- }
-
- Base::Console().Log("Unknown spaceball event\n");
- return true;
-}
-#endif // if/else QT_VERSION >= 0x050000
-
#include "3Dconnexion/moc_GuiNativeEventLinuxX11.cpp"
diff --git a/src/Gui/3Dconnexion/GuiNativeEventWin32.cpp b/src/Gui/3Dconnexion/GuiNativeEventWin32.cpp
index 2fcf5df8a6..9029309eda 100644
--- a/src/Gui/3Dconnexion/GuiNativeEventWin32.cpp
+++ b/src/Gui/3Dconnexion/GuiNativeEventWin32.cpp
@@ -45,9 +45,7 @@ http://www.3dconnexion.com/forum/viewtopic.php?f=19&t=4968&sid=72c018bdcf0e6edc9
#include
#include
#include "GuiApplicationNativeEventAware.h"
-#if QT_VERSION >= 0x050000
- #include "GuiRawInputEventFilter.h"
-#endif // #if QT_VERSION >= 0x050000
+#include "GuiRawInputEventFilter.h"
Gui::GuiNativeEvent* Gui::GuiNativeEvent::gMouseInput = 0;
@@ -277,12 +275,8 @@ void Gui::GuiNativeEvent::initSpaceball(QMainWindow *mainWindow)
if (InitializeRawInput((HWND)mainWindow->winId())) {
gMouseInput = this;
-#if QT_VERSION >= 0x050000
qApp->installNativeEventFilter(
new Gui::RawInputEventFilter(Gui::GuiNativeEvent::RawInputEventFilter));
-#else
- qApp->setEventFilter(Gui::GuiNativeEvent::RawInputEventFilter);
-#endif
Base::Console().Log("3Dconnexion device initialized.\n");
}
else {
diff --git a/src/Gui/Application.cpp b/src/Gui/Application.cpp
index 132c6f6218..3c08f1f89b 100644
--- a/src/Gui/Application.cpp
+++ b/src/Gui/Application.cpp
@@ -1745,6 +1745,7 @@ void setCategoryFilterRules()
stream << "qt.qpa.xcb.warning=false\n";
stream << "qt.qpa.mime.warning=false\n";
stream << "qt.svg.warning=false\n";
+ stream << "qt.xkb.compose.warning=false\n";
stream.flush();
QLoggingCategory::setFilterRules(filter);
}
diff --git a/src/Gui/CMakeLists.txt b/src/Gui/CMakeLists.txt
index bd08153797..2d42991bda 100644
--- a/src/Gui/CMakeLists.txt
+++ b/src/Gui/CMakeLists.txt
@@ -666,6 +666,7 @@ SET(Editor_CPP_SRCS
PythonConsole.cpp
PythonConsolePy.cpp
PythonDebugger.cpp
+ PythonTracing.cpp
PythonEditor.cpp
SyntaxHighlighter.cpp
TextEdit.cpp
@@ -677,6 +678,7 @@ SET(Editor_HPP_SRCS
PythonConsole.h
PythonConsolePy.h
PythonDebugger.h
+ PythonTracing.h
PythonEditor.h
SyntaxHighlighter.h
TextEdit.h
diff --git a/src/Gui/PreferencePages/DlgSettingsPythonConsole.cpp b/src/Gui/PreferencePages/DlgSettingsPythonConsole.cpp
index 6e59fad4ca..0734266741 100644
--- a/src/Gui/PreferencePages/DlgSettingsPythonConsole.cpp
+++ b/src/Gui/PreferencePages/DlgSettingsPythonConsole.cpp
@@ -44,6 +44,7 @@ void DlgSettingsPythonConsole::saveSettings()
ui->PythonWordWrap->onSave();
ui->PythonBlockCursor->onSave();
ui->PythonSaveHistory->onSave();
+ ui->ProfilerInterval->onSave();
}
void DlgSettingsPythonConsole::loadSettings()
@@ -51,14 +52,15 @@ void DlgSettingsPythonConsole::loadSettings()
ui->PythonWordWrap->onRestore();
ui->PythonBlockCursor->onRestore();
ui->PythonSaveHistory->onRestore();
+ ui->ProfilerInterval->onRestore();
}
-void DlgSettingsPythonConsole::changeEvent(QEvent *e)
+void DlgSettingsPythonConsole::changeEvent(QEvent* event)
{
- if (e->type() == QEvent::LanguageChange) {
+ if (event->type() == QEvent::LanguageChange) {
ui->retranslateUi(this);
}
- QWidget::changeEvent(e);
+ QWidget::changeEvent(event);
}
#include "moc_DlgSettingsPythonConsole.cpp"
diff --git a/src/Gui/PreferencePages/DlgSettingsPythonConsole.ui b/src/Gui/PreferencePages/DlgSettingsPythonConsole.ui
index e72f80f3cf..b7f2ac20b6 100644
--- a/src/Gui/PreferencePages/DlgSettingsPythonConsole.ui
+++ b/src/Gui/PreferencePages/DlgSettingsPythonConsole.ui
@@ -78,6 +78,35 @@ horizontal space in Python console
+ -
+
+
+ Python profiler interval (milliseconds):
+
+
+
+ -
+
+
+ The interval at which the profiler runs when there's Python code running (to keep the GUI responding). Set to 0 to disable.
+
+
+ 0
+
+
+ 5000
+
+
+ 200
+
+
+ ProfilerInterval
+
+
+ PythonConsole
+
+
+
@@ -102,6 +131,11 @@ horizontal space in Python console
QCheckBox
+
+ Gui::PrefSpinBox
+ QSpinBox
+
+
diff --git a/src/Gui/PythonConsole.cpp b/src/Gui/PythonConsole.cpp
index 588940fd67..718e79cf73 100644
--- a/src/Gui/PythonConsole.cpp
+++ b/src/Gui/PythonConsole.cpp
@@ -32,6 +32,7 @@
# include
# include
# include
+# include
# include
#endif
@@ -40,6 +41,7 @@
#include "PythonConsole.h"
#include "PythonConsolePy.h"
+#include "PythonTracing.h"
#include "Application.h"
#include "CallTips.h"
#include "FileDialog.h"
@@ -77,9 +79,8 @@ inline bool cursorBeyond( const QTextCursor &cursor, const QTextCursor &limit, i
if (cursor.hasSelection()) {
return (cursor.selectionStart() >= pos && cursor.selectionEnd() >= pos);
}
- else {
- return cursor.position() >= (pos + shift);
- }
+
+ return cursor.position() >= (pos + shift);
}
struct PythonConsoleP
@@ -87,9 +88,9 @@ struct PythonConsoleP
enum Output {Error = 20, Message = 21};
enum CopyType {Normal, History, Command};
CopyType type;
- PyObject *_stdoutPy, *_stderrPy, *_stdinPy, *_stdin;
- InteractiveInterpreter* interpreter;
- CallTipsList* callTipsList;
+ PyObject *_stdoutPy=nullptr, *_stderrPy=nullptr, *_stdinPy=nullptr, *_stdin=nullptr;
+ InteractiveInterpreter* interpreter=nullptr;
+ CallTipsList* callTipsList=nullptr;
ConsoleHistory history;
QString output, error, info, historyFile;
QStringList statements;
@@ -99,12 +100,6 @@ struct PythonConsoleP
PythonConsoleP()
{
type = Normal;
- _stdoutPy = nullptr;
- _stderrPy = nullptr;
- _stdinPy = nullptr;
- _stdin = nullptr;
- interpreter = nullptr;
- callTipsList = nullptr;
interactive = false;
historyFile = QString::fromUtf8((App::Application::getUserAppDataDir() + "PythonHistory.log").c_str());
colormap[QLatin1String("Text")] = qApp->palette().windowText().color();
@@ -123,12 +118,15 @@ struct PythonConsoleP
colormap[QLatin1String("Python error")] = Qt::red;
}
};
+
struct InteractiveInterpreterP
{
- PyObject* interpreter;
- PyObject* sysmodule;
+ PyObject* interpreter{nullptr};
+ PyObject* sysmodule{nullptr};
QStringList buffer;
+ PythonTracing trace;
};
+
} // namespace Gui
InteractiveInterpreter::InteractiveInterpreter()
@@ -302,6 +300,16 @@ bool InteractiveInterpreter::runSource(const char* source) const
return false;
}
+bool InteractiveInterpreter::isOccupied() const
+{
+ return d->trace.isActive();
+}
+
+bool InteractiveInterpreter::interrupt() const
+{
+ return d->trace.interrupt();
+}
+
/* Execute a code object.
*
* When an exception occurs, a traceback is displayed.
@@ -309,6 +317,13 @@ bool InteractiveInterpreter::runSource(const char* source) const
*/
void InteractiveInterpreter::runCode(PyCodeObject* code) const
{
+ if (isOccupied()) {
+ return;
+ }
+
+ d->trace.fetchFromSettings();
+ PythonTracingLocker tracelock(d->trace);
+
Base::PyGILStateLocker lock;
PyObject *module, *dict, *presult; /* "exec code in d, d" */
module = PyImport_AddModule("__main__"); /* get module, init python */
@@ -485,6 +500,10 @@ PythonConsole::PythonConsole(QWidget *parent)
d->output = d->info;
printPrompt(PythonConsole::Complete);
loadHistory();
+
+ flusher = new QTimer(this);
+ connect(flusher, &QTimer::timeout, this, &PythonConsole::flushOutput);
+ flusher->start(100);
}
/** Destroys the object and frees any allocated resources */
@@ -565,6 +584,12 @@ void PythonConsole::keyPressEvent(QKeyEvent * e)
QTextCursor cursor = this->textCursor();
QTextCursor inputLineBegin = this->inputBegin();
+ if (e->key() == Qt::Key_C && e->modifiers() == Qt::ControlModifier) {
+ if (d->interpreter->interrupt()) {
+ return;
+ }
+ }
+
if (!cursorBeyond( cursor, inputLineBegin ))
{
/**
@@ -740,6 +765,15 @@ void PythonConsole::onFlush()
printPrompt(PythonConsole::Flush);
}
+void PythonConsole::flushOutput()
+{
+ if (d->interpreter->isOccupied()) {
+ if (d->output.length() > 0 || d->error.length() > 0) {
+ printPrompt(PythonConsole::Complete);
+ }
+ }
+}
+
/** Prints the ps1 prompt (>>> ) for complete and ps2 prompt (... ) for
* incomplete commands to the console window.
*/
@@ -830,6 +864,11 @@ void PythonConsole::runSource(const QString& line)
return;
}
+ if (d->interpreter->isOccupied()) {
+ insertPythonError(QString::fromLatin1("Previous command still running!"));
+ return;
+ }
+
bool incomplete = false;
Base::PyGILStateLocker lock;
PyObject* default_stdout = PySys_GetObject("stdout");
diff --git a/src/Gui/PythonConsole.h b/src/Gui/PythonConsole.h
index 1db269840e..1375334cd5 100644
--- a/src/Gui/PythonConsole.h
+++ b/src/Gui/PythonConsole.h
@@ -24,6 +24,7 @@
#define GUI_PYTHONCONSOLE_H
#include
+#include
#include "PythonEditor.h"
@@ -42,6 +43,9 @@ public:
InteractiveInterpreter();
~InteractiveInterpreter();
+ bool isOccupied() const;
+ bool interrupt() const;
+
bool push(const char*);
int compileCommand(const char*) const;
bool hasPendingInput( ) const;
@@ -151,6 +155,7 @@ private:
void appendOutput(const QString&, int);
void loadHistory() const;
void saveHistory() const;
+ void flushOutput();
Q_SIGNALS:
void pendingSource( );
@@ -158,13 +163,13 @@ Q_SIGNALS:
private:
struct PythonConsoleP* d;
+ PythonConsoleHighlighter* pythonSyntax{nullptr};
+ QString *_sourceDrain{nullptr};
+ QString _historyFile;
+ QTimer *flusher{nullptr};
+
friend class PythonStdout;
friend class PythonStderr;
-
-private:
- PythonConsoleHighlighter* pythonSyntax;
- QString *_sourceDrain;
- QString _historyFile;
};
/**
diff --git a/src/Gui/PythonTracing.cpp b/src/Gui/PythonTracing.cpp
new file mode 100644
index 0000000000..d128f1d308
--- /dev/null
+++ b/src/Gui/PythonTracing.cpp
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+
+/***************************************************************************
+ * Copyright (c) 2023 Werner Mayer *
+ * *
+ * This file is part of FreeCAD. *
+ * *
+ * FreeCAD is free software: you can redistribute it and/or modify it *
+ * under the terms of the GNU Lesser General Public License as *
+ * published by the Free Software Foundation, either version 2.1 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * FreeCAD is distributed in the hope that it will be useful, but *
+ * WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with FreeCAD. If not, see *
+ * . *
+ * *
+ **************************************************************************/
+
+#include "PreCompiled.h"
+#ifndef _PreComp_
+#include
+#include
+#endif
+
+#include "PythonTracing.h"
+#include
+
+using namespace Gui;
+
+struct PythonTracing::Private
+{
+ bool active{false};
+ int timeout{200}; //NOLINT
+
+ // NOLINTBEGIN
+ static int profilerInterval;
+ static bool profilerDisabled;
+ // NOLINTEND
+};
+
+// NOLINTBEGIN
+int PythonTracing::Private::profilerInterval = 200;
+bool PythonTracing::Private::profilerDisabled = false;
+// NOLINTEND
+
+PythonTracing::PythonTracing()
+ : d{std::make_unique()}
+{
+}
+
+PythonTracing::~PythonTracing() = default;
+
+bool PythonTracing::isActive() const
+{
+ return d->active;
+}
+
+void PythonTracing::activate()
+{
+ d->active = true;
+ setPythonTraceEnabled(true);
+}
+
+void PythonTracing::deactivate()
+{
+ d->active = false;
+ setPythonTraceEnabled(false);
+}
+
+void PythonTracing::fetchFromSettings()
+{
+ const long defaultTimeout = 200;
+
+ auto parameterGroup = App::GetApplication().GetParameterGroupByPath(
+ "User parameter:BaseApp/Preferences/PythonConsole");
+ int interval = static_cast(parameterGroup->GetInt("ProfilerInterval", defaultTimeout));
+ setTimeout(interval);
+}
+
+bool PythonTracing::interrupt() const
+{
+ if (isActive()) {
+ PyErr_SetInterrupt();
+ return true;
+ }
+
+ return false;
+}
+
+void PythonTracing::setTimeout(int ms)
+{
+ d->timeout = ms;
+}
+
+int PythonTracing::timeout() const
+{
+ return d->timeout;
+}
+
+void PythonTracing::setPythonTraceEnabled(bool enabled) const
+{
+ Py_tracefunc trace = nullptr;
+ if (enabled && timeout() > 0) {
+ Private::profilerInterval = timeout();
+ trace = &tracer_callback;
+ }
+ else {
+ Private::profilerDisabled = true;
+ }
+
+ PyEval_SetTrace(trace, nullptr);
+}
+
+/*
+ * This callback ensures that Qt runs its event loop (i.e. updates the GUI, processes keyboard and
+ * mouse events, etc.) at least every 200 ms, even when there is long-running Python code on the
+ * main thread. It is registered as the global trace function of the Python environment.
+ */
+int PythonTracing::tracer_callback(PyObject *obj, PyFrameObject *frame, int what, PyObject *arg)
+{
+ Q_UNUSED(obj)
+ Q_UNUSED(frame)
+ Q_UNUSED(what)
+ Q_UNUSED(arg)
+
+ static QTime lastCalledTime = QTime::currentTime();
+ QTime currTime = QTime::currentTime();
+
+ // if previous code object was executed
+ if (Private::profilerDisabled) {
+ Private::profilerDisabled = false;
+ lastCalledTime = currTime;
+ }
+
+ int ms = lastCalledTime.msecsTo(currTime);
+
+ if (ms >= Private::profilerInterval) {
+ lastCalledTime = currTime;
+ QGuiApplication::processEvents();
+ }
+
+ return 0;
+}
+
+// ------------------------------------------------------------------------------------------------
+
+PythonTracingLocker::PythonTracingLocker(PythonTracing& trace)
+ : trace{trace}
+{
+ trace.activate();
+}
+
+PythonTracingLocker::~PythonTracingLocker()
+{
+ trace.deactivate();
+}
diff --git a/src/Gui/PythonTracing.h b/src/Gui/PythonTracing.h
new file mode 100644
index 0000000000..8f09cef301
--- /dev/null
+++ b/src/Gui/PythonTracing.h
@@ -0,0 +1,118 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+
+/***************************************************************************
+ * Copyright (c) 2023 Werner Mayer *
+ * *
+ * This file is part of FreeCAD. *
+ * *
+ * FreeCAD is free software: you can redistribute it and/or modify it *
+ * under the terms of the GNU Lesser General Public License as *
+ * published by the Free Software Foundation, either version 2.1 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * FreeCAD is distributed in the hope that it will be useful, but *
+ * WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with FreeCAD. If not, see *
+ * . *
+ * *
+ **************************************************************************/
+
+#ifndef GUI_PYTHONTRACING_H
+#define GUI_PYTHONTRACING_H
+
+#include
+#include
+#include
+#include
+
+
+namespace Gui {
+
+class GuiExport PythonTracing
+{
+public:
+ PythonTracing();
+ ~PythonTracing();
+
+ PythonTracing(const PythonTracing&) = delete;
+ PythonTracing(PythonTracing&&) = delete;
+ PythonTracing& operator = (const PythonTracing&) = delete;
+ PythonTracing& operator = (PythonTracing&&) = delete;
+
+ /*!
+ * \brief isActive
+ * Returns true if the tracing is active, false otherwise.
+ * \return
+ */
+ bool isActive() const;
+ /*!
+ * \brief activate
+ * Activates the Python tracing.
+ */
+ void activate();
+ /*!
+ * \brief deactivate
+ * Deactivates the Python tracing.
+ */
+ void deactivate();
+ /*!
+ * \brief fetchFromSettings
+ * Fetch parameters from user settings.
+ */
+ void fetchFromSettings();
+ /*!
+ * \brief interrupt
+ * If the tracing is enabled it interrupts the Python interpreter.
+ * True is returned if the tracing is active, false otherwise.
+ */
+ bool interrupt() const;
+ /*!
+ * \brief setTimeout
+ * Sets the interval after which the Qt event loop will be processed.
+ */
+ void setTimeout(int ms);
+ /*!
+ * \brief timeout
+ * \return the timeout of processing the event loop.
+ */
+ int timeout() const;
+
+private:
+ void setPythonTraceEnabled(bool enabled) const;
+ static int tracer_callback(PyObject *obj, PyFrameObject *frame, int what, PyObject *arg);
+
+private:
+ struct Private;
+ std::unique_ptr d;
+};
+
+class GuiExport PythonTracingLocker
+{
+public:
+ /*!
+ * \brief PythonTracingLocker
+ * Activates the passed tracing object.
+ * \param trace
+ */
+ explicit PythonTracingLocker(PythonTracing& trace);
+ /*!
+ * Deactivates the tracing object.
+ */
+ ~PythonTracingLocker();
+
+ PythonTracingLocker(const PythonTracingLocker&) = delete;
+ PythonTracingLocker(PythonTracingLocker&&) = delete;
+ PythonTracingLocker& operator = (const PythonTracingLocker&) = delete;
+ PythonTracingLocker& operator = (PythonTracingLocker&&) = delete;
+
+private:
+ PythonTracing& trace;
+};
+
+} // namespace Gui
+
+#endif // GUI_PYTHONTRACING_H
diff --git a/src/Mod/Draft/draftguitools/gui_trackers.py b/src/Mod/Draft/draftguitools/gui_trackers.py
index 9cf06de6f9..5dd232932b 100644
--- a/src/Mod/Draft/draftguitools/gui_trackers.py
+++ b/src/Mod/Draft/draftguitools/gui_trackers.py
@@ -530,7 +530,7 @@ class arcTracker(Tracker):
"""An arc tracker."""
def __init__(self, dotted=False, scolor=None, swidth=None,
- start=0, end=math.pi*2, normal=None):
+ start=0, end=math.pi*2):
self.circle = None
self.startangle = math.degrees(start)
self.endangle = math.degrees(end)
@@ -538,10 +538,11 @@ class arcTracker(Tracker):
self.trans.translation.setValue([0, 0, 0])
self.sep = coin.SoSeparator()
self.autoinvert = True
- if normal:
- self.normal = normal
- else:
- self.normal = FreeCAD.DraftWorkingPlane.axis
+ self.normal = FreeCAD.DraftWorkingPlane.axis
+ ang = DraftVecUtils.angle(self.getDeviation(),
+ FreeCAD.DraftWorkingPlane.u,
+ self.normal)
+ self.ang_offset = math.degrees(ang)
self.recompute()
super().__init__(dotted, scolor, swidth,
[self.trans, self.sep], name="arcTracker")
@@ -578,10 +579,7 @@ class arcTracker(Tracker):
"""Return the angle of a given vector in radians."""
c = self.trans.translation.getValue()
center = Vector(c[0], c[1], c[2])
- rad = pt.sub(center)
- a = DraftVecUtils.angle(rad, self.getDeviation(), self.normal)
- # print(a)
- return a
+ return DraftVecUtils.angle(self.getDeviation(), pt.sub(center), self.normal)
def getAngles(self):
"""Return the start and end angles in degrees."""
@@ -589,11 +587,11 @@ class arcTracker(Tracker):
def setStartPoint(self, pt):
"""Set the start angle from a point."""
- self.setStartAngle(-self.getAngle(pt))
+ self.setStartAngle(self.getAngle(pt))
def setEndPoint(self, pt):
"""Set the end angle from a point."""
- self.setEndAngle(-self.getAngle(pt))
+ self.setEndAngle(self.getAngle(pt))
def setApertureAngle(self, ang):
"""Set the end angle by giving the aperture angle."""
@@ -622,12 +620,16 @@ class arcTracker(Tracker):
if self.circle:
self.sep.removeChild(self.circle)
self.circle = None
- if (self.endangle < self.startangle) or not self.autoinvert:
- c = Part.makeCircle(1, Vector(0, 0, 0),
- self.normal, self.endangle, self.startangle)
+ if self.autoinvert is False:
+ ang_sta = self.endangle
+ ang_end = self.startangle
+ elif self.endangle < self.startangle:
+ ang_sta = self.endangle + self.ang_offset
+ ang_end = self.startangle + self.ang_offset
else:
- c = Part.makeCircle(1, Vector(0, 0, 0),
- self.normal, self.startangle, self.endangle)
+ ang_sta = self.startangle + self.ang_offset
+ ang_end = self.endangle + self.ang_offset
+ c = Part.makeCircle(1, Vector(0, 0, 0), self.normal, ang_sta, ang_end)
buf = c.writeInventor(2, 0.01)
try:
ivin = coin.SoInput()
@@ -779,7 +781,7 @@ class ghostTracker(Tracker):
def setMatrix(self, matrix):
"""Set the transformation matrix.
-
+
The 4th column of the matrix (the position) is ignored.
"""
m = coin.SbMatrix(matrix.A11, matrix.A12, matrix.A13, matrix.A14,
diff --git a/src/Mod/Fem/App/FemPostFilter.cpp b/src/Mod/Fem/App/FemPostFilter.cpp
index ff9fb3c9bd..aad66d32e0 100644
--- a/src/Mod/Fem/App/FemPostFilter.cpp
+++ b/src/Mod/Fem/App/FemPostFilter.cpp
@@ -162,7 +162,7 @@ FemPostDataAlongLineFilter::FemPostDataAlongLineFilter()
m_probe->SetPassPointArrays(1);
m_probe->SetPassCellArrays(1);
// needs vtk > 6.1
-#if (VTK_MAJOR_VERSION > 6) || (VTK_MINOR_VERSION > 1)
+#if (VTK_MAJOR_VERSION > 6) && (VTK_MINOR_VERSION > 1)
m_probe->ComputeToleranceOff();
m_probe->SetTolerance(0.01);
#endif
@@ -311,7 +311,7 @@ FemPostDataAtPointFilter::FemPostDataAtPointFilter()
m_probe->SetPassPointArrays(1);
m_probe->SetPassCellArrays(1);
// needs vtk > 6.1
-#if (VTK_MAJOR_VERSION > 6) || (VTK_MINOR_VERSION > 1)
+#if (VTK_MAJOR_VERSION > 6) && (VTK_MINOR_VERSION > 1)
m_probe->ComputeToleranceOff();
m_probe->SetTolerance(0.01);
#endif
diff --git a/src/Mod/Fem/Gui/DlgSettingsFemGeneral.ui b/src/Mod/Fem/Gui/DlgSettingsFemGeneral.ui
index 63ec752603..ea264c56f8 100644
--- a/src/Mod/Fem/Gui/DlgSettingsFemGeneral.ui
+++ b/src/Mod/Fem/Gui/DlgSettingsFemGeneral.ui
@@ -69,7 +69,7 @@
- Let the application manage (create, delete) the working directories for all solver. Use temporary directories.
+ Let the application manage (create, delete) the working directories for all solvers. Use temporary directories.
true
diff --git a/src/Mod/Part/Gui/DlgScale.cpp b/src/Mod/Part/Gui/DlgScale.cpp
index 05fbdf1aa5..3666740351 100644
--- a/src/Mod/Part/Gui/DlgScale.cpp
+++ b/src/Mod/Part/Gui/DlgScale.cpp
@@ -68,6 +68,12 @@ DlgScale::DlgScale(QWidget* parent, Qt::WindowFlags fl)
ui->dsbYScale->setDecimals(Base::UnitsApi::getDecimals());
ui->dsbZScale->setDecimals(Base::UnitsApi::getDecimals());
findShapes();
+
+ // this will mark as selected all the items in treeWidget that are selected in the document
+ Gui::ItemViewSelection sel(ui->treeWidget);
+ sel.applyFrom(Gui::Selection().getObjectsOfType(Part::Feature::getClassTypeId()));
+ sel.applyFrom(Gui::Selection().getObjectsOfType(App::Link::getClassTypeId()));
+ sel.applyFrom(Gui::Selection().getObjectsOfType(App::Part::getClassTypeId()));
}
void DlgScale::setupConnections()
@@ -102,15 +108,8 @@ void DlgScale::onUniformScaleToggled(bool state)
}
}
-App::DocumentObject& DlgScale::getShapeToScale() const
-{
-// Base::Console().Message("DS::getShapeToScale()\n");
- std::vector objs = this->getShapesToScale();
- if (objs.empty())
- throw Base::ValueError("No shapes selected");
- return *(objs[0]);
-}
-
+//! find all the scalable objects in the active document and load them into the
+//! list widget
void DlgScale::findShapes()
{
// Base::Console().Message("DS::findShapes()\n");
@@ -141,6 +140,7 @@ void DlgScale::findShapes()
}
}
+//! return true if shape can be scaled.
bool DlgScale::canScale(const TopoDS_Shape& shape) const
{
if (shape.IsNull()) {
@@ -156,11 +156,13 @@ bool DlgScale::canScale(const TopoDS_Shape& shape) const
if (type == TopAbs_COMPOUND ||
type == TopAbs_COMPSOLID) {
TopExp_Explorer xp;
- xp.Init(shape, TopAbs_SHAPE);
+ xp.Init(shape, TopAbs_EDGE);
for ( ; xp.More() ; xp.Next()) {
- // there is at least 1 sub shape inside the compound
+ // there is at least 1 edge inside the compound, so as long as it isn't null,
+ // we can scale this shape. We can stop looking as soon as we find a non-null
+ // edge.
if (!xp.Current().IsNull()) {
- // found a non-null shape
+ // found a non-null edge
return true;
}
}
@@ -186,6 +188,7 @@ void DlgScale::accept()
};
}
+// create a FeatureScale for each scalable object
void DlgScale::apply()
{
// Base::Console().Message("DS::apply()\n");
@@ -264,6 +267,8 @@ void DlgScale::reject()
QDialog::reject();
}
+//! retrieve the document objects associated with the selected items in the list
+//! widget
std::vector DlgScale::getShapesToScale() const
{
// Base::Console().Message("DS::getShapesToScale()\n");
@@ -282,6 +287,8 @@ std::vector DlgScale::getShapesToScale() const
return objects;
}
+//! return true if at least one item in the list widget corresponds to an
+//! available document object in the document
bool DlgScale::validate()
{
QList items = ui->treeWidget->selectedItems();
@@ -299,6 +306,7 @@ bool DlgScale::validate()
return !objects.empty();
}
+//! update a FeatureScale with the parameters from the UI
void DlgScale::writeParametersToFeature(App::DocumentObject &feature, App::DocumentObject* base) const
{
// Base::Console().Message("DS::writeParametersToFeature()\n");
diff --git a/src/Mod/Sandbox/App/AppSandbox.cpp b/src/Mod/Sandbox/App/AppSandbox.cpp
index 37b569ce65..4618589aa8 100644
--- a/src/Mod/Sandbox/App/AppSandbox.cpp
+++ b/src/Mod/Sandbox/App/AppSandbox.cpp
@@ -146,7 +146,7 @@ public:
return genericSetAttro( name_, value );
}
}
- virtual int sequence_length()
+ virtual PyCxx_ssize_t sequence_length()
{
// len(x)
return m_array.size();
diff --git a/src/Mod/Sandbox/App/DocumentThread.cpp b/src/Mod/Sandbox/App/DocumentThread.cpp
index ecec31d779..b1a68a867f 100644
--- a/src/Mod/Sandbox/App/DocumentThread.cpp
+++ b/src/Mod/Sandbox/App/DocumentThread.cpp
@@ -31,6 +31,7 @@
#include
#include
+#include
#include
#include
#include
@@ -88,7 +89,7 @@ void WorkerThread::run()
// --------------------------------------
-QMutex PythonThread::mutex(QMutex::Recursive);
+QRecursiveMutex PythonThread::mutex;
PythonThread::PythonThread(QObject* parent)
: QThread(parent)
diff --git a/src/Mod/Sandbox/App/DocumentThread.h b/src/Mod/Sandbox/App/DocumentThread.h
index b8329c38c8..aa607d86a2 100644
--- a/src/Mod/Sandbox/App/DocumentThread.h
+++ b/src/Mod/Sandbox/App/DocumentThread.h
@@ -25,7 +25,7 @@
#define SANDBOX_DOCUMENTTHREAD_H
#include
-#include
+#include
#include
#include
@@ -63,7 +63,7 @@ public:
protected:
void run();
- static QMutex mutex;
+ static QRecursiveMutex mutex;
};
class SandboxAppExport MeshLoaderThread : public QThread
diff --git a/src/Mod/Sandbox/Gui/CMakeLists.txt b/src/Mod/Sandbox/Gui/CMakeLists.txt
index 67431d322b..4476da5eaf 100644
--- a/src/Mod/Sandbox/Gui/CMakeLists.txt
+++ b/src/Mod/Sandbox/Gui/CMakeLists.txt
@@ -37,14 +37,7 @@ set(SandboxGui_MOC_HDRS
GLGraphicsView.h
)
-fc_wrap_cpp(SandboxGui_MOC_SRCS ${SandboxGui_MOC_HDRS})
-SOURCE_GROUP("Moc" FILES ${SandboxGui_MOC_SRCS})
-
-if(BUILD_QT5)
- qt5_add_resources(Resource_SRCS Resources/Sandbox.qrc)
-else()
- qt4_add_resources(Resource_SRCS Resources/Sandbox.qrc)
-endif()
+qt_add_resources(Resource_SRCS Resources/Sandbox.qrc)
SET(Resource_SRCS
${Resource_SRCS}
Resources/Sandbox.qrc
diff --git a/src/Mod/Sandbox/Gui/Command.cpp b/src/Mod/Sandbox/Gui/Command.cpp
index 0f034ec871..5709af9019 100644
--- a/src/Mod/Sandbox/Gui/Command.cpp
+++ b/src/Mod/Sandbox/Gui/Command.cpp
@@ -68,6 +68,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -933,7 +934,7 @@ void CmdTestGrabWidget::activated(int)
{
QCalendarWidget* c = new QCalendarWidget();
c->hide();
- QPixmap p = QPixmap::grabWidget(c, c->rect());
+ QPixmap p = c->grab(c->rect());
QLabel* label = new QLabel();
label->resize(c->size());
label->setPixmap(p);
@@ -1055,7 +1056,7 @@ void CmdTestImageNode::activated(int)
QString text = QString::fromLatin1("Distance: 2.7jgiorjgor84mm");
QFont font;
QFontMetrics fm(font);
- int w = fm.width(text);
+ int w = Gui::QtTools::horizontalAdvance(fm, text);
int h = fm.height();
diff --git a/src/Mod/Sandbox/Gui/GLGraphicsView.cpp b/src/Mod/Sandbox/Gui/GLGraphicsView.cpp
index b3ee4eb1ac..6cae14de5f 100644
--- a/src/Mod/Sandbox/Gui/GLGraphicsView.cpp
+++ b/src/Mod/Sandbox/Gui/GLGraphicsView.cpp
@@ -48,7 +48,6 @@
#include
#include
#include
-#include
#include
#include
#include
@@ -57,6 +56,7 @@
#include
#include "GLGraphicsView.h"
+#include
#include
#include
@@ -239,10 +239,12 @@ SceneEventFilter::eventFilter(QObject *, QEvent * qevent)
}
case QEvent::GraphicsSceneWheel:
{
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
QGraphicsSceneWheelEvent* ev = static_cast(qevent);
sceneev.reset(new QWheelEvent(ev->pos().toPoint(), ev->delta(), ev->buttons(),
ev->modifiers(), ev->orientation()));
qevent = sceneev.get();
+#endif
break;
}
case QEvent::GraphicsSceneResize:
@@ -351,7 +353,9 @@ GraphicsScene::GraphicsScene()
pos += QPointF(0, 10 + rect.height());
}
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
m_time.start();
+#endif
sorendermanager = new SoRenderManager;
sorendermanager->setAutoClipping(SoRenderManager::VARIABLE_NEAR_PLANE);
@@ -572,14 +576,18 @@ void GraphicsScene::drawBackground(QPainter *painter, const QRectF &)
return;
}
+#if 0
glViewport(0, 0, width(), height());
/**/
glClearColor(m_backgroundColor.redF(), m_backgroundColor.greenF(), m_backgroundColor.blueF(), 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+#endif
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
const int delta = m_time.elapsed() - m_lastTime;
m_lastTime += delta;
+#endif
sorendermanager->render(true/*PRIVATE(this)->clearwindow*/,
@@ -625,7 +633,9 @@ void GraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
if (event->isAccepted())
return;
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
m_mouseEventTime = m_time.elapsed();
+#endif
event->accept();
}
@@ -654,10 +664,12 @@ GraphicsView3D::GraphicsView3D(Gui::Document* doc, QWidget* parent)
: Gui::MDIView(doc, parent), m_scene(new GraphicsScene()), m_view(new GraphicsView)
{
m_view->installEventFilter(m_scene->getEventFilter());
- QGLFormat f;
+#if 0
+ QtGLFormat f;
f.setSampleBuffers(true);
f.setSamples(8);
m_view->setViewport(new QGLWidget(f));
+#endif
m_view->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
m_view->setScene(m_scene);
m_scene->setNavigationModeFile(QUrl(QString::fromLatin1("coin:///scxml/navigation/examiner.xml")));
@@ -698,5 +710,4 @@ void GraphicsView3D::OnChange(ParameterGrp::SubjectType &rCaller,ParameterGrp::M
m_scene->setBackgroundColor(QColor::fromRgbF(r1, g1, b1));
}
}
-
#include "moc_GLGraphicsView.cpp"
diff --git a/src/Mod/Sandbox/Gui/Overlay.cpp b/src/Mod/Sandbox/Gui/Overlay.cpp
index e7fa9e8f7c..61ca950f4d 100644
--- a/src/Mod/Sandbox/Gui/Overlay.cpp
+++ b/src/Mod/Sandbox/Gui/Overlay.cpp
@@ -63,20 +63,11 @@ public:
p.drawText(200,200,QString::fromLatin1("Render to QImage"));
}
-#if !defined(HAVE_QT5_OPENGL)
- img = QtGLWidget::convertToGLFormat(img);
-#endif
fbo = new QtGLFramebufferObject(v->getGLWidget()->size());
fbo->bind();
//glClear(GL_COLOR_BUFFER_BIT);
fbo->release();
{
-#if !defined(HAVE_QT5_OPENGL)
- QPainter p(fbo);
- p.setPen(Qt::white);
- p.drawText(200,200,QString::fromLatin1("Render to QtGLFramebufferObject"));
- p.end();
-#endif
//img = fbo->toImage();
//img = QtGLWidget::convertToGLFormat(img);
}
@@ -626,18 +617,6 @@ void DrawingPlane::drawLineTo(const QPoint &endPoint)
{
Q_UNUSED(endPoint);
return;
-#if !defined(HAVE_QT5_OPENGL)
- QPainter painter(fbo);
- //QPainter painter(_pcView3D->getGLWidget());
- painter.setPen(QPen(myPenColor, myPenWidth, Qt::SolidLine, Qt::RoundCap,
- Qt::RoundJoin));
- //painter.setOpacity(0.5);
- //painter.drawLine(lastPoint.x(), fbo->height()-lastPoint.y(), endPoint.x(), fbo->height()-endPoint.y());
- painter.drawLine(lastPoint.x(), lastPoint.y(), endPoint.x(), endPoint.y());
-
- //_pcView3D->scheduleRedraw();
- lastPoint = endPoint;
-#endif
}
//Gui::Document* doc = Gui::Application::Instance->activeDocument();
//Gui::View3DInventorViewer* view = static_cast(doc->getActiveView())->getViewer();
diff --git a/src/Mod/Sandbox/Gui/TaskPanelView.cpp b/src/Mod/Sandbox/Gui/TaskPanelView.cpp
index ad2e78b1ad..10ac3b1f5c 100644
--- a/src/Mod/Sandbox/Gui/TaskPanelView.cpp
+++ b/src/Mod/Sandbox/Gui/TaskPanelView.cpp
@@ -364,8 +364,6 @@ public:
Q_UNUSED(MainWindow);
} // retranslateUi
};
-#else
-#include
#endif
TaskPanelView::TaskPanelView(QWidget *parent)
@@ -580,96 +578,6 @@ TaskPanelView::TaskPanelView(QWidget *parent)
connect(ui->rbAndroidScheme, SIGNAL(toggled(bool)), androidAction, SIGNAL(toggled(bool)));
func->toggle(androidAction, boost::bind(&TaskPanelView::on_rbAndroidScheme_toggled, this, bp::_1));
}
-#else
- setWindowTitle(QLatin1String("Task View"));
-
- QGridLayout* gridLayout = new QGridLayout(this);
- iisTaskPanel *taskPanel = new iisTaskPanel(this);
- iisTaskBox *tb1 = new iisTaskBox(
- QPixmap(QString::fromLatin1(":/icons/document-save.svg")),QLatin1String("Expandable Group"),true, this);
- taskPanel->addWidget(tb1);
- gridLayout->addWidget(taskPanel, 0, 0, 2, 1);
-
- iisIconLabel *i1 = new iisIconLabel(
- Gui::BitmapFactory().iconFromTheme("document-new"), QLatin1String("Create new file"), tb1);
- tb1->addIconLabel(i1);
- connect(i1, SIGNAL(activated()), action, SIGNAL(triggered()));
-
- iisIconLabel *i2 = new iisIconLabel(
- Gui::BitmapFactory().iconFromTheme("document-open"), QLatin1String("Load a file"), tb1);
- tb1->addIconLabel(i2);
- connect(i2, SIGNAL(activated()), action, SIGNAL(triggered()));
-
- tb1->groupLayout()->addWidget(new QPushButton(QLatin1String("Just a button"), this));
-
- iisIconLabel *i3 = new iisIconLabel(
- Gui::BitmapFactory().iconFromTheme("document-save"), QLatin1String("Save current file"), tb1);
- tb1->addIconLabel(i3);
-
- iisIconLabel *i4 = new iisIconLabel(
- Gui::BitmapFactory().iconFromTheme("document-print"), QLatin1String("Print file contents"), tb1);
- tb1->addIconLabel(i4);
- i4->setColors(Qt::red, Qt::green, Qt::gray);
- i4->setFocusPen(QPen());
-
- tb1->groupLayout()->addWidget(new QPushButton(QLatin1String("Just another button"), this));
-
- iisTaskBox *tb2 = new iisTaskBox(
- Gui::BitmapFactory().pixmap("edit-redo"), QLatin1String("Non-expandable Group"), false, this);
- taskPanel->addWidget(tb2);
-
- iisIconLabel *i21 = new iisIconLabel(
- Gui::BitmapFactory().iconFromTheme("document-new"), QLatin1String("Create new file"), tb2);
- tb2->addIconLabel(i21);
-
- iisIconLabel *i22 = new iisIconLabel(
- Gui::BitmapFactory().iconFromTheme("document-open"), QLatin1String("Load a file"), tb2);
- tb2->addIconLabel(i22);
-
- iisIconLabel *i23 = new iisIconLabel(
- Gui::BitmapFactory().iconFromTheme("document-save"), QLatin1String("Save current file"), tb2);
- tb2->addIconLabel(i23);
- i23->setEnabled(false);
-
- iisIconLabel *i24 = new iisIconLabel(
- Gui::BitmapFactory().iconFromTheme("document-print"), QLatin1String("Print file contents"), tb2);
- tb2->addIconLabel(i24);
-
-
- // Other widgets can be also added to the panel
- QLabel *l1 = new QLabel(QLatin1String("Action Group without header"), this);
- taskPanel->addWidget(l1);
-
- iisTaskGroup *tb3 = new iisTaskGroup(this);
- taskPanel->addWidget(tb3);
-
- iisIconLabel *i31 = new iisIconLabel(
- Gui::BitmapFactory().iconFromTheme("document-new"), QLatin1String("Create new file"), tb3);
- tb3->addIconLabel(i31);
-
- QHBoxLayout *hb3 = new QHBoxLayout();
- tb3->groupLayout()->addLayout(hb3);
-
- iisIconLabel *i32 = new iisIconLabel(
- Gui::BitmapFactory().iconFromTheme("document-open"), QLatin1String("Load a file"), tb3);
- tb3->addIconLabel(i32);
- hb3->addWidget(i32);
-
- iisIconLabel *i33 = new iisIconLabel(
- Gui::BitmapFactory().iconFromTheme("document-save"), QLatin1String("Save current file"), tb3);
- tb3->addIconLabel(i33);
- i33->setDisabled(true);
- hb3->addWidget(i33);
-
- iisIconLabel *i34 = new iisIconLabel(
- Gui::BitmapFactory().iconFromTheme("document-print"), QLatin1String("Print file contents"), tb3);
- tb3->addIconLabel(i34);
-
- taskPanel->addStretch();
- taskPanel->setScheme(iisWinXPTaskPanelScheme::defaultScheme());
- tb1->setScheme(iisWinXPTaskPanelScheme::defaultScheme());
- tb2->setScheme(iisWinXPTaskPanelScheme2::defaultScheme());
- tb3->setScheme(iisTaskPanelScheme::defaultScheme());
#endif
}
diff --git a/src/Mod/Sandbox/Gui/Workbench.cpp b/src/Mod/Sandbox/Gui/Workbench.cpp
index 11a9fb9e61..baae5e1508 100644
--- a/src/Mod/Sandbox/Gui/Workbench.cpp
+++ b/src/Mod/Sandbox/Gui/Workbench.cpp
@@ -37,6 +37,7 @@
#include
#include "Workbench.h"
+#include
#include
#include
#include
@@ -61,7 +62,7 @@ Workbench::Workbench()
QGridLayout* pLayout = new QGridLayout(tree);
pLayout->setSpacing(0);
- pLayout->setMargin (0);
+ pLayout->setContentsMargins(0, 0, 0, 0);
pLayout->addWidget(treeWidget, 0, 0);
tree->setObjectName
@@ -159,8 +160,7 @@ void SoWidgetShape::GLRender(SoGLRenderAction * /*action*/)
#if defined(HAVE_QT5_OPENGL)
this->image = QPixmap::grabWidget(w, w->rect()).toImage();
#else
- this->image = QPixmap::grabWidget(w, w->rect()).toImage();
- this->image = QtGLWidget::convertToGLFormat(this->image);
+ this->image = w->grab(w->rect()).toImage();
#endif
glRasterPos2d(10,10);
glDrawPixels(this->image.width(),this->image.height(),GL_RGBA,GL_UNSIGNED_BYTE,this->image.bits());
@@ -285,7 +285,6 @@ void SoWidgetShape::setWidget(QWidget* w)
this->image = img.toImage();
#if !defined(HAVE_QT5_OPENGL)
- this->image = QPixmap::grabWidget(w, w->rect()).toImage();
- this->image = QtGLWidget::convertToGLFormat(this->image);
+ this->image = w->grab(w->rect()).toImage();
#endif
}
diff --git a/src/Mod/Tux/CMakeLists.txt b/src/Mod/Tux/CMakeLists.txt
index 656e883fc2..78995ffec2 100644
--- a/src/Mod/Tux/CMakeLists.txt
+++ b/src/Mod/Tux/CMakeLists.txt
@@ -30,4 +30,3 @@ INSTALL(
DESTINATION
Mod/Tux
)
-
diff --git a/src/Mod/Tux/InitGui.py b/src/Mod/Tux/InitGui.py
index 86e1c49dcf..e02e7da59a 100644
--- a/src/Mod/Tux/InitGui.py
+++ b/src/Mod/Tux/InitGui.py
@@ -33,4 +33,3 @@ if p.GetGroup("PersistentToolbars").GetBool("Enabled", 1):
import PersistentToolbarsGui
else:
pass
-
diff --git a/src/Mod/Tux/NavigationIndicatorGui.py b/src/Mod/Tux/NavigationIndicatorGui.py
index 243a6a8d89..e20c0be897 100644
--- a/src/Mod/Tux/NavigationIndicatorGui.py
+++ b/src/Mod/Tux/NavigationIndicatorGui.py
@@ -36,7 +36,9 @@ try:
def translate(context, text):
"convenience function for Qt 4 translator"
return QtGui.QApplication.translate(context, text, None, _encoding)
+
except AttributeError:
+
def translate(context, text):
"convenience function for Qt 5 translator"
return QtGui.QApplication.translate(context, text, None)
@@ -44,6 +46,7 @@ except AttributeError:
class IndicatorButton(QtGui.QPushButton):
"""Detect language change events."""
+
def __init__(self, parent=None):
super(IndicatorButton, self).__init__()
@@ -56,7 +59,7 @@ class IndicatorButton(QtGui.QPushButton):
return super(IndicatorButton, self).changeEvent(event)
def onChange(self, paramGrp, param):
- if(param == "NavigationStyle"):
+ if param == "NavigationStyle":
setCurrent()
@@ -78,14 +81,27 @@ def retranslateUi():
t0 = translate("NavigationIndicator", "Navigation style not recognized.")
global t1
- t1 = "Blender " + text06 + """
+ t1 = (
+ "Blender "
+ + text06
+ + """
- | """ + text01 + """ |
- """ + text02 + """ |
- """ + text03 + """ |
- """ + text04 + """ |
- """ + text04 + """ |
+ """
+ + text01
+ + """ |
+ """
+ + text02
+ + """ |
+ """
+ + text03
+ + """ |
+ """
+ + text04
+ + """ |
+ """
+ + text04
+ + """ |
 |
@@ -95,17 +111,35 @@ def retranslateUi():
 |
- """ + text08 + ": " + text10 + "
"
+ """
+ + text08
+ + ": "
+ + text10
+ + ""
+ )
global t2
- t2 = "CAD " + text06 + """
+ t2 = (
+ "CAD "
+ + text06
+ + """
- | """ + text01 + """ |
- """ + text02 + """ |
- """ + text03 + """ |
- """ + text03 + """ |
- """ + text04 + """ |
+ """
+ + text01
+ + """ |
+ """
+ + text02
+ + """ |
+ """
+ + text03
+ + """ |
+ """
+ + text03
+ + """ |
+ """
+ + text04
+ + """ |
 |
@@ -115,18 +149,38 @@ def retranslateUi():
 |
- """ + text08 + ": " + text10 + ""
+ """
+ + text08
+ + ": "
+ + text10
+ + ""
+ )
global t3
- t3 = "Gesture " + text06 + """
+ t3 = (
+ "Gesture "
+ + text06
+ + """
- | """ + text01 + """ |
- """ + text02 + """ |
- """ + text03 + """ |
- """ + text03 + """ |
- """ + text04 + """ |
- """ + text05 + """ |
+ """
+ + text01
+ + """ |
+ """
+ + text02
+ + """ |
+ """
+ + text03
+ + """ |
+ """
+ + text03
+ + """ |
+ """
+ + text04
+ + """ |
+ """
+ + text05
+ + """ |
 |
@@ -137,12 +191,24 @@ def retranslateUi():
 |
- | """ + text01 + """ |
- """ + text02 + """ |
- """ + text03 + """ |
- """ + text04 + """ |
- """ + text04 + """ |
- """ + text05 + """ |
+ """
+ + text01
+ + """ |
+ """
+ + text02
+ + """ |
+ """
+ + text03
+ + """ |
+ """
+ + text04
+ + """ |
+ """
+ + text04
+ + """ |
+ """
+ + text05
+ + """ |
 |
@@ -153,19 +219,43 @@ def retranslateUi():
 |
- """ + text02 + ": " + text07 + """
- """ + text08 + ": " + text09 + "
"
+ """
+ + text02
+ + ": "
+ + text07
+ + """
+ """
+ + text08
+ + ": "
+ + text09
+ + "
"
+ )
global t4
- t4 = "MayaGesture " + text06 + """
+ t4 = (
+ "MayaGesture "
+ + text06
+ + """
- | """ + text01 + """ |
- """ + text02 + """ |
- """ + text02 + """ |
- """ + text03 + """ |
- """ + text04 + """ |
- """ + text05 + """ |
+ """
+ + text01
+ + """ |
+ """
+ + text02
+ + """ |
+ """
+ + text02
+ + """ |
+ """
+ + text03
+ + """ |
+ """
+ + text04
+ + """ |
+ """
+ + text05
+ + """ |
 |
@@ -176,12 +266,24 @@ def retranslateUi():
 |
- | """ + text01 + """ |
- """ + text02 + """ |
- """ + text03 + """ |
- """ + text04 + """ |
- """ + text04 + """ |
- """ + text05 + """ |
+ """
+ + text01
+ + """ |
+ """
+ + text02
+ + """ |
+ """
+ + text03
+ + """ |
+ """
+ + text04
+ + """ |
+ """
+ + text04
+ + """ |
+ """
+ + text05
+ + """ |
 |
@@ -192,19 +294,43 @@ def retranslateUi():
 |
- """ + text02 + ": " + text07 + """
- """ + text08 + ": " + text09 + "
"
+ """
+ + text02
+ + ": "
+ + text07
+ + """
+ """
+ + text08
+ + ": "
+ + text09
+ + "
"
+ )
global t5
- t5 = "OpenCascade " + text06 + """
+ t5 = (
+ "OpenCascade "
+ + text06
+ + """
- | """ + text01 + """ |
- """ + text02 + """ |
- """ + text02 + """ |
- """ + text03 + """ |
- """ + text04 + """ |
- """ + text04 + """ |
+ """
+ + text01
+ + """ |
+ """
+ + text02
+ + """ |
+ """
+ + text02
+ + """ |
+ """
+ + text03
+ + """ |
+ """
+ + text04
+ + """ |
+ """
+ + text04
+ + """ |
 |
@@ -215,16 +341,30 @@ def retranslateUi():
 |
"""
+ )
global t6
- t6 = "OpenInventor " + text06 + """
+ t6 = (
+ "OpenInventor "
+ + text06
+ + """
- | """ + text01 + """ |
- """ + text02 + """ |
- """ + text02 + """ |
- """ + text03 + """ |
- """ + text04 + """ |
+ """
+ + text01
+ + """ |
+ """
+ + text02
+ + """ |
+ """
+ + text02
+ + """ |
+ """
+ + text03
+ + """ |
+ """
+ + text04
+ + """ |
 |
@@ -234,17 +374,35 @@ def retranslateUi():
 |
- """ + text08 + ": " + text10 + ""
+ """
+ + text08
+ + ": "
+ + text10
+ + ""
+ )
global t7
- t7 = "OpenSCAD " + text06 + """
+ t7 = (
+ "OpenSCAD "
+ + text06
+ + """
- | """ + text01 + """ |
- """ + text02 + """ |
- """ + text02 + """ |
- """ + text03 + """ |
- """ + text04 + """ |
+ """
+ + text01
+ + """ |
+ """
+ + text02
+ + """ |
+ """
+ + text02
+ + """ |
+ """
+ + text03
+ + """ |
+ """
+ + text04
+ + """ |
 |
@@ -254,16 +412,30 @@ def retranslateUi():
 |
"""
+ )
global t8
- t8 = "Revit " + text06 + """
+ t8 = (
+ "Revit "
+ + text06
+ + """
- | """ + text01 + """ |
- """ + text02 + """ |
- """ + text03 + """ |
- """ + text04 + """ |
- """ + text04 + """ |
+ """
+ + text01
+ + """ |
+ """
+ + text02
+ + """ |
+ """
+ + text03
+ + """ |
+ """
+ + text04
+ + """ |
+ """
+ + text04
+ + """ |
 |
@@ -273,16 +445,32 @@ def retranslateUi():
 |
- """ + text08 + ": " + text10 + ""
+ """
+ + text08
+ + ": "
+ + text10
+ + ""
+ )
global t9
- t9 = "TinkerCAD " + text06 + """
+ t9 = (
+ "TinkerCAD "
+ + text06
+ + """
- | """ + text01 + """ |
- """ + text02 + """ |
- """ + text03 + """ |
- """ + text04 + """ |
+ """
+ + text01
+ + """ |
+ """
+ + text02
+ + """ |
+ """
+ + text03
+ + """ |
+ """
+ + text04
+ + """ |
 |
@@ -291,17 +479,33 @@ def retranslateUi():
 |
"""
+ )
global t10
- t10 = "Touchpad " + text06 + """
+ t10 = (
+ "Touchpad "
+ + text06
+ + """
- | """ + text01 + """ |
- """ + text02 + """ |
- """ + text02 + """ |
- """ + text03 + """ |
- """ + text03 + """ |
- """ + text04 + """ |
+ """
+ + text01
+ + """ |
+ """
+ + text02
+ + """ |
+ """
+ + text02
+ + """ |
+ """
+ + text03
+ + """ |
+ """
+ + text03
+ + """ |
+ """
+ + text04
+ + """ |
 |
@@ -312,11 +516,21 @@ def retranslateUi():
 |
- | """ + text01 + """ |
- """ + text02 + """ |
- """ + text03 + """ |
- """ + text03 + """ |
- """ + text04 + """ |
+ """
+ + text01
+ + """ |
+ """
+ + text02
+ + """ |
+ """
+ + text03
+ + """ |
+ """
+ + text03
+ + """ |
+ """
+ + text04
+ + """ |
 |
@@ -326,7 +540,12 @@ def retranslateUi():
 |
- """ + text02 + ": " + text07 + "
"
+ """
+ + text02
+ + ": "
+ + text07
+ + "
"
+ )
menuSettings.setTitle(translate("NavigationIndicator", "Settings"))
menuOrbit.setTitle(translate("NavigationIndicator", "Orbit style"))
@@ -389,7 +608,7 @@ a1.setData("Gui::BlenderNavigationStyle")
a1.setObjectName("Indicator_NavigationBlender")
a2 = QtGui.QAction(gStyle)
-a2.setIcon(QtGui.QIcon(':/icons/NavigationCAD_dark.svg'))
+a2.setIcon(QtGui.QIcon(":/icons/NavigationCAD_dark.svg"))
a2.setText("CAD ")
a2.setData("Gui::CADNavigationStyle")
a2.setObjectName("Indicator_NavigationCAD")
diff --git a/src/Mod/Tux/PersistentToolbarsGui.py b/src/Mod/Tux/PersistentToolbarsGui.py
index 5f3b4c0ed1..781766d3ba 100644
--- a/src/Mod/Tux/PersistentToolbarsGui.py
+++ b/src/Mod/Tux/PersistentToolbarsGui.py
@@ -28,6 +28,7 @@ conectedToolbars = []
timer = QtCore.QTimer()
mw = Gui.getMainWindow()
+
def pythonToolbars():
"""Manage Python based toolbar in BIM workbench."""
@@ -85,10 +86,12 @@ def onRestore(active):
# Reduce flickering.
for i in toolbars:
- if (i not in topRestore and
- i not in leftRestore and
- i not in rightRestore and
- i not in bottomRestore):
+ if (
+ i not in topRestore
+ and i not in leftRestore
+ and i not in rightRestore
+ and i not in bottomRestore
+ ):
area = mw.toolBarArea(toolbars[i])
diff --git a/src/Tools/DownloadStatistics.py b/src/Tools/DownloadStatistics.py
deleted file mode 100644
index d335cb52de..0000000000
--- a/src/Tools/DownloadStatistics.py
+++ /dev/null
@@ -1,8 +0,0 @@
-import requests
-
-r = requests.get("https://api.github.com/repos/FreeCAD/FreeCAD/releases")
-myobj = r.json()
-for p in myobj:
- if "assets" in p:
- for asset in p["assets"]:
- print(asset["name"] + ": " + str(asset["download_count"]) + " downloads")
diff --git a/src/Tools/astylerc b/src/Tools/astylerc
deleted file mode 100644
index 35a82136e9..0000000000
--- a/src/Tools/astylerc
+++ /dev/null
@@ -1,30 +0,0 @@
-# Use these options with: astyle --options= SourceFile.cpp
-#
-
-# Do not create a copy of the original, same as -n
-suffix=none
-
-# set 4 spaces per indent, same as -s4
-indent=spaces=4
-
-# break brackets from class and function declarations, same as -ly
-brackets=linux
-brackets=break-closing
-
-# don't break complex statements and multiple statements residing on a single line, same as -o
-one-line=keep-statements
-
-# don't break one-line blocks, same as -O
-one-line=keep-blocks
-
-# convert tabs into single spaces, same as -V
-#convert-tabs
-
-# indent switch blocks, same as -K
-#indent-cases
-
-# indent multi-line preprocessor definitions ending with a backslash, same as -w
-#indent-preprocessor
-
-# remove space padding around parenthesis on the inside and outside, same as -U
-#unpad=paren
diff --git a/src/Tools/updatets.py b/src/Tools/updatets.py
index 9adcf991f5..0aa18108d1 100755
--- a/src/Tools/updatets.py
+++ b/src/Tools/updatets.py
@@ -148,7 +148,7 @@ directories = [
"tsdir": "Gui/Resources/translations",
},
{
- "tsname": "Start",
+ "tsname": "StartPage",
"workingdir": "./src/Mod/Start/",
"tsdir": "Gui/Resources/translations",
},