Mercurial > octave
view libgui/graphics/qt-graphics-toolkit.cc @ 29602:767cda46e091
qt-graphics-toolkit.cc: Use correct format specifier for "void *" type.
* libgui/graphics/qt-graphics-toolkit.cc (initialize, update, finalize,
create_object): Use "%p" as format specifier for "void *" type. (Reported by
CodeQL.)
author | Markus Mützel <markus.muetzel@gmx.de> |
---|---|
date | Tue, 04 May 2021 16:15:50 +0200 |
parents | 3d34b70b5a49 |
children | 6ea4a84df9c7 |
line wrap: on
line source
//////////////////////////////////////////////////////////////////////// // // Copyright (C) 2011-2021 The Octave Project Developers // // See the file COPYRIGHT.md in the top-level directory of this // distribution or <https://octave.org/copyright/>. // // This file is part of Octave. // // Octave is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Octave 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 General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Octave; see the file COPYING. If not, see // <https://www.gnu.org/licenses/>. // //////////////////////////////////////////////////////////////////////// #if defined (HAVE_CONFIG_H) # include "config.h" #endif #include <cstdint> #include <QApplication> #include <QFontMetrics> #include <QThread> #include "ButtonGroup.h" #include "CheckBoxControl.h" #include "ContextMenu.h" #include "EditControl.h" #include "Figure.h" #include "ListBoxControl.h" #include "Logger.h" #include "Menu.h" #include "Object.h" #include "ObjectProxy.h" #include "Panel.h" #include "PopupMenuControl.h" #include "PushButtonControl.h" #include "PushTool.h" #include "QtHandlesUtils.h" #include "RadioButtonControl.h" #include "SliderControl.h" #include "Table.h" #include "TextControl.h" #include "ToggleButtonControl.h" #include "ToggleTool.h" #include "ToolBar.h" #include "qt-graphics-toolkit.h" #include "octave-qobject.h" #include "event-manager.h" #include "graphics.h" #include "interpreter.h" //#if INTPTR_MAX == INT32_MAX //# define OCTAVE_PTR_TYPE octave_uint32 //# define OCTAVE_INTPTR_TYPE uint32_t //# define OCTAVE_PTR_SCALAR uint32_scalar_value //#else # define OCTAVE_PTR_TYPE octave_uint64 # define OCTAVE_INTPTR_TYPE uint64_t # define OCTAVE_PTR_SCALAR uint64_scalar_value //#endif namespace QtHandles { static std::string toolkitObjectProperty (const graphics_object& go) { if (go.isa ("figure")) return "__plot_stream__"; else if (go.isa ("uicontrol") || go.isa ("uipanel") || go.isa ("uibuttongroup") || go.isa ("uimenu") || go.isa ("uicontextmenu") || go.isa ("uitable") || go.isa ("uitoolbar") || go.isa ("uipushtool") || go.isa ("uitoggletool")) return "__object__"; else qCritical ("QtHandles::qt_graphics_toolkit: no __object__ property known for object " "of type %s", go.type ().c_str ()); return ""; } qt_graphics_toolkit::qt_graphics_toolkit (octave::interpreter& interp, octave::base_qobject& oct_qobj) : QObject (), base_graphics_toolkit ("qt"), m_interpreter (interp), m_octave_qobj (oct_qobj) { // Implemented with a signal/slot connection in order to properly // cross from the interpreter thread (where requests to create // graphics object are initiated) to the GUI application thread // (where they are actually created and displayed). // We need to make sure the GUI Object and its proxy are properly // created before the initialize method returns, so we use a // BlockingQueuedConnection. After the signal is emitted, the interpreter // thread is locked until the slot has returned. connect (this, &qt_graphics_toolkit::create_object_signal, this, &qt_graphics_toolkit::create_object, Qt::BlockingQueuedConnection); } bool qt_graphics_toolkit::initialize (const graphics_object& go) { if (go.isa ("figure") || (go.isa ("uicontrol") && go.get ("style").string_value () != "frame") || go.isa ("uipanel") || go.isa ("uibuttongroup") || go.isa ("uimenu") || go.isa ("uicontextmenu") || go.isa ("uitable") || go.isa ("uitoolbar") || go.isa ("uipushtool") || go.isa ("uitoggletool")) { // FIXME: We need to unlock the mutex here but we have no way to know // if it was previously locked by this thread, and thus if we should // re-lock it. gh_manager& gh_mgr = m_interpreter.get_gh_manager (); gh_mgr.unlock (); Logger::debug ("qt_graphics_toolkit::initialize %s from thread %p", go.type ().c_str (), QThread::currentThreadId ()); ObjectProxy *proxy = new ObjectProxy (); graphics_object gObj (go); OCTAVE_PTR_TYPE tmp (reinterpret_cast<OCTAVE_INTPTR_TYPE> (proxy)); gObj.get_properties ().set (toolkitObjectProperty (go), tmp); emit create_object_signal (go.get_handle ().value ()); return true; } return false; } void qt_graphics_toolkit::update (const graphics_object& go, int pId) { // Rule out obvious properties we want to ignore. if (pId == figure::properties::ID___PLOT_STREAM__ || pId == uicontrol::properties::ID___OBJECT__ || pId == uipanel::properties::ID___OBJECT__ || pId == uibuttongroup::properties::ID___OBJECT__ || pId == uimenu::properties::ID___OBJECT__ || pId == uicontextmenu::properties::ID___OBJECT__ || pId == uitable::properties::ID___OBJECT__ || pId == uitoolbar::properties::ID___OBJECT__ || pId == uipushtool::properties::ID___OBJECT__ || pId == uitoggletool::properties::ID___OBJECT__ || pId == base_properties::ID___MODIFIED__) return; Logger::debug ("qt_graphics_toolkit::update %s(%d) from thread %p", go.type ().c_str (), pId, QThread::currentThreadId ()); ObjectProxy *proxy = toolkitObjectProxy (go); if (proxy) { if (go.isa ("uicontrol") && pId == uicontrol::properties::ID_STYLE) { // Special case: we need to recreate the control widget // associated with the octave graphics_object finalize (go); initialize (go); } else proxy->update (pId); } } void qt_graphics_toolkit::finalize (const graphics_object& go) { // FIXME: We need to unlock the mutex here but we have no way to know if // if it was previously locked by this thread, and thus if we should // re-lock it. gh_manager& gh_mgr = m_interpreter.get_gh_manager (); gh_mgr.unlock (); Logger::debug ("qt_graphics_toolkit::finalize %s from thread %p", go.type ().c_str (), QThread::currentThreadId ()); ObjectProxy *proxy = toolkitObjectProxy (go); if (proxy) { proxy->finalize (); delete proxy; graphics_object gObj (go); gObj.get_properties ().set (toolkitObjectProperty (go), Matrix ()); } } void qt_graphics_toolkit::redraw_figure (const graphics_object& go) const { if (go.get_properties ().is_visible ()) { ObjectProxy *proxy = toolkitObjectProxy (go); if (proxy) proxy->redraw (); } } void qt_graphics_toolkit::show_figure (const graphics_object& go) const { if (go.get_properties ().is_visible ()) { ObjectProxy *proxy = toolkitObjectProxy (go); if (proxy) proxy->show (); } } void qt_graphics_toolkit::print_figure (const graphics_object& go, const std::string& term, const std::string& file_cmd, const std::string& /*debug_file*/) const { ObjectProxy *proxy = toolkitObjectProxy (go); if (proxy) proxy->print (QString::fromStdString (file_cmd), QString::fromStdString (term)); } uint8NDArray qt_graphics_toolkit::get_pixels (const graphics_object& go) const { uint8NDArray retval; if (go.isa ("figure")) { ObjectProxy *proxy = toolkitObjectProxy (go); if (proxy) retval = proxy->get_pixels (); } return retval; } Matrix qt_graphics_toolkit::get_text_extent (const graphics_object& go) const { Matrix ext (1, 4, 0.0); if (go.isa ("uicontrol")) { octave_value str = go.get ("string"); if (! str.isempty ()) { const uicontrol::properties& up = dynamic_cast<const uicontrol::properties&> (go.get_properties ()); Matrix bb = up.get_boundingbox (false); QFont font = Utils::computeFont<uicontrol> (up, bb(3)); QFontMetrics fm (font); QString s; QSize sz; if (str.is_string ()) { s = QString::fromStdString (str.string_value ()); sz = fm.size (Qt::TextSingleLine, s); ext(2) = sz.width (); ext(3) = sz.height (); } else if (str.iscellstr ()) { string_vector sv = str.string_vector_value (); double wd = 0.0; double hg = 0.0; for (octave_idx_type ii = 0; ii < sv.numel (); ii++) { s = QString::fromStdString (sv(ii)); sz = fm.size (Qt::TextSingleLine, s); wd = std::max (wd, static_cast<double> (sz.width ())); hg = std::max (hg, static_cast<double> (sz.height ())); } ext(2) = wd; // FIXME: Find a better way to determine the height of e.g. // listbox uicontrol objects ext(3) = hg * sv.numel (); } } } return ext; } Object* qt_graphics_toolkit::toolkitObject (const graphics_object& go) { ObjectProxy *proxy = toolkitObjectProxy (go); if (proxy) return proxy->object (); return nullptr; } ObjectProxy* qt_graphics_toolkit::toolkitObjectProxy (const graphics_object& go) { if (go) { octave_value ov = go.get (toolkitObjectProperty (go)); if (ov.is_defined () && ! ov.isempty ()) { OCTAVE_INTPTR_TYPE ptr = ov.OCTAVE_PTR_SCALAR ().value (); return reinterpret_cast<ObjectProxy *> (ptr); } } return nullptr; } void qt_graphics_toolkit::interpreter_event (const octave::fcn_callback& fcn) { octave::event_manager& evmgr = m_interpreter.get_event_manager (); evmgr.post_event (fcn); } void qt_graphics_toolkit::interpreter_event (const octave::meth_callback& meth) { octave::event_manager& evmgr = m_interpreter.get_event_manager (); evmgr.post_event (meth); } void qt_graphics_toolkit::create_object (double handle) { gh_manager& gh_mgr = m_interpreter.get_gh_manager (); octave::autolock guard (gh_mgr.graphics_lock ()); graphics_object go (gh_mgr.get_object (graphics_handle (handle))); if (! go.valid_object ()) { qWarning ("qt_graphics_toolkit::create_object: invalid object for handle %g", handle); return; } if (go.get_properties ().is_beingdeleted ()) { qWarning ("qt_graphics_toolkit::create_object: object is being deleted"); return; } ObjectProxy *proxy = qt_graphics_toolkit::toolkitObjectProxy (go); if (! proxy) { qWarning ("qt_graphics_toolkit::create_object: no proxy for handle %g", handle); return; } Logger::debug ("qt_graphics_toolkit::create_object: " "create %s from thread %p", go.type ().c_str (), QThread::currentThreadId ()); Object *obj = nullptr; if (go.isa ("figure")) obj = Figure::create (m_octave_qobj, m_interpreter, go); else if (go.isa ("uicontrol")) { uicontrol::properties& up = Utils::properties<uicontrol> (go); if (up.style_is ("pushbutton")) obj = PushButtonControl::create (m_octave_qobj, m_interpreter, go); else if (up.style_is ("edit")) obj = EditControl::create (m_octave_qobj, m_interpreter, go); else if (up.style_is ("checkbox")) obj = CheckBoxControl::create (m_octave_qobj, m_interpreter, go); else if (up.style_is ("radiobutton")) obj = RadioButtonControl::create (m_octave_qobj, m_interpreter, go); else if (up.style_is ("togglebutton")) obj = ToggleButtonControl::create (m_octave_qobj, m_interpreter, go); else if (up.style_is ("text")) obj = TextControl::create (m_octave_qobj, m_interpreter, go); else if (up.style_is ("popupmenu")) obj = PopupMenuControl::create (m_octave_qobj, m_interpreter, go); else if (up.style_is ("slider")) obj = SliderControl::create (m_octave_qobj, m_interpreter, go); else if (up.style_is ("listbox")) obj = ListBoxControl::create (m_octave_qobj, m_interpreter, go); } else if (go.isa ("uibuttongroup")) obj = ButtonGroup::create (m_octave_qobj, m_interpreter, go); else if (go.isa ("uipanel")) obj = Panel::create (m_octave_qobj, m_interpreter, go); else if (go.isa ("uimenu")) obj = Menu::create (m_octave_qobj, m_interpreter, go); else if (go.isa ("uicontextmenu")) obj = ContextMenu::create (m_octave_qobj, m_interpreter, go); else if (go.isa ("uitable")) obj = Table::create (m_octave_qobj, m_interpreter, go); else if (go.isa ("uitoolbar")) obj = ToolBar::create (m_octave_qobj, m_interpreter, go); else if (go.isa ("uipushtool")) obj = PushTool::create (m_octave_qobj, m_interpreter, go); else if (go.isa ("uitoggletool")) obj = ToggleTool::create (m_octave_qobj, m_interpreter, go); else qWarning ("qt_graphics_toolkit::create_object: unsupported type '%s'", go.type ().c_str ()); if (obj) { proxy->setObject (obj); obj->do_connections (this); } } void qt_graphics_toolkit::gh_callback_event (const graphics_handle& h, const std::string& nm) { gh_manager& gh_mgr = m_interpreter.get_gh_manager (); gh_mgr.post_callback (h, nm); } void qt_graphics_toolkit::gh_callback_event (const graphics_handle& h, const std::string& nm, const octave_value& data) { gh_manager& gh_mgr = m_interpreter.get_gh_manager (); gh_mgr.post_callback (h, nm, data); } void qt_graphics_toolkit::gh_set_event (const graphics_handle& h, const std::string& nm, const octave_value& value) { gh_manager& gh_mgr = m_interpreter.get_gh_manager (); gh_mgr.post_set (h, nm, value); } void qt_graphics_toolkit::gh_set_event (const graphics_handle& h, const std::string& nm, const octave_value& value, bool notify_toolkit) { gh_manager& gh_mgr = m_interpreter.get_gh_manager (); gh_mgr.post_set (h, nm, value, notify_toolkit); } void qt_graphics_toolkit::gh_set_event (const graphics_handle& h, const std::string& nm, const octave_value& value, bool notify_toolkit, bool redraw_figure) { gh_manager& gh_mgr = m_interpreter.get_gh_manager (); gh_mgr.post_set (h, nm, value, notify_toolkit, redraw_figure); } };