PDA

View Full Version : Deleting and disabling properties in designer for custom plugins...



thawkins
22nd March 2007, 01:25
I have a custom plugin that does exactly what I want for it to do in designer. Part of its design is that it has set sizes that I control from an enum of sizes accessed in the property editor of designer with Q_PROPERTY(). All of that works, no problemo. My question(s) are:

1. Is there a way to "gray out" options that are not in use in the property editor. For instance, I have an enum in my plugin that places a particular icon on my plugin, one of them being a text field that the user can input and have displayed on the widget. I'd like to set it up so that if the enum is set to something other than "use text for the plugin" value, the text entry line I made is grayed out and unusable (I actually programatically block changing that field now by playing with the set() method associated with that property, but would like something more elegant looking).

2. Is there any way to completely delete some of the built in properties for a widget from showing up on the designer property editor? My custom plugin described above is derived from QPushButton. Like I mentioned, I have set sizes that are controlled via an enum accessed via Q_PROPERTY(). I would like to be ale to delete (or hide if nothing else) all of the size and other unwanted properties that are listed under the QPushButton part of the property editor pane.

Any help would be appreciated.

wysota
22nd March 2007, 02:18
Ad 1. Try using the Q_PROPERTY macro with DESIGNABLE option set to false, it should make the property invisible in Designer. If you want something more complicated (like being able to enable/disable a property on a temporary basis), you'll need to access the property browser from within your Designer plugin like this:


QDesignerFormWindowInterface *form = QDesignerFormWindowInterface::findFormWindow(mywid get);
if(form){
QDesignerFormEditorInterface *editor = form->core();
QExtensionManager *manager = editor->extensionManager();
QDesignerPropertySheetExtension *sheet;
sheet = qt_extension<QDesignerPropertySheetExtension*>(manager, mywidget);
int propertyIndex = sheet->indexOf(propName);
sheet->setVisible(propertyIndex, false); // or true if you want to make it visible again
}
where "mywidget" is the widget you want to manipulate the property for. You can implement it in a slot connected to a signal informing about a property change (there is such a signal in QDesignerPropertyEditorInterface).

Ad 2. You can do it the same way as described above (try using "DESIGNABLE false" first).

thawkins
22nd March 2007, 17:41
Ad 1. Try using the Q_PROPERTY macro with DESIGNABLE option set to false, it should make the property invisible in Designer. If you want something more complicated (like being able to enable/disable a property on a temporary basis), you'll need to access the property browser from within your Designer plugin like this:


QDesignerFormWindowInterface *form = QDesignerFormWindowInterface::findFormWindow(mywid get);
if(form){
QDesignerFormEditorInterface *editor = form->core();
QExtensionManager *manager = editor->extensionManager();
QDesignerPropertySheetExtension *sheet;
sheet = qt_extension<QDesignerPropertySheetExtension*>(manager, mywidget);
int propertyIndex = sheet->indexOf(propName);
sheet->setVisible(propertyIndex, false); // or true if you want to make it visible again
}
where "mywidget" is the widget you want to manipulate the property for. You can implement it in a slot connected to a signal informing about a property change (there is such a signal in QDesignerPropertyEditorInterface).


OK, I see exactly what you are talking about. I'm still having a few issues. I implemented the following function, using the code above as a template:



//================================================== ===================
// METHOD : setPropertyEditorItems()
//
// DESCRIPTION:
// Used by plugins in order to hide/show specific property editor properties
//
// PRECONDITIONS:
// A valid list of properties
//
// POSTCONDITIONS:
// NONE
//
// EXCEPTIONS:
// NONE
//
// PARAMETERS:
// pTheWidget: A Pointer to the widget whos properties in designer are to be updated
// QStringListToChange: the QStringList list of the names of property editor properties to hide or show
// bShowProperties: A bool, when true, will show the properties in QStringListToHide, when false will hide them
//
// RETURN VALUE:
// True if able to complete operation, false otherwise
//================================================== ===================
bool setPropertyEditorItems(QWidget *pTheWidget, QStringList QStringListToChange, bool bShowProperties)
{
bool bRetVal = false;
int iLoopVal, iPropertyIndex;
QDesignerFormWindowInterface *pFormWindow = 0;

// attempting to get a pointer to the property editor control methods
pFormWindow = QDesignerFormWindowInterface::findFormWindow(pTheW idget);
if (pFormWindow && false == QStringListToChange.isEmpty())
{
bRetVal = true;

QDesignerFormEditorInterface *pFormEditor = pFormWindow->core();
QExtensionManager *pExtensionManager = pFormEditor->extensionManager();
QDesignerPropertySheetExtension *pPropertySheet;
pPropertySheet = qt_extension<QDesignerPropertySheetExtension*>(pExtensionManager, pTheWidget);

// now traversing our list and setting the properties accordingly
for (iLoopVal = 0; iLoopVal < QStringListToChange.size(); iLoopVal++)
{
iPropertyIndex = pPropertySheet->indexOf(QStringListToChange[iLoopVal]);
std::cout << "Found index of " << iPropertyIndex << " for string " << QStringListToChange[iLoopVal].toStdString() << std::endl;
std::cout << "Setting value to " << bShowProperties << std::endl;
pPropertySheet->setVisible(iPropertyIndex, bShowProperties);
}
}

// reporting the results of the operation
return bRetVal;
};


For a test case, I call the method above from another object in the following way:



QString QStringListToChange;

QStringListToChange << "myfakestuff" << "geometry" << "enabled" << "sizePolicy" << "buttonSize";
setPropertyEditorItems(this, QStringListToChange, false);


This is the output I see on the terminal (running Qt 4.1.2 on linux, btw):



Found index of -1 for string myfakestuff
Setting value to 0
Found index of 4 for string geometry
Setting value to 0
Found index of 3 for string enabled
Setting value to 0
Found index of 17 for string sizePolicy
Setting value to 0
Found index of 54 for string buttonSize
Setting value to 0


So from the output I know that all the property names I am using appear to be valid (except for myfakestuff, which is not a valid name, I put it in to test what would happen). Btw buttonSize is a custom property I specified with Q_PROPERTY(). Finally, here a screenshot of what the property editor looks like AFTER I start a blank form and drag my custom widget into it. Shouldn't the properties above not be visible?

wysota
22nd March 2007, 18:18
What about using Q_PROPERTY with DESIGNABLE set to false?

About the properties being visible - maybe you need to "refresh" the property sheet somehow?

thawkins
22nd March 2007, 18:45
What about using Q_PROPERTY with DESIGNABLE set to false?

About the properties being visible - maybe you need to "refresh" the property sheet somehow?


How would you use the designable thing on native properties? (Ones you didn't create with Q_PROPERTY like baseSize and things like that). The overall "goal" is that I basically want to hide all of the other properties in the property editor except for the once that I created.

thawkins
22nd March 2007, 21:57
Well, it turns out I may have to implement some classes, which I wanted to avoid. I did some rooting around in the Qt source code for designer and found this definition for isVisible() (which is used by designer to evaluate whether to place a property in the editor box):



bool QDesignerPropertySheet::isVisible(int index) const
{
if (isAdditionalProperty(index)) {
if (isFakeLayoutProperty(index) && m_object->isWidgetType()) {
QWidget *widget = qobject_cast<QWidget*>(m_object);
return (widget->layout() != 0);
}

return m_info.value(index).visible;
}

if (isFakeProperty(index))
return true;

QMetaProperty p = meta->property(index);
return (p.isWritable() && p.isDesignable(m_object)) || m_info.value(index).visible;
}


Now, the major issue I see with this is that the last line:



return (p.isWritable() && p.isDesignable(m_object)) || m_info.value(index).visible;


Since almost all of the "default" properties shown in the property editor are both writable and designable, this means the only ones I can really control are the ones that I create, because I can make isDesignable return false.

The only other way I can see of making this work is to somehow be able to change the isDesignable value on "default" properties, which I haven't seen anything to do. That leaves me with investigating some type of solution where I develop my own class that re-implements the propertyextensionsheet, which I was trying to avoid.

wysota
22nd March 2007, 22:21
How would you use the designable thing on native properties? (Ones you didn't create with Q_PROPERTY like baseSize and things like that). The overall "goal" is that I basically want to hide all of the other properties in the property editor except for the once that I created.

"Redeclare" the property in a subclass.

thawkins
23rd March 2007, 16:17
"Redeclare" the property in a subclass.
Wysota,

That does seem to produce a result that works for me, however it seems kind of inefficient in the long term because I want to disable all of the properties for the widgets I derive from for my custom plugin in designer and I need to create multiple plugins so I wanted a generic approach that I could inherit or something for every plugin I make (as opposed to having to manually redeclare and hide the specific properties for the Qt class I am inheriting from). I will play around with the subclassing/class factory method suggested in the Qt documentation and if I figure out an elegant generic solution I will post it here. If not, at least I know that your suggestion will work, it's just that it would be a little bit more time consuming.

I can't believe no one else creating plugins have ever wanted to do something like this. Oh well, thanks for you diligent help.

wysota
23rd March 2007, 22:55
You know, I wanted to say that right in the beginning - why do you want to hide a property in Designer? This won't stop anyone from using it in code anyway, so what's the point? If you want to disable all the properties (only in Designer!) then the proper way to go is to implement a QDesignerPropertySheetExtension for your widget - this will substitute the default property browser with yours. You can specify your own properties there and handle them the way you want. Of course it won't stop anyone from calling the property methods (or QObject::setProperty()) directly from code.

thawkins
24th March 2007, 03:42
You know, I wanted to say that right in the beginning - why do you want to hide a property in Designer? This won't stop anyone from using it in code anyway, so what's the point? If you want to disable all the properties (only in Designer!) then the proper way to go is to implement a QDesignerPropertySheetExtension for your widget - this will substitute the default property browser with yours. You can specify your own properties there and handle them the way you want. Of course it won't stop anyone from calling the property methods (or QObject::setProperty()) directly from code.


I'm generating a library of custom plugins that will be used by another group (non-programmers) to lay out GUI screens. I'm not real concerned about somebody doing what you said because the intended audience will be non-programming UI designers. I really wish there was a way to add more slots that can be seen in designer, but we can't have everything. :rolleyes:

wysota
24th March 2007, 10:12
I really wish there was a way to add more slots that can be seen in designer, but we can't have everything. :rolleyes:
You mean without subclassing? What would it give a non-programmer? Anyway, you might want to take a look at this:
QDesignerMemberSheetExtension

thawkins
24th March 2007, 18:51
You mean without subclassing? What would it give a non-programmer? Anyway, you might want to take a look at this:
QDesignerMemberSheetExtension

I briefly took a look at that. I guess I got somewhat discouraged because I've searched this and a couple other forums and everyones says the same thing, that you can't have custom slots from within designer. I'm still working on getting the property sheet stuff working with QDesignerPropertySheetExtension. I'll play around with that next to see if some type of custom slots are possible by implementing my own QDesignerMemberSheetExtension.

wysota
24th March 2007, 20:49
Why would you want to allow an ui designer (the person) to create custom slots if he/she can't implement them? The problem is people treat Qt Designer as an IDE, but it's not one - it's a layout editor, you shouldn't implement any logic there. To be honest I'm surprised why Trolltech implemented writing scripts in QtScript in Designer (since 4.3), as it clearly violates their own rule of removing the editor part from Designer.

thawkins
24th March 2007, 22:04
Why would you want to allow an ui designer (the person) to create custom slots if he/she can't implement them? The problem is people treat Qt Designer as an IDE, but it's not one - it's a layout editor, you shouldn't implement any logic there. To be honest I'm surprised why Trolltech implemented writing scripts in QtScript in Designer (since 4.3), as it clearly violates their own rule of removing the editor part from Designer.

I don't think you understand, or maybe I'm not saying it right. I don't want a user to be able to create and modify a slot from scratch in Qt, merely to have slots that were defined in code visible in the slot editor in designer. I think if they went through the trouble of exposing properties and such with Q_PROPERTY(), Q_ENUM, etc, why is there no equivalent for slots and signals? That wouldn't seem to violate their rules and in fact would make designer more useful as a layout tool. As it stands now, when you develop a plugin you still have to programmatically attach any of the slots that you wrote. This takes away from the usefulness of designer for anything accept the layout of built in widgets as anything else requires further coding to work.

wysota
24th March 2007, 23:35
I don't think you understand, or maybe I'm not saying it right. I don't want a user to be able to create and modify a slot from scratch in Qt, merely to have slots that were defined in code visible in the slot editor in designer. I think if they went through the trouble of exposing properties and such with Q_PROPERTY(), Q_ENUM, etc, why is there no equivalent for slots and signals?
I think you had to make some mistake, as my custom slots are perfectly visible in Designer (screenshot attached).

thawkins
25th March 2007, 04:40
I think you had to make some mistake, as my custom slots are perfectly visible in Designer (screenshot attached).

And so it is. Mine appear to show up as well. I never looked before because I hadn't gotten a chance to play with that feature in my custom plugins and I've read so much about not having custom slots show up in designer. Oh well, just goes to show you can't take everything at face value. :o