diff --git a/src/Gui/DlgSettings3DView.ui b/src/Gui/DlgSettings3DView.ui index 2f719433f7..d966d5482a 100644 --- a/src/Gui/DlgSettings3DView.ui +++ b/src/Gui/DlgSettings3DView.ui @@ -7,7 +7,7 @@ 0 0 477 - 505 + 630 @@ -323,6 +323,25 @@ + + + + Prevents view tilting when pinch-zooming. Affects only Gesture nav. style. Mouse tilting is not disabled by this setting. + + + Disable touchscreen tilt gesture + + + true + + + DisableTouchTilt + + + View + + + @@ -344,7 +363,16 @@ 6 - + + 0 + + + 0 + + + 0 + + 0 @@ -423,6 +451,16 @@ + + + + QFrame::StyledPanel + + + QFrame::Raised + + + @@ -598,13 +636,8 @@
Gui/Widgets.h
- Gui::PrefColorButton - Gui::ColorButton -
Gui/PrefWidgets.h
-
- - Gui::PrefSlider - QSlider + Gui::PrefCheckBox + QCheckBox
Gui/PrefWidgets.h
@@ -613,13 +646,18 @@
Gui/PrefWidgets.h
- Gui::PrefCheckBox - QCheckBox + Gui::PrefComboBox + QComboBox
Gui/PrefWidgets.h
- Gui::PrefComboBox - QComboBox + Gui::PrefColorButton + Gui::ColorButton +
Gui/PrefWidgets.h
+
+ + Gui::PrefSlider + QSlider
Gui/PrefWidgets.h
diff --git a/src/Gui/DlgSettings3DViewImp.cpp b/src/Gui/DlgSettings3DViewImp.cpp index 6bcbff2d2e..7d51135f1e 100644 --- a/src/Gui/DlgSettings3DViewImp.cpp +++ b/src/Gui/DlgSettings3DViewImp.cpp @@ -88,6 +88,7 @@ void DlgSettings3DViewImp::saveSettings() checkBoxZoomAtCursor->onSave(); checkBoxInvertZoom->onSave(); + checkBoxDisableTilt->onSave(); spinBoxZoomStep->onSave(); checkBoxDragAtCursor->onSave(); CheckBox_CornerCoordSystem->onSave(); @@ -107,6 +108,7 @@ void DlgSettings3DViewImp::loadSettings() { checkBoxZoomAtCursor->onRestore(); checkBoxInvertZoom->onRestore(); + checkBoxDisableTilt->onRestore(); spinBoxZoomStep->onRestore(); checkBoxDragAtCursor->onRestore(); CheckBox_CornerCoordSystem->onRestore(); diff --git a/src/Gui/FileDialog.cpp b/src/Gui/FileDialog.cpp index 7b55ed658a..cd1017fe73 100644 --- a/src/Gui/FileDialog.cpp +++ b/src/Gui/FileDialog.cpp @@ -48,6 +48,21 @@ using namespace Gui; +namespace Gui { +bool dontUseNativeDialog() +{ +#if defined(USE_QT_FILEDIALOG) + bool notNativeDialog = true; +#else + bool notNativeDialog = false; +#endif + + ParameterGrp::handle group = App::GetApplication().GetUserParameter(). + GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Dialog"); + notNativeDialog = group->GetBool("DontUseNativeDialog", notNativeDialog); + return notNativeDialog; +} +} /* TRANSLATOR Gui::FileDialog */ @@ -147,56 +162,59 @@ QString FileDialog::getSaveFileName (QWidget * parent, const QString & caption, #if QT_VERSION < 0x040800 && defined(FC_OS_MACOSX) options |= QFileDialog::DontUseNativeDialog; #endif + // NOTE: We must not change the specified file name afterwards as we may return the name of an already // existing file. Hence we must extract the first matching suffix from the filter list and append it // before showing the file dialog. -#if defined(USE_QT_FILEDIALOG) - QList urls; + QString file; + if (dontUseNativeDialog()) { + QList urls; #if QT_VERSION >= 0x050000 - options |= QFileDialog::DontUseNativeDialog; - urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)); - urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)); - urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)); - urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::MusicLocation)); - urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation)); - urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::MoviesLocation)); + options |= QFileDialog::DontUseNativeDialog; + urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)); + urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)); + urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)); + urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::MusicLocation)); + urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation)); + urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::MoviesLocation)); #else - urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::DesktopLocation)); - urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation)); - urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::HomeLocation)); - urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::MusicLocation)); - urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::PicturesLocation)); - urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::MoviesLocation)); + urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::DesktopLocation)); + urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation)); + urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::HomeLocation)); + urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::MusicLocation)); + urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::PicturesLocation)); + urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::MoviesLocation)); #endif - urls << QUrl::fromLocalFile(getWorkingDirectory()); - urls << QUrl::fromLocalFile(restoreLocation()); - urls << QUrl::fromLocalFile(QDir::currentPath()); + urls << QUrl::fromLocalFile(getWorkingDirectory()); + urls << QUrl::fromLocalFile(restoreLocation()); + urls << QUrl::fromLocalFile(QDir::currentPath()); - QString file; - FileDialog dlg(parent); - dlg.setWindowTitle(windowTitle); - dlg.setSidebarUrls(urls); - dlg.setIconProvider(new FileIconProvider()); - dlg.setFileMode(QFileDialog::AnyFile); - dlg.setAcceptMode(QFileDialog::AcceptSave); - dlg.setDirectory(dirName); - dlg.setOptions(options); - dlg.setNameFilters(filter.split(QLatin1String(";;"))); - dlg.onSelectedFilter(dlg.selectedNameFilter()); - dlg.setNameFilterDetailsVisible(true); - dlg.setConfirmOverwrite(true); - if (dlg.exec() == QDialog::Accepted) { - if (selectedFilter) - *selectedFilter = dlg.selectedNameFilter(); - file = dlg.selectedFiles().front(); + FileDialog dlg(parent); + dlg.setWindowTitle(windowTitle); + dlg.setSidebarUrls(urls); + dlg.setIconProvider(new FileIconProvider()); + dlg.setFileMode(QFileDialog::AnyFile); + dlg.setAcceptMode(QFileDialog::AcceptSave); + dlg.setDirectory(dirName); + dlg.setOptions(options); + dlg.setNameFilters(filter.split(QLatin1String(";;"))); + dlg.onSelectedFilter(dlg.selectedNameFilter()); + dlg.setNameFilterDetailsVisible(true); + dlg.setConfirmOverwrite(true); + if (dlg.exec() == QDialog::Accepted) { + if (selectedFilter) + *selectedFilter = dlg.selectedNameFilter(); + file = dlg.selectedFiles().front(); + } } -#else - QString file = QFileDialog::getSaveFileName(parent, windowTitle, dirName, filter, selectedFilter, options); + else { + file = QFileDialog::getSaveFileName(parent, windowTitle, dirName, filter, selectedFilter, options); #if QT_VERSION >= 0x040600 - file = QDir::fromNativeSeparators(file); -#endif + file = QDir::fromNativeSeparators(file); #endif + } + if (!file.isEmpty()) { setWorkingDirectory(file); return file; @@ -238,55 +256,58 @@ QString FileDialog::getOpenFileName(QWidget * parent, const QString & caption, c QString windowTitle = caption; if (windowTitle.isEmpty()) windowTitle = FileDialog::tr("Open"); + #if QT_VERSION < 0x040800 && defined(FC_OS_MACOSX) options |= QFileDialog::DontUseNativeDialog; #endif -#if defined(USE_QT_FILEDIALOG) - QList urls; + QString file; + if (dontUseNativeDialog()) { + QList urls; #if QT_VERSION >= 0x050000 - options |= QFileDialog::DontUseNativeDialog; - urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)); - urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)); - urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)); - urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::MusicLocation)); - urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation)); - urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::MoviesLocation)); + options |= QFileDialog::DontUseNativeDialog; + urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)); + urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)); + urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)); + urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::MusicLocation)); + urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation)); + urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::MoviesLocation)); #else - urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::DesktopLocation)); - urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation)); - urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::HomeLocation)); - urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::MusicLocation)); - urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::PicturesLocation)); - urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::MoviesLocation)); + urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::DesktopLocation)); + urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation)); + urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::HomeLocation)); + urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::MusicLocation)); + urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::PicturesLocation)); + urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::MoviesLocation)); #endif - urls << QUrl::fromLocalFile(getWorkingDirectory()); - urls << QUrl::fromLocalFile(restoreLocation()); - urls << QUrl::fromLocalFile(QDir::currentPath()); + urls << QUrl::fromLocalFile(getWorkingDirectory()); + urls << QUrl::fromLocalFile(restoreLocation()); + urls << QUrl::fromLocalFile(QDir::currentPath()); - QString file; - FileDialog dlg(parent); - dlg.setWindowTitle(windowTitle); - dlg.setSidebarUrls(urls); - dlg.setIconProvider(new FileIconProvider()); - dlg.setFileMode(QFileDialog::ExistingFile); - dlg.setAcceptMode(QFileDialog::AcceptOpen); - dlg.setDirectory(dirName); - dlg.setOptions(options); - dlg.setNameFilters(filter.split(QLatin1String(";;"))); - dlg.setNameFilterDetailsVisible(true); - if (dlg.exec() == QDialog::Accepted) { - if (selectedFilter) - *selectedFilter = dlg.selectedNameFilter(); - file = dlg.selectedFiles().front(); + FileDialog dlg(parent); + dlg.setWindowTitle(windowTitle); + dlg.setSidebarUrls(urls); + dlg.setIconProvider(new FileIconProvider()); + dlg.setFileMode(QFileDialog::ExistingFile); + dlg.setAcceptMode(QFileDialog::AcceptOpen); + dlg.setDirectory(dirName); + dlg.setOptions(options); + dlg.setNameFilters(filter.split(QLatin1String(";;"))); + dlg.setNameFilterDetailsVisible(true); + if (dlg.exec() == QDialog::Accepted) { + if (selectedFilter) + *selectedFilter = dlg.selectedNameFilter(); + file = dlg.selectedFiles().front(); + } } -#else - QString file = QFileDialog::getOpenFileName(parent, windowTitle, dirName, filter, selectedFilter, options); + else { + file = QFileDialog::getOpenFileName(parent, windowTitle, dirName, filter, selectedFilter, options); #if QT_VERSION >= 0x040600 - file = QDir::fromNativeSeparators(file); -#endif + file = QDir::fromNativeSeparators(file); #endif + } + if (!file.isEmpty()) { setWorkingDirectory(file); return file; @@ -309,61 +330,64 @@ QStringList FileDialog::getOpenFileNames (QWidget * parent, const QString & capt QString windowTitle = caption; if (windowTitle.isEmpty()) windowTitle = FileDialog::tr("Open"); + #if QT_VERSION < 0x040800 && defined(FC_OS_MACOSX) options |= QFileDialog::DontUseNativeDialog; #endif -#if defined(USE_QT_FILEDIALOG) - QList urls; + QStringList files; + if (dontUseNativeDialog()) { + QList urls; #if QT_VERSION >= 0x050000 - options |= QFileDialog::DontUseNativeDialog; - urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)); - urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)); - urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)); - urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::MusicLocation)); - urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation)); - urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::MoviesLocation)); + options |= QFileDialog::DontUseNativeDialog; + urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)); + urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)); + urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)); + urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::MusicLocation)); + urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation)); + urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::MoviesLocation)); #else - urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::DesktopLocation)); - urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation)); - urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::HomeLocation)); - urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::MusicLocation)); - urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::PicturesLocation)); - urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::MoviesLocation)); + urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::DesktopLocation)); + urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation)); + urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::HomeLocation)); + urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::MusicLocation)); + urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::PicturesLocation)); + urls << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::MoviesLocation)); #endif - urls << QUrl::fromLocalFile(getWorkingDirectory()); - urls << QUrl::fromLocalFile(restoreLocation()); - urls << QUrl::fromLocalFile(QDir::currentPath()); + urls << QUrl::fromLocalFile(getWorkingDirectory()); + urls << QUrl::fromLocalFile(restoreLocation()); + urls << QUrl::fromLocalFile(QDir::currentPath()); - QStringList files; - FileDialog dlg(parent); - dlg.setWindowTitle(windowTitle); - dlg.setSidebarUrls(urls); - dlg.setIconProvider(new FileIconProvider()); - dlg.setFileMode(QFileDialog::ExistingFiles); - dlg.setAcceptMode(QFileDialog::AcceptOpen); - dlg.setDirectory(dirName); - dlg.setOptions(options); - dlg.setNameFilters(filter.split(QLatin1String(";;"))); - dlg.setNameFilterDetailsVisible(true); - if (dlg.exec() == QDialog::Accepted) { - if (selectedFilter) - *selectedFilter = dlg.selectedNameFilter(); - files = dlg.selectedFiles(); + FileDialog dlg(parent); + dlg.setWindowTitle(windowTitle); + dlg.setSidebarUrls(urls); + dlg.setIconProvider(new FileIconProvider()); + dlg.setFileMode(QFileDialog::ExistingFiles); + dlg.setAcceptMode(QFileDialog::AcceptOpen); + dlg.setDirectory(dirName); + dlg.setOptions(options); + dlg.setNameFilters(filter.split(QLatin1String(";;"))); + dlg.setNameFilterDetailsVisible(true); + if (dlg.exec() == QDialog::Accepted) { + if (selectedFilter) + *selectedFilter = dlg.selectedNameFilter(); + files = dlg.selectedFiles(); + } } -#else - QStringList files = QFileDialog::getOpenFileNames(parent, windowTitle, dirName, filter, selectedFilter, options); + else { + files = QFileDialog::getOpenFileNames(parent, windowTitle, dirName, filter, selectedFilter, options); #if QT_VERSION >= 0x040600 - for (QStringList::iterator it = files.begin(); it != files.end(); ++it) { - *it = QDir::fromNativeSeparators(*it); + for (QStringList::iterator it = files.begin(); it != files.end(); ++it) { + *it = QDir::fromNativeSeparators(*it); + } +#endif } -#endif -#endif + if (!files.isEmpty()) { setWorkingDirectory(files.front()); } - + return files; } @@ -673,11 +697,10 @@ void FileChooser::chooseFile() prechosenDirectory = FileDialog::getWorkingDirectory(); } -#if defined(USE_QT_FILEDIALOG) - QFileDialog::Options dlgOpt = QFileDialog::DontUseNativeDialog; -#else QFileDialog::Options dlgOpt; -#endif + if (dontUseNativeDialog()) { + dlgOpt = QFileDialog::DontUseNativeDialog; + } QString fn; if ( mode() == File ) { diff --git a/src/Gui/GestureNavigationStyle.cpp b/src/Gui/GestureNavigationStyle.cpp index 46bc4fe97c..1613aaef63 100644 --- a/src/Gui/GestureNavigationStyle.cpp +++ b/src/Gui/GestureNavigationStyle.cpp @@ -236,10 +236,13 @@ SbBool GestureNavigationStyle::processSoEvent(const SoEvent * const ev) if (evIsGesture) { const SoGestureEvent* gesture = static_cast(ev); switch(gesture->state) { - case SoGestureEvent::SbGSStart: + case SoGestureEvent::SbGSStart:{ //assert(!inGesture);//start of another gesture before the first finished? Happens all the time for Pan gesture... No idea why! --DeepSOIC inGesture = true; - break; + + enableGestureTilt = !(App::GetApplication().GetParameterGroupByPath + ("User parameter:BaseApp/Preferences/View")->GetBool("DisableTouchTilt",true)); + }break; case SoGestureEvent::SbGSUpdate: assert(inGesture);//gesture update without start? inGesture = true; @@ -551,7 +554,7 @@ SbBool GestureNavigationStyle::processSoEvent(const SoEvent * const ev) NavigationStyle::panCamera(viewer->getSoRenderManager()->getCamera(), ratio, this->panningplane, panDist, SbVec2f(0,0)); } NavigationStyle::doZoom(viewer->getSoRenderManager()->getCamera(),-logf(event->deltaZoom),this->normalizePixelPos(event->curCenter)); - if (event->deltaAngle != 0) + if (event->deltaAngle != 0 && enableGestureTilt) NavigationStyle::doRotate(viewer->getSoRenderManager()->getCamera(),event->deltaAngle,this->normalizePixelPos(event->curCenter)); processed = true; } diff --git a/src/Gui/NavigationStyle.h b/src/Gui/NavigationStyle.h index 6144c73952..127fa210ae 100644 --- a/src/Gui/NavigationStyle.h +++ b/src/Gui/NavigationStyle.h @@ -412,6 +412,7 @@ protected: bool thisClickIsComplex;//a flag that becomes set when a complex clicking pattern is detected (i.e., two or more mouse buttons were down at the same time). bool inGesture; //a flag that is used to filter out mouse events during gestures. + bool enableGestureTilt = false; //fetched from settings }; class GuiExport OpenCascadeNavigationStyle : public UserNavigationStyle { diff --git a/src/Gui/SoTouchEvents.cpp b/src/Gui/SoTouchEvents.cpp index d7bd48bb98..0e1bf608fe 100644 --- a/src/Gui/SoTouchEvents.cpp +++ b/src/Gui/SoTouchEvents.cpp @@ -84,8 +84,8 @@ SoGesturePinchEvent::SoGesturePinchEvent(QPinchGesture* qpinch, QWidget *widget) deltaZoom = qpinch->scaleFactor(); totalZoom = qpinch->totalScaleFactor(); - deltaAngle = qpinch->rotationAngle(); - totalAngle = qpinch->totalRotationAngle(); + deltaAngle = -unbranchAngle((qpinch->rotationAngle()-qpinch->lastRotationAngle()) / 180.0 * M_PI); + totalAngle = -qpinch->totalRotationAngle() / 180 * M_PI; state = SbGestureState(qpinch->state()); @@ -102,6 +102,18 @@ SbBool SoGesturePinchEvent::isSoGesturePinchEvent(const SoEvent *ev) const return ev->isOfType(SoGesturePinchEvent::getClassTypeId()); } +/*! + * \brief SoGesturePinchEvent::unbranchAngle : utility function to bring an angle into -pi..pi region. + * \param ang - in radians + * \return + */ +double SoGesturePinchEvent::unbranchAngle(double ang) +{ + const double Pi = 3.14159265358979323846; + return ang - 2.0*Pi*floor((ang+Pi)/(2.0*Pi)); +} + + //----------------------------SoGestureSwipeEvent-------------------------------- SO_EVENT_SOURCE(SoGestureSwipeEvent); diff --git a/src/Gui/SoTouchEvents.h b/src/Gui/SoTouchEvents.h index 02dc18a8c3..980931709e 100644 --- a/src/Gui/SoTouchEvents.h +++ b/src/Gui/SoTouchEvents.h @@ -91,6 +91,8 @@ public: double deltaAngle; double totalAngle; + static double unbranchAngle(double ang); + }; class SoGestureSwipeEvent : public SoGestureEvent { diff --git a/src/Gui/Tree.cpp b/src/Gui/Tree.cpp index becb53194e..b28ee5c9e0 100644 --- a/src/Gui/Tree.cpp +++ b/src/Gui/Tree.cpp @@ -702,7 +702,6 @@ void TreeWidget::dropEvent(QDropEvent *event) Gui::Document* gui = vpTarget->getDocument(); if (da == Qt::LinkAction) { -#if 0 // Open command gui->openCommand("Drop object"); for (QList::Iterator it = items.begin(); it != items.end(); ++it) { @@ -720,7 +719,6 @@ void TreeWidget::dropEvent(QDropEvent *event) } gui->commitCommand(); -#endif } else { if (!vpTarget->canDropObjects()) { diff --git a/src/Gui/View3DInventorViewer.cpp b/src/Gui/View3DInventorViewer.cpp index 975f81e78d..3a74c33725 100644 --- a/src/Gui/View3DInventorViewer.cpp +++ b/src/Gui/View3DInventorViewer.cpp @@ -922,6 +922,8 @@ void View3DInventorViewer::setNavigationType(Base::Type t) if (t.isBad()) return; + this->winGestureTuneState = View3DInventorViewer::ewgtsNeedTuning; //triggers enable/disable rotation gesture when preferences change + if (this->navigation && this->navigation->getTypeId() == t) return; // nothing to do diff --git a/src/Gui/ViewProvider.cpp b/src/Gui/ViewProvider.cpp index e1995d1425..de33ebe772 100644 --- a/src/Gui/ViewProvider.cpp +++ b/src/Gui/ViewProvider.cpp @@ -716,6 +716,19 @@ void ViewProvider::dropObject(App::DocumentObject* obj) throw Base::RuntimeError("ViewProvider::dropObject: no extension for dropping given object available."); } +void ViewProvider::replaceObject(App::DocumentObject* oldValue, App::DocumentObject* newValue) +{ + auto vector = getExtensionsDerivedFromType(); + for (Gui::ViewProviderExtension* ext : vector) { + if (ext->extensionCanDropObject(newValue)) { + ext->extensionReplaceObject(oldValue, newValue); + return; + } + } + + throw Base::RuntimeError("ViewProvider::dropObject: no extension for dropping given object available."); +} + void ViewProvider::Restore(Base::XMLReader& reader) { setStatus(Gui::isRestoring, true); diff --git a/src/Gui/ViewProvider.h b/src/Gui/ViewProvider.h index 9c6867e444..c5e7a6ff39 100644 --- a/src/Gui/ViewProvider.h +++ b/src/Gui/ViewProvider.h @@ -195,6 +195,8 @@ public: virtual bool canDropObject(App::DocumentObject*) const; /** Add an object to the view provider by drag and drop */ virtual void dropObject(App::DocumentObject*); + /** Replace an object to the view provider by drag and drop */ + virtual void replaceObject(App::DocumentObject*, App::DocumentObject*); //@} /** @name Signals of the view provider */ diff --git a/src/Gui/ViewProviderExtension.h b/src/Gui/ViewProviderExtension.h index 4e4520d100..aba6b3846e 100644 --- a/src/Gui/ViewProviderExtension.h +++ b/src/Gui/ViewProviderExtension.h @@ -63,6 +63,7 @@ public: virtual bool extensionCanDropObjects() const { return false; } virtual bool extensionCanDropObject(App::DocumentObject*) const { return true; } virtual void extensionDropObject(App::DocumentObject*) { } + virtual void extensionReplaceObject(App::DocumentObject* /*oldValue*/, App::DocumentObject* /*newValue*/) { } /// Hides the view provider virtual void extensionHide(void) { } diff --git a/src/Gui/ViewProviderGroupExtension.cpp b/src/Gui/ViewProviderGroupExtension.cpp index 0b5beb1a1f..be1f52945c 100644 --- a/src/Gui/ViewProviderGroupExtension.cpp +++ b/src/Gui/ViewProviderGroupExtension.cpp @@ -110,6 +110,29 @@ void ViewProviderGroupExtension::extensionDropObject(App::DocumentObject* obj) { Gui::Command::doCommand(Gui::Command::App, cmd.toUtf8()); } +void ViewProviderGroupExtension::extensionReplaceObject(App::DocumentObject* oldValue, App::DocumentObject* newValue) { + + App::DocumentObject* grp = static_cast(getExtendedViewProvider()->getObject()); + App::Document* doc = grp->getDocument(); + + // build Python command for execution + QString cmd; + cmd = QString::fromLatin1("App.getDocument(\"%1\").getObject(\"%2\").removeObject(" + "App.getDocument(\"%1\").getObject(\"%3\"))") + .arg(QString::fromLatin1(doc->getName())) + .arg(QString::fromLatin1(grp->getNameInDocument())) + .arg(QString::fromLatin1(oldValue->getNameInDocument())); + + Gui::Command::doCommand(Gui::Command::App, cmd.toUtf8()); + cmd = QString::fromLatin1("App.getDocument(\"%1\").getObject(\"%2\").addObject(" + "App.getDocument(\"%1\").getObject(\"%3\"))") + .arg(QString::fromLatin1(doc->getName())) + .arg(QString::fromLatin1(grp->getNameInDocument())) + .arg(QString::fromLatin1(newValue->getNameInDocument())); + + Gui::Command::doCommand(Gui::Command::App, cmd.toUtf8()); +} + std::vector< App::DocumentObject* > ViewProviderGroupExtension::extensionClaimChildren(void) const { auto* group = getExtendedViewProvider()->getObject()->getExtensionByType(); diff --git a/src/Gui/ViewProviderGroupExtension.h b/src/Gui/ViewProviderGroupExtension.h index 58c73e0353..2e25622841 100644 --- a/src/Gui/ViewProviderGroupExtension.h +++ b/src/Gui/ViewProviderGroupExtension.h @@ -46,6 +46,7 @@ public: virtual bool extensionCanDropObjects() const override; virtual bool extensionCanDropObject(App::DocumentObject*) const override; virtual void extensionDropObject(App::DocumentObject*) override; + virtual void extensionReplaceObject(App::DocumentObject* oldValue, App::DocumentObject* newValue) override; virtual void extensionHide(void) override; virtual void extensionShow(void) override; diff --git a/src/Gui/WinNativeGestureRecognizers.cpp b/src/Gui/WinNativeGestureRecognizers.cpp index 188c108470..76a1aee543 100644 --- a/src/Gui/WinNativeGestureRecognizers.cpp +++ b/src/Gui/WinNativeGestureRecognizers.cpp @@ -42,6 +42,8 @@ #include #include +#include +#include QT_BEGIN_NAMESPACE @@ -129,7 +131,7 @@ QGestureRecognizer::Result WinNativeGestureRecognizerPinch::recognize(QGesture * } double ang = 0.0; if (bRotate) - ang=GID_ROTATE_ANGLE_FROM_ARGUMENT(LOWORD(ev->argument)); + ang = -GID_ROTATE_ANGLE_FROM_ARGUMENT(LOWORD(ev->argument)) / M_PI * 180.0; if (q->state() == Qt::NoGesture) { //start of a new gesture, prefill stuff //d->isNewSequence = true; @@ -146,11 +148,13 @@ QGestureRecognizer::Result WinNativeGestureRecognizerPinch::recognize(QGesture * q->setTotalRotationAngle(0.0); q->setLastRotationAngle(0.0); q->setRotationAngle(0.0); q->setTotalScaleFactor(1.0); q->setLastScaleFactor(1.0); q->setScaleFactor(1.0); if(bZoom) { - q->lastFingerDistance = ev->argument; - q->fingerDistance = ev->argument; + q->myLastFingerDistance = ev->argument; + q->myFingerDistance = ev->argument; + q->myStartFingerDistance = ev->argument; } else if (bRotate) { q->myLastRotationAngle = 0; q->myRotationAngle = 0; + q->myStartAngle = 0; } } else {//in the middle of gesture @@ -158,24 +162,24 @@ QGestureRecognizer::Result WinNativeGestureRecognizerPinch::recognize(QGesture * q->setLastCenterPoint(q->centerPoint()); q->setLastRotationAngle(q->rotationAngle()); q->setLastScaleFactor(q->scaleFactor()); - q->lastFingerDistance = q->fingerDistance; + q->myLastFingerDistance = q->myFingerDistance; q->myLastRotationAngle = q->myRotationAngle; //update the current values if (bZoom) - q->fingerDistance = ev->argument; + q->myFingerDistance = ev->argument; if (bRotate) q->myRotationAngle = ang; if(ev->gestureType == QNativeGestureEvent::GestureEnd){ - q->fingerDistance = q->lastFingerDistance;//the end-of-gesture event holds no finger separation data, hence we are using the last value. + q->myFingerDistance = q->myLastFingerDistance;//the end-of-gesture event holds no finger separation data, hence we are using the last value. q->myRotationAngle = q->myLastRotationAngle; } if (bZoom) q->setScaleFactor( - (qreal)(q->fingerDistance) / (qreal)(q->lastFingerDistance) + (qreal)(q->myFingerDistance) / (qreal)(q->myLastFingerDistance) ); if (bRotate) - q->setRotationAngle(qreal(unbranchAngle(q->myRotationAngle - q->myLastRotationAngle))); + q->setRotationAngle(q->myRotationAngle); q->setCenterPoint( QPointF( qreal(ev->position.x()), @@ -183,20 +187,20 @@ QGestureRecognizer::Result WinNativeGestureRecognizerPinch::recognize(QGesture * ) ); - //compute the changes + //detect changes QPinchGesture::ChangeFlags cf = 0; if ( q->scaleFactor() != 1.0 ) cf |= QPinchGesture::ScaleFactorChanged; if (q->lastCenterPoint() != q->centerPoint()) cf |= QPinchGesture::CenterPointChanged; - if (q->rotationAngle() != 0.0) + if (q->rotationAngle() != q->lastRotationAngle()) cf |= QPinchGesture::RotationAngleChanged; q->setChangeFlags(cf); - //increment totals + //update totals q->setTotalChangeFlags (q->totalChangeFlags() | q->changeFlags()); q->setTotalScaleFactor (q->totalScaleFactor() * q->scaleFactor()); - q->setTotalRotationAngle (q->totalRotationAngle() + q->rotationAngle()); + q->setTotalRotationAngle (q->rotationAngle()); } } return result; @@ -207,7 +211,7 @@ void WinNativeGestureRecognizerPinch::reset(QGesture* gesture) { QGestureRecognizer::reset(gesture);//resets the state of the gesture, which is not write-accessible otherwise QPinchGestureN *q = static_cast(gesture); - q->lastFingerDistance = 0; + q->myLastFingerDistance = 0; q->setTotalChangeFlags(0); q->setChangeFlags(0); q->setLastCenterPoint(QPointF()); @@ -220,8 +224,8 @@ void WinNativeGestureRecognizerPinch::reset(QGesture* gesture) q->setStartCenterPoint(q->centerPoint()); q->setTotalRotationAngle(0.0); q->setLastRotationAngle(0.0); q->setRotationAngle(0.0); q->setTotalScaleFactor(1.0); q->setLastScaleFactor(1.0); q->setScaleFactor(1.0); - q->lastFingerDistance = 0; - q->fingerDistance = 0; + q->myLastFingerDistance = 0; + q->myFingerDistance = 0; } //function prototype for dymanic linking @@ -255,8 +259,16 @@ void WinNativeGestureRecognizerPinch::TuneWindowsGestures(QWidget* target) cfgs[0].dwID = GID_PAN; cfgs[0].dwWant = GC_PAN; cfgs[0].dwBlock = GC_PAN_WITH_GUTTER;//disables stickiness to pure vertical/pure horizontal pans - cfgs[1].dwID = GID_ROTATE; - cfgs[1].dwWant = GC_ROTATE; + + bool enableGestureTilt = !(App::GetApplication().GetParameterGroupByPath + ("User parameter:BaseApp/Preferences/View")->GetBool("DisableTouchTilt",true)); + if(enableGestureTilt){ + cfgs[1].dwID = GID_ROTATE; + cfgs[1].dwWant = GC_ROTATE; + } else { + cfgs[1].dwID = GID_ROTATE; + cfgs[1].dwBlock = GC_ROTATE; + } //set the options bool ret = dllSetGestureConfig(w, 0, nCfg, cfgs, sizeof(GESTURECONFIG)); @@ -269,17 +281,6 @@ void WinNativeGestureRecognizerPinch::TuneWindowsGestures(QWidget* target) #endif } -/*! - * \brief WinNativeGestureRecognizerPinch::unbranchAngle utility function to bring an angle into -pi..pi region. - * \param ang - * \return - */ -double WinNativeGestureRecognizerPinch::unbranchAngle(double ang) -{ - const double Pi = 3.14159265358979323846; - return ang - 2.0*Pi*floor((ang+Pi)/(2.0*Pi)); -} - #endif //!defined(QT_NO_NATIVE_GESTURES) #endif // GESTURE_MESS diff --git a/src/Gui/WinNativeGestureRecognizers.h b/src/Gui/WinNativeGestureRecognizers.h index b58faabbfe..b287a577bc 100644 --- a/src/Gui/WinNativeGestureRecognizers.h +++ b/src/Gui/WinNativeGestureRecognizers.h @@ -50,10 +50,12 @@ class QPinchGestureN: public QPinchGesture { public: - int lastFingerDistance;//distance between fingers, in pixels - int fingerDistance; - double myRotationAngle; - double myLastRotationAngle; + int myFingerDistance = 0; //distance between fingers, in pixels + int myLastFingerDistance = 0; + int myStartFingerDistance = 0; //finger distance at gesture start + double myRotationAngle = 0.0; + double myLastRotationAngle = 0.0; + double myStartAngle = 0.0; }; class WinNativeGestureRecognizerPinch : public QGestureRecognizer @@ -64,7 +66,6 @@ public: virtual Result recognize ( QGesture* gesture, QObject* watched, QEvent* event ); virtual void reset ( QGesture* gesture ); static void TuneWindowsGestures(QWidget* target); - static double unbranchAngle(double ang); }; #endif //GESTUREMESS diff --git a/src/Mod/Part/Gui/ViewProviderBoolean.cpp b/src/Mod/Part/Gui/ViewProviderBoolean.cpp index 7aa4668049..2782326343 100644 --- a/src/Mod/Part/Gui/ViewProviderBoolean.cpp +++ b/src/Mod/Part/Gui/ViewProviderBoolean.cpp @@ -152,6 +152,18 @@ bool ViewProviderBoolean::onDelete(const std::vector &) return true; } +void ViewProviderBoolean::replaceObject(App::DocumentObject* oldValue, App::DocumentObject* newValue) +{ + Part::Boolean* pBool = static_cast(getObject()); + if (oldValue == pBool->Base.getValue()) { + pBool->Base.setValue(newValue); + } + else if (oldValue == pBool->Tool.getValue()) { + pBool->Tool.setValue(newValue); + } +} + + PROPERTY_SOURCE(PartGui::ViewProviderMultiFuse,PartGui::ViewProviderPart) ViewProviderMultiFuse::ViewProviderMultiFuse() @@ -279,6 +291,13 @@ void ViewProviderMultiFuse::dropObject(App::DocumentObject* obj) pBool->Shapes.setValues(pShapes); } +void ViewProviderMultiFuse::replaceObject(App::DocumentObject* oldValue, App::DocumentObject* newValue) +{ + Part::MultiFuse* pBool = static_cast(getObject()); + std::vector pShapes = pBool->Shapes.getValues(); + std::replace(pShapes.begin(), pShapes.end(), oldValue, newValue); + pBool->Shapes.setValues(pShapes); +} PROPERTY_SOURCE(PartGui::ViewProviderMultiCommon,PartGui::ViewProviderPart) @@ -406,3 +425,11 @@ void ViewProviderMultiCommon::dropObject(App::DocumentObject* obj) pShapes.push_back(obj); pBool->Shapes.setValues(pShapes); } + +void ViewProviderMultiCommon::replaceObject(App::DocumentObject* oldValue, App::DocumentObject* newValue) +{ + Part::MultiFuse* pBool = static_cast(getObject()); + std::vector pShapes = pBool->Shapes.getValues(); + std::replace(pShapes.begin(), pShapes.end(), oldValue, newValue); + pBool->Shapes.setValues(pShapes); +} diff --git a/src/Mod/Part/Gui/ViewProviderBoolean.h b/src/Mod/Part/Gui/ViewProviderBoolean.h index 3c379309ab..c9abc06263 100644 --- a/src/Mod/Part/Gui/ViewProviderBoolean.h +++ b/src/Mod/Part/Gui/ViewProviderBoolean.h @@ -44,6 +44,7 @@ public: QIcon getIcon(void) const; void updateData(const App::Property*); bool onDelete(const std::vector &); + virtual void replaceObject(App::DocumentObject*, App::DocumentObject*); }; /// ViewProvider for the MultiFuse feature @@ -70,6 +71,8 @@ public: bool canDropObjects() const; bool canDropObject(App::DocumentObject*) const; void dropObject(App::DocumentObject*); + /** Replace an object to the view provider by drag and drop */ + virtual void replaceObject(App::DocumentObject*, App::DocumentObject*); }; /// ViewProvider for the MultiFuse feature @@ -96,6 +99,8 @@ public: bool canDropObjects() const; bool canDropObject(App::DocumentObject*) const; void dropObject(App::DocumentObject*); + /** Replace an object to the view provider by drag and drop */ + virtual void replaceObject(App::DocumentObject*, App::DocumentObject*); }; diff --git a/src/Mod/Part/Gui/ViewProviderCompound.cpp b/src/Mod/Part/Gui/ViewProviderCompound.cpp index ed9796dc48..4992579ddb 100644 --- a/src/Mod/Part/Gui/ViewProviderCompound.cpp +++ b/src/Mod/Part/Gui/ViewProviderCompound.cpp @@ -154,3 +154,11 @@ void ViewProviderCompound::dropObject(App::DocumentObject* obj) pShapes.push_back(obj); pComp->Links.setValues(pShapes); } + +void ViewProviderCompound::replaceObject(App::DocumentObject* oldValue, App::DocumentObject* newValue) +{ + Part::Compound* pBool = static_cast(getObject()); + std::vector pShapes = pBool->Links.getValues(); + std::replace(pShapes.begin(), pShapes.end(), oldValue, newValue); + pBool->Links.setValues(pShapes); +} diff --git a/src/Mod/Part/Gui/ViewProviderCompound.h b/src/Mod/Part/Gui/ViewProviderCompound.h index e72b9b278b..0ea8ff955a 100644 --- a/src/Mod/Part/Gui/ViewProviderCompound.h +++ b/src/Mod/Part/Gui/ViewProviderCompound.h @@ -48,6 +48,8 @@ public: bool canDropObjects() const; bool canDropObject(App::DocumentObject*) const; void dropObject(App::DocumentObject*); + /** Replace an object to the view provider by drag and drop */ + virtual void replaceObject(App::DocumentObject*, App::DocumentObject*); protected: void updateData(const App::Property*);