1

I am trying to develop a user interface in Qt, which is connected to some logic. I have successfully sent signals from the logic to the user interface, but now I require to do it the other way around too. I face a QMainWindow: No such file or directory error when I try to compile the project.

I know for sure that it is a problem of including the classes to each other, and therefore I have tried to perform some forward declaration. But I have been unable to do it properly. I have tried many ways but I don't seem to achieve it.

I tried to create an empty class in the client's header file, class QTGUI; and include the qtgui.hpp only in client.cpp, and the same analogous thing with QTGUI files. What am I doing wrong?

Thank you very much in advance.


Updated CMakeLists and source codes. The original stuff is below.

Main CMakeLists

cmake_minimum_required(VERSION 2.6)
project(backendCode)

find_package(Boost COMPONENTS system)
include_directories(${Boost_INCLUDE_DIR})

SET(THREADLIBS "-lpthread -lboost_thread")

SET(FSLIBS "-lboost_filesystem -lboost_system")

add_subdirectory(gui)
add_subdirectory(server)

GUI CMakeLists: In comparison with the original code, I included the client stuff here.

cmake_minimum_required(VERSION 3.0.0 FATAL_ERROR)
project(QtGui)

set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)

find_package(Qt5Widgets REQUIRED)
find_package(Qt5Network REQUIRED)

include_directories(${Qt5Widgets_INCLUDE_DIRS})
add_definitions(${QT_DEFINITIONS})


add_executable(main main.cpp qtgui.cpp ../common/inotify.cpp 
../client/client.cpp ../common/message.cpp)
target_link_libraries(main Qt5::Widgets Qt5::Network ${Boost_LIBRARIES} 
${THREADLIBS})

QTGUI.h

#ifndef QTGUI_H
#define QTGUI_H

#include <QMainWindow>
#include <QFileSystemWatcher>

#include <boost/enable_shared_from_this.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/signals2.hpp>

#include "../common/inotify.hpp"

class Client;

namespace Ui {
class QTGUI;
}

class QTGUI : public QMainWindow
{
    Q_OBJECT

public:
...
private:
    boost::shared_ptr<Client> client_;
    Ui::QTGUI* ui;
};
#endif // QTGUI_H

QTGUI.cpp

#include "QTGUI.h"
#include "ui_qtgui.h"

#include <iostream>

#include <QHostAddress>
#include <QRegExp>
#include <QIntValidator>
#include <QFileDialog>

#include <unistd.h>
#include <pwd.h>
#include <sys/types.h>

#include "../client/client.hpp"
...

CLIENT.HPP

#ifndef CLIENT_HPP
#define CLIENT_HPP

#include <boost/asio.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/thread.hpp>

#include <boost/signals2.hpp>

#include "../common/message.hpp"

class QTGUI;

class Client : public boost::enable_shared_from_this<Client>
{
    {
        public:
        ...
        private:
        boost::shared_ptr<QTGUI> ui_;
        };

        #endif // CLIENT_H

CLIENT.CPP

#include <boost/bind.hpp>

#include <cstdio> /* sprintf */

#include "client.hpp"
#include "../gui/QTGUI.h"

#include <unistd.h>

Client::Client():
...

Original code

I have the following in my main CMakeLists:

cmake_minimum_required(VERSION 2.6)
project(backendCode)

find_package(Boost COMPONENTS system)
include_directories(${Boost_INCLUDE_DIR})

SET(BOOSTHREAD "-lpthread -lboost_thread")

SET(FSLIBS "-lboost_filesystem -lboost_system")

add_subdirectory(gui)
add_subdirectory(client)
add_subdirectory(server)

The following, in the gui CMakeLists:

cmake_minimum_required(VERSION 3.0.0 FATAL_ERROR)
project(QtGUI)

set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)

find_package(Qt5Widgets REQUIRED)
find_package(Qt5Network REQUIRED)

include_directories(${Qt5Widgets_INCLUDE_DIRS})
add_definitions(${QT_DEFINITIONS})


add_executable(main main.cpp qtgui.cpp ../common/inotify.cpp)
target_link_libraries(main client Qt5::Widgets Qt5::Network ${Boost_LIBRARIES} 
${BOOSTHREAD})

In the qtgui.h header file I have the following code:

#ifndef QTGUI_H
#define QTGUI_H

#include <QMainWindow>

#include <boost/enable_shared_from_this.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/signals2.hpp>

#include "../client/client.hpp"

namespace Ui {
class QTGUI;
}
class QTGUI    : public QMainWindow
{
    Q_OBJECT
...
    private:
        boost::shared_ptr<Client> client_;
};
#endif

Finally, in the client.hpp file I have the following code:

#ifndef CLIENT_HPP
#define CLIENT_HPP

#include <boost/asio.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/thread.hpp>

#include <boost/signals2.hpp>

#include "../gui/qtgui.h"

class QTGUI;

class Client : public boost::enable_shared_from_this<Client>
{
    ...
private:
    boost::shared_ptr<QTGUI> ui_;
};
#endif

EDIT: Added the namespace thing into the qtgui.h.

MikelAlejoBR
  • 302
  • 5
  • 15

1 Answers1

1

Your client code, compiled without Qt support, includes a file that includes a Qt header. This won't ever work. The #include "../gui/qtgui.h" line in client.hpp is the source of the problem.

The forward declaration in client.hpp would be pointless since you've already included the qtgui.h. Choose one or the other. Most likely, you do not want to include qtgui.h in client.hpp. That should solve your problem.

Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
  • If I don't include qtgui.h then I go back to the start point. However, if I leave the class QTGUI; in the client.hpp then when compiling I get an ui was not declared on this scope error. Could it be because of the namespace Ui of the qtgui.h file? PS: Sorry I did not include that in the original question. It has been updated. – MikelAlejoBR Jun 03 '16 at 13:21
  • @StrikeTeam You don't need to include it. I don't know what you mean by square one. It's supposed to work. Your code works for me if I follow the answer. – Kuba hasn't forgotten Monica Jun 03 '16 at 13:47
  • Let me explain myself better: if I leave the `class QTGUI;` inside the `client.hpp` file, in order to have it declared to use its signal functions, then the compiler complaints about `error: 'ui' was not declared in this scope`. – MikelAlejoBR Jun 03 '16 at 13:58
  • Okey solved. I firstly followed [this](http://stackoverflow.com/questions/8868916/qt-c-yet-another-issue-about-accessing-ui-files) and then [this](http://stackoverflow.com/questions/12466055/field-has-incomplete-type-error), and it seems to compile. Thank you very much indeed. – MikelAlejoBR Jun 03 '16 at 14:08
  • @StrikeTeam Show the full source that reproduces the issue. Otherwise we'll be going in circles. At the moment, your design is broken. You can't use a class that uses Qt APIs in its interface (public or private doesn't matter) from a module that doesn't know anything about Qt. If you insist on using Qt in that class, put it into a [PIMPL](http://stackoverflow.com/q/25250171/1329652). Nothing Qt-related must appear in that class's header! – Kuba hasn't forgotten Monica Jun 03 '16 at 14:08
  • On the one hand, I have the Qt class QTGUI which has some slots for the signals that the CLIENT sends. Now, I want to be able to make the QTGUI send some signals to the CLIENT slots. That is why, I need somehow to access the GUI from the client in order to use the GUI's signals. However I made it compile. Should I still post the entire source code? – MikelAlejoBR Jun 03 '16 at 14:17
  • According to your cmakelists, the client is not using Qt?! Or at least you don't show that. – Kuba hasn't forgotten Monica Jun 03 '16 at 14:23
  • Finally, I solved thanks to the PIMPL pattern, as you pointed out earlier. There was no other way of making it work. Thank you again for all your help. – MikelAlejoBR Jun 03 '16 at 16:10