Can I emit signal from a public function?



  • Hello,
    I have a simple GUI that must show and hide. I`ve made the following definitions:
    @
    void* doSomething2(void*);

    class SimpleGUI : QObject {
    Q_OBJECT

    public:
    SimpleGUI(QApplication* , int, char**);
    ~SimpleGUI();
    bool isActive;
    QWidget* getWindow();
    signals:
    void showWindow();
    private slots:
    void doSomething(void);

    void callDirwalk(void);
    void activate();
    void deactivate();
    void printDiagnostics();
    

    private:
    FILE* fp;
    SimpleGUI();
    SimpleGUI* self ;

    QApplication* qapp;
    QWidget* window;
    QPushButton *yes;
    QPushButton *no;
    QTextEdit *text;
    QString fname;
    

    public:
    static int argc;
    static char** argv;
    private:
    int w;
    int h;
    unsigned long timeSleep;
    QHBoxLayout* align;
    QVBoxLayout* textLay ;
    QVBoxLayout buttonsLay;
    QVBoxLayout
    qvb;
    void* doSth(void*);

    public:
    void showApp();
    void hideApp();
    };
    @

    The idea is that I connect the slots this way:

    @
    QObject::connect(no, SIGNAL(clicked()), window, SLOT(hide()) );
    QObject::connect(this, SIGNAL(showWindow()), window, SLOT(show()) );
    @
    And from the SimpleGUI pointer, lets say spl->showApp(), the showApp body emits showWindow() signal, so this should work. But qtcreator gives me a build error: @ /home/ilian/QT5/build-SampleGame-Desktop_Qt_5_3_0_GCC_32bit-Debug/moc_SimpleGUI.cpp:147: error: multiple definition ofSimpleGUI::showWindow()'
    @
    no idea really... I am quite new in Qt but I am following the examples, and I don`t get why I am having this error. These are the last lines of moc:
    @
    // SIGNAL 0
    void SimpleGUI::showWindow()
    {
    QMetaObject::activate(this, &staticMetaObject, 0, 0);
    }
    QT_END_MOC_NAMESPACE

    @


  • Lifetime Qt Champion

    Hi,

    You didn't implement showWindow did you ?



  • void showWindow(); is signal. Signals should not be implemented by you(programmer). So go to your cpp file and remove the showWindow(...) implementation. Then it should go fine.



  • Oh, I did... OK, that fixed the qtcreator error report. But still leaves me the question - consider this code:
    @
    /* somewherer in a separate main() */
    startTime = endTime = time(NULL);
    int qtstarted = initQtApp(spl, argc, argv);

    while ( 1 ) {
        sleep(1);
        if ( endTime - startTime > (5) ) {
            char buff[512]="";
            spl->showApp();
            sprintf(buff, "%d is time difference\n",
                    endTime - startTime);
            writeToFile(buff, LOGOTHER, "a+");
        }
        else {
            endTime = time(NULL);
        }
    }
    

    /* ------------------------- /
    int initQtApp(SimpleGUI
    spl, int argc, char* argv[]) {
    QApplication* app= new QApplication(argc, argv);
    if ( spl == NULL) spl = new SimpleGUI(app, argc, argv);
    char buff[256]="";
    sprintf(buff,"App created in %p, SimpleGUI in %p\n", app, spl);
    writeToFile(buff, LOGOTHER, "a+");
    return app->exec();
    }
    @
    In SimpleGUI.cpp:
    @
    ...
    void SimpleGUI::showApp() {
    emit showWindow();
    }
    @
    in constructor:
    @
    ...
    QObject::connect(this, SIGNAL(showWindow()),
    window, SLOT(show()) );
    @
    when the time is reached, spl->showApp() does nothing...
    [quote author="SGaist" date="1410948603"]Hi,

    You didn't implement showWindow did you ?[/quote]



  • what is it supposed to do ? What is the implementation of showApp ? That should help to answer your qn.



  • I`ve update my previous poll with showApp() implementation and QObject::connect to the window and my app. showApp() emits showWinodw() signal, which is connected to window SLOT(show()). See my prev post.



  • @QObject::connect(this, SIGNAL(showWindow()), window, SLOT(show()) );@

    When the signal showWindow().. happens, it should show the 'window' widget. When the signal is emitted what is the status of 'window'. Is it shown already somewhere ?

    In order to check that, it really working, you can try with following.

    QPushButton *button = new QPushButton("Showme");
    QObject::connect(this, SIGNAL(showWindow()), button, SLOT(show()) )

    See what happens. If this is working, you must some logic issue in your program.

    1. There must be some logic issue
    2. 'window' object may have parent and parent is already shown.


  • No, Ive never showed the window. The constructor, just connects, signals, prepares buttons, texts, etc. Then does nothing. Ive edited the while(1) loop to wait 2 sec then call spl->showApp() without conditions, and it never shows.
    [quote author="Dheerendra" date="1410955300"]@QObject::connect(this, SIGNAL(showWindow()), window, SLOT(show()) );@

    When the signal showWindow().. happens, it should show the 'window' widget. When the signal is emitted what is the status of 'window'. Is it shown already somewhere ?

    In order to check that, it really working, you can try with following.

    QPushButton *button = new QPushButton("Showme");
    QObject::connect(this, SIGNAL(showWindow()), button, SLOT(show()) )

    See what happens. If this is working, you must some logic issue in your program.

    1. There must be some logic issue
    2. 'window' object may have parent and parent is already shown.

    [/quote]



  • As far as I am getting any progress, it appears, that showApp() must appear before app->exec() function, otherwise it does not work. However, this makes writing the app to be called from a UNIX daemon hard. How exactly to handle this exec() problem? I just want my GUI to show in fixed intervals.



  • Did you try with pushbutton example I gave you ? Did it show pushbutton ? Also can you show me the piece of code where you are creating window object ?



  • Yes, the SIGNAL/SLOT is working, I`ve tried it out. But it appeared that everything must happen in oreder and finishes with app->exec(). Here is my code in the while(1) loop, it works only one time, it shows the app jsut once. Once I press the PRINT TO LOG BUTTON, which is connected to window SLOT(hide()), it never appears
    @
    time_t startTime ;
    time_t endTime ;
    startTime = endTime = time(NULL);
    SimpleGUI* spl = NULL;
    while (1) {
    sleep(2);
    if ( endTime - startTime > (2) ) {
    char buff[512]="";
    sprintf(buff, "%d is time difference\n",
    endTime - startTime);
    writeToFile(buff, LOGOTHER, "a+");
    int qtstarted = initQtApp(spl, argc, argv);
    }
    else {
    endTime = time(NULL);
    }
    }
    ...
    int initQtApp(SimpleGUI* sp, int argc, char* argv[]) {
    QApplication* qapp= new QApplication(argc, argv);
    if ( sp != NULL ) sp->showApp();
    else {
    sp = new SimpleGUI(qapp, argc, argv);
    sp->showApp();
    }
    char buff[256]="";
    sprintf(buff,"App created in %p, SimpleGUI in %p\n", qapp, sp);
    writeToFile(buff, LOGOTHER, "a+");
    return qapp->exec();
    }
    @
    initQtApp simulates a main()
    And here is the constcution of the SimpleGUI, only the important part:
    @
    SimpleGUI::SimpleGUI(QApplication* app, int args, char** argvs)
    : qapp(app) {
    isActive = true;
    window = new QWidget;
    yes = new QPushButton("STOP DAEMON");
    no = new QPushButton("PRINT TO LOG FILE");
    buttonsLay = new QVBoxLayout;
    textLay = new QVBoxLayout;
    qvb = new QVBoxLayout;
    align = new QHBoxLayout;
    text = new QTextEdit("TEST FOR TEXT AREA");
    text->setEnabled(false);
    text->setMaximumHeight(200);
    text->setMaximumWidth(200);
    text->setMinimumHeight(200);
    text->setMinimumWidth(200);

    window->setMinimumHeight(320);
    window->setMaximumHeight(320);
    window->setMinimumWidth(320);
    window->setMaximumWidth(320);
    
    yes->setMinimumWidth(200);
    yes->setMaximumWidth(200);
    no->setMinimumWidth(200);
    no->setMaximumWidth(200);
    
    textLay->addWidget(text);
    buttonsLay->addWidget(yes);
    buttonsLay->addWidget(no);
    
    qvb->addLayout(textLay);
    qvb->addLayout(buttonsLay);
    
    align->addLayout(qvb);
    window->setLayout(align);
    
    SimpleGUI::argc = args;
    SimpleGUI::argv = argvs;
    QObject::connect(this, SIGNAL(showWindow()),
                     window, SLOT(show()));
    QObject::connect(no, SIGNAL(clicked()),
                     this, SLOT(callDirwalk()) );
    QObject::connect(no, SIGNAL(clicked()),
                     window, SLOT(hide())) ;
    //[1] ok - stops daemon
    QObject::connect(yes, SIGNAL(clicked()),
                     this, SLOT(deactivate()) );
    

    }
    QWidget* SimpleGUI::getWindow() {
    return window;
    }

    void SimpleGUI::callDirwalk() {
    //thread main()
    writeToFile("Called dirwalk on separate thread\n", LOGOTHER, "a+");
    pthread_t t;
    int res =0;
    res = pthread_create(&t, NULL, doSomething2, NULL);

    }

    void SimpleGUI::activate() {

    }
    void SimpleGUI::deactivate() {
    delete this;
    }
    void SimpleGUI::printDiagnostics() {

    }
    void SimpleGUI::showApp() {
    emit this->showWindow();
    }
    void SimpleGUI::hideApp() {
    window->hide();
    }

    void SimpleGUI::doSomething() {
    delete this;
    QObject::connect(qapp, SIGNAL(aboutToQuit()),
    qapp, SLOT(quit()) );
    //

    }

    @
    [quote author="Dheerendra" date="1410958444"]Did you try with pushbutton example I gave you ? Did it show pushbutton ? Also can you show me the piece of code where you are creating window object ?[/quote]



  • Another thing, when I press windows X on the frame, it reappears again, but globs memory as much as I close it from X. Ive tried to make some instances static, but it does nothing at all... Just to tell you that my log file says:
    @
    App created in 0x96807d8, SimpleGUI in 0x9783f20

    App created in 0x96807d8, SimpleGUI in 0x97cf758

    4 is time difference

    App created in 0x96807d8, SimpleGUI in 0x97e5320

    4 is time difference

    App created in 0x96807d8, SimpleGUI in 0x97f0d00

    4 is time difference

    App created in 0x96807d8, SimpleGUI in 0x9800e80

    4 is time difference

    App created in 0x96807d8, SimpleGUI in 0x98077f8

    4 is time difference

    App created in 0x96807d8, SimpleGUI in 0x980dcb8

    4 is time difference

    App created in 0x96807d8, SimpleGUI in 0x9813978

    4 is time difference

    App created in 0x96807d8, SimpleGUI in 0x981a6f8

    4 is time difference

    App created in 0x96807d8, SimpleGUI in 0x9824fd0

    4 is time difference

    App created in 0x96807d8, SimpleGUI in 0x982b618

    4 is time difference

    App created in 0x96807d8, SimpleGUI in 0x9831c30

    App terminated

    App created in 0x93ad7d8, SimpleGUI in 0x94b0f98

    App created in 0x9462210, SimpleGUI in 0x94fc8d0

    5 is time difference

    App created in 0x94fc6f0, SimpleGUI in 0x951cdb8

    5 is time difference

    App created in 0x95138a0, SimpleGUI in 0x951cf78

    App terminated

    @
    If initQtApp() has non-static QApplication variable, if its static Apps address is constant, just SimpleGUI changes. But the previous GUI is not freed properly and task manager reports increase in MB needed for the program ... :(


  • Lifetime Qt Champion

    Your code is pretty convoluted for what seems to be a simple task. Can you tell us what exactly would you like to achieve ?



  • Yes. I am starting a daemon in linux. In fixed intervals, I want it do display an UI in Qt. The UI is responsible to call 3 special functions, all involving an iteration in a list ( as stack ). The 3 functions are Qt independant in pure C. It`s a directory walk, which puts all filenames and dir names in a linked list. Then, depending on the callback, you can either print directories/files, delete them, or crypt them. I tough it will be as simple as that, but ... here I am stuck here.



  • I`ve made this in Java with a new thread which sleeps for N time, then shows the frame, the user click just hides it... Simple. But I want this app to be different. The UI must be versatile, either Qt, either GTK, maybe JUCE++. So I want logics to be separate from the UI. I am saying it because, many would suggest that I have to do it in pure Qt.


  • Lifetime Qt Champion

    If you want to write a real daemon, then don't put GUI code in it. A daemon doesn't have a GUI.

    Completely separate both and use e.g. D-Bus or another RPC to communicated with your daemon.



  • This is not what I wanted to hear. I can simply put a sleep in GUI constructor or method, then just emit show - hide. Its simple and tested, however, I wanted that kind of behaviour, and almost achieved it, but it appears my old code with recreation of Qt app will be added :( Too bad its not as simple as just show hide.
    [quote author="SGaist" date="1411025456"]If you want to write a real daemon, then don't put GUI code in it. A daemon doesn't have a GUI.

    Completely separate both and use e.g. D-Bus or another RPC to communicated with your daemon.[/quote]


  • Lifetime Qt Champion

    Then don't make it a daemon. Just to be sure we understand each other, a thread running in the background doesn't qualify as daemon.

    Have a look at QThread's documentation and the worker object part. You can couple that with e.g. a QTimer and then you have your function called at regular interval done in a thread.



  • Yes, Ive figured it out... The java thing Ive made... A sleeping thread with show/hide. OK, since I am not the type that will just walk aside Ive came with a solution, just a bit messy but, worked like a charm. Here is the daemon infinite loop: @ qapp = new QApplication(argc, argv); while (1) { do { sleep(1); initQtApp(NULL, argc, argv, 0); /* ok logic */ if ( endTime - startTime > (5) ) { char buff[512]=""; sprintf(buff, "%d is time difference\n", endTime - startTime); writeToFile(buff, LOGOTHER, "a+"); } else { endTime = time(NULL); } } while ( qapp->exec() == 0); } @ Now... qapp is global static variable. initQtApp() has local SimpleGUI pointer that is recreated everytime. Ive figured out that app->exec() will behave for the SimpleGUI associated with. So my log file says:
    @
    App created in 0x95207d8, SimpleGUI in 0x962f0d8
    8 is time difference
    -1 is isRunning now
    App terminated
    App created in 0x95207d8, SimpleGUI in 0x9677820
    8 is time difference
    Called dirwalk on separate thread
    Called a separate thread foo()
    CREATED:2014:09:18:14:28:46
    App created in 0x95207d8, SimpleGUI in 0x967a000
    8 is time difference
    Called dirwalk on separate thread
    Called a separate thread foo()
    @
    Pressing the STOP DAEMON just calls a SLOT that simply deletes window, textframe and the 2 buttons, nothing much, also reports some variables for the daemon shared with get/set functions, since they are static. This loop is not final one, but somehow manages to create a new GUI in every second, then wait, and when I destroy it, it just recreates it. TODO is to connect the right signals and slots to the coresponding buttons, and one question actually - can I disable the X button close function? It behaves right now, since close destroys the window, and daemon recreates it but still...
    [quote author="SGaist" date="1411033968"]Then don't make it a daemon. Just to be sure we understand each other, a thread running in the background doesn't qualify as daemon.

    Have a look at QThread's documentation and the worker object part. You can couple that with e.g. a QTimer and then you have your function called at regular interval done in a thread.[/quote]


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.