PDA

View Full Version : A list for storing member functions/slots?



Akiva
14th September 2013, 16:18
I apologize before hand for asking what I am sure is a very noobish question, but after looking around google for hours, I just can't figure out how to find an answer to my question, nor where to start looking in c++ documentation. My suspicion is that it has to do with my ignorance towards function pointers.

Now, something like this makes sense to me:

.h snippet

QList<QToolButton *> *list_Button;
QToolButton *card_AbandonedMine;


.cpp snippet

card_AbandonedMine=new QToolButton;
list_Button->append(card_AbandonedMine);


which I might make a loop like this:

void DominionLinux::createCards()
{
for( int i = 0; i < list.size(); i++ )
{
list_Button->at(i)->setCheckable(true);
}
}
That all works perfectly, and my hope is that I can also add function slots into this. The reason I can't use just one type of function, is because each slot has unique arguments.

Now as far as creating some sort of list, I have tried applying the same principle to a member function/slot, but the closest I have come is for my program to run, but then unexpectantly crash. I went in with basically the same mindset:

.h snippet

QList<void *> *list_Slots;
private slot:
void *SLOTcard_AbandonedMine(bool Checked=false, bool matchOpponent=false);;


.cpp snippet

void* DominionLinux::SLOTcard_AbandonedMine(bool Checked, bool TryMatchOpponent)
{
if (Checked == true)
{
ui->verticalLayout_Enabled->addWidget(card_AbandonedMine);
}
else if (Checked == false)
{
ui->verticalLayout_Disabled->addWidget(card_AbandonedMine);
}

}

void DominionLinux::createList()
{
connect(card_AbandonedMine,SIGNAL(toggled(bool)), this, SLOT(SLOTcard_AbandonedMine(bool)));
list_Slots->append(SLOTcard_AbandonedMine(false,false)); // If I disable this line, my program will work fine
}


And it stops with this message:

The inferior stopped because it received a signal from the Operating System.

Signal name :
SIGSEGV
Signal meaning :
Segmentation fault

and this is the output

g++ -o DominionLinux main.o DominionLinux.o qrc_cards.o moc_DominionLinux.o -lQt5Widgets -L/usr/lib/i386-linux-gnu -lQt5Network -lQt5Gui -lQt5Core -lGL -lpthread
{ test -n "" && DESTDIR="" || DESTDIR=.; } && test $(gdb --version | sed -e 's,[^0-9]\+\([0-9]\)\.\([0-9]\).*,\1\2,;q') -gt 72 && gdb --nx --batch --quiet -ex 'set confirm off' -ex "save gdb-index $DESTDIR" -ex quit 'DominionLinux' && test -f DominionLinux.gdb-index && objcopy --add-section '.gdb_index=DominionLinux.gdb-index' --set-section-flags '.gdb_index=readonly' 'DominionLinux' 'DominionLinux' && rm -f DominionLinux.gdb-index || true
08:08:12: The process "/usr/bin/make" exited normally.
08:08:13: Elapsed time: 00:07.

All I really want is just a very base and simple example of how to make some sort of list for a function/ member function/ slot (if there is a difference), so I can call it in an iterator loop.

Hope this made sense~ Thanks in advance.

wysota
14th September 2013, 17:32
What is the type of list_Slots?

Akiva
14th September 2013, 17:54
Ah sorry, that was a typo of mine when I was pasting the example code. The first line should read,
QList<void *> *list_Slots;

wysota
14th September 2013, 18:19
Why a pointer to a list? Did you initialize the pointer with an object? And why void*?

Akiva
14th September 2013, 18:39
From who I asked, and from what I read, I got the idea that <void*> was a way to accomplish this. Someone on IRC said that I could do it with old school function pointers, and typed out "void *". I did a google search for "QList<Void*> ...." and found some results, so I sheepishly tried to emulate it. Mind you I didnt find much code, and I really did not know where to search and find an answer. All the code relating to my attempt was posted above; I didnt initialize it with any object.

Believe me; I am happy to scrap my existing code if some one can just give me a simple example of the way to do this.

wysota
14th September 2013, 20:23
Using void* is practically an error in C++. I don't know what you need those pointers for but most probably you should rather have some common base class for the objects you return and store that in the list. And I still don't know if you initialized the list pointer or not. It's very uncommon to have a pointer to a QList.

ChrisW67
14th September 2013, 21:49
Ignoring for a moment how you want to achieve it could you please explain what you are trying to achieve? For what purpose do you want this list of actions? To use a Perl idiom "there's more than one way to do it" but not all options are elegant or the first thing you think of.

Akiva
14th September 2013, 21:52
So I should make a new class, fill it with my 200 some odd slots, create 200 some odd objects, and append them to QList<myclass*>?

Edit:
Sorry, didnt see ninja post

What I am trying to accomplish is simple:

I have 215 QToolbuttons, and each one of them has a unique function. To make things simple, I would like to define the basic properties and instructions of the QToolbuttons by using an iterating "for" loop.

wysota
14th September 2013, 22:19
I have 215 QToolbuttons, and each one of them has a unique function. To make things simple, I would like to define the basic properties and instructions of the QToolbuttons by using an iterating "for" loop.

And how is storing a void* result of some slot call going to help with that?

Akiva
14th September 2013, 23:08
I already gave you an answer to that question; it was based on sheer ignorance, and a suggestion from #Qt. As said, I went ahead and failed, and tried to search for an answer to my question, but was not able to pinpoint an answer. That is why I have come to the beginners section of this QT forum to ask for some basic guidance. I should reiterate that I have no investment in maintaining my current code if it is simply incorrect, and I can not tell if you honestly are curious as to whether there is a way to use QList<void*> in order to accomplish my goal, or whether it is a rhetorical question aimed to berate me for my ignorance towards function pointers. Either way, what is important to me is to first have a working example, to which I can then use as an educational tool.

Therefore what would be most helpful to me in my opinion is for a kind individual to volunteer a very basic example, including how to prototype the slot and the list into a header, how to declare/define/write it in the source, and then how to append the slot into the list. There is obviously no obligation for anyone to do that, but I hold out hope that someone does not mind to do so.

wysota
14th September 2013, 23:31
The problem is we still don't know what you are trying to do. Vague descriptions about "basic properties and instructions" are of little help. So far I only know that you have a slot declared to return void* that doesn't return anything that you call and try to store the unreturned return value in a list that's supposedly uninitialized. I can't see any attempt to use any for loop in your code thus I have no idea what you are trying to do, what you already tried, etc. It would be really helpful if you restated your problem in a clear and comprehensive way, possibly backed by an example.

Just to be clear -- I don't see any "function pointer" in your code. The only pointers I see are a pointer to a list that itself holds pointers to "something". If by the following code:

list.append(someFunc(param1, param2));
you thought you were appending a function pointer to a list then you were wrong. someFunc(param1, param2) is a function invocation, and not a function pointer. The latter is someFunc which I already told you a couple of posts ago.

Still no idea what it has to do with your problem, whatever it is.

Akiva
15th September 2013, 00:50
Thank you for your honest reply.

You are right to point out that my terminology could be more concise, and I greatly appreciate it, despite any apparent frustration on my part. It forces me to elevate my venacular, and become a better programmer.

By "Basic Properties" I merely meant to do the same thing as what QtDesigner's "Property Editor" does. For example, the property editor will allow you to set the maximum and minimum sizes of most QWidgets, as well as some other things. I am not sure what other term to use besides "Properties".
By instructions, I merely meant to reference any various signals or slots pertaining to the QToolButton, and in my case, the task of connecting my signals to my slots. My use of the term "Instructions" must clearly be wrong, so I apologize.

I'll try to be even more concise with my example. All I want to accomplish is this:


ListOfSlots->append(NameOfSomeSlot());
ListOfButtons->append(NameOfSomeButton)

for( int i = 0; i < ListOfSlots.size(); i++ )
{
connect(ListOfButtons->at(i),SIGNAL(clicked()), this, SLOT(ListOfSlots->at(i)()));
}

I really appreciate your patience in all of this.

wysota
15th September 2013, 01:17
To me what you want to accomplish will not make your code shorter as you still have to add all those slot names to the list, but here you go:


QList<const char*> slotList;
slotList << SLOT(slot1());
slotList << SLOT(slot2());
// ...

for(int i=0; i< listOfButtons.size();++i) {
connect(listOfButtons->at(i), SIGNAL(clicked()), this, slotList.at(i));
}

Having said that I have to admit it all makes little sense to me. I'm assuming you are programming some kind of game (possibly a board game?) and you are using all those buttons for some kind of fields or pieces. In my opinion a much better approach would be to use Graphics View or at least to use a QSignalMapper and connect all your buttons to a single slot keyed by the button id.

Akiva
15th September 2013, 03:00
Ha, you are right about a few things there, especially about having to add all all these to a list partially defeating the purpose of such a loop. Despite this, we have our reasons to do this. One such reason is to easily change the signal and perhaps add some more later. For what its worth, here is our: project https://launchpad.net/dominion.linux

So you were quite on target with the board game suspicion.

Anyway, I will look at the Signal Mapper for sure; There is always so much to learn!

ChrisW67
15th September 2013, 04:33
Since each QToolButton is a QObject you already have a generic way to get/set any declared property of the button without knowing the specific class of the button: QObject::property() and QObject::setProperty(). You can access information on available properties through the QMetaObject of the QToolButton.

If all the tool buttons belong to a single parent object then you can access them using the child list of the parent using QObject::findChildren() without necessarily maintanng a separate list.

Have a think about how these functions might be useful to you.

anda_skoa
15th September 2013, 11:56
Good suggestion Chris.

Additional to that all buttons could connect to the same slot, QObject::sender() could be used to retrieve the button and then QObject::property() could be used to extract the respective parameters.

Of, if all buttons have the same types of parameters but just different values, create a QToolButton subclass that has methods for those and cast QObject::sender() to that class and call the getters directly.

Another option would be to have separate receiver objects, one for each button. Each such instance would get its individual parameters upon construction, thus not needing any in the slot.

e.g.


class ButtonReceiver : public QObject
{
Q_OBJECT
public:
ButtonReceiver( /* parameter */, QObject *parent = 0);

public slots:
void onButtonClicked();
};




QList<ButtonReceiver*> receiverList;




for (int i = 0; i < buttonList; ++i) {
connect(buttonList[i], SIGNAL(clicked()), receiverList[i], SLOT(onButtonClicked()));
}


Cheers,
_

wysota
16th September 2013, 03:20
I have taken a look at the code in the repository mentioned by OP. The code there contains a couple hundred of practically identical slots generated by some external python tool.