Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

QGIS custom widgets plugins for Qt Designer #1325

Merged
merged 16 commits into from
May 19, 2014
Merged

Conversation

3nids
Copy link
Member

@3nids 3nids commented Apr 25, 2014

This adds a new library for using custom widgets in Qt Designer.

I implemented as a first try a a group box for scale dependent visibility.

I successfully built this on ubuntu, but did not try on Win/Mac.

@jef-n may you have a look at the CMakeList files?
@timlinux would be nice to have your opinon since I believe you were waiting for such feature ;) Also, could you have a look if it works well on mac?

@3nids
Copy link
Member Author

3nids commented Apr 25, 2014

Here is how it looks like in Qt Designer
image

@timlinux
Copy link
Member

Hi @3nids

Ah this is awesome! I will test on my ubuntu and give you any feedback. Do I need to do anything special to make designer aware of the widgets?

Sorry I just this week replaced my mac's OS with ubuntu (finally got it to work with 14.04) so I am unable to test it there.

@3nids
Copy link
Member Author

3nids commented Apr 26, 2014

Hi @timlinux,
You just need to compile using -DWITH_CUSTOM_WIDGETS=TRUE since I set it to false by default.

Then, the built library should automatically be installed in the Qt Designer plugin folder.
make install | grep custom should show you the path it went to.
On my computer: /usr/lib/x86_64-linux-gnu/qt4/plugins/designer/libqgis_customwidgets.so

I had access to the widgets from the standalone designer and also within creator.

Thanks for testing this!

@@ -285,6 +290,12 @@ ENDIF (ENABLE_TESTS)

INCLUDE( ${QT_USE_FILE} )

IF (WITH_CUSTOM_WIDGETS)
ADD_DEFINITIONS(-DQT_PLUGIN)
ADD_DEFINITIONS(-DQT_NO_DEBUG)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@3nids
Copy link
Member Author

3nids commented May 2, 2014

My main concerns are:

  • the CMakeList, especially creating a new var WITH_CUSTOM_WIDGETS: is this necessary, should it be true by default?
  • I tested on ubuntu, but I don't have any other dev environment.
  • regarding the include problem [0], I solved this by redirecting all custom widgets import to qgis.gui. This is working, but I am not sure this is the best solution
  • I did not export QgisCustomWidgets to CUSTOMWIDGETS_EXPORT

[0] http://lists.osgeo.org/pipermail/qgis-developer/2014-May/032425.html

@3nids
Copy link
Member Author

3nids commented May 2, 2014

There is a problem with the definition of flags in QgsMapLayerComboBox.
If trying to compile a widget with a QgsMapLayerComboBox with pyuic4, I get: AttributeError: unknown enum QgsMapLayerProxyModel::VectorLayer

@mhugent
Copy link
Contributor

mhugent commented May 5, 2014

assigned to @NathanW2

@3nids
Copy link
Member Author

3nids commented May 5, 2014

@wonder-sk is having a look at it too.

@wonder-sk
Copy link
Member

Nice stuff Denis! I think one of @timlinux dreams will soon come true, he has hoped for this for years! :-) The possibility to have useful QGIS widgets directly in designer will make the design of dialogs much easier. Below are my comments...

root CMakeLists.txt:

  • the new definitions from root CMakeLists.txt should go to CMakeLists file for customwidgets
  • no need for macro CUSTOMWIDGETS_EXPORT - custom widgets can instead use just QDESIGNER_WIDGET_EXPORT as suggested by Qt documentation
  • there should not be any need to change global INCLUDE_DIRECTORIES

Custom Widgets CMakeLists.txt:

  • there are APPLE-specific sections - have you tested it? The customwidgets library in fact is not a usual shared library, it is a plugin meant to be loaded during runtime. On OS X there is a difference between these two and therefore most of the APPLE-specific stuff is likely invalid. If you can't or don't want to test on OS X, better remove that stuff - someone with Mac knowledge will add what is necessary later. There are already few Qt plugins in QGIS codebase, here's some inspiration: src/providers/oracle/ocispatial/CMakeLists.txt, src/providers/spatialite/qspatialite/CMakeLists.txt
  • header files should not be installed anywhere - they are just implementations of interfaces, not a new API

Custom Widgets:

  • domXml() - I think there's no need to add the default tooltip and "what's this" text
  • we should define properties for widgets to allow setting them in Qt Designer

Python support:

  • the way how the imports are done for python (with changes to sys.modules on load of qgis module) does not look very good to me. It should be possible to use pyuic's widget plugins feature. The functionality is very poorly documented, but that should solve the import problem in a much nicer way. One needs to add a small python module into PyQt4 installation, then during pyuic4 run, the module will be checked (using a simple interface) whether it supports custom widgets of a given type - if it does, it provides name of the module for import. PyKDE4 uses this functionality, for example. On my Ubuntu installation the directory is /usr/lib/python2.7/dist-packages/PyQt4/uic/widget-plugins. It will require probably a bit of poking to find out how exactly to do that, the documentation is non-existent, one has to look at existing files in that directory and probably a bit into pyuic4 code (not a big thing really).

maplayercombobox:

  • use filters() instead of getFilters() to stay consistent

scalevisibilitywidget:

  • trick with showEvent() - generally not a good idea. isn't it possible to put that code into constructor? If necessary, should be protected
  • looks like sometimes we use "scale" for scale denominator and sometimes for scale - nothing to improve in this PR, just complaining :)
  • minimumScale(), maximumScale() should not be slots
  • setFromLayer() - instead of this I would propose setScaleRange(min, max) which is more generic and does not depend on QgsMapLayer
  • for such simple widget it would be nicer to build the widget's children and layout directly in the cpp code instead of using .ui file and generating ui header file for it
  • it would be good to use it also in: 1. raster layer dialog, 2. "rule properties" dialog for rule-based renderer
  • maybe "scale range" widget would be better term?

@timlinux
Copy link
Member

timlinux commented May 6, 2014

Nice stuff Denis! I think one of @timlinux dreams will soon come true, he has hoped for this for years! :-) The possibility to have useful QGIS widgets directly in designer will make the design of dialogs much easier.

Yeah! Soon the day will come when I can open designer, drop in a legend widget, a map canvas widget and a navigation toolbar widget and then write a few lines of python to add some layers and then smile broadly for 7 weeks :-)

the way how the imports are done for python (with changes to sys.modules on load of qgis module) does not look very good to me. It should be possible to use pyuic's widget plugins feature. The functionality is very poorly documented, but that should solve the import problem in a much nicer way. One needs to add a small python module into PyQt4 installation, then during pyuic4 run, the module will be checked (using a simple interface) whether it supports custom widgets of a given type - if it does, it provides name of the module for import. PyKDE4 uses this functionality, for example. On my Ubuntu installation the directory is /usr/lib/python2.7/dist-packages/PyQt4/uic/widget-plugins.

Any other ways to manage this? I have 4 different versions of QGIS installed under /usr/local/qgis-<version> and it would be nice to not have to pollute my global python package dir with stuff from from one specific QGIS version. I guess in my case I could set PYTHONPATH before launching designer, pointing to an independent package dir?

@3nids I love what you are doing here - rock on!

@3nids
Copy link
Member Author

3nids commented May 7, 2014

@wonder-sk thanks a lot for this detailed review, I will come back ASAP with a reworked PR!
@timlinux thanks a lot! I hope it'll be merged in 2.4!

@wonder-sk
Copy link
Member

Any other ways to manage this? I have 4 different versions of QGIS
installed under /usr/local/qgis- and it would be nice to not
have to pollute my global python package dir with stuff from from one
specific QGIS version. I guess in my case I could set PYTHONPATH before
launching designer, pointing to an independent package dir?

@timlinux that is my concern, too - but the module should be pretty much
independent from any particular QGIS version and only few lines of code -
basically just saying that any classes coming from Qt Designer and being
present in qgis.gui module shall be imported from qgis.gui module.

But this thing only relates to pyuic4. There is another, broader issue with
multiple versions of QGIS and Qt plugins they provide: each QGIS version
tries to copy 'its' Qt plugins to the global Qt plugins directory (e.g.
/usr/lib/qt4/plugins), so individual versions of QGIS will replace the
plugin files of previous installation, and that's not very nice. I believe
you will also need to setup LD_LIBRARY_PATH towards the correct QGIS
version before starting Qt Designer in order to have it working (the
plugins link to qgis_core / qgis_gui libraries). I think ideally the Qt
plugins should be inside QGIS installation, so they will not interfere with
the rest of the system. But for running Qt Designer it means that you would
need to update QT_PLUGIN_PATH variable to include a directory inside QGIS
installation in order to have access to the widgets. Hope that makes some
sense...

@3nids
Copy link
Member Author

3nids commented May 8, 2014

I fixed issues you reported.
A few remarks:

  • Python support: now a specific module is added to the widget-plugins of PyQt4/uic package. It works nicely on ubuntu. I also added QgsMapLayerProxyModel to the module, so it knows where to look for settings the filter flags (kudos to @m-kuhn).
  • QgsScaleRangeWidget::showEvent: I replaced it by a reloadProjectScales method
  • On ubuntu 14.04, widgets are properly integrated in standalone QtDesigner, but not in the designer within QtCreator. I believe the problem is that Qt Creator 3 was built under Qt5, and its designer search for plugins in lib/qt5. I tried to copy the Qt4 custom widget lib, and the integrated designer finds it, but it fails at loading it. As far as I see it, I can see only 2 solutions:
    1. build your own QtCreator under Qt4
    2. use standalone QtDesiner built under Qt4
  • I did not test under win/mac, it would be cool if someone could give it a try!

@NathanW2
Copy link
Member

NathanW2 commented May 8, 2014

Nice! This will be bloody handy.

On Fri, May 9, 2014 at 12:50 AM, Denis Rouzaud notifications@github.comwrote:

I fixed issues you reported.
A few remarks:

Python support: now a specific module is added to the widget-plugins
of PyQt4/uic package. It works nicely on ubuntu. I also added
QgsMapLayerProxyModel to the module, so it knows where to look for settings
the filter flags (kudos to @m-kuhn https://github.com/m-kuhn).
-

On ubuntu 14.04, widgets are properly integrated in standalone
QtDesigner, but not in the designer within QtCreator. No idea why. It was
working on ubuntu 13.10.

QgsScaleRangeWidget::showEvent: I need to keep, because I can't know
otherwise when the project settings change.

I did not tested under win/mac, it would be cool if someone could give
it a try!


Reply to this email directly or view it on GitHubhttps://github.com//pull/1325#issuecomment-42559048
.

ENDIF (NOT ANDROID)

# make sure that UI files will be processed first
ADD_DEPENDENCIES(qgis_customwidgets ui)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • no need to install headers
  • no need for dependency on ui target anymore
  • actually no need to build for android at all - there is no designer AFAIK
  • no need for QGIS_CUSTOMWIDGETS_UI_HDRS
  • no need for ${CMAKE_CURRENT_BINARY_DIR}/../ui in INCLUDE_DIRECTORIES
  • no need for PUBLIC_HEADER in INSTALL(TARGETS ...)

@wonder-sk
Copy link
Member

Regarding Qt Creator - yes if the creator is built with Qt5 it will likely not accept Qt4 plugins. In addition to the options you give it should be possible to use older version of Creator (< 2.8 I believe) where its binaries were still built with Qt4.

@3nids
Copy link
Member Author

3nids commented May 12, 2014

thanks again, and again ;)

Last 3 commits should fix your remarks.

For the uic packages, I sticked to MODULE and not CW_FILTER because it was not working with QgsMapLayerComboBox which uses flags (QgsMapLayerProxyModel::Filters). But it does compiles using MODULE. There is virtually no documentation at all on this, I am moving in the dark...

I left UI related lines commented in the CMakeList as I am pretty sure they'll be back one day. OK, for you?

I hope we're getting closer ;)

3nids added a commit that referenced this pull request May 19, 2014
QGIS custom widgets plugins for Qt Designer
@3nids 3nids merged commit a5b77b9 into qgis:master May 19, 2014
@3nids 3nids deleted the qtdesignerplugin branch May 19, 2014 06:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants