diff --git a/source/RobotAPI/components/units/RobotUnit/DefaultWidgetDescriptions.cpp b/source/RobotAPI/components/units/RobotUnit/DefaultWidgetDescriptions.cpp index f576152c547645d3a6923ab2ef199a6599efbd93..76e6e1d7a3b978cb345c7c03078c96ba34a60fb0 100644 --- a/source/RobotAPI/components/units/RobotUnit/DefaultWidgetDescriptions.cpp +++ b/source/RobotAPI/components/units/RobotUnit/DefaultWidgetDescriptions.cpp @@ -28,11 +28,12 @@ namespace armarx { StringComboBoxPtr makeRNSComboBox( const VirtualRobot::RobotPtr& robot, + const std::string& name, const std::set<std::string>& preferredSet, const std::string& mostPreferred) { StringComboBoxPtr rns = new StringComboBox; - rns->name = "rns"; + rns->name = name; std::string currentPreferred; for (const auto& name : robot->getRobotNodeSetNames()) { diff --git a/source/RobotAPI/components/units/RobotUnit/DefaultWidgetDescriptions.h b/source/RobotAPI/components/units/RobotUnit/DefaultWidgetDescriptions.h index d0e194f2e73bfb932e92237010fa726e3527b3ea..5b9f002679faa75e4aac63adb3bf54a5c61d22a6 100644 --- a/source/RobotAPI/components/units/RobotUnit/DefaultWidgetDescriptions.h +++ b/source/RobotAPI/components/units/RobotUnit/DefaultWidgetDescriptions.h @@ -36,6 +36,7 @@ namespace armarx { StringComboBoxPtr makeRNSComboBox( const VirtualRobot::RobotPtr& robot, + const std::string& name = "RobotNodeSet", const std::set<std::string>& preferredSet = {}, const std::string& mostPreferred = ""); } diff --git a/source/RobotAPI/components/units/RobotUnit/RobotUnit.cpp b/source/RobotAPI/components/units/RobotUnit/RobotUnit.cpp index 7a64d003a2d49a8f3fce68aef92e42ee5987b77c..d67a5fecde19e100ea4770002354d634fdb7e265 100644 --- a/source/RobotAPI/components/units/RobotUnit/RobotUnit.cpp +++ b/source/RobotAPI/components/units/RobotUnit/RobotUnit.cpp @@ -416,11 +416,11 @@ namespace armarx LVL1KinematicUnitPassThroughControllerConfigPtr config = new LVL1KinematicUnitPassThroughControllerConfig; \ config->controlMode=controlMode; \ config->deviceName=controlDeviceName; \ - LVL1ControllerPtr lvl1 = createLVL1Controller( \ - "LVL1KinematicUnitPassThroughController", \ - "LVL1KU_PTCtrl_"+controlDeviceName+"_"+controlMode, \ - config, \ - false ); \ + const LVL1ControllerPtr& lvl1 = createLVL1Controller( \ + "LVL1KinematicUnitPassThroughController", \ + "LVL1KU_PTCtrl_"+controlDeviceName+"_"+controlMode, \ + config, \ + false ); \ pt = LVL1KinematicUnitPassThroughControllerPtr::dynamicCast(lvl1); \ ARMARX_CHECK_EXPRESSION(pt); \ } \ @@ -450,9 +450,9 @@ namespace armarx properties->setProperty(confPre + "RobotFileNameProject", robotProjectName); IceInternal::Handle<UnitT> unit = Component::create<UnitT>(properties , configName, configDomain); //fill devices (sensor + controller) - unit->setupData(getProperty<std::string>("RobotFileName").getValue(), robot->clone(robot->getName()), std::move(devs), this); + unit->setupData(getProperty<std::string>("RobotFileName").getValue(), robot->clone(), std::move(devs), this); //add - addUnit(unit); + addUnit(std::move(unit)); } void RobotUnit::initializePlatformUnit() @@ -505,7 +505,7 @@ namespace armarx unit->pt = ctrl; unit->platformSensorIndex = sensorDevices.index(robotPlatformName); //add - addUnit(unit); + addUnit(std::move(unit)); } void RobotUnit::initializeForceTorqueUnit() @@ -566,7 +566,7 @@ namespace armarx IceInternal::Handle<UnitT> unit = Component::create<UnitT>(properties , configName, configDomain); unit->devs = ftdevs; //add - addUnit(unit); + addUnit(std::move(unit)); } void RobotUnit::initializeInertialMeasurementUnit() @@ -607,7 +607,7 @@ namespace armarx IceInternal::Handle<UnitT> unit = Component::create<UnitT>(properties , configName, configDomain); unit->devs = imudevs; //add - addUnit(unit); + addUnit(std::move(unit)); } void RobotUnit::addUnit(ManagedIceObjectPtr unit) @@ -615,6 +615,12 @@ namespace armarx auto guard = getGuard(); throwIfStateIsNot(RobotUnitState::InitializingUnits, __FUNCTION__); getArmarXManager()->addObjectAsync(unit, "", true, false); + //maybe add it to the sub units + RobotUnitSubUnitPtr rsu = RobotUnitSubUnitPtr::dynamicCast(unit); + if (rsu) + { + subUnits.emplace_back(std::move(rsu)); + } units.emplace_back(std::move(unit)); } @@ -906,7 +912,11 @@ namespace armarx return createLVL1Controller(className, instanceName, LVL1ControllerRegistry::get(className)->GenerateConfigFromVariants(variants), GlobalIceCurrent/*to select ice overload*/); } - LVL1ControllerPtr RobotUnit::createLVL1Controller(const std::string& className, const std::string& instanceName, const LVL1ControllerConfigPtr& config, bool deletable) + const LVL1ControllerPtr& RobotUnit::createLVL1Controller( + const std::string& className, + const std::string& instanceName, + const LVL1ControllerConfigPtr& config, + bool deletable) { auto guard = getGuard(); throwIfDevicesNotReady(__FUNCTION__); @@ -936,7 +946,7 @@ namespace armarx initLVL1UsedControlTargets.clear(); initLVL1ThreadId = std::thread::id{}; }; - LVL1ControllerPtr lvl1 = factory->create(LVL1ControllerDescriptionProviderInterfacePtr::dynamicCast(RobotUnitPtr {this}), config, robot); + LVL1ControllerPtr lvl1 {factory->create(LVL1ControllerDescriptionProviderInterfacePtr::dynamicCast(RobotUnitPtr {this}), config, robot)}; std::vector<char> ctrlDeviceUsedBitmap(getNumberOfControlDevices(), false); std::vector<std::size_t> ctrlDeviceUsedIndices; @@ -956,9 +966,9 @@ namespace armarx std::move(ctrlDeviceUsedIndices), deletable); getArmarXManager()->addObjectAsync(lvl1, instanceName, false, false); - lvl1Controllers[instanceName] = lvl1; + lvl1Controllers[instanceName] = std::move(lvl1); listenerPrx->lvl1ControllerCreated(instanceName); - return lvl1; + return lvl1Controllers.at(instanceName); } void RobotUnit::setActivateControllersRequest(std::set<LVL1ControllerPtr, LVL1Controller::IdComp>&& ctrls) @@ -1159,7 +1169,7 @@ namespace armarx void RobotUnit::publish() { auto begPublish = Now(); - static const int spamdelay = 1; + static const int spamdelay = 30; std::set<RobotUnitState> skipStates { RobotUnitState::PreComponentInitialization, @@ -1220,9 +1230,8 @@ namespace armarx { ARMARX_DEBUG << deactivateSpam(spamdelay) << "updating units with new sensor values"; publishNewSensorDataTime = TimeUtil::GetTime(); - for (ManagedIceObjectPtr& u : units) + for (RobotUnitSubUnitPtr& rsu : subUnits) { - RobotUnitSubUnitPtr rsu = RobotUnitSubUnitPtr::dynamicCast(u); if (rsu && rsu->getObjectScheduler() && rsu->getProxy()) { debugObserverMap["publishTimings_UnitUpdate_" + rsu->getName()] = new TimedVariant @@ -1322,8 +1331,9 @@ namespace armarx { ARMARX_TIMER(TimestampVariant) { - for (const LVL1ControllerPtr& lvl1 : getMapValues(lvl1Controllers)) + for (const auto& pair : lvl1Controllers) { + const LVL1ControllerPtr& lvl1 = pair.second; debugObserverMap["publishTimings_LVL1Updates_" + lvl1->getInstanceName()] = new TimedVariant { ARMARX_TIMER(TimestampVariant) @@ -1401,11 +1411,10 @@ namespace armarx void RobotUnit::removeAllUnits() { + subUnits.clear(); for (ManagedIceObjectPtr& unit : units) { - checkRefCountIsOne(unit, unit->getName()); - getArmarXManager()->removeObjectBlocking(unit); - checkRefCountIsOne(unit, unit->getName()); + getArmarXManager()->removeObjectBlocking(unit->getName()); } units.clear(); } @@ -1431,7 +1440,6 @@ namespace armarx { ARMARX_FATAL << deactivateSpam(0.1) << "PUBLISHER TASK IS RUNNING EVEN AFTER IT WAS STOPPED!"; } - checkRefCountIsOne(publisherTask, "publisherTask"); publisherTask = nullptr; //since the drawer queues draw events and we want to clear the layers, we have to sleep here std::this_thread::sleep_until(tPublisherStopped + std::chrono::milliseconds {100}); @@ -1452,8 +1460,7 @@ namespace armarx for (auto& n2lvl1 : lvl1ControllersToBeDeleted) { LVL1ControllerPtr& lvl1 = n2lvl1.second; - getArmarXManager()->removeObjectBlocking(lvl1); - checkRefCountIsOne(lvl1, lvl1->getName()); + getArmarXManager()->removeObjectBlocking(lvl1->getName()); } lvl1ControllersToBeDeleted.clear(); } @@ -1462,8 +1469,7 @@ namespace armarx for (auto& n2lvl1 : lvl1Controllers) { LVL1ControllerPtr& lvl1 = n2lvl1.second; - getArmarXManager()->removeObjectBlocking(lvl1); - checkRefCountIsOne(lvl1, lvl1->getName()); + getArmarXManager()->removeObjectBlocking(lvl1->getName()); } lvl1Controllers.clear(); } @@ -1918,29 +1924,31 @@ namespace armarx ctrl.reserve(names.size()); for (const auto& name : names) { - auto it = lvl1Controllers.find(name); - if (it == lvl1Controllers.end()) - { - std::stringstream ss; - ss << "RobotUnit: there is no LVL1Controller with name '" << name - << "'. Existing LVL1Controllers are: " << getLVL1ControllerNames(); - throw InvalidArgumentException {ss.str()}; - } - if (!it->second) - { - std::stringstream ss; - ss << "RobotUnit: The LVL1Controller with name '" << name - << "'. Is a nullptr! This should never be the case (invariant)! \nMap:\n" << lvl1Controllers; - ARMARX_FATAL << ss.str(); - throw InvalidArgumentException {ss.str()}; - } - ctrl.emplace_back(it->second); + ctrl.emplace_back(getLVL1ControllerNotNull(name)); } return ctrl; } - LVL1ControllerPtr RobotUnit::getLVL1ControllerNotNull(const std::string& name) const + const LVL1ControllerPtr& RobotUnit::getLVL1ControllerNotNull(const std::string& name) const { - return getLVL1ControllersNotNull(std::vector<std::string> {name}).at(0); + auto guard = getGuard(); + throwIfDevicesNotReady(__FUNCTION__); + auto it = lvl1Controllers.find(name); + if (it == lvl1Controllers.end()) + { + std::stringstream ss; + ss << "RobotUnit: there is no LVL1Controller with name '" << name + << "'. Existing LVL1Controllers are: " << getLVL1ControllerNames(); + throw InvalidArgumentException {ss.str()}; + } + if (!it->second) + { + std::stringstream ss; + ss << "RobotUnit: The LVL1Controller with name '" << name + << "'. Is a nullptr! This should never be the case (invariant)! \nMap:\n" << lvl1Controllers; + ARMARX_FATAL << ss.str(); + throw InvalidArgumentException {ss.str()}; + } + return it->second; } StringLVL1ControllerPrxDictionary RobotUnit::getAllLVL1Controllers(const Ice::Current&) const diff --git a/source/RobotAPI/components/units/RobotUnit/RobotUnit.h b/source/RobotAPI/components/units/RobotUnit/RobotUnit.h index a88ccc9f4e03138ab5cd82d34784c32af0234424..0dd43861fc72e4eaa2e6ebc1bf6a4d8ec4efe7be 100644 --- a/source/RobotAPI/components/units/RobotUnit/RobotUnit.h +++ b/source/RobotAPI/components/units/RobotUnit/RobotUnit.h @@ -41,6 +41,7 @@ #include <ArmarXCore/observers/DebugObserver.h> #include <RobotAPI/interface/units/RobotUnit/RobotUnitInterface.h> +#include "Units/RobotUnitSubUnit.h" #include "LVL0Controllers/LVL0Controller.h" #include "LVL1Controllers/LVL1Controller.h" #include "Devices/ControlDevice.h" @@ -51,9 +52,6 @@ namespace armarx { - TYPEDEF_PTRS_HANDLE(RobotSubUnitUpdateInterface); - class RobotSubUnitUpdateInterface: virtual public ManagedIceObject {}; - TYPEDEF_PTRS_HANDLE(RobotUnit); class DynamicLibrary; @@ -146,7 +144,6 @@ namespace armarx { lvl1->rtDeactivateControllerBecauseOfError(); } - static void RtSetLVL1ControllerActive(const LVL1ControllerPtr& lvl1, bool activate, bool deactivateBecauseOfError = false) { if (activate) @@ -166,19 +163,19 @@ namespace armarx } } static void InitLVL1Controler( - LVL1ControllerPtr lvl1, + const LVL1ControllerPtr& lvl1, RobotUnit* ru, std::size_t ctrlId, StringStringDictionary ctrlDeviceControlModeMap, std::vector<char> ctrlDeviceUsedBitmap, std::vector<std::size_t> ctrlDeviceUsedIndices, bool deletable - ) + ) noexcept { lvl1->robotUnitInit(ru, ctrlId, std::move(ctrlDeviceControlModeMap), std::move(ctrlDeviceUsedBitmap), std::move(ctrlDeviceUsedIndices), deletable); } static void PublishLVL1Controller( - LVL1ControllerPtr lvl1, + const LVL1ControllerPtr& lvl1, const SensorAndControl& sac, const DebugDrawerInterfacePrx& draw, const DebugObserverInterfacePrx& observer @@ -186,26 +183,26 @@ namespace armarx { lvl1 ->publish(sac, draw, observer); } - bool GetLVL1ControllerStatusReportedActive(LVL1ControllerPtr lvl1) + bool GetLVL1ControllerStatusReportedActive(const LVL1ControllerPtr& lvl1) { return lvl1->statusReportedActive; } - bool GetLVL1ControllerStatusReportedRequested(LVL1ControllerPtr lvl1) + bool GetLVL1ControllerStatusReportedRequested(const LVL1ControllerPtr& lvl1) { return lvl1->statusReportedRequested; } - void UpdateLVL1ControllerStatusReported(LVL1ControllerPtr lvl1) + void UpdateLVL1ControllerStatusReported(const LVL1ControllerPtr& lvl1) { lvl1->statusReportedActive = lvl1->isActive.load(); lvl1->statusReportedRequested = lvl1->isRequested.load(); } - void SetLVL1ControllerRequested(LVL1ControllerPtr lvl1, bool requested) + void SetLVL1ControllerRequested(const LVL1ControllerPtr& lvl1, bool requested) { lvl1->isRequested = requested; } void DeactivateLVL1ControllerPublishing( - LVL1ControllerPtr lvl1, + const LVL1ControllerPtr& lvl1, const DebugDrawerInterfacePrx& draw, const DebugObserverInterfacePrx& observer) { @@ -305,7 +302,11 @@ namespace armarx /// @brief The RobotUnit's state std::atomic<RobotUnitState> state {RobotUnitState::PreComponentInitialization}; std::map<std::string, DynamicLibraryPtr> loadedLibs; + /// @brief holds all units managed by the RobotUnit std::vector<ManagedIceObjectPtr> units; + /// @brief holds a copy of all units managed by the RobotUnit derived from RobotUnitSubUnit + /// this is done to prevent casting + std::vector<RobotUnitSubUnitPtr> subUnits; std::thread::id rtThreadId; mutable MutexType dataMutex; static const std::set<RobotUnitState> devicesReadyStates; @@ -332,8 +333,6 @@ namespace armarx template<class Cont> static Ice::StringSeq GetNonNullNames(const Cont& c); - template<class PtrT> - void checkRefCountIsOne(const PtrT& p, const std::string& name) const; GuardType getGuard() const; inline const KeyValueVector<std::string, SensorDevicePtr>& getSensorDevices() const; inline const KeyValueVector<std::string, ControlDevicePtr>& getControlDevices() const; @@ -469,7 +468,7 @@ namespace armarx virtual ControlTargetBase* getControlTarget(const std::string& deviceName, const std::string& controlMode) override; virtual LVL1ControllerInterfacePrx createLVL1Controller(const std::string& className, const std::string& instanceName, const LVL1ControllerConfigPtr& config, const Ice::Current&) override; virtual LVL1ControllerInterfacePrx createLVL1ControllerFromVariantConfig(const std::string& className, const std::string& instanceName, const StringVariantBaseMap& variants, const Ice::Current&) override; - LVL1ControllerPtr createLVL1Controller(const std::string& className, const std::string& instanceName, const LVL1ControllerConfigPtr& config, bool deletable); + const LVL1ControllerPtr& createLVL1Controller(const std::string& className, const std::string& instanceName, const LVL1ControllerConfigPtr& config, bool deletable); //deleting lvl1 controllers virtual void deleteLVL1Controller(const std::string& name, const Ice::Current& = GlobalIceCurrent) override; virtual void deleteLVL1Controllers(const Ice::StringSeq& names, const Ice::Current& = GlobalIceCurrent) override; @@ -526,7 +525,7 @@ namespace armarx virtual LVL1ControllerInterfacePrx getLVL1Controller(const std::string& name, const Ice::Current&) const override; virtual StringLVL1ControllerPrxDictionary getAllLVL1Controllers(const Ice::Current&) const override; std::vector<LVL1ControllerPtr> getLVL1ControllersNotNull(const std::vector<std::string>& names) const; - LVL1ControllerPtr getLVL1ControllerNotNull(const std::string& name) const; + const LVL1ControllerPtr& getLVL1ControllerNotNull(const std::string& name) const; virtual LVL1ControllerStatus getLVL1ControllerStatus(const std::string& name, const Ice::Current& = GlobalIceCurrent) const override; virtual LVL1ControllerStatusSeq getLVL1ControllerStatuses(const Ice::Current&) const override; @@ -682,15 +681,5 @@ namespace armarx } return result; } - - template<class PtrT> - void RobotUnit::checkRefCountIsOne(const PtrT& p, const std::string& name) const - { - const auto uc = p->__getRef(); - if (uc != 1) - { - ARMARX_WARNING << "Pointer " << name << " should have usecount 1 but instead hase usecount " << uc; - } - } } #endif diff --git a/source/RobotAPI/components/units/RobotUnit/Units/KinematicSubUnit.cpp b/source/RobotAPI/components/units/RobotUnit/Units/KinematicSubUnit.cpp index dffcd51c327ffaae41900f45781d6a494edb52b7..8103be99cf068348d6580b44cfe6c7599d8167eb 100644 --- a/source/RobotAPI/components/units/RobotUnit/Units/KinematicSubUnit.cpp +++ b/source/RobotAPI/components/units/RobotUnit/Units/KinematicSubUnit.cpp @@ -21,7 +21,11 @@ */ #include "KinematicSubUnit.h" -void armarx::KinematicSubUnit::setupData(std::string relRobFile, VirtualRobot::RobotPtr rob, std::map<std::string, ActuatorData> newDevs, RobotUnit* newRobotUnit) +void armarx::KinematicSubUnit::setupData( + std::string relRobFile, + VirtualRobot::RobotPtr rob, + std::map<std::string, ActuatorData>&& newDevs, + RobotUnit* newRobotUnit) { std::lock_guard<std::mutex> guard {dataMutex}; ARMARX_CHECK_EXPRESSION(getState() == eManagedIceObjectCreated); @@ -110,7 +114,7 @@ void armarx::KinematicSubUnit::update(const armarx::SensorAndControl& sc, const { ARMARX_WARNING << deactivateSpam(5) << "these actuators have no sensor!:\n" << actuatorsWithoutSensor; } - ARMARX_DEBUG << deactivateSpam(1) << "reporting updated data:\n" + ARMARX_DEBUG << deactivateSpam(30) << "reporting updated data:\n" << ctrlModes.size() << " \tcontrol modes (updated = " << ctrlModesAValueChanged << ")\n" << ang.size() << " \tjoint angles (updated = " << angAValueChanged << ")\n" << vel.size() << " \tjoint velocities (updated = " << velAValueChanged << ")\n" diff --git a/source/RobotAPI/components/units/RobotUnit/Units/KinematicSubUnit.h b/source/RobotAPI/components/units/RobotUnit/Units/KinematicSubUnit.h index 7bbf7d699ca8362a577483a16177af5953bdeecf..fbcc16ea6885b3949060b9d6f593cb00a5fa198b 100644 --- a/source/RobotAPI/components/units/RobotUnit/Units/KinematicSubUnit.h +++ b/source/RobotAPI/components/units/RobotUnit/Units/KinematicSubUnit.h @@ -55,7 +55,7 @@ namespace armarx const LVL1ControllerPtr getController(ControlMode c) const; }; - void setupData(std::string relRobFile, VirtualRobot::RobotPtr rob, std::map<std::string, ActuatorData> newDevs, RobotUnit* newRobotUnit); + void setupData(std::string relRobFile, VirtualRobot::RobotPtr rob, std::map<std::string, ActuatorData>&& newDevs, RobotUnit* newRobotUnit); virtual void update(const SensorAndControl& sc, const LVL0AndLVL1Controllers& c) override; // KinematicUnitInterface interface diff --git a/source/RobotAPI/gui-plugins/RobotUnitPlugin/RobotUnitControlDevicesWidget.ui b/source/RobotAPI/gui-plugins/RobotUnitPlugin/RobotUnitControlDevicesWidget.ui index a85b02187b6a4f17fc056d5125e99675eb04fe76..a883ebbc7669035ae823e537df1635365296fd4f 100644 --- a/source/RobotAPI/gui-plugins/RobotUnitPlugin/RobotUnitControlDevicesWidget.ui +++ b/source/RobotAPI/gui-plugins/RobotUnitPlugin/RobotUnitControlDevicesWidget.ui @@ -31,6 +31,12 @@ <property name="alternatingRowColors"> <bool>true</bool> </property> + <property name="verticalScrollMode"> + <enum>QAbstractItemView::ScrollPerPixel</enum> + </property> + <property name="horizontalScrollMode"> + <enum>QAbstractItemView::ScrollPerPixel</enum> + </property> <attribute name="headerDefaultSectionSize"> <number>100</number> </attribute> diff --git a/source/RobotAPI/gui-plugins/RobotUnitPlugin/RobotUnitLVL1ControllerClassesWidget.ui b/source/RobotAPI/gui-plugins/RobotUnitPlugin/RobotUnitLVL1ControllerClassesWidget.ui index 6fe68fa356bebc7138ce4e4857f4e829abc1c07f..722e8bf333d1de71612b6e67d180fe30aea4cf27 100644 --- a/source/RobotAPI/gui-plugins/RobotUnitPlugin/RobotUnitLVL1ControllerClassesWidget.ui +++ b/source/RobotAPI/gui-plugins/RobotUnitPlugin/RobotUnitLVL1ControllerClassesWidget.ui @@ -31,6 +31,12 @@ <property name="alternatingRowColors"> <bool>true</bool> </property> + <property name="verticalScrollMode"> + <enum>QAbstractItemView::ScrollPerPixel</enum> + </property> + <property name="horizontalScrollMode"> + <enum>QAbstractItemView::ScrollPerPixel</enum> + </property> <column> <property name="text"> <string>Class</string> diff --git a/source/RobotAPI/gui-plugins/RobotUnitPlugin/RobotUnitLVL1ControllersWidget.ui b/source/RobotAPI/gui-plugins/RobotUnitPlugin/RobotUnitLVL1ControllersWidget.ui index 50cd855467321971cc20b1f72ff8bbbc73f0d494..58650a1146314f020088f60bdf37a5fa8d502cef 100644 --- a/source/RobotAPI/gui-plugins/RobotUnitPlugin/RobotUnitLVL1ControllersWidget.ui +++ b/source/RobotAPI/gui-plugins/RobotUnitPlugin/RobotUnitLVL1ControllersWidget.ui @@ -31,6 +31,12 @@ <property name="alternatingRowColors"> <bool>true</bool> </property> + <property name="verticalScrollMode"> + <enum>QAbstractItemView::ScrollPerPixel</enum> + </property> + <property name="horizontalScrollMode"> + <enum>QAbstractItemView::ScrollPerPixel</enum> + </property> <attribute name="headerDefaultSectionSize"> <number>100</number> </attribute> diff --git a/source/RobotAPI/gui-plugins/RobotUnitPlugin/RobotUnitSensorDevicesWidget.ui b/source/RobotAPI/gui-plugins/RobotUnitPlugin/RobotUnitSensorDevicesWidget.ui index 9d4f498c50bfe2415964c85226568945222c4a76..03e397e283b4874f686cc7f718da448445d6bea9 100644 --- a/source/RobotAPI/gui-plugins/RobotUnitPlugin/RobotUnitSensorDevicesWidget.ui +++ b/source/RobotAPI/gui-plugins/RobotUnitPlugin/RobotUnitSensorDevicesWidget.ui @@ -31,6 +31,12 @@ <property name="alternatingRowColors"> <bool>true</bool> </property> + <property name="verticalScrollMode"> + <enum>QAbstractItemView::ScrollPerPixel</enum> + </property> + <property name="horizontalScrollMode"> + <enum>QAbstractItemView::ScrollPerPixel</enum> + </property> <attribute name="headerDefaultSectionSize"> <number>100</number> </attribute>