├── README.md ├── section 3 ├── qt6ca-3-10 │ ├── CMakeLists.txt │ ├── counter.cpp │ ├── counter.h │ └── main.cpp ├── qt6ca-3-11 │ ├── CMakeLists.txt │ ├── counter.cpp │ ├── counter.h │ └── main.cpp ├── qt6ca-3-12 │ ├── CMakeLists.txt │ ├── main.cpp │ ├── worker.cpp │ └── worker.h ├── qt6ca-3-13 │ ├── CMakeLists.txt │ ├── consumer.cpp │ ├── consumer.h │ ├── main.cpp │ ├── producer.cpp │ └── producer.h ├── qt6ca-3-14 │ ├── CMakeLists.txt │ ├── main.cpp │ ├── widget.cpp │ └── widget.h ├── qt6ca-3-16 │ ├── CMakeLists.txt │ └── main.cpp ├── qt6ca-3-17 │ ├── CMakeLists.txt │ └── main.cpp ├── qt6ca-3-18 │ ├── CMakeLists.txt │ └── main.cpp ├── qt6ca-3-19 │ ├── CMakeLists.txt │ ├── main.cpp │ ├── test.cpp │ └── test.h ├── qt6ca-3-20 │ ├── CMakeLists.txt │ └── main.cpp ├── qt6ca-3-21 │ ├── CMakeLists.txt │ ├── main.cpp │ ├── test.cpp │ └── test.h ├── qt6ca-3-22 │ ├── CMakeLists.txt │ └── main.cpp ├── qt6ca-3-23 │ ├── CMakeLists.txt │ └── main.cpp ├── qt6ca-3-24 │ ├── CMakeLists.txt │ ├── main.cpp │ ├── manager.cpp │ ├── manager.h │ ├── worker.cpp │ └── worker.h ├── qt6ca-3-4 │ ├── CMakeLists.txt │ └── main.cpp ├── qt6ca-3-5 │ ├── CMakeLists.txt │ └── main.cpp ├── qt6ca-3-6 │ ├── CMakeLists.txt │ ├── main.cpp │ ├── test.cpp │ └── test.h ├── qt6ca-3-7 │ ├── CMakeLists.txt │ ├── main.cpp │ ├── test.cpp │ ├── test.h │ ├── worker.cpp │ └── worker.h ├── qt6ca-3-8 │ ├── CMakeLists.txt │ ├── counter.cpp │ ├── counter.h │ ├── main.cpp │ ├── manager.cpp │ └── manager.h ├── qt6ca-3-9 │ ├── CMakeLists.txt │ ├── counter.cpp │ ├── counter.h │ └── main.cpp └── qt6ca-3-assign │ ├── CMakeLists.txt │ └── main.cpp ├── section 4 ├── qt6ca-4-16 │ ├── CMakeLists.txt │ └── main.cpp ├── qt6ca-4-17 │ ├── CMakeLists.txt │ ├── main.cpp │ ├── worker.cpp │ └── worker.h ├── qt6ca-4-18 │ ├── CMakeLists.txt │ ├── chat.cpp │ ├── chat.h │ ├── commandline.cpp │ ├── commandline.h │ └── main.cpp ├── qt6ca-4-19 │ ├── CMakeLists.txt │ ├── client.cpp │ ├── client.h │ └── main.cpp ├── qt6ca-4-20 │ ├── CMakeLists.txt │ ├── client.cpp │ ├── client.h │ └── main.cpp ├── qt6ca-4-21 │ ├── CMakeLists.txt │ ├── client.cpp │ ├── client.h │ └── main.cpp ├── qt6ca-4-22 │ ├── CMakeLists.txt │ └── main.cpp ├── qt6ca-4-23 │ ├── CMakeLists.txt │ └── main.cpp ├── qt6ca-4-24 │ ├── CMakeLists.txt │ ├── client.cpp │ ├── client.h │ └── main.cpp ├── qt6ca-4-25 │ ├── CMakeLists.txt │ ├── main.cpp │ ├── worker.cpp │ └── worker.h ├── qt6ca-4-26 │ ├── CMakeLists.txt │ ├── client.cpp │ ├── client.h │ └── main.cpp ├── qt6ca-4-27 │ ├── CMakeLists.txt │ ├── main.cpp │ ├── worker.cpp │ └── worker.h ├── qt6ca-4-28 │ ├── CMakeLists.txt │ ├── main.cpp │ ├── worker.cpp │ └── worker.h ├── qt6ca-4-29 │ ├── CMakeLists.txt │ ├── main.cpp │ ├── worker.cpp │ └── worker.h ├── qt6ca-4-30 │ ├── CMakeLists.txt │ ├── main.cpp │ ├── server.cpp │ └── server.h ├── qt6ca-4-31 │ ├── CMakeLists.txt │ ├── client.cpp │ ├── client.h │ ├── main.cpp │ ├── server.cpp │ └── server.h ├── qt6ca-4-32 │ ├── CMakeLists.txt │ ├── client.cpp │ ├── client.h │ ├── main.cpp │ ├── server.cpp │ └── server.h ├── qt6ca-4-33 │ ├── server.crt │ ├── server.csr │ ├── server.key │ └── server.key.org ├── qt6ca-4-34 │ ├── CMakeLists.txt │ ├── main.cpp │ ├── server.cpp │ └── server.h ├── qt6ca-4-35 │ ├── CMakeLists.txt │ ├── main.cpp │ ├── server.cpp │ └── server.h └── qt6ca-4-assign │ ├── CMakeLists.txt │ └── main.cpp ├── section 5 ├── qt6ca-5-10 │ ├── myapp │ │ ├── CMakeLists.txt │ │ ├── inc │ │ │ ├── mylib.h │ │ │ └── mylib_global.h │ │ └── main.cpp │ └── mylib │ │ ├── CMakeLists.txt │ │ ├── mylib.cpp │ │ ├── mylib.h │ │ └── mylib_global.h ├── qt6ca-5-12 │ ├── myapp │ │ ├── CMakeLists.txt │ │ ├── inc │ │ │ └── mylib.h │ │ └── main.cpp │ └── mylib │ │ ├── CMakeLists.txt │ │ ├── mylib.cpp │ │ └── mylib.h ├── qt6ca-5-13 │ ├── myapp │ │ ├── CMakeLists.txt │ │ ├── main.cpp │ │ └── plugin.h │ └── myplugin │ │ ├── CMakeLists.txt │ │ ├── myplugin.cpp │ │ ├── myplugin.h │ │ ├── myplugin_global.h │ │ └── plugin.h ├── qt6ca-5-9 │ ├── CMakeLists.txt │ ├── myapp │ │ ├── CMakeLists.txt │ │ └── main.cpp │ └── mylib │ │ ├── CMakeLists.txt │ │ ├── mylib.cpp │ │ ├── mylib.h │ │ └── mylib_global.h └── qt6ca-5-assign │ ├── cats │ ├── CMakeLists.txt │ ├── cats.cpp │ ├── cats.h │ └── plugin.h │ ├── myapp │ ├── CMakeLists.txt │ ├── main.cpp │ └── plugin.h │ └── myplugin │ ├── CMakeLists.txt │ ├── myplugin.cpp │ ├── myplugin.h │ └── plugin.h ├── section 6 ├── qt6ca-6-5 │ ├── CMakeLists.txt │ └── main.cpp ├── qt6ca-6-6 │ ├── CMakeLists.txt │ └── main.cpp ├── qt6ca-6-7 │ ├── CMakeLists.txt │ └── main.cpp ├── qt6ca-6-8 │ ├── CMakeLists.txt │ ├── main.cpp │ ├── user.cpp │ └── user.h └── qt6ca-6-assign │ ├── CMakeLists.txt │ └── main.cpp ├── section 7 ├── qt6ca-7-3 │ ├── CMakeLists.txt │ ├── cat.cpp │ ├── cat.h │ └── main.cpp ├── qt6ca-7-4 │ ├── CMakeLists.txt │ ├── dog.cpp │ ├── dog.h │ └── main.cpp ├── qt6ca-7-5 │ ├── CMakeLists.txt │ ├── main.cpp │ ├── widget.cpp │ └── widget.h ├── qt6ca-7-6 │ ├── CMakeLists.txt │ ├── main.cpp │ ├── widget.cpp │ └── widget.h ├── qt6ca-7-7 │ ├── CMakeLists.txt │ ├── main.cpp │ ├── widget.cpp │ └── widget.h ├── qt6ca-7-8 │ ├── CMakeLists.txt │ ├── main.cpp │ ├── widget.cpp │ └── widget.h └── qt6ca-7-assign │ ├── CMakeLists.txt │ ├── main.cpp │ ├── widget.cpp │ └── widget.h └── section 8 ├── qt6ca-8-10 ├── CMakeLists.txt └── main.cpp ├── qt6ca-8-6 ├── CMakeLists.txt └── main.cpp ├── qt6ca-8-7 ├── CMakeLists.txt └── main.cpp ├── qt6ca-8-8 ├── CMakeLists.txt └── main.cpp └── qt6ca-8-9 ├── CMakeLists.txt └── main.cpp /section 3/qt6ca-3-10/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-3-10 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) 16 | 17 | add_executable(qt6ca-3-10 18 | main.cpp 19 | counter.cpp 20 | counter.h 21 | ) 22 | target_link_libraries(qt6ca-3-10 Qt${QT_VERSION_MAJOR}::Core) 23 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-10/counter.cpp: -------------------------------------------------------------------------------- 1 | #include "counter.h" 2 | 3 | Counter::Counter(QMutex *mutex, int *value) 4 | { 5 | m_value = value; 6 | m_mutex = mutex; 7 | } 8 | 9 | 10 | void Counter::run() 11 | { 12 | //Wait until we can do stuff... 13 | 14 | m_mutex->lock(); //We will wait until we can lock! 15 | 16 | //Our code here 17 | QThread::currentThread()->msleep(50); 18 | *m_value = *m_value + 1; 19 | qInfo() << *m_value << QThread::currentThread(); 20 | 21 | m_mutex->unlock(); //Other threads can lock 22 | } 23 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-10/counter.h: -------------------------------------------------------------------------------- 1 | #ifndef COUNTER_H 2 | #define COUNTER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class Counter : public QRunnable 10 | { 11 | public: 12 | Counter(QMutex* mutex,int* value); 13 | 14 | // QRunnable interface 15 | public: 16 | void run(); 17 | 18 | private: 19 | int* m_value; 20 | QMutex* m_mutex; 21 | }; 22 | 23 | #endif // COUNTER_H 24 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-10/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Mutex 5 | 6 | Why 7 | We want to protect an object from thread issues 8 | 9 | How 10 | QMutex 11 | 12 | Two threads updating the same thing at the same time 13 | 14 | */ 15 | 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include "counter.h" 23 | 24 | int main(int argc, char *argv[]) 25 | { 26 | QCoreApplication a(argc, argv); 27 | 28 | QThread::currentThread()->setObjectName("Main"); 29 | QThreadPool* pool = QThreadPool::globalInstance(); 30 | 31 | QMutex mutex; 32 | int value = 0; 33 | qInfo() << pool->maxThreadCount() << " Threads"; 34 | 35 | for(int i = 0; i < 100; i++) 36 | { 37 | Counter* c = new Counter(&mutex,&value); 38 | c->setAutoDelete(true); 39 | pool->start(c); 40 | } 41 | 42 | return a.exec(); 43 | } 44 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-11/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-3-11 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) 16 | 17 | add_executable(qt6ca-3-11 18 | main.cpp 19 | counter.cpp 20 | counter.h 21 | ) 22 | target_link_libraries(qt6ca-3-11 Qt${QT_VERSION_MAJOR}::Core) 23 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-11/counter.cpp: -------------------------------------------------------------------------------- 1 | #include "counter.h" 2 | 3 | Counter::Counter(QMutex *mutex, int *value) 4 | { 5 | m_value = value; 6 | m_mutex = mutex; 7 | } 8 | 9 | 10 | void Counter::run() 11 | { 12 | //Wait until we can do stuff... 13 | 14 | 15 | //Our code here 16 | QThread::currentThread()->msleep(50); 17 | 18 | QMutexLocker locker(m_mutex); 19 | *m_value = *m_value + 1; 20 | qInfo() << *m_value << QThread::currentThread(); 21 | 22 | 23 | } 24 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-11/counter.h: -------------------------------------------------------------------------------- 1 | #ifndef COUNTER_H 2 | #define COUNTER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class Counter : public QRunnable 11 | { 12 | public: 13 | Counter(QMutex* mutex,int* value); 14 | 15 | // QRunnable interface 16 | public: 17 | void run(); 18 | 19 | private: 20 | int* m_value; 21 | QMutex* m_mutex; 22 | }; 23 | 24 | #endif // COUNTER_H 25 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-11/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Mutex Locker 5 | 6 | Why 7 | We want to protect an object from thread issues 8 | But we want to make it easier 9 | 10 | How 11 | QMutexLocker 12 | 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include "counter.h" 21 | 22 | int main(int argc, char *argv[]) 23 | { 24 | QCoreApplication a(argc, argv); 25 | 26 | QThread::currentThread()->setObjectName("Main"); 27 | QThreadPool* pool = QThreadPool::globalInstance(); 28 | 29 | QMutex mutex; 30 | int value = 0; 31 | 32 | qInfo() << pool->maxThreadCount() << " Threads"; 33 | 34 | for (int i = 0; i < 100; i++) 35 | { 36 | Counter* c = new Counter(&mutex, &value); 37 | c->setAutoDelete(true); 38 | pool->start(c); 39 | } 40 | 41 | return a.exec(); 42 | } 43 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-12/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-3-12 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) 16 | 17 | add_executable(qt6ca-3-12 18 | main.cpp 19 | worker.cpp 20 | worker.h 21 | ) 22 | target_link_libraries(qt6ca-3-12 Qt${QT_VERSION_MAJOR}::Core) 23 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-12/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Semaphores 5 | 6 | Why 7 | Generalize a mutex 8 | Lock and unlock multiple resources 9 | 10 | How 11 | QSemaphore 12 | 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | #include "worker.h" 19 | 20 | int main(int argc, char *argv[]) 21 | { 22 | QCoreApplication a(argc, argv); 23 | 24 | QList values; 25 | values.resize(10); 26 | values.fill(0); 27 | 28 | QSemaphore sema(values.size()); 29 | qInfo() << values; 30 | 31 | QThread thread1; 32 | QThread thread2; 33 | thread1.setObjectName("Thread 1"); 34 | thread2.setObjectName("Thread 2"); 35 | 36 | Worker worker1(&sema,&values); 37 | Worker worker2(&sema,&values); 38 | worker1.moveToThread(&thread1); 39 | worker2.moveToThread(&thread2); 40 | 41 | QObject::connect(&thread1,&QThread::started,&worker1,&Worker::run); 42 | QObject::connect(&thread2,&QThread::started,&worker2,&Worker::run); 43 | 44 | thread1.start(); 45 | thread2.start(); 46 | 47 | return a.exec(); 48 | } 49 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-12/worker.cpp: -------------------------------------------------------------------------------- 1 | #include "worker.h" 2 | 3 | 4 | Worker::Worker(QSemaphore *sema, QList *values, QObject *parent) 5 | { 6 | m_sema = sema; 7 | m_values = values; 8 | } 9 | 10 | void Worker::run() 11 | { 12 | qInfo() << "Run" << QThread::currentThread(); 13 | int max = QRandomGenerator::global()->bounded(1,m_values->size()); 14 | 15 | qInfo() << "Acquiring" << max << QThread::currentThread(); 16 | m_sema->acquire(max); 17 | 18 | qInfo() << "Acquired" << m_sema->available() << QThread::currentThread(); 19 | for(int i = 0; i < max; i++) 20 | { 21 | qInfo() << "Modify" << i << QThread::currentThread(); 22 | int value = QRandomGenerator::global()->bounded(100); 23 | m_values->replace(i,value); 24 | QThread::currentThread()->msleep(250); 25 | } 26 | 27 | qInfo() << "Release" << max << QThread::currentThread(); 28 | m_sema->release(max); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-12/worker.h: -------------------------------------------------------------------------------- 1 | #ifndef WORKER_H 2 | #define WORKER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | class Worker : public QObject 12 | { 13 | Q_OBJECT 14 | public: 15 | explicit Worker(QSemaphore *sema,QList *values, QObject *parent = nullptr); 16 | 17 | signals: 18 | 19 | public slots: 20 | void run(); 21 | 22 | private: 23 | QSemaphore *m_sema; 24 | QList *m_values; 25 | 26 | }; 27 | 28 | #endif // WORKER_H 29 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-13/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-3-13 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) 16 | 17 | add_executable(qt6ca-3-13 18 | main.cpp 19 | producer.cpp 20 | producer.h 21 | consumer.cpp 22 | consumer.h 23 | ) 24 | target_link_libraries(qt6ca-3-13 Qt${QT_VERSION_MAJOR}::Core) 25 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-13/consumer.cpp: -------------------------------------------------------------------------------- 1 | #include "consumer.h" 2 | 3 | 4 | Consumer::Consumer(QMutex *mutex, QWaitCondition *valueReady, int *value, QObject *parent) 5 | { 6 | Q_UNUSED(parent); 7 | m_mutex = mutex; 8 | m_valueReady = valueReady; 9 | m_value = value; 10 | } 11 | 12 | void Consumer::run() 13 | { 14 | qInfo() << "Consumer running"; 15 | m_mutex->lock(); 16 | qInfo() << "Consumer locked the mutex"; 17 | if(*m_value == 0) 18 | { 19 | qInfo() << "Consumer is waiting on a value"; 20 | m_valueReady->wait(m_mutex); 21 | } 22 | 23 | qInfo() << "Consuming:" << *m_value; 24 | } 25 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-13/consumer.h: -------------------------------------------------------------------------------- 1 | #ifndef CONSUMER_H 2 | #define CONSUMER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class Consumer : public QObject 11 | { 12 | Q_OBJECT 13 | public: 14 | explicit Consumer(QMutex *mutex, QWaitCondition *valueReady, int *value, QObject *parent = nullptr); 15 | 16 | 17 | public slots: 18 | void run(); 19 | 20 | private: 21 | QMutex *m_mutex; 22 | QWaitCondition *m_valueReady; 23 | int *m_value; 24 | 25 | }; 26 | 27 | #endif // CONSUMER_H 28 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-13/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Wait conditions 5 | 6 | Why 7 | Sync threads 8 | 9 | How 10 | QWaitCondition 11 | 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include "producer.h" 19 | #include "consumer.h" 20 | 21 | int main(int argc, char *argv[]) 22 | { 23 | QCoreApplication a(argc, argv); 24 | 25 | QWaitCondition valueReady; 26 | QMutex mutex; 27 | QThread producerThread; 28 | QThread consumerThread; 29 | int value = 0; 30 | 31 | Producer *producer = new Producer(&mutex,&valueReady,&value); 32 | Consumer *consumer = new Consumer(&mutex,&valueReady,&value); 33 | 34 | producer->moveToThread(&producerThread); 35 | consumer->moveToThread(&consumerThread); 36 | 37 | QObject::connect(&producerThread,&QThread::started,producer,&Producer::run); 38 | QObject::connect(&consumerThread,&QThread::started,consumer,&Consumer::run); 39 | 40 | producerThread.start(); 41 | consumerThread.start(); 42 | 43 | 44 | 45 | return a.exec(); 46 | } 47 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-13/producer.cpp: -------------------------------------------------------------------------------- 1 | #include "producer.h" 2 | 3 | 4 | Producer::Producer(QMutex *mutex, QWaitCondition *valueReady, int *value, QObject *parent) 5 | { 6 | Q_UNUSED(parent); 7 | m_mutex = mutex; 8 | m_valueReady = valueReady; 9 | m_value = value; 10 | } 11 | 12 | void Producer::run() 13 | { 14 | qInfo() << "Producer running"; 15 | QThread::currentThread()->msleep(3000); 16 | 17 | m_mutex->lock(); 18 | qInfo() << "Producer creating value"; 19 | *m_value = QRandomGenerator::global()->bounded(1000); 20 | qInfo() << "Producer waking up consumer"; 21 | m_mutex->unlock(); 22 | 23 | m_valueReady->wakeAll(); 24 | 25 | } 26 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-13/producer.h: -------------------------------------------------------------------------------- 1 | #ifndef PRODUCER_H 2 | #define PRODUCER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | class Producer : public QObject 12 | { 13 | Q_OBJECT 14 | public: 15 | explicit Producer(QMutex *mutex,QWaitCondition *valueReady,int *value,QObject *parent = nullptr); 16 | 17 | signals: 18 | 19 | public slots: 20 | void run(); 21 | 22 | private: 23 | QMutex *m_mutex; 24 | QWaitCondition *m_valueReady; 25 | int *m_value; 26 | }; 27 | 28 | #endif // PRODUCER_H 29 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-14/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-3-14 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) 16 | 17 | add_executable(qt6ca-3-14 18 | main.cpp 19 | widget.cpp 20 | widget.h 21 | ) 22 | target_link_libraries(qt6ca-3-14 Qt${QT_VERSION_MAJOR}::Core) 23 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-14/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | What 3 | Signals and slots across threads 4 | 5 | Why 6 | Some minor complications 7 | 8 | How 9 | Qt Signal Types 10 | 11 | */ 12 | 13 | #include 14 | #include 15 | #include "widget.h" 16 | 17 | int main(int argc, char *argv[]) 18 | { 19 | QCoreApplication a(argc, argv); 20 | 21 | Widget* producer = new Widget(); 22 | Widget* consumer = new Widget(); 23 | 24 | producer->setObjectName("Producer"); 25 | consumer->setObjectName("Consumer"); 26 | producer->setIsSender(true); 27 | producer->setAutoDelete(true); 28 | consumer->setAutoDelete(true); 29 | 30 | QObject::connect(producer,&Widget::started,consumer,&Widget::workStarted,Qt::QueuedConnection); 31 | QObject::connect(producer,&Widget::update,consumer,&Widget::workReady,Qt::QueuedConnection); 32 | QObject::connect(producer,&Widget::finished,consumer,&Widget::workFinished,Qt::QueuedConnection); 33 | 34 | QThreadPool::globalInstance()->start(producer); 35 | QThreadPool::globalInstance()->start(consumer); 36 | 37 | return a.exec(); 38 | } 39 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-14/widget.cpp: -------------------------------------------------------------------------------- 1 | #include "widget.h" 2 | 3 | Widget::Widget(QObject *parent) : QObject(parent) 4 | { 5 | m_isSender = false; 6 | } 7 | 8 | void Widget::workStarted() 9 | { 10 | qInfo() << this << "Started" << sender(); 11 | } 12 | 13 | void Widget::workFinished() 14 | { 15 | qInfo() << this << "Finished" << sender(); 16 | m_isActive = false; 17 | } 18 | 19 | void Widget::workReady(int i) 20 | { 21 | qInfo() << this << "Work" << i << sender(); 22 | } 23 | 24 | void Widget::run() 25 | { 26 | if(m_isSender) 27 | { 28 | qInfo() << this << "Starting work..."; 29 | emit started(); 30 | 31 | for(int i = 0; i < 10; i++) 32 | { 33 | qInfo() << this << "Update..."; 34 | emit update(i); 35 | QThread::currentThread()->msleep(500); 36 | } 37 | qInfo() << this << "Finished..."; 38 | emit finished(); 39 | } 40 | else 41 | { 42 | qInfo() << this << "Waiting for signals..."; 43 | m_isActive = true; 44 | while(m_isActive) 45 | { 46 | QThread::currentThread()->msleep(100); 47 | } 48 | } 49 | 50 | qInfo() << this << "Done"; 51 | } 52 | 53 | bool Widget::isSender() const 54 | { 55 | return m_isSender; 56 | } 57 | 58 | void Widget::setIsSender(bool newIsSender) 59 | { 60 | m_isSender = newIsSender; 61 | } 62 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-14/widget.h: -------------------------------------------------------------------------------- 1 | #ifndef WIDGET_H 2 | #define WIDGET_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class Widget : public QObject, public QRunnable 10 | { 11 | Q_OBJECT 12 | public: 13 | explicit Widget(QObject *parent = nullptr); 14 | 15 | signals: 16 | void started(); 17 | void finished(); 18 | void update(int i); 19 | 20 | public slots: 21 | void workStarted(); 22 | void workFinished(); 23 | void workReady(int i); 24 | 25 | public: 26 | void run(); 27 | bool isSender() const; 28 | void setIsSender(bool newIsSender); 29 | 30 | private: 31 | bool m_isSender; 32 | bool m_isActive; 33 | }; 34 | 35 | #endif // WIDGET_H 36 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-16/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-3-16 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Concurrent REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Concurrent REQUIRED) 16 | 17 | add_executable(qt6ca-3-16 18 | main.cpp 19 | ) 20 | target_link_libraries(qt6ca-3-16 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Concurrent) 21 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-16/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | What 3 | Intro to Qt Concurrent 4 | 5 | Why 6 | Its very easy 7 | Removes the complexity of threading 8 | Baked right into Qt 9 | 10 | How 11 | QtConcurrent 12 | 13 | */ 14 | 15 | #include 16 | #include 17 | 18 | int do_map(int value) 19 | { 20 | qInfo() << "Do stuff: " << value; 21 | int num = value * 10; 22 | return num; 23 | } 24 | 25 | int main(int argc, char *argv[]) 26 | { 27 | QCoreApplication a(argc, argv); 28 | 29 | QList values; 30 | for(int i = 0; i < 9; i++) 31 | { 32 | values << i; 33 | } 34 | 35 | qInfo() << "Starting..."; 36 | QList updated = QtConcurrent::blockingMapped(values,&do_map); 37 | qInfo() << "Finished"; 38 | qInfo() << updated; 39 | 40 | 41 | return a.exec(); 42 | } 43 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-17/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-3-17 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Concurrent REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Concurrent REQUIRED) 16 | 17 | add_executable(qt6ca-3-17 18 | main.cpp 19 | ) 20 | target_link_libraries(qt6ca-3-17 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Concurrent) 21 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-17/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | QtConcurrent::run 5 | 6 | Why 7 | Easily run on a thread 8 | 9 | How 10 | QtConcurrent::run 11 | 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | void loop() 20 | { 21 | for (int i = 0; i < 10;i++) 22 | { 23 | qInfo() << "Loop" << i << " on: " << QThread::currentThread(); 24 | } 25 | } 26 | 27 | void test() 28 | { 29 | qInfo() << "Test on: " << QThread::currentThread(); 30 | loop(); 31 | } 32 | 33 | 34 | int main(int argc, char *argv[]) 35 | { 36 | QCoreApplication a(argc, argv); 37 | QThread::currentThread()->setObjectName("Main"); 38 | 39 | QThreadPool pool; 40 | QFuture future = QtConcurrent::run(&pool,test); 41 | qInfo() << "Main on: " << QThread::currentThread(); 42 | 43 | return a.exec(); 44 | } 45 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-18/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-3-18 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Concurrent REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Concurrent REQUIRED) 16 | 17 | add_executable(qt6ca-3-18 18 | main.cpp 19 | ) 20 | target_link_libraries(qt6ca-3-18 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Concurrent) 21 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-18/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Qt Concurrent issues 5 | 6 | Why 7 | We live in the real world 8 | Its great, but we lose a lot of control 9 | 10 | How 11 | Example code: we have to use Futures to get values back 12 | 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | void test(QString name, int max) 21 | { 22 | for (int i = 0;i < max;i++) 23 | { 24 | qInfo() << name << i << QThread::currentThread(); 25 | } 26 | } 27 | 28 | int main(int argc, char *argv[]) 29 | { 30 | QCoreApplication a(argc, argv); 31 | 32 | QString name = "name"; 33 | 34 | QFuture future = QtConcurrent::run(test,name,5); 35 | qInfo() << "Do stuff here"; 36 | 37 | //Wait for finished 38 | future.waitForFinished(); //Block 39 | qInfo() << "Done"; 40 | 41 | return a.exec(); 42 | } 43 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-19/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-3-19 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Concurrent REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Concurrent REQUIRED) 16 | 17 | add_executable(qt6ca-3-19 18 | main.cpp 19 | test.cpp 20 | test.h 21 | ) 22 | target_link_libraries(qt6ca-3-19 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Concurrent) 23 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-19/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Waiting for values in the future 5 | 6 | Why 7 | Threading is not syncronous 8 | 9 | How 10 | QFutureWatcher - signals and slots based approach 11 | 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include "test.h" 21 | 22 | void multiply(int &value) 23 | { 24 | qInfo() << "Called: " << value; 25 | value = value * 10; 26 | } 27 | 28 | int main(int argc, char *argv[]) 29 | { 30 | QCoreApplication a(argc, argv); 31 | 32 | QList list; 33 | for(int i = 0; i < 100; i++) 34 | { 35 | list.append(i); 36 | } 37 | 38 | QFutureWatcher watcher; 39 | Test test; 40 | QObject::connect(&watcher, &QFutureWatcher::finished,&test,&Test::finished); //Auto connect "should" work 41 | 42 | QFuture future = QtConcurrent::map(list,&multiply); 43 | watcher.setFuture(future); 44 | 45 | qInfo() << "Back in main!"; 46 | 47 | watcher.waitForFinished(); //Blocking 48 | 49 | qInfo() << "Done!"; 50 | qInfo() << list; 51 | 52 | return a.exec(); 53 | } 54 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-19/test.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | Test::Test(QObject *parent) : QObject(parent) 4 | { 5 | 6 | } 7 | 8 | void Test::finished() 9 | { 10 | //When Qt Concurrent is done 11 | qInfo() << this << "Processing..."; 12 | } 13 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-19/test.h: -------------------------------------------------------------------------------- 1 | #ifndef TEST_H 2 | #define TEST_H 3 | 4 | #include 5 | #include 6 | 7 | class Test : public QObject 8 | { 9 | Q_OBJECT 10 | public: 11 | explicit Test(QObject *parent = nullptr); 12 | 13 | signals: 14 | 15 | public slots: 16 | void finished(); 17 | 18 | }; 19 | 20 | #endif // TEST_H 21 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-20/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-3-20 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Concurrent REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Concurrent REQUIRED) 16 | 17 | add_executable(qt6ca-3-20 18 | main.cpp 19 | ) 20 | target_link_libraries(qt6ca-3-20 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Concurrent) 21 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-20/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Returning values 5 | 6 | Why 7 | We want to get the result 8 | 9 | How 10 | Future results 11 | 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | int multiply(const int &value) 22 | { 23 | qInfo() << "Called: " << value; 24 | int num = value * 10; 25 | return num; 26 | } 27 | 28 | int main(int argc, char *argv[]) 29 | { 30 | QCoreApplication a(argc, argv); 31 | 32 | QList list; 33 | for (int i = 0;i < 100; i++) 34 | { 35 | list.append(i); 36 | } 37 | 38 | QFutureWatcher watcher; 39 | QFuture future = QtConcurrent::mapped(list,&multiply); 40 | watcher.setFuture(future); 41 | //Set signals and slots here 42 | 43 | qInfo() << "Back in main!"; 44 | 45 | //Do other things with the watcher if needed 46 | watcher.waitForFinished(); 47 | 48 | qInfo() << "Done!"; 49 | qInfo() << future.results(); 50 | 51 | 52 | return a.exec(); 53 | } 54 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-21/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-3-21 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Concurrent REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Concurrent REQUIRED) 16 | 17 | add_executable(qt6ca-3-21 18 | main.cpp 19 | test.cpp 20 | test.h 21 | ) 22 | target_link_libraries(qt6ca-3-21 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Concurrent) 23 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-21/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Future watcher signals and slots 5 | 6 | Why 7 | We want to use Qt signals and slots 8 | 9 | How 10 | QFutureWatcher Slots 11 | 12 | */ 13 | 14 | 15 | #include 16 | #include "test.h" 17 | 18 | int main(int argc, char *argv[]) 19 | { 20 | QCoreApplication a(argc, argv); 21 | 22 | Test test; 23 | test.process(); 24 | 25 | 26 | return a.exec(); 27 | } 28 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-21/test.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | Test::Test(QObject *parent) : QObject(parent) 4 | { 5 | //Connect 6 | /* 7 | void canceled(); 8 | void finished(); 9 | void paused(); 10 | void progressRangeChanged(int minimum, int maximum); 11 | void progressTextChanged(const QString &progressText); 12 | void progressValueChanged(int progressValue); 13 | void resultReadyAt(int index); 14 | void resultsReadyAt(int beginIndex, int endIndex); 15 | void resumed(); 16 | void started(); 17 | */ 18 | 19 | connect(&watcher, &QFutureWatcher::canceled, this, &Test::canceled); 20 | connect(&watcher, &QFutureWatcher::finished, this, &Test::finished); 21 | 22 | //Qt5 23 | //connect(&watcher, &QFutureWatcher::paused, this, &Test::paused); 24 | 25 | connect(&watcher, &QFutureWatcher::suspending, this, &Test::suspending); 26 | connect(&watcher, &QFutureWatcher::suspended, this, &Test::suspended); 27 | 28 | connect(&watcher, &QFutureWatcher::progressRangeChanged, this, &Test::progressRangeChanged); 29 | connect(&watcher, &QFutureWatcher::progressTextChanged, this, &Test::progressTextChanged); 30 | connect(&watcher, &QFutureWatcher::progressValueChanged, this, &Test::progressValueChanged); 31 | connect(&watcher, &QFutureWatcher::resultReadyAt, this, &Test::resultReadyAt); 32 | connect(&watcher, &QFutureWatcher::resumed, this, &Test::resumed); 33 | connect(&watcher, &QFutureWatcher::started, this, &Test::started); 34 | 35 | } 36 | 37 | void Test::process() 38 | { 39 | QMutex mutex; 40 | mutex.lock(); 41 | list.clear(); 42 | for(int i = 0; i < 100; i++) 43 | { 44 | list.append(i); 45 | } 46 | mutex.unlock(); 47 | 48 | future = QtConcurrent::map(list,&Test::multiply); 49 | watcher.setFuture(future); 50 | } 51 | 52 | void Test::multiply(int &value) 53 | { 54 | qInfo() << "Called" << value; 55 | value = value * 10; 56 | 57 | //Slow this down 58 | QThread::currentThread()->msleep(250); 59 | } 60 | 61 | void Test::canceled() 62 | { 63 | qInfo() << "Canceled"; 64 | } 65 | 66 | void Test::finished() 67 | { 68 | qInfo() << "Finished"; 69 | qInfo() << list; 70 | } 71 | 72 | void Test::suspending() 73 | { 74 | qInfo() << "Suspending"; 75 | } 76 | 77 | void Test::suspended() 78 | { 79 | qInfo() << "Suspended"; 80 | } 81 | 82 | void Test::progressRangeChanged(int minimum, int maximum) 83 | { 84 | qInfo() << "Range " << minimum << " to " << maximum; 85 | } 86 | 87 | void Test::progressTextChanged(const QString &progressText) 88 | { 89 | qInfo() << "Text: " << progressText; 90 | } 91 | 92 | void Test::progressValueChanged(int progressValue) 93 | { 94 | qInfo() << "Progress: " << progressValue; 95 | } 96 | 97 | void Test::resultReadyAt(int index) 98 | { 99 | qInfo() << "ReadyAt: " << index; 100 | } 101 | 102 | void Test::resultsReadyAt(int beginIndex, int endIndex) 103 | { 104 | qInfo() << "ResultsReadyAt " << beginIndex << " to " << endIndex; 105 | } 106 | 107 | void Test::resumed() 108 | { 109 | qInfo() << "Resumed"; 110 | } 111 | 112 | void Test::started() 113 | { 114 | qInfo() << "Started"; 115 | } 116 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-21/test.h: -------------------------------------------------------------------------------- 1 | #ifndef TEST_H 2 | #define TEST_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | class Test : public QObject 13 | { 14 | Q_OBJECT 15 | public: 16 | explicit Test(QObject *parent = nullptr); 17 | 18 | void process(); 19 | static void multiply(int &value); 20 | 21 | signals: 22 | public slots: 23 | void canceled(); 24 | void finished(); 25 | void suspending(); 26 | void suspended(); 27 | void progressRangeChanged(int minimum, int maximum); 28 | void progressTextChanged(const QString &progressText); 29 | void progressValueChanged(int progressValue); 30 | void resultReadyAt(int index); 31 | void resultsReadyAt(int beginIndex, int endIndex); 32 | void resumed(); 33 | void started(); 34 | 35 | private: 36 | QFutureWatcher watcher; 37 | QFuture future; 38 | QList list; 39 | 40 | }; 41 | 42 | #endif // TEST_H 43 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-22/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-3-22 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Concurrent REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Concurrent REQUIRED) 16 | 17 | add_executable(qt6ca-3-22 18 | main.cpp 19 | ) 20 | target_link_libraries(qt6ca-3-22 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Concurrent) 21 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-22/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Interate over Future values 5 | 6 | Why 7 | We want to sync values 8 | 9 | How 10 | QFutureIterator 11 | 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | int multiply(const int &value) 21 | { 22 | qInfo() << "Called: " << value; 23 | int num = value * 10; 24 | return num; 25 | } 26 | 27 | int main(int argc, char *argv[]) 28 | { 29 | QCoreApplication a(argc, argv); 30 | 31 | QList list; 32 | for (int i = 0;i < 100;i++) 33 | { 34 | list.append(i); 35 | } 36 | 37 | //Do stuff async ----------------------------------- 38 | QFutureWatcher watcher; 39 | QFuture future = QtConcurrent::mapped(list,&multiply); 40 | watcher.setFuture(future); 41 | 42 | //Blocking style ---------------------------------------- 43 | watcher.waitForFinished(); 44 | 45 | 46 | //Java style ------------------------------------------ 47 | QFutureIterator iter(future); 48 | while(iter.hasNext()) 49 | { 50 | qInfo() << "Java: " << iter.next(); 51 | } 52 | 53 | //Index style (normal c++) ---------------------------- 54 | for(int i = 0; i < future.results().length(); i++) 55 | { 56 | qInfo() << "Index: " << future.resultAt(i); 57 | } 58 | 59 | //Qt style--------------------------------- 60 | foreach(int i, future.results()) 61 | { 62 | qInfo() << "Qt: " << i; 63 | } 64 | 65 | //STD -------------------- 66 | QList values = future.results(); 67 | for(auto i = values.begin(); i < values.end(); i++) 68 | { 69 | qInfo() << "STD: " << *i; 70 | } 71 | 72 | qInfo() << "Done"; 73 | 74 | return a.exec(); 75 | } 76 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-23/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-3-23 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Concurrent REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Concurrent REQUIRED) 16 | 17 | add_executable(qt6ca-3-23 18 | main.cpp 19 | ) 20 | target_link_libraries(qt6ca-3-23 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Concurrent) 21 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-23/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Sync future values 5 | 6 | Why 7 | We want values in the future in a specific order 8 | 9 | How 10 | QFutureSynchronizer 11 | 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | void dostuff(int value) 22 | { 23 | for (int i = 0;i < 10; i++) 24 | { 25 | QThread::currentThread()->msleep(100); 26 | qInfo() << "Thread: " << value << " = " << i; 27 | } 28 | } 29 | 30 | void runthread() 31 | { 32 | QFutureSynchronizer sync; 33 | for(int i = 0; i < 3; i++) 34 | { 35 | QFuture f = QtConcurrent::run(&dostuff,i); 36 | sync.addFuture(f); 37 | } 38 | 39 | //sync.waitForFinished(); 40 | //waitForFinished called in the QFutureSynchronizer deconstructor 41 | 42 | } 43 | 44 | int main(int argc, char *argv[]) 45 | { 46 | QCoreApplication a(argc, argv); 47 | 48 | runthread(); 49 | qInfo() << "Done"; 50 | 51 | return a.exec(); 52 | } 53 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-24/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-3-24 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Concurrent REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Concurrent REQUIRED) 16 | 17 | add_executable(qt6ca-3-24 18 | main.cpp 19 | worker.cpp 20 | worker.h 21 | manager.cpp 22 | manager.h 23 | ) 24 | target_link_libraries(qt6ca-3-24 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Concurrent) 25 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-24/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Threaded example 5 | 6 | Why 7 | We want to see a simple example bringing it all together 8 | 9 | How 10 | Manager controller workers 11 | 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include "manager.h" 18 | 19 | int main(int argc, char *argv[]) 20 | { 21 | QCoreApplication a(argc, argv); 22 | 23 | Manager manager; 24 | QTextStream cin(stdin); 25 | qInfo() << "Type START to begin"; 26 | qInfo() << "Type QUIT to quit"; 27 | 28 | do 29 | { 30 | QString command; 31 | cin >> command; 32 | 33 | if(command.toUpper() == "START") manager.process(); 34 | if(command.toUpper() == "QUIT") manager.quit(); 35 | 36 | }while(true); 37 | 38 | return a.exec(); 39 | } 40 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-24/manager.cpp: -------------------------------------------------------------------------------- 1 | #include "manager.h" 2 | 3 | Manager::Manager(QObject *parent) : QObject(parent) 4 | { 5 | 6 | } 7 | 8 | Manager::~Manager() 9 | { 10 | quit(); 11 | } 12 | 13 | void Manager::process() 14 | { 15 | QFuture value = QtConcurrent::run(Manager::createWorker,this); 16 | } 17 | 18 | void Manager::quit() 19 | { 20 | qInfo() << "Stopping Manager"; 21 | emit stop(); 22 | } 23 | 24 | void Manager::createWorker(Manager *manager) 25 | { 26 | qInfo() << "Creating Worker"; 27 | Worker* worker = new Worker(); 28 | connect(manager,&Manager::start, worker, &Worker::start); // Qt::QueuedConnection 29 | connect(manager,&Manager::stop, worker, &Worker::stop); // Qt::QueuedConnection 30 | worker->start(); 31 | } 32 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-24/manager.h: -------------------------------------------------------------------------------- 1 | #ifndef MANAGER_H 2 | #define MANAGER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "worker.h" 9 | 10 | class Manager : public QObject 11 | { 12 | Q_OBJECT 13 | public: 14 | explicit Manager(QObject *parent = nullptr); 15 | ~Manager(); 16 | 17 | signals: 18 | void start(); 19 | void stop(); 20 | 21 | public slots: 22 | void process(); 23 | void quit(); 24 | 25 | private: 26 | static void createWorker(Manager* manager); 27 | 28 | }; 29 | 30 | #endif // MANAGER_H 31 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-24/worker.cpp: -------------------------------------------------------------------------------- 1 | #include "worker.h" 2 | 3 | Worker::Worker(QObject *parent) : QObject(parent) 4 | { 5 | qInfo() << this << "Constructed on " << QThread::currentThread(); 6 | connect(&timer,&QTimer::timeout,this, &Worker::timeout); 7 | timer.setInterval(1000); 8 | } 9 | 10 | Worker::~Worker() 11 | { 12 | qInfo() << this << "Deconstructed on " << QThread::currentThread(); 13 | } 14 | 15 | void Worker::start() 16 | { 17 | qInfo() << this << "Started on " << QThread::currentThread(); 18 | timer.start(); 19 | loop.exec(); // Processing stays here 20 | 21 | qInfo() << this << "Loop finished on " << QThread::currentThread(); 22 | 23 | //this->deleteLater(); //may hold on to this for a while! 24 | delete this; 25 | } 26 | 27 | void Worker::stop() 28 | { 29 | qInfo() << this << "Stopping on " << QThread::currentThread(); 30 | timer.stop(); 31 | loop.quit(); 32 | qInfo() << this << "Stopped on " << QThread::currentThread(); 33 | } 34 | 35 | void Worker::timeout() 36 | { 37 | qInfo() << this << "Timeout on " << QThread::currentThread(); 38 | } 39 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-24/worker.h: -------------------------------------------------------------------------------- 1 | #ifndef WORKER_H 2 | #define WORKER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class Worker : public QObject 11 | { 12 | Q_OBJECT 13 | public: 14 | explicit Worker(QObject *parent = nullptr); 15 | ~Worker(); 16 | signals: 17 | 18 | public slots: 19 | void start(); 20 | void stop(); 21 | void timeout(); 22 | 23 | private: 24 | QTimer timer; 25 | QEventLoop loop; 26 | 27 | }; 28 | 29 | #endif // WORKER_H 30 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-4/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-3-4 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) 16 | 17 | add_executable(qt6ca-3-4 18 | main.cpp 19 | ) 20 | target_link_libraries(qt6ca-3-4 Qt${QT_VERSION_MAJOR}::Core) 21 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-4/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Synchronous example 5 | 6 | Why 7 | Understand whats happening when we run code 8 | 9 | How 10 | Synchronous code 11 | 12 | */ 13 | 14 | #include 15 | #include 16 | 17 | void test() 18 | { 19 | qInfo() << "Testing" << QThread::currentThread(); 20 | } 21 | 22 | int main(int argc, char *argv[]) 23 | { 24 | QCoreApplication a(argc, argv); 25 | 26 | QThread::currentThread()->setObjectName("Main Thread"); 27 | qInfo() << "Starting" << QThread::currentThread(); 28 | test(); 29 | qInfo() << "Finished" << QThread::currentThread(); 30 | 31 | return a.exec(); 32 | } 33 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-5/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-3-5 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) 16 | 17 | add_executable(qt6ca-3-5 18 | main.cpp 19 | ) 20 | target_link_libraries(qt6ca-3-5 Qt${QT_VERSION_MAJOR}::Core) 21 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-5/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Asynchronous example 5 | 6 | Why 7 | Understand whats happening when we run code 8 | 9 | How 10 | Asynchronous code 11 | 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | void test() 19 | { 20 | qInfo() << "Testing" << QThread::currentThread(); 21 | } 22 | 23 | 24 | int main(int argc, char *argv[]) 25 | { 26 | QCoreApplication a(argc, argv); 27 | 28 | QThread::currentThread()->setObjectName("Main Thread"); 29 | 30 | qInfo() << "Starting" << QThread::currentThread(); 31 | QTimer timer; 32 | timer.singleShot(3000,&test); 33 | qInfo() << "Finished" << QThread::currentThread(); 34 | 35 | return a.exec(); 36 | } 37 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-6/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-3-6 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) 16 | 17 | add_executable(qt6ca-3-6 18 | main.cpp 19 | test.h 20 | test.cpp 21 | ) 22 | target_link_libraries(qt6ca-3-6 Qt${QT_VERSION_MAJOR}::Core) 23 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-6/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Threaded example 5 | 6 | Why 7 | Understand whats happening when we run code 8 | 9 | How 10 | Threaded code 11 | 12 | */ 13 | 14 | #include 15 | #include 16 | #include "test.h" 17 | 18 | int main(int argc, char *argv[]) 19 | { 20 | QCoreApplication a(argc, argv); 21 | 22 | QThread::currentThread()->setObjectName("Main Thread"); 23 | qInfo() << "Starting" << QThread::currentThread(); 24 | 25 | QThread worker; 26 | worker.setObjectName("Worker Thread"); 27 | 28 | Test test; 29 | test.moveToThread(&worker); 30 | QObject::connect(&worker,&QThread::started,&test,&Test::run); 31 | worker.start(); 32 | 33 | qInfo() << "Finished" << QThread::currentThread(); 34 | 35 | return a.exec(); 36 | } 37 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-6/test.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | Test::Test(QObject *parent) : QObject(parent) 4 | { 5 | 6 | } 7 | 8 | void Test::run() 9 | { 10 | qInfo() << "Running" << QThread::currentThread(); 11 | m_timer.singleShot(3000,this,&Test::timeout); 12 | qInfo() << "Finished" << QThread::currentThread(); 13 | } 14 | 15 | void Test::timeout() 16 | { 17 | qInfo() << "Timeout" << QThread::currentThread(); 18 | } 19 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-6/test.h: -------------------------------------------------------------------------------- 1 | #ifndef TEST_H 2 | #define TEST_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class Test : public QObject 10 | { 11 | Q_OBJECT 12 | public: 13 | explicit Test(QObject *parent = nullptr); 14 | 15 | signals: 16 | 17 | public slots: 18 | void run(); 19 | 20 | private slots: 21 | void timeout(); 22 | 23 | private: 24 | QTimer m_timer; 25 | 26 | }; 27 | 28 | #endif // TEST_H 29 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-7/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-3-7 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) 16 | 17 | add_executable(qt6ca-3-7 18 | main.cpp 19 | test.cpp 20 | test.h 21 | worker.cpp 22 | worker.h 23 | ) 24 | target_link_libraries(qt6ca-3-7 Qt${QT_VERSION_MAJOR}::Core) 25 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-7/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Inheriting QThread 5 | 6 | Why 7 | This is BAD, do not do this! 8 | Folks familiar with java will try this 9 | Its bad because you can easily break the way threading works 10 | This is super confusing as Qt documentation even uses this! 11 | 12 | How 13 | Threaded code 14 | 15 | */ 16 | 17 | 18 | #include 19 | #include 20 | #include "test.h" 21 | #include "worker.h" 22 | 23 | int main(int argc, char *argv[]) 24 | { 25 | QCoreApplication a(argc, argv); 26 | QThread::currentThread()->setObjectName("Main Thread"); 27 | 28 | Test thread; 29 | thread.setObjectName("Thread 1"); 30 | 31 | Worker worker; 32 | worker.moveToThread(&thread); 33 | QObject::connect(&thread,&QThread::started,&worker,&Worker::work); 34 | thread.start(); 35 | 36 | return a.exec(); 37 | } 38 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-7/test.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | Test::Test(QObject *parent) : QThread(parent) 4 | { 5 | 6 | } 7 | 8 | 9 | void Test::run() 10 | { 11 | //Notice after 3 seconds nothing happens!!! 12 | m_timer.singleShot(3000,this,&Test::test); 13 | test(); 14 | } 15 | 16 | void Test::test() 17 | { 18 | //Notice this gets run last! 19 | qInfo() << "TESTING" << currentThread(); 20 | 21 | terminate(); 22 | 23 | //Bad things happen from here... 24 | } 25 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-7/test.h: -------------------------------------------------------------------------------- 1 | #ifndef TEST_H 2 | #define TEST_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class Test : public QThread 10 | { 11 | Q_OBJECT 12 | public: 13 | explicit Test(QObject *parent = nullptr); 14 | 15 | signals: 16 | 17 | 18 | // QThread interface 19 | protected: 20 | void run(); 21 | 22 | private: 23 | void test(); 24 | QTimer m_timer; 25 | }; 26 | 27 | #endif // TEST_H 28 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-7/worker.cpp: -------------------------------------------------------------------------------- 1 | #include "worker.h" 2 | 3 | Worker::Worker(QObject *parent) : QObject(parent) 4 | { 5 | 6 | } 7 | 8 | void Worker::work() 9 | { 10 | for(int i = 0; i < 10; i++) 11 | { 12 | qInfo() << "Work" << i << QThread::currentThread(); 13 | QThread::currentThread()->msleep(1000); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-7/worker.h: -------------------------------------------------------------------------------- 1 | #ifndef WORKER_H 2 | #define WORKER_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class Worker : public QObject 9 | { 10 | Q_OBJECT 11 | public: 12 | explicit Worker(QObject *parent = nullptr); 13 | 14 | signals: 15 | 16 | public slots: 17 | void work(); 18 | 19 | }; 20 | 21 | #endif // WORKER_H 22 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-8/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-3-8 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) 16 | 17 | add_executable(qt6ca-3-8 18 | main.cpp 19 | counter.cpp 20 | counter.h 21 | manager.cpp 22 | manager.h 23 | ) 24 | target_link_libraries(qt6ca-3-8 Qt${QT_VERSION_MAJOR}::Core) 25 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-8/counter.cpp: -------------------------------------------------------------------------------- 1 | #include "counter.h" 2 | 3 | Counter::Counter(QObject *parent) : QObject(parent) 4 | { 5 | qInfo() << this << "Constructed"; 6 | } 7 | 8 | Counter::~Counter() 9 | { 10 | qInfo() << this << "Deconstructed"; 11 | } 12 | 13 | void Counter::start() 14 | { 15 | for(int i = 0; i < 20; i++) 16 | { 17 | qInfo() << QThread::currentThread()->objectName() << " = " << i; 18 | auto value = static_cast(QRandomGenerator::global()->bounded(500)); 19 | QThread::currentThread()->msleep(value); 20 | qInfo() << QThread::currentThread()->objectName() << " Complete"; 21 | 22 | } 23 | 24 | qInfo() << this << "Completed!"; 25 | deleteLater(); 26 | 27 | QThread::currentThread()->quit(); 28 | } 29 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-8/counter.h: -------------------------------------------------------------------------------- 1 | #ifndef COUNTER_H 2 | #define COUNTER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class Counter : public QObject 10 | { 11 | Q_OBJECT 12 | public: 13 | explicit Counter(QObject *parent = nullptr); 14 | ~Counter(); 15 | signals: 16 | 17 | public slots: 18 | void start(); 19 | }; 20 | 21 | #endif // COUNTER_H 22 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-8/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Thread lifecycle 5 | 6 | Why 7 | Threads might not live forever 8 | 9 | How 10 | Threaded code 11 | 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include "manager.h" 18 | 19 | int main(int argc, char *argv[]) 20 | { 21 | QCoreApplication a(argc, argv); 22 | QThread::currentThread()->setObjectName("Main"); 23 | 24 | Manager m; 25 | m.start(); 26 | 27 | return a.exec(); 28 | } 29 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-8/manager.cpp: -------------------------------------------------------------------------------- 1 | #include "manager.h" 2 | 3 | Manager::Manager(QObject *parent) : QObject(parent) 4 | { 5 | for(int i = 0; i < 5; i++) 6 | { 7 | QThread* thread = new QThread(this); 8 | thread->setObjectName("Thread " + QString::number(i)); 9 | qInfo() << "Created: " << thread->objectName(); 10 | connect(thread,&QThread::started, this, &Manager::started); 11 | connect(thread,&QThread::finished, this, &Manager::finished); 12 | threads.append(thread); 13 | } 14 | } 15 | 16 | void Manager::start() 17 | { 18 | qInfo() << "Starting..."; 19 | foreach(QThread* thread,threads) 20 | { 21 | qInfo() << "Starting: " << thread->objectName(); 22 | Counter* c = new Counter(); //RAW Pointer!!! 23 | c->moveToThread(thread); 24 | connect(thread,&QThread::started, c,&Counter::start); 25 | thread->start(); 26 | } 27 | } 28 | 29 | void Manager::started() 30 | { 31 | qInfo() << "Starting" << sender(); 32 | QThread* thread = qobject_cast(sender()); 33 | if(!thread) return; 34 | qInfo() << "Started: " << thread->objectName(); 35 | } 36 | 37 | void Manager::finished() 38 | { 39 | qInfo() << "Finishing" << sender(); 40 | QThread* thread = qobject_cast(sender()); 41 | if(!thread) return; 42 | qInfo() << "Children" << thread->children().length(); 43 | qInfo() << "Finished: " << thread->objectName(); 44 | 45 | threads.removeAll(thread); 46 | delete thread; 47 | } 48 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-8/manager.h: -------------------------------------------------------------------------------- 1 | #ifndef MANAGER_H 2 | #define MANAGER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "counter.h" 8 | 9 | class Manager : public QObject 10 | { 11 | Q_OBJECT 12 | public: 13 | explicit Manager(QObject *parent = nullptr); 14 | void start(); 15 | 16 | signals: 17 | 18 | public slots: 19 | void started(); 20 | void finished(); 21 | 22 | private: 23 | QList threads; 24 | }; 25 | 26 | #endif // MANAGER_H 27 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-9/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-3-9 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) 16 | 17 | add_executable(qt6ca-3-9 18 | main.cpp 19 | counter.cpp 20 | counter.h 21 | ) 22 | target_link_libraries(qt6ca-3-9 Qt${QT_VERSION_MAJOR}::Core) 23 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-9/counter.cpp: -------------------------------------------------------------------------------- 1 | #include "counter.h" 2 | 3 | Counter::Counter() 4 | { 5 | 6 | } 7 | 8 | 9 | void Counter::run() 10 | { 11 | qInfo() << "Starting: " << QThread::currentThread(); 12 | 13 | for (int i = 0; i < 20; i++) { 14 | //comment this out to see the threads being reused 15 | qInfo() << QThread::currentThread() << " = " << i; 16 | auto value = static_cast(QRandomGenerator::global()->bounded(100)); 17 | QThread::currentThread()->msleep(value); 18 | 19 | } 20 | 21 | qInfo() << "Finished: " << QThread::currentThread(); 22 | } 23 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-9/counter.h: -------------------------------------------------------------------------------- 1 | #ifndef COUNTER_H 2 | #define COUNTER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class Counter : public QRunnable 11 | { 12 | public: 13 | Counter(); 14 | 15 | // QRunnable interface 16 | public: 17 | void run(); 18 | }; 19 | 20 | #endif // COUNTER_H 21 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-9/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Thread Pools 5 | 6 | Why 7 | We want multiple resuable threads 8 | 9 | How 10 | QTreadPool and QRunnable 11 | 12 | */ 13 | 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include "counter.h" 20 | 21 | int main(int argc, char *argv[]) 22 | { 23 | QCoreApplication a(argc, argv); 24 | QThread::currentThread()->setObjectName("Main"); 25 | 26 | QThreadPool* pool = QThreadPool::globalInstance(); 27 | qInfo() << pool->maxThreadCount() << "Threads"; 28 | 29 | for(int i = 0; i < 100; i++) 30 | { 31 | Counter* c = new Counter(); 32 | c->setAutoDelete(true); 33 | pool->start(c); 34 | } 35 | 36 | return a.exec(); 37 | } 38 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-assign/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-3-assign LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Concurrent REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Concurrent REQUIRED) 16 | 17 | add_executable(qt6ca-3-assign 18 | main.cpp 19 | ) 20 | target_link_libraries(qt6ca-3-assign Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Concurrent) 21 | -------------------------------------------------------------------------------- /section 3/qt6ca-3-assign/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Assignment 5 | 6 | Why 7 | Practice what you learned 8 | 9 | How 10 | Counting files in folders 11 | 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | void count(QString path) 21 | { 22 | QDirIterator it(path, QDir::Files,QDirIterator::Subdirectories); 23 | int value = 0; 24 | while(it.hasNext()) 25 | { 26 | qInfo() < future = QtConcurrent::run(&count,root.path()); 40 | qInfo() << "Counting file..."; 41 | 42 | //Do other things... 43 | 44 | future.waitForFinished(); 45 | 46 | qInfo() << "Done"; 47 | 48 | 49 | return a.exec(); 50 | } 51 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-16/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-4-16 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Network REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Network REQUIRED) 16 | 17 | add_executable(qt6ca-4-16 18 | main.cpp 19 | ) 20 | target_link_libraries(qt6ca-4-16 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Network) 21 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-16/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Network interfaces and addresses 5 | 6 | Why 7 | We can have more than one! 8 | 9 | How 10 | QHostAddress 11 | 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | int main(int argc, char *argv[]) 20 | { 21 | QCoreApplication a(argc, argv); 22 | 23 | QList list = QNetworkInterface::allAddresses(); 24 | 25 | for(int i = 0; i < list.count(); i++) 26 | { 27 | QHostAddress address = list.at(i); 28 | qInfo() << address.toString(); 29 | 30 | //Never goes on the network 31 | qInfo() << "\t Loopback:" << address.isLoopback(); 32 | 33 | //Send to many 34 | qInfo() << "\t Multicast:" << address.isMulticast(); 35 | 36 | switch (address.protocol()) 37 | { 38 | case QAbstractSocket::UnknownNetworkLayerProtocol: 39 | qInfo() << "\tProtocol: Unknown"; 40 | break; 41 | case QAbstractSocket::AnyIPProtocol: 42 | qInfo() << "\tProtocol: Any"; 43 | break; 44 | case QAbstractSocket::IPv4Protocol: 45 | qInfo() << "\tProtocol: IP4"; 46 | break; 47 | case QAbstractSocket::IPv6Protocol: 48 | qInfo() << "\tProtocol: IP6"; 49 | break; 50 | } 51 | } 52 | 53 | return a.exec(); 54 | } 55 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-17/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-4-17 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Network REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Network REQUIRED) 16 | 17 | add_executable(qt6ca-4-17 18 | main.cpp 19 | worker.cpp 20 | worker.h 21 | ) 22 | target_link_libraries(qt6ca-4-17 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Network) 23 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-17/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | UDP 5 | 6 | Why 7 | We want to send and recive and not care about a connection 8 | 9 | How 10 | QUdpSocket 11 | 12 | */ 13 | 14 | #include 15 | #include "worker.h" 16 | 17 | int main(int argc, char *argv[]) 18 | { 19 | QCoreApplication a(argc, argv); 20 | 21 | Worker worker; 22 | worker.start(); 23 | 24 | return a.exec(); 25 | } 26 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-17/worker.cpp: -------------------------------------------------------------------------------- 1 | #include "worker.h" 2 | 3 | Worker::Worker(QObject *parent) : QObject(parent) 4 | { 5 | connect(&timer,&QTimer::timeout,this,&Worker::timeout); 6 | connect(&socket,&QUdpSocket::readyRead,this,&Worker::readyRead); 7 | timer.setInterval(1000); 8 | } 9 | 10 | void Worker::start() 11 | { 12 | if(!socket.bind(port)) // QAbstractSocket::ShareAddress 13 | { 14 | qInfo() << socket.errorString(); 15 | return; 16 | } 17 | 18 | qInfo() << "Started UDP on " << socket.localAddress() << ":" << socket.localPort(); 19 | 20 | broadcast(); 21 | } 22 | 23 | void Worker::stop() 24 | { 25 | timer.stop(); 26 | socket.close(); 27 | qInfo() << "Stopped"; 28 | } 29 | 30 | void Worker::timeout() 31 | { 32 | QString date = QDateTime::currentDateTime().toString(); 33 | QByteArray data = date.toLatin1(); 34 | 35 | QNetworkDatagram datagram(data,QHostAddress::Broadcast,port); 36 | qInfo() << "Send: " << data; 37 | socket.writeDatagram(datagram); 38 | } 39 | 40 | void Worker::readyRead() 41 | { 42 | while(socket.hasPendingDatagrams()) 43 | { 44 | QNetworkDatagram datagram = socket.receiveDatagram(); 45 | qInfo() << "Read: " << datagram.data() << " from " << datagram.senderAddress() << ":" << datagram.senderPort(); 46 | } 47 | } 48 | 49 | void Worker::broadcast() 50 | { 51 | qInfo() << "Broadcasting..."; 52 | timer.start(); 53 | } 54 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-17/worker.h: -------------------------------------------------------------------------------- 1 | #ifndef WORKER_H 2 | #define WORKER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | class Worker : public QObject 13 | { 14 | Q_OBJECT 15 | public: 16 | explicit Worker(QObject *parent = nullptr); 17 | 18 | signals: 19 | public slots: 20 | void start(); 21 | void stop(); 22 | void timeout(); 23 | void readyRead(); 24 | void broadcast(); 25 | 26 | private: 27 | QUdpSocket socket; 28 | QTimer timer; 29 | quint16 port = 2021; //Note < 1024 those admin ports / special services. HTTP, FTP, POP3, SMTP 30 | }; 31 | 32 | #endif // WORKER_H 33 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-18/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-4-18 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Network Concurrent REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Network Concurrent REQUIRED) 16 | 17 | add_executable(qt6ca-4-18 18 | main.cpp 19 | chat.cpp 20 | chat.h 21 | commandline.cpp 22 | commandline.h 23 | ) 24 | target_link_libraries(qt6ca-4-18 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Network Qt${QT_VERSION_MAJOR}::Concurrent) 25 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-18/chat.cpp: -------------------------------------------------------------------------------- 1 | #include "chat.h" 2 | 3 | Chat::Chat(QObject *parent) : QObject(parent) 4 | { 5 | if(!socket.bind(port,QUdpSocket::ShareAddress)) 6 | { 7 | qInfo() << socket.errorString(); 8 | } 9 | else 10 | { 11 | qInfo() << "Started on: " << socket.localAddress() << ":" << socket.localPort(); 12 | connect(&socket,&QUdpSocket::readyRead,this, &Chat::readyRead); 13 | } 14 | } 15 | 16 | void Chat::command(QString value) 17 | { 18 | QString message = name + ": "; 19 | if(name.isEmpty()) 20 | { 21 | name = value; 22 | message = name + ": joined"; 23 | send(message); 24 | return; 25 | } 26 | 27 | message.append(value); 28 | send(message); 29 | } 30 | 31 | void Chat::send(QString value) 32 | { 33 | QByteArray data = value.toLatin1(); 34 | QNetworkDatagram datagram(data,QHostAddress::Broadcast, port); 35 | 36 | if(!socket.writeDatagram(datagram)) 37 | { 38 | qInfo() << socket.errorString(); 39 | } 40 | } 41 | 42 | void Chat::readyRead() 43 | { 44 | while(socket.hasPendingDatagrams()) 45 | { 46 | QNetworkDatagram datagram = socket.receiveDatagram(); 47 | qInfo() << datagram.data(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-18/chat.h: -------------------------------------------------------------------------------- 1 | #ifndef CHAT_H 2 | #define CHAT_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | class Chat : public QObject 11 | { 12 | Q_OBJECT 13 | public: 14 | explicit Chat(QObject *parent = nullptr); 15 | 16 | signals: 17 | 18 | public slots: 19 | void command(QString value); 20 | void send(QString value); 21 | void readyRead(); 22 | 23 | private: 24 | QString name; 25 | QUdpSocket socket; 26 | quint16 port = 2020; 27 | 28 | }; 29 | 30 | #endif // CHAT_H 31 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-18/commandline.cpp: -------------------------------------------------------------------------------- 1 | #include "commandline.h" 2 | 3 | CommandLine::CommandLine(QObject *parent, FILE *fileHandler) : QObject(parent), cin(fileHandler) 4 | { 5 | 6 | } 7 | 8 | void CommandLine::monitor() 9 | { 10 | while(true) 11 | { 12 | QString value = cin.readLine(); 13 | emit command(value); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-18/commandline.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMANDLINE_H 2 | #define COMMANDLINE_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class CommandLine : public QObject 9 | { 10 | Q_OBJECT 11 | public: 12 | explicit CommandLine(QObject *parent = nullptr, FILE *fileHandler = nullptr); 13 | 14 | [[noreturn]] void monitor(); 15 | 16 | signals: 17 | void command(QString value); 18 | 19 | private: 20 | QTextStream cin; 21 | 22 | }; 23 | 24 | #endif // COMMANDLINE_H 25 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-18/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | UDP Chat example 5 | 6 | Why 7 | We want to see how it works 8 | 9 | How 10 | See the code 11 | 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include "commandline.h" 18 | #include "chat.h" 19 | 20 | int main(int argc, char *argv[]) 21 | { 22 | QCoreApplication a(argc, argv); 23 | 24 | CommandLine cli(&a,stdin); 25 | 26 | QFuture future = QtConcurrent::run(&CommandLine::monitor,&cli); 27 | 28 | Chat chat; 29 | QObject::connect(&cli,&CommandLine::command,&chat,&Chat::command,Qt::QueuedConnection); 30 | 31 | qInfo() << "Enter your name to begin:"; 32 | 33 | return a.exec(); 34 | } 35 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-19/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-4-19 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Network REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Network REQUIRED) 16 | 17 | add_executable(qt6ca-4-19 18 | main.cpp 19 | client.cpp 20 | client.h 21 | ) 22 | target_link_libraries(qt6ca-4-19 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Network) 23 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-19/client.cpp: -------------------------------------------------------------------------------- 1 | #include "client.h" 2 | 3 | Client::Client(QObject *parent) : QObject(parent) 4 | { 5 | connect(&socket,&QTcpSocket::connected,this,&Client::connected); 6 | connect(&socket,&QTcpSocket::disconnected,this,&Client::disconnected); 7 | 8 | connect(&socket,&QTcpSocket::stateChanged,this,&Client::stateChanged); 9 | connect(&socket,&QTcpSocket::readyRead,this,&Client::readyRead); 10 | //Qt 5 11 | //connect(&socket,QOverload::of(&QAbstractSocket::error),this,&Client::error); //Explain 12 | connect(&socket,&QTcpSocket::errorOccurred,this,&Client::error); 13 | } 14 | 15 | void Client::connectToHost(QString host, quint16 port) 16 | { 17 | if(socket.isOpen()) disconnect(); 18 | qInfo() << "Connecting to: " << host << " on port " << port; 19 | 20 | socket.connectToHost(host,port); 21 | 22 | } 23 | 24 | void Client::disconnect() 25 | { 26 | socket.close(); 27 | socket.waitForDisconnected(); 28 | } 29 | 30 | void Client::connected() 31 | { 32 | qInfo() << "Connected!"; 33 | 34 | qInfo() << "Sending"; 35 | socket.write("HELLO\r\n"); 36 | } 37 | 38 | void Client::disconnected() 39 | { 40 | qInfo() << "Disconnected"; 41 | } 42 | 43 | void Client::error(QAbstractSocket::SocketError socketError) 44 | { 45 | qInfo() << "Error:" << socketError << " " << socket.errorString(); 46 | } 47 | 48 | void Client::stateChanged(QAbstractSocket::SocketState socketState) 49 | { 50 | QMetaEnum metaEnum = QMetaEnum::fromType(); 51 | qInfo() << "State:" << metaEnum.valueToKey(socketState); 52 | } 53 | 54 | void Client::readyRead() 55 | { 56 | qInfo() << "Data from: " << sender() << " bytes: " << socket.bytesAvailable(); 57 | qInfo() << "Data: " << socket.readAll(); 58 | } 59 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-19/client.h: -------------------------------------------------------------------------------- 1 | #ifndef CLIENT_H 2 | #define CLIENT_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | class Client : public QObject 12 | { 13 | Q_OBJECT 14 | public: 15 | explicit Client(QObject *parent = nullptr); 16 | 17 | signals: 18 | 19 | public slots: 20 | void connectToHost(QString host, quint16 port); 21 | void disconnect(); 22 | 23 | private slots: 24 | void connected(); 25 | void disconnected(); 26 | void error(QAbstractSocket::SocketError socketError); 27 | void stateChanged(QAbstractSocket::SocketState socketState); 28 | void readyRead(); 29 | 30 | private: 31 | QTcpSocket socket; 32 | 33 | }; 34 | 35 | #endif // CLIENT_H 36 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-19/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | TCP Sockets 5 | 6 | Why 7 | We need to understand the connection life cycle 8 | 9 | How 10 | QTcpSocket 11 | 12 | */ 13 | 14 | 15 | #include 16 | #include "client.h" 17 | 18 | int main(int argc, char *argv[]) 19 | { 20 | QCoreApplication a(argc, argv); 21 | 22 | Client client; 23 | client.connectToHost("www.voidrealms.com", 80); 24 | 25 | return a.exec(); 26 | } 27 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-20/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-4-20 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Network REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Network REQUIRED) 16 | 17 | add_executable(qt6ca-4-20 18 | main.cpp 19 | client.cpp 20 | client.h 21 | ) 22 | target_link_libraries(qt6ca-4-20 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Network) 23 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-20/client.cpp: -------------------------------------------------------------------------------- 1 | #include "client.h" 2 | 3 | Client::Client(QObject *parent) : QObject(parent) 4 | { 5 | connect(&socket,&QTcpSocket::connected,this,&Client::connected); 6 | connect(&socket,&QTcpSocket::disconnected,this,&Client::disconnected); 7 | 8 | connect(&socket,&QTcpSocket::stateChanged,this,&Client::stateChanged); 9 | connect(&socket,&QTcpSocket::readyRead,this,&Client::readyRead); 10 | //Qt 5 11 | //connect(&socket,QOverload::of(&QAbstractSocket::error),this,&Client::error); //Explain 12 | connect(&socket,&QTcpSocket::errorOccurred,this,&Client::error); 13 | 14 | //Proxy Stuff 15 | // QNetworkProxy proxy(QNetworkProxy::HttpProxy,"190.7.141.66",47576); //Error 16 | QNetworkProxy proxy(QNetworkProxy::HttpProxy,"180.250.65.83",8080); //Ok 17 | 18 | //Set auth 19 | //proxy.setUser("user"); 20 | //proxy.setPassword("pass"); 21 | 22 | //App proxy 23 | QNetworkProxy::setApplicationProxy(proxy); 24 | 25 | //Per socket 26 | socket.setProxy(proxy); 27 | } 28 | 29 | void Client::connectToHost(QString host, quint16 port) 30 | { 31 | if(socket.isOpen()) disconnect(); 32 | qInfo() << "Connecting to: " << host << " on port " << port; 33 | 34 | socket.connectToHost(host,port); 35 | 36 | } 37 | 38 | void Client::disconnect() 39 | { 40 | socket.close(); 41 | socket.waitForDisconnected(); 42 | } 43 | 44 | void Client::connected() 45 | { 46 | qInfo() << "Connected!"; 47 | 48 | qInfo() << "Sending"; 49 | //socket.write("HELLO\r\n"); 50 | 51 | QByteArray data; 52 | data.append("GET /get HTTP/1.1\r\n"); 53 | data.append("User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)\r\n"); 54 | data.append("Host: local\r\n"); 55 | data.append("Connection: Close\r\n"); 56 | data.append("\r\n"); 57 | socket.write(data); 58 | 59 | socket.waitForBytesWritten(); 60 | } 61 | 62 | void Client::disconnected() 63 | { 64 | qInfo() << "Disconnected"; 65 | } 66 | 67 | void Client::error(QAbstractSocket::SocketError socketError) 68 | { 69 | qInfo() << "Error:" << socketError << " " << socket.errorString(); 70 | } 71 | 72 | void Client::stateChanged(QAbstractSocket::SocketState socketState) 73 | { 74 | QMetaEnum metaEnum = QMetaEnum::fromType(); 75 | qInfo() << "State:" << metaEnum.valueToKey(socketState); 76 | } 77 | 78 | void Client::readyRead() 79 | { 80 | qInfo() << "Data from: " << sender() << " bytes: " << socket.bytesAvailable(); 81 | qInfo() << "Data: " << socket.readAll(); 82 | } 83 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-20/client.h: -------------------------------------------------------------------------------- 1 | #ifndef CLIENT_H 2 | #define CLIENT_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | class Client : public QObject 12 | { 13 | Q_OBJECT 14 | public: 15 | explicit Client(QObject *parent = nullptr); 16 | 17 | signals: 18 | 19 | public slots: 20 | void connectToHost(QString host, quint16 port); 21 | void disconnect(); 22 | 23 | private slots: 24 | void connected(); 25 | void disconnected(); 26 | void error(QAbstractSocket::SocketError socketError); 27 | void stateChanged(QAbstractSocket::SocketState socketState); 28 | void readyRead(); 29 | 30 | private: 31 | QTcpSocket socket; 32 | 33 | }; 34 | 35 | #endif // CLIENT_H 36 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-20/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Network Proxy 5 | 6 | Why 7 | We want to connect to a host via a proxy 8 | Could be a company policy 9 | Maybe we want to mask our identity 10 | 11 | How 12 | QNetworkProxy 13 | 14 | https://free-proxy-list.net/ 15 | 16 | */ 17 | 18 | 19 | #include 20 | #include "client.h" 21 | 22 | int main(int argc, char *argv[]) 23 | { 24 | QCoreApplication a(argc, argv); 25 | 26 | Client client; 27 | client.connectToHost("www.httpbin.org", 80); 28 | 29 | return a.exec(); 30 | } 31 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-21/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-4-21 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Network REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Network REQUIRED) 16 | 17 | add_executable(qt6ca-4-21 18 | main.cpp 19 | client.cpp 20 | client.h 21 | ) 22 | target_link_libraries(qt6ca-4-21 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Network) 23 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-21/client.h: -------------------------------------------------------------------------------- 1 | #ifndef CLIENT_H 2 | #define CLIENT_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | class Client : public QObject 14 | { 15 | Q_OBJECT 16 | public: 17 | explicit Client(QObject *parent = nullptr); 18 | 19 | signals: 20 | 21 | public slots: 22 | void connectToHost(QString host, quint16 port); 23 | void disconnect(); 24 | 25 | private slots: 26 | void connected(); 27 | void disconnected(); 28 | void error(QAbstractSocket::SocketError socketError); 29 | void stateChanged(QAbstractSocket::SocketState socketState); 30 | void readyRead(); 31 | //SSL 32 | void encrypted(); 33 | void encryptedBytesWritten(qint64 written); 34 | void modeChanged(QSslSocket::SslMode mode); 35 | void peerVerifyError(const QSslError &error); 36 | void preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator *authenticator); 37 | void sslErrors(const QList &errors); 38 | 39 | private: 40 | QSslSocket socket; 41 | 42 | }; 43 | 44 | #endif // CLIENT_H 45 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-21/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | SSL Client 5 | 6 | Why 7 | We want an encrypted TCP connection 8 | 9 | How 10 | QSsLSocket 11 | 12 | */ 13 | 14 | 15 | #include 16 | #include "client.h" 17 | 18 | int main(int argc, char *argv[]) 19 | { 20 | QCoreApplication a(argc, argv); 21 | 22 | Client client; 23 | //client.connectToHost("www.httpbin.org", 80); //Not encrypted 24 | client.connectToHost("httpbin.org", 443); //SSL - OpenSsl 25 | return a.exec(); 26 | } 27 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-22/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-4-22 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Network REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Network REQUIRED) 16 | 17 | add_executable(qt6ca-4-22 18 | main.cpp 19 | ) 20 | target_link_libraries(qt6ca-4-22 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Network) 21 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-22/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Synchronous TCP 5 | 6 | Why 7 | We want to use TCP, and block while doing it 8 | 9 | How 10 | Example code 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | int main(int argc, char *argv[]) 18 | { 19 | QCoreApplication a(argc, argv); 20 | 21 | QTcpSocket socket; 22 | socket.connectToHost("voidrealms.com", 80); 23 | qInfo() << "Connecting..."; 24 | 25 | if(socket.waitForConnected(6000)) 26 | { 27 | qInfo() << "Connected sending request"; 28 | 29 | QByteArray data; 30 | data.append("GET / HTTP/1.1\r\n"); 31 | data.append("Host: local\r\n"); 32 | data.append("Connection: Close\r\n"); 33 | data.append("\r\n"); 34 | 35 | socket.write(data); 36 | socket.waitForBytesWritten(); 37 | 38 | if(socket.waitForReadyRead(60000)) 39 | { 40 | QByteArray response = socket.readAll(); 41 | qInfo() << "Response: " << response.length() << "bytes"; 42 | qInfo() << "Response: " << response; 43 | } 44 | 45 | socket.waitForDisconnected(); 46 | qInfo() << "Done"; 47 | } 48 | else 49 | { 50 | qInfo() << socket.errorString(); 51 | } 52 | 53 | return a.exec(); 54 | } 55 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-23/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-4-23 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Network REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Network REQUIRED) 16 | 17 | add_executable(qt6ca-4-23 18 | main.cpp 19 | ) 20 | target_link_libraries(qt6ca-4-23 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Network) 21 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-23/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Synchronous UDP 5 | 6 | Why 7 | We want UDP but we also want to block 8 | 9 | How 10 | Example code 11 | 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | bool bind(QUdpSocket* socket, quint16 port) 21 | { 22 | if(socket->bind(port,QUdpSocket::ShareAddress)) return true; 23 | 24 | qInfo() << socket->errorString(); 25 | return false; 26 | } 27 | 28 | void send(QUdpSocket* socket, quint16 port) 29 | { 30 | qInfo() << "Sending..."; 31 | QString date = QDateTime::currentDateTime().toString(); 32 | QByteArray data = date.toLatin1(); 33 | 34 | QNetworkDatagram datagram(data,QHostAddress::Broadcast,port); 35 | if(socket->writeDatagram(datagram) <= 0) 36 | { 37 | qInfo() << socket->errorString(); 38 | } 39 | } 40 | 41 | void read(QUdpSocket* socket) 42 | { 43 | qInfo() << "Reading..."; 44 | socket->waitForReadyRead(60000); 45 | while(socket->hasPendingDatagrams()) 46 | { 47 | QNetworkDatagram datagram = socket->receiveDatagram(); 48 | qInfo() << datagram.data(); 49 | } 50 | } 51 | 52 | int main(int argc, char *argv[]) 53 | { 54 | QCoreApplication a(argc, argv); 55 | 56 | QUdpSocket broadcaster; 57 | QUdpSocket client; 58 | quint16 port = 4569; 59 | 60 | qInfo() << "Binding..."; 61 | if(bind(&broadcaster,port) && bind(&client,port)) 62 | { 63 | send(&broadcaster,port); 64 | read(&client); 65 | } 66 | else 67 | { 68 | qInfo() << "Could not bind"; 69 | } 70 | 71 | return a.exec(); 72 | } 73 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-24/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-4-24 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Network REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Network REQUIRED) 16 | 17 | add_executable(qt6ca-4-24 18 | main.cpp 19 | client.cpp 20 | client.h 21 | ) 22 | target_link_libraries(qt6ca-4-24 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Network) 23 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-24/client.cpp: -------------------------------------------------------------------------------- 1 | #include "client.h" 2 | 3 | Client::Client(QObject *parent) : QObject(parent) 4 | { 5 | 6 | connect(&socket,&QTcpSocket::connected,this,&Client::connected); 7 | connect(&socket,&QTcpSocket::disconnected,this,&Client::disconnected); 8 | 9 | connect(&socket,&QTcpSocket::stateChanged,this,&Client::stateChanged); 10 | connect(&socket,&QTcpSocket::readyRead,this,&Client::readyRead); 11 | //Qt 5 12 | //connect(&socket,QOverload::of(&QAbstractSocket::error),this,&Client::error); //Explain 13 | connect(&socket,&QTcpSocket::errorOccurred,this,&Client::error); 14 | } 15 | 16 | void Client::connectToHost(QString host, quint16 port) 17 | { 18 | qInfo() << Q_FUNC_INFO << QThread::currentThread(); 19 | if(socket.isOpen()) disconnect(); 20 | qInfo() << "Connecting to: " << host << " on port " << port; 21 | 22 | socket.connectToHost(host,port); 23 | } 24 | 25 | void Client::disconnect() 26 | { 27 | qInfo() << Q_FUNC_INFO << QThread::currentThread(); 28 | socket.close(); 29 | } 30 | 31 | void Client::connected() 32 | { 33 | qInfo() << Q_FUNC_INFO << QThread::currentThread(); 34 | qInfo() << "Connected!"; 35 | 36 | qInfo() << "Sending"; 37 | socket.write("HELLO\r\n"); 38 | } 39 | 40 | void Client::disconnected() 41 | { 42 | qInfo() << Q_FUNC_INFO << QThread::currentThread(); 43 | qInfo() << "Disconnected"; 44 | } 45 | 46 | void Client::error(QAbstractSocket::SocketError socketError) 47 | { 48 | qInfo() << Q_FUNC_INFO << QThread::currentThread(); 49 | qInfo() << "Error:" << socketError << " " << socket.errorString(); 50 | } 51 | 52 | void Client::stateChanged(QAbstractSocket::SocketState socketState) 53 | { 54 | //qInfo() << Q_FUNC_INFO << QThread::currentThread(); 55 | QMetaEnum metaEnum = QMetaEnum::fromType(); 56 | qInfo() << "State: " << metaEnum.valueToKey(socketState); 57 | } 58 | 59 | void Client::readyRead() 60 | { 61 | qInfo() << Q_FUNC_INFO << QThread::currentThread(); 62 | qInfo() << "Data from: " << sender() << " bytes: " << socket.bytesAvailable() ; 63 | qInfo() << "Data: " << socket.readAll(); 64 | } 65 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-24/client.h: -------------------------------------------------------------------------------- 1 | #ifndef CLIENT_H 2 | #define CLIENT_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | class Client : public QObject 13 | { 14 | Q_OBJECT 15 | public: 16 | explicit Client(QObject *parent = nullptr); 17 | 18 | signals: 19 | 20 | public slots: 21 | void connectToHost(QString host, quint16 port); 22 | void disconnect(); 23 | 24 | private slots: 25 | void connected(); 26 | void disconnected(); 27 | void error(QAbstractSocket::SocketError socketError); 28 | void stateChanged(QAbstractSocket::SocketState socketState); 29 | void readyRead(); 30 | 31 | private: 32 | QTcpSocket socket; 33 | }; 34 | 35 | #endif // CLIENT_H 36 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-24/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Asynchronous TCP 5 | 6 | Why 7 | This is how you would typically work with it 8 | 9 | How 10 | Signals and slots 11 | Note this blocks in the slots! 12 | 13 | */ 14 | 15 | #include 16 | #include 17 | #include "client.h" 18 | 19 | int main(int argc, char *argv[]) 20 | { 21 | QCoreApplication a(argc, argv); 22 | QThread::currentThread()->setObjectName("Main Thread"); 23 | 24 | Client client; 25 | client.connectToHost("www.voidrealms.com",80); 26 | 27 | qInfo() << "*** Free to do other things ***"; 28 | return a.exec(); 29 | } 30 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-25/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-4-25 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Network REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Network REQUIRED) 16 | 17 | add_executable(qt6ca-4-25 18 | main.cpp 19 | worker.cpp 20 | worker.h 21 | ) 22 | target_link_libraries(qt6ca-4-25 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Network) 23 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-25/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Asynchronous UDP 5 | 6 | Why 7 | This is how we normally work with it 8 | 9 | How 10 | Remember slots block! 11 | 12 | */ 13 | 14 | #include 15 | #include 16 | #include "worker.h" 17 | 18 | int main(int argc, char *argv[]) 19 | { 20 | QCoreApplication a(argc, argv); 21 | 22 | QThread::currentThread()->setObjectName("Main Thread"); 23 | Worker worker; 24 | worker.start(); 25 | 26 | return a.exec(); 27 | } 28 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-25/worker.cpp: -------------------------------------------------------------------------------- 1 | #include "worker.h" 2 | 3 | Worker::Worker(QObject *parent) : QObject(parent) 4 | { 5 | connect(&timer,&QTimer::timeout,this,&Worker::timeout); 6 | connect(&socket,&QUdpSocket::readyRead,this,&Worker::readyRead); 7 | timer.setInterval(1000); 8 | } 9 | 10 | void Worker::start() 11 | { 12 | qInfo() << Q_FUNC_INFO << QThread::currentThread(); 13 | if(!socket.bind(port)) 14 | { 15 | qInfo() << socket.errorString(); 16 | return; 17 | } 18 | 19 | qInfo() << "Started UDP on " << socket.localAddress() << ":" << socket.localPort(); 20 | 21 | broadcast(); 22 | } 23 | 24 | void Worker::stop() 25 | { 26 | qInfo() << Q_FUNC_INFO << QThread::currentThread(); 27 | timer.stop(); 28 | socket.close(); 29 | qInfo() << "Stopped"; 30 | } 31 | 32 | void Worker::timeout() 33 | { 34 | qInfo() << Q_FUNC_INFO << QThread::currentThread(); 35 | QString date = QDateTime::currentDateTime().toString(); 36 | QByteArray data = date.toLatin1(); 37 | 38 | QNetworkDatagram datagram(data,QHostAddress::Broadcast,port); 39 | qInfo() << "Send: " << data; 40 | socket.writeDatagram(datagram); 41 | } 42 | 43 | void Worker::readyRead() 44 | { 45 | qInfo() << Q_FUNC_INFO << QThread::currentThread(); 46 | while (socket.hasPendingDatagrams()) 47 | { 48 | QNetworkDatagram datagram = socket.receiveDatagram(); 49 | qInfo() << "Read: " << datagram.data() << " from " << datagram.senderAddress() << ":" << datagram.senderPort(); 50 | } 51 | } 52 | 53 | void Worker::broadcast() 54 | { 55 | qInfo() << Q_FUNC_INFO << QThread::currentThread(); 56 | qInfo() << "Broadcasting..."; 57 | timer.start(); 58 | } 59 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-25/worker.h: -------------------------------------------------------------------------------- 1 | #ifndef WORKER_H 2 | #define WORKER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | 13 | class Worker : public QObject 14 | { 15 | Q_OBJECT 16 | public: 17 | explicit Worker(QObject *parent = nullptr); 18 | 19 | signals: 20 | 21 | public slots: 22 | void start(); 23 | void stop(); 24 | void timeout(); 25 | void readyRead(); 26 | void broadcast(); 27 | 28 | private: 29 | QUdpSocket socket; 30 | QTimer timer; 31 | quint16 port = 2020; //Note < 1024 those admin ports / special services. HTTP, FTP, POP3, SMTP 32 | }; 33 | 34 | #endif // WORKER_H 35 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-26/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-4-26 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Network REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Network REQUIRED) 16 | 17 | add_executable(qt6ca-4-26 18 | main.cpp 19 | client.cpp 20 | client.h 21 | ) 22 | target_link_libraries(qt6ca-4-26 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Network) 23 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-26/client.cpp: -------------------------------------------------------------------------------- 1 | #include "client.h" 2 | 3 | Client::Client(QObject *parent) : QObject(parent) 4 | { 5 | m_host = ""; 6 | m_port = 0; 7 | } 8 | 9 | Client::~Client() 10 | { 11 | qInfo() << Q_FUNC_INFO << QThread::currentThread(); 12 | qInfo() << "Deconstructor"; 13 | } 14 | 15 | void Client::connectToHost(QString host, quint16 port) 16 | { 17 | qInfo() << Q_FUNC_INFO << QThread::currentThread(); 18 | if(socket->isOpen()) disconnect(); 19 | qInfo() << "Connecting to: " << host << " on port " << port; 20 | 21 | socket->connectToHost(host,port); 22 | } 23 | 24 | void Client::disconnect() 25 | { 26 | qInfo() << Q_FUNC_INFO << QThread::currentThread(); 27 | socket->close(); 28 | } 29 | 30 | void Client::run() 31 | { 32 | //Our code starts running on a thread here... 33 | qInfo() << Q_FUNC_INFO << QThread::currentThread(); 34 | 35 | socket = new QTcpSocket(this); 36 | connect(socket,&QTcpSocket::connected,this,&Client::connected); 37 | connect(socket,&QTcpSocket::disconnected,this,&Client::disconnected); 38 | 39 | connect(socket,&QTcpSocket::stateChanged,this,&Client::stateChanged); 40 | connect(socket,&QTcpSocket::readyRead,this,&Client::readyRead); 41 | //Qt 5 42 | //connect(&socket,QOverload::of(&QAbstractSocket::error),this,&Client::error); //Explain 43 | connect(socket,&QTcpSocket::errorOccurred,this,&Client::error); 44 | 45 | connectToHost(m_host,m_port); 46 | 47 | //Design choices here! 48 | socket->waitForDisconnected(); //BLOCK 49 | qInfo() << "Complete!"; 50 | deleteLater(); 51 | 52 | 53 | }//Keep the thread alive 54 | 55 | void Client::connected() 56 | { 57 | qInfo() << Q_FUNC_INFO << QThread::currentThread(); 58 | qInfo() << "Connected!"; 59 | 60 | qInfo() << "Sending"; 61 | socket->write("HELLO\r\n"); 62 | } 63 | 64 | void Client::disconnected() 65 | { 66 | qInfo() << Q_FUNC_INFO << QThread::currentThread(); 67 | qInfo() << "Disconnected"; 68 | } 69 | 70 | void Client::error(QAbstractSocket::SocketError socketError) 71 | { 72 | qInfo() << Q_FUNC_INFO << QThread::currentThread(); 73 | qInfo() << "Error:" << socketError << " " << socket->errorString(); 74 | } 75 | 76 | void Client::stateChanged(QAbstractSocket::SocketState socketState) 77 | { 78 | //qInfo() << Q_FUNC_INFO << QThread::currentThread(); 79 | QMetaEnum metaEnum = QMetaEnum::fromType(); 80 | qInfo() << "State: " << metaEnum.valueToKey(socketState); 81 | } 82 | 83 | void Client::readyRead() 84 | { 85 | qInfo() << Q_FUNC_INFO << QThread::currentThread(); 86 | qInfo() << "Data from: " << sender() << " bytes: " << socket->bytesAvailable() ; 87 | qInfo() << "Data: " << socket->readAll(); 88 | } 89 | 90 | quint16 Client::port() const 91 | { 92 | return m_port; 93 | } 94 | 95 | void Client::setPort(quint16 newPort) 96 | { 97 | m_port = newPort; 98 | } 99 | 100 | const QString &Client::host() const 101 | { 102 | return m_host; 103 | } 104 | 105 | void Client::setHost(const QString &newHost) 106 | { 107 | m_host = newHost; 108 | } 109 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-26/client.h: -------------------------------------------------------------------------------- 1 | #ifndef CLIENT_H 2 | #define CLIENT_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | class Client : public QObject 14 | { 15 | Q_OBJECT 16 | public: 17 | explicit Client(QObject *parent = nullptr); 18 | ~Client(); 19 | 20 | const QString &host() const; 21 | void setHost(const QString &newHost); 22 | 23 | quint16 port() const; 24 | void setPort(quint16 newPort); 25 | 26 | signals: 27 | 28 | public slots: 29 | void connectToHost(QString host, quint16 port); 30 | void disconnect(); 31 | void run(); 32 | 33 | private slots: 34 | void connected(); 35 | void disconnected(); 36 | void error(QAbstractSocket::SocketError socketError); 37 | void stateChanged(QAbstractSocket::SocketState socketState); 38 | void readyRead(); 39 | 40 | private: 41 | QTcpSocket* socket; 42 | QString m_host; 43 | quint16 m_port; 44 | }; 45 | 46 | #endif // CLIENT_H 47 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-26/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Threaded TCP 5 | 6 | Why 7 | We want to use both Threaded and Async code 8 | 9 | How 10 | QThread and QTcpSocket 11 | 12 | */ 13 | 14 | #include 15 | #include 16 | #include "client.h" 17 | 18 | int main(int argc, char *argv[]) 19 | { 20 | QCoreApplication a(argc, argv); 21 | 22 | QThread::currentThread()->setObjectName("Main Thread"); 23 | 24 | QThread thread; 25 | thread.setObjectName("Client Thread"); 26 | 27 | Client* client = new Client(); 28 | client->moveToThread(&thread); 29 | QObject::connect(&thread, &QThread::started,client,&Client::run); 30 | client->setHost("voidrealms.com"); 31 | client->setPort(80); 32 | 33 | thread.start(); 34 | 35 | 36 | 37 | 38 | return a.exec(); 39 | } 40 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-27/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-4-27 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Network REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Network REQUIRED) 16 | 17 | add_executable(qt6ca-4-27 18 | main.cpp 19 | worker.cpp 20 | worker.h 21 | ) 22 | target_link_libraries(qt6ca-4-27 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Network) 23 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-27/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Threaded UDP 5 | 6 | Why 7 | We want to use threading and async 8 | 9 | How 10 | Remember slots block! 11 | 12 | */ 13 | 14 | #include 15 | #include 16 | #include "worker.h" 17 | 18 | int main(int argc, char *argv[]) 19 | { 20 | QCoreApplication a(argc, argv); 21 | 22 | QThread::currentThread()->setObjectName("Main Thread"); 23 | 24 | QThread thread; 25 | thread.setObjectName("Worker Thread"); 26 | Worker* worker = new Worker(); 27 | worker->moveToThread(&thread); 28 | QObject::connect(&thread,&QThread::started,worker,&Worker::start); 29 | thread.start(); 30 | 31 | return a.exec(); 32 | } 33 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-27/worker.cpp: -------------------------------------------------------------------------------- 1 | #include "worker.h" 2 | 3 | Worker::Worker(QObject *parent) : QObject(parent) 4 | { 5 | 6 | } 7 | 8 | Worker::~Worker() 9 | { 10 | qInfo() << Q_FUNC_INFO << QThread::currentThread(); 11 | qInfo() << "Deconstructed"; 12 | } 13 | 14 | void Worker::start() 15 | { 16 | qInfo() << Q_FUNC_INFO << QThread::currentThread(); 17 | 18 | timer = new QTimer(this); 19 | socket = new QUdpSocket(this); 20 | loop = new QEventLoop(this); 21 | counter = 0; 22 | 23 | connect(timer,&QTimer::timeout,this,&Worker::timeout); 24 | connect(socket,&QUdpSocket::readyRead,this,&Worker::readyRead); 25 | timer->setInterval(1000); 26 | 27 | if(!socket->bind(port)) 28 | { 29 | qInfo() << socket->errorString(); 30 | return; 31 | } 32 | 33 | qInfo() << "Started UDP on " << socket->localAddress() << ":" << socket->localPort(); 34 | 35 | broadcast(); 36 | loop->exec(); //BLOCK 37 | } 38 | 39 | void Worker::stop() 40 | { 41 | qInfo() << Q_FUNC_INFO << QThread::currentThread(); 42 | timer->stop(); 43 | socket->close(); 44 | 45 | if(loop) 46 | { 47 | qInfo() << "Stopping event loop"; 48 | loop->quit(); 49 | delete loop; 50 | } 51 | 52 | qInfo() << "Stopped"; 53 | deleteLater(); 54 | } 55 | 56 | void Worker::timeout() 57 | { 58 | qInfo() << Q_FUNC_INFO << QThread::currentThread(); 59 | QString date = QDateTime::currentDateTime().toString(); 60 | QByteArray data = date.toLatin1(); 61 | 62 | QNetworkDatagram datagram(data,QHostAddress::Broadcast,port); 63 | qInfo() << "Send: " << data; 64 | socket->writeDatagram(datagram); 65 | 66 | counter++; 67 | if(counter >= 3) stop(); 68 | 69 | } 70 | 71 | void Worker::readyRead() 72 | { 73 | qInfo() << Q_FUNC_INFO << QThread::currentThread(); 74 | while (socket->hasPendingDatagrams()) 75 | { 76 | QNetworkDatagram datagram = socket->receiveDatagram(); 77 | qInfo() << "Read: " << datagram.data() << " from " << datagram.senderAddress() << ":" << datagram.senderPort(); 78 | } 79 | } 80 | 81 | void Worker::broadcast() 82 | { 83 | qInfo() << Q_FUNC_INFO << QThread::currentThread(); 84 | qInfo() << "Broadcasting..."; 85 | timer->start(); 86 | } 87 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-27/worker.h: -------------------------------------------------------------------------------- 1 | #ifndef WORKER_H 2 | #define WORKER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | class Worker : public QObject 14 | { 15 | Q_OBJECT 16 | public: 17 | explicit Worker(QObject *parent = nullptr); 18 | ~Worker(); 19 | 20 | signals: 21 | 22 | public slots: 23 | void start(); 24 | void stop(); 25 | void timeout(); 26 | void readyRead(); 27 | void broadcast(); 28 | 29 | private: 30 | QUdpSocket* socket; 31 | QTimer* timer; 32 | QEventLoop *loop; 33 | quint16 port = 2020; //Note < 1024 those admin ports / special services. HTTP, FTP, POP3, SMTP 34 | int counter; 35 | }; 36 | 37 | #endif // WORKER_H 38 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-28/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-4-28 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Network REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Network REQUIRED) 16 | 17 | add_executable(qt6ca-4-28 18 | main.cpp 19 | worker.cpp 20 | worker.h 21 | ) 22 | target_link_libraries(qt6ca-4-28 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Network) 23 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-28/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Make HTTP Calls 5 | 6 | Why 7 | We want to work with web servers 8 | 9 | How 10 | QNetworkAccessManager HTTP 11 | 12 | */ 13 | 14 | #include 15 | #include "worker.h" 16 | 17 | int main(int argc, char *argv[]) 18 | { 19 | QCoreApplication a(argc, argv); 20 | Worker worker; 21 | worker.get("https://postman-echo.com/get?foo1=bar1&foo2=bar2"); 22 | 23 | QByteArray data; 24 | data.append("param1=hello"); 25 | data.append("&"); 26 | data.append("param2=foo"); 27 | 28 | worker.post("https://postman-echo.com/post",data); 29 | 30 | return a.exec(); 31 | } 32 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-28/worker.cpp: -------------------------------------------------------------------------------- 1 | #include "worker.h" 2 | 3 | Worker::Worker(QObject *parent) : QObject(parent) 4 | { 5 | connect(&manager,&QNetworkAccessManager::authenticationRequired,this,&Worker::authenticationRequired); 6 | connect(&manager,&QNetworkAccessManager::encrypted,this,&Worker::encrypted); 7 | connect(&manager,&QNetworkAccessManager::preSharedKeyAuthenticationRequired,this,&Worker::preSharedKeyAuthenticationRequired); 8 | connect(&manager,&QNetworkAccessManager::proxyAuthenticationRequired,this,&Worker::proxyAuthenticationRequired); 9 | connect(&manager,&QNetworkAccessManager::sslErrors,this,&Worker::sslErrors); 10 | 11 | } 12 | 13 | void Worker::get(QString location) 14 | { 15 | qInfo() << "Getting from server..."; 16 | QNetworkReply* reply = manager.get(QNetworkRequest(QUrl(location))); 17 | connect(reply,&QNetworkReply::readyRead,this,&Worker::readyRead); 18 | } 19 | 20 | void Worker::post(QString location, QByteArray data) 21 | { 22 | qInfo() << "Posting to the server..."; 23 | QNetworkRequest request = QNetworkRequest(QUrl(location)); 24 | request.setHeader(QNetworkRequest::ContentTypeHeader, "test/plain"); //mime type 25 | 26 | QNetworkReply* reply = manager.post(request,data); 27 | connect(reply,&QNetworkReply::readyRead,this,&Worker::readyRead); 28 | } 29 | 30 | void Worker::readyRead() 31 | { 32 | qInfo() << "ReadyRead"; 33 | QNetworkReply* reply = qobject_cast(sender()); 34 | if(reply) qInfo() << reply->readAll(); 35 | } 36 | 37 | void Worker::authenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator) 38 | { 39 | Q_UNUSED(reply); 40 | Q_UNUSED(authenticator); 41 | qInfo() << "authenticationRequired"; 42 | } 43 | 44 | void Worker::encrypted(QNetworkReply *reply) 45 | { 46 | Q_UNUSED(reply); 47 | qInfo() << "encrypted"; 48 | } 49 | 50 | //void Worker::finished(QNetworkReply *reply) 51 | void Worker::finished() 52 | { 53 | QNetworkReply* reply = qobject_cast(sender()); 54 | qInfo() << "finished"; 55 | reply->deleteLater(); 56 | } 57 | 58 | void Worker::preSharedKeyAuthenticationRequired(QNetworkReply *reply, QSslPreSharedKeyAuthenticator *authenticator) 59 | { 60 | Q_UNUSED(reply); 61 | Q_UNUSED(authenticator); 62 | qInfo() << "preSharedKeyAuthenticationRequired"; 63 | } 64 | 65 | void Worker::proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator) 66 | { 67 | Q_UNUSED(proxy); 68 | Q_UNUSED(authenticator); 69 | qInfo() << "proxyAuthenticationRequired"; 70 | } 71 | 72 | void Worker::sslErrors(QNetworkReply *reply, const QList &errors) 73 | { 74 | Q_UNUSED(reply); 75 | Q_UNUSED(errors); 76 | qInfo() << "sslErrors"; 77 | } 78 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-28/worker.h: -------------------------------------------------------------------------------- 1 | #ifndef WORKER_H 2 | #define WORKER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | 13 | class Worker : public QObject 14 | { 15 | Q_OBJECT 16 | public: 17 | explicit Worker(QObject *parent = nullptr); 18 | 19 | signals: 20 | 21 | public slots: 22 | void get(QString location); 23 | void post(QString location, QByteArray data); 24 | 25 | private slots: 26 | void readyRead(); 27 | void authenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator); 28 | void encrypted(QNetworkReply *reply); 29 | //void finished(QNetworkReply *reply); 30 | void finished(); 31 | void preSharedKeyAuthenticationRequired(QNetworkReply *reply, QSslPreSharedKeyAuthenticator *authenticator); 32 | void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator); 33 | void sslErrors(QNetworkReply *reply, const QList &errors); 34 | 35 | private: 36 | QNetworkAccessManager manager; 37 | }; 38 | 39 | #endif // WORKER_H 40 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-29/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-4-29 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Network REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Network REQUIRED) 16 | 17 | add_executable(qt6ca-4-29 18 | main.cpp 19 | worker.cpp 20 | worker.h 21 | ) 22 | target_link_libraries(qt6ca-4-29 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Network) 23 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-29/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Work with FTP servers 5 | 6 | Why 7 | We want to upload and download using FTP 8 | 9 | How 10 | QNetworkAccessManager FTP 11 | 12 | NOTE - they took FTP out of Qt 6 and will eventually move it to a different lib 13 | You will get Error: QNetworkReply::ProtocolUnknownError 14 | Even using Core5Compat wont fix this, you will need to wait until they release the module, or make your own 15 | (You can always use Qt5) 16 | 17 | https://www.qt.io/blog/qt-network-in-qt-6 18 | https://doc-snapshots.qt.io/qt6-dev/qtscxml-ftpclient-example.html 19 | 20 | 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include "worker.h" 27 | #include 28 | 29 | //QNetworkAccessManager - FTP Example 30 | 31 | void upload(Worker* worker, QString path) 32 | { 33 | QString location = "ftp://speedtest.tele2.net/upload/VoidRealms-" + QString::number(QDateTime::currentSecsSinceEpoch()) + ".bin"; 34 | worker->upload(location,path); 35 | 36 | } 37 | 38 | void download(Worker* worker, QString path) 39 | { 40 | QString location = "ftp://speedtest.tele2.net/512KB.zip"; 41 | worker->download(location,path); 42 | } 43 | 44 | int main(int argc, char *argv[]) 45 | { 46 | QCoreApplication a(argc, argv); 47 | 48 | QNetworkAccessManager manager; 49 | qInfo() << manager.supportedSchemes(); //Shows what is supported in Qt 6 50 | 51 | Worker worker; 52 | //upload(&worker,"test.txt"); 53 | //download(&worker,"test.zip"); 54 | 55 | return a.exec(); 56 | } 57 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-29/worker.cpp: -------------------------------------------------------------------------------- 1 | #include "worker.h" 2 | 3 | Worker::Worker(QObject *parent) : QObject(parent) 4 | { 5 | connect(&manager,&QNetworkAccessManager::finished,this,&Worker::finished); 6 | } 7 | 8 | void Worker::upload(QString location, QString path) 9 | { 10 | qInfo() << "Uploading: " << path; 11 | 12 | file.setFileName(path); 13 | if(!file.open(QIODevice::ReadOnly)) 14 | { 15 | qInfo() << file.errorString(); 16 | return; 17 | } 18 | 19 | QUrl url(location); 20 | //url.setPassword("anonymous"); 21 | //url.setUserName("anonymous"); 22 | //url.setPort(21); 23 | 24 | QNetworkRequest request = QNetworkRequest(url); 25 | QNetworkReply* reply = manager.put(request,&file); 26 | wire(reply); 27 | 28 | } 29 | 30 | void Worker::download(QString location, QString path) 31 | { 32 | qInfo() << "Downloading: " << path; 33 | 34 | file.setFileName(path); 35 | if(!file.open(QIODevice::WriteOnly)) 36 | { 37 | qInfo() << file.errorString(); 38 | return; 39 | } 40 | 41 | QUrl url(location); 42 | //url.setPassword("anonymous"); 43 | //url.setUserName("anonymous"); 44 | //url.setPort(21); 45 | 46 | QNetworkRequest request = QNetworkRequest(url); 47 | 48 | QNetworkReply* reply = manager.get(request); 49 | wire(reply); 50 | } 51 | 52 | void Worker::readyRead() 53 | { 54 | QNetworkReply* reply = qobject_cast(sender()); 55 | if(reply) 56 | { 57 | QByteArray data = reply->readAll(); 58 | file.write(data); 59 | } 60 | } 61 | 62 | void Worker::finished(QNetworkReply *reply) 63 | { 64 | qInfo() << "Finished"; 65 | file.close(); 66 | reply->close(); 67 | } 68 | 69 | void Worker::uploadProgress(qint64 bytesSent, qint64 bytesTotal) 70 | { 71 | if(bytesTotal <= 0) return; 72 | qInfo() << "Uploading: " << bytesSent << " of " << bytesTotal; 73 | 74 | } 75 | 76 | void Worker::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) 77 | { 78 | if(bytesTotal <= 0) return; 79 | qInfo() << "Downloading: " << bytesReceived << " of " << bytesTotal; 80 | } 81 | 82 | void Worker::error(QNetworkReply::NetworkError code) 83 | { 84 | qInfo() << "Error: " << code; 85 | } 86 | 87 | void Worker::wire(QNetworkReply *reply) 88 | { 89 | connect(reply,&QNetworkReply::readyRead,this,&Worker::readyRead); 90 | connect(reply,&QNetworkReply::uploadProgress,this,&Worker::uploadProgress); 91 | connect(reply,&QNetworkReply::downloadProgress,this,&Worker::downloadProgress); 92 | //Qt5 93 | //connect(reply,QOverload::of(&QNetworkReply::error),this,&Worker::error); 94 | connect(reply,&QNetworkReply::errorOccurred,this,&Worker::error); 95 | } 96 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-29/worker.h: -------------------------------------------------------------------------------- 1 | #ifndef WORKER_H 2 | #define WORKER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class Worker : public QObject 11 | { 12 | Q_OBJECT 13 | public: 14 | explicit Worker(QObject *parent = nullptr); 15 | 16 | void upload(QString location, QString path); 17 | void download(QString location, QString path); 18 | 19 | signals: 20 | 21 | public slots: 22 | 23 | private slots: 24 | void readyRead(); 25 | void finished(QNetworkReply *reply); 26 | void uploadProgress(qint64 bytesSent, qint64 bytesTotal); 27 | void downloadProgress(qint64 bytesReceived, qint64 bytesTotal); 28 | void error(QNetworkReply::NetworkError code); 29 | private: 30 | QNetworkAccessManager manager; 31 | QFile file; 32 | 33 | void wire(QNetworkReply* reply); 34 | }; 35 | 36 | #endif // WORKER_H 37 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-30/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-4-30 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Network REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Network REQUIRED) 16 | 17 | add_executable(qt6ca-4-30 18 | main.cpp 19 | server.cpp 20 | server.h 21 | ) 22 | target_link_libraries(qt6ca-4-30 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Network) 23 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-30/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Create a TCP Server 5 | 6 | Why 7 | We want to make a custom server 8 | 9 | How 10 | QTcpServer 11 | 12 | */ 13 | 14 | #include 15 | #include "server.h" 16 | 17 | int main(int argc, char *argv[]) 18 | { 19 | QCoreApplication a(argc, argv); 20 | 21 | Server server; 22 | server.start(); 23 | 24 | 25 | return a.exec(); 26 | } 27 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-30/server.cpp: -------------------------------------------------------------------------------- 1 | #include "server.h" 2 | 3 | Server::Server(QObject *parent) : QObject(parent) 4 | { 5 | connect(&server,&QTcpServer::newConnection,this,&Server::newConnection); 6 | } 7 | 8 | void Server::start() 9 | { 10 | if(!server.listen(QHostAddress::Any,4509)) 11 | { 12 | qWarning() << server.errorString(); 13 | return; 14 | } 15 | 16 | qInfo() << "Listening..."; 17 | } 18 | 19 | void Server::quit() 20 | { 21 | server.close(); 22 | } 23 | 24 | void Server::newConnection() 25 | { 26 | QTcpSocket* socket = server.nextPendingConnection(); 27 | connect(socket,&QTcpSocket::disconnected,this,&Server::disconnected); 28 | connect(socket,&QTcpSocket::readyRead,this,&Server::readyRead); 29 | 30 | qInfo() << "Connected" << socket; 31 | } 32 | 33 | void Server::disconnected() 34 | { 35 | QTcpSocket* socket = qobject_cast(sender()); 36 | qInfo() << "Disconnected" << socket; 37 | qInfo() << "Parent" << socket->parent(); 38 | 39 | socket->deleteLater(); 40 | } 41 | 42 | void Server::readyRead() 43 | { 44 | QTcpSocket* socket = qobject_cast(sender()); 45 | qInfo() << "ReadyReady" << socket; 46 | qInfo() << socket->readAll(); 47 | } 48 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-30/server.h: -------------------------------------------------------------------------------- 1 | #ifndef SERVER_H 2 | #define SERVER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class Server : public QObject 11 | { 12 | Q_OBJECT 13 | public: 14 | explicit Server(QObject *parent = nullptr); 15 | 16 | signals: 17 | 18 | public slots: 19 | void start(); 20 | void quit(); 21 | void newConnection(); 22 | void disconnected(); 23 | void readyRead(); 24 | 25 | private: 26 | QTcpServer server; 27 | }; 28 | 29 | #endif // SERVER_H 30 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-31/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-4-31 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Network REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Network REQUIRED) 16 | 17 | add_executable(qt6ca-4-31 18 | main.cpp 19 | client.cpp 20 | client.h 21 | server.cpp 22 | server.h 23 | ) 24 | target_link_libraries(qt6ca-4-31 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Network) 25 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-31/client.cpp: -------------------------------------------------------------------------------- 1 | #include "client.h" 2 | 3 | Client::Client(QObject *parent, qintptr handle) : QObject(parent) 4 | { 5 | this->handle = handle; 6 | } 7 | 8 | 9 | void Client::run() 10 | { 11 | qInfo() << this << " run " << QThread::currentThread(); 12 | 13 | QTcpSocket* socket = new QTcpSocket(nullptr); 14 | if(!socket->setSocketDescriptor(handle)) 15 | { 16 | qCritical() << socket->errorString(); 17 | delete socket; 18 | return; 19 | } 20 | 21 | socket->waitForReadyRead(); 22 | QByteArray request = socket->readAll(); 23 | qInfo() << "Request Length: " << request.length(); 24 | 25 | QByteArray data("Hello World!"); 26 | QByteArray response; 27 | response.append("HTTP/1.1 200 OK\r\n"); 28 | response.append("Content-Type: text/plain\r\n"); 29 | response.append("Content-Length: " + QString::number(data.length()).toUtf8() + "\r\n"); 30 | response.append("Connection: close\r\n"); 31 | response.append("\r\n"); 32 | response.append(data); 33 | 34 | socket->write(response); 35 | socket->waitForBytesWritten(); 36 | socket->close(); 37 | socket->deleteLater(); 38 | 39 | qInfo() << this << " done " << QThread::currentThread(); 40 | } 41 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-31/client.h: -------------------------------------------------------------------------------- 1 | #ifndef CLIENT_H 2 | #define CLIENT_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class Client : public QObject, public QRunnable 11 | { 12 | Q_OBJECT 13 | public: 14 | explicit Client(QObject *parent = nullptr, qintptr handle = 0); 15 | 16 | signals: 17 | 18 | // QRunnable interface 19 | public: 20 | void run(); 21 | 22 | private: 23 | qintptr handle; 24 | }; 25 | 26 | #endif // CLIENT_H 27 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-31/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | High performance multi-threaded TCP server 5 | 6 | Why 7 | Lets see how to make it fast 8 | 9 | How 10 | Code example 11 | Test with Siege 12 | https://www.joedog.org/siege-home/ 13 | 14 | siege -c 1 127.0.0.1:2020 15 | siege -c 10 127.0.0.1:2020 16 | siege -c 100 127.0.0.1:2020 17 | 18 | */ 19 | 20 | #include 21 | #include "server.h" 22 | 23 | int main(int argc, char *argv[]) 24 | { 25 | QCoreApplication a(argc, argv); 26 | 27 | Server server; 28 | server.start(2020); 29 | 30 | return a.exec(); 31 | } 32 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-31/server.cpp: -------------------------------------------------------------------------------- 1 | #include "server.h" 2 | 3 | Server::Server(QObject *parent) : QTcpServer(parent) 4 | { 5 | pool.setMaxThreadCount(200); 6 | qInfo() << "Threads: " << pool.maxThreadCount(); 7 | } 8 | 9 | void Server::start(quint16 port) 10 | { 11 | qInfo() << this << " start " << QThread::currentThread(); 12 | if(this->listen(QHostAddress::Any, port)) 13 | { 14 | qInfo() << "Server started on " << port; 15 | } 16 | else 17 | { 18 | qCritical() << this->errorString(); 19 | } 20 | } 21 | 22 | void Server::quit() 23 | { 24 | this->close(); 25 | qInfo() << "Server Stopped!"; 26 | } 27 | 28 | void Server::incomingConnection(qintptr handle) 29 | { 30 | //Not version friendly!!! 31 | qInfo() << "Incomming Connection " << handle << " on " << QThread::currentThread(); 32 | Client* client = new Client(nullptr, handle); 33 | client->setAutoDelete(true); 34 | pool.start(client); 35 | 36 | } 37 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-31/server.h: -------------------------------------------------------------------------------- 1 | #ifndef SERVER_H 2 | #define SERVER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "client.h" 11 | 12 | class Server : public QTcpServer 13 | { 14 | Q_OBJECT 15 | public: 16 | explicit Server(QObject *parent = nullptr); 17 | 18 | signals: 19 | 20 | public slots: 21 | void start(quint16 port); 22 | void quit(); 23 | 24 | private: 25 | QThreadPool pool; 26 | 27 | // QTcpServer interface 28 | protected: 29 | void incomingConnection(qintptr handle) Q_DECL_OVERRIDE; 30 | }; 31 | 32 | #endif // SERVER_H 33 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-32/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-4-32 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Network REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Network REQUIRED) 16 | 17 | add_executable(qt6ca-4-32 18 | main.cpp 19 | client.cpp 20 | client.h 21 | server.cpp 22 | server.h 23 | ) 24 | target_link_libraries(qt6ca-4-32 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Network) 25 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-32/client.cpp: -------------------------------------------------------------------------------- 1 | #include "client.h" 2 | 3 | Client::Client(QObject *parent, qintptr handle) : QObject(parent) 4 | { 5 | this->handle = handle; 6 | } 7 | 8 | 9 | void Client::run() 10 | { 11 | qInfo() << this << " run " << QThread::currentThread(); 12 | 13 | QTcpSocket* socket = new QTcpSocket(nullptr); 14 | if(!socket->setSocketDescriptor(handle)) 15 | { 16 | qCritical() << socket->errorString(); 17 | delete socket; 18 | return; 19 | } 20 | 21 | socket->waitForReadyRead(); 22 | QByteArray request = socket->readAll(); 23 | qInfo() << "Request Length: " << request.length(); 24 | 25 | QByteArray data("Hello World!"); 26 | QByteArray response; 27 | response.append("HTTP/1.1 200 OK\r\n"); 28 | response.append("Content-Type: text/plain\r\n"); 29 | response.append("Content-Length: " + QString::number(data.length()).toUtf8() + "\r\n"); 30 | response.append("Connection: close\r\n"); 31 | response.append("\r\n"); 32 | response.append(data); 33 | 34 | socket->write(response); 35 | socket->waitForBytesWritten(); 36 | socket->close(); 37 | socket->deleteLater(); 38 | 39 | qInfo() << this << " done " << QThread::currentThread(); 40 | } 41 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-32/client.h: -------------------------------------------------------------------------------- 1 | #ifndef CLIENT_H 2 | #define CLIENT_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class Client : public QObject, public QRunnable 11 | { 12 | Q_OBJECT 13 | public: 14 | explicit Client(QObject *parent = nullptr, qintptr handle = 0); 15 | 16 | signals: 17 | 18 | // QRunnable interface 19 | public: 20 | void run(); 21 | 22 | private: 23 | qintptr handle; 24 | }; 25 | 26 | #endif // CLIENT_H 27 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-32/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | High performance multi-threaded TCP server 5 | 6 | Why 7 | Lets see how to make it fast 8 | 9 | How 10 | Code example 11 | Test with Siege 12 | https://www.joedog.org/siege-home/ 13 | 14 | siege -c 1 127.0.0.1:2020 15 | siege -c 10 127.0.0.1:2020 16 | siege -c 100 127.0.0.1:2020 17 | 18 | */ 19 | 20 | #include 21 | #include "server.h" 22 | 23 | int main(int argc, char *argv[]) 24 | { 25 | QCoreApplication a(argc, argv); 26 | 27 | Server server; 28 | server.start(2020); 29 | 30 | return a.exec(); 31 | } 32 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-32/server.cpp: -------------------------------------------------------------------------------- 1 | #include "server.h" 2 | 3 | Server::Server(QObject *parent) : QTcpServer(parent) 4 | { 5 | pool.setMaxThreadCount(200); 6 | qInfo() << "Threads: " << pool.maxThreadCount(); 7 | } 8 | 9 | void Server::start(quint16 port) 10 | { 11 | qInfo() << this << " start " << QThread::currentThread(); 12 | if(this->listen(QHostAddress::Any, port)) 13 | { 14 | qInfo() << "Server started on " << port; 15 | } 16 | else 17 | { 18 | qCritical() << this->errorString(); 19 | } 20 | } 21 | 22 | void Server::quit() 23 | { 24 | this->close(); 25 | qInfo() << "Server Stopped!"; 26 | } 27 | 28 | void Server::incomingConnection(qintptr handle) 29 | { 30 | //Not version friendly!!! 31 | qInfo() << "Incomming Connection " << handle << " on " << QThread::currentThread(); 32 | Client* client = new Client(nullptr, handle); 33 | client->setAutoDelete(true); 34 | pool.start(client); 35 | 36 | } 37 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-32/server.h: -------------------------------------------------------------------------------- 1 | #ifndef SERVER_H 2 | #define SERVER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "client.h" 11 | 12 | class Server : public QTcpServer 13 | { 14 | Q_OBJECT 15 | public: 16 | explicit Server(QObject *parent = nullptr); 17 | 18 | signals: 19 | 20 | public slots: 21 | void start(quint16 port); 22 | void quit(); 23 | 24 | private: 25 | QThreadPool pool; 26 | 27 | // QTcpServer interface 28 | protected: 29 | void incomingConnection(qintptr handle) Q_DECL_OVERRIDE; 30 | }; 31 | 32 | #endif // SERVER_H 33 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-33/server.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICtjCCAh8CFFKYqxL2nd0zzDHZr9EA0dHgM05gMA0GCSqGSIb3DQEBCwUAMIGZ 3 | MQswCQYDVQQGEwJVUzERMA8GA1UECAwITWljaGlnYW4xFTATBgNVBAcMDEJhdHRs 4 | ZSBDcmVlazETMBEGA1UECgwKVm9pZFJlYWxtczELMAkGA1UECwwCVlIxFzAVBgNV 5 | BAMMDlZvaWRSZWFsbXMuY29tMSUwIwYJKoZIhvcNAQkBFhZiY2Fpcm5zQHZvaWRy 6 | ZWFsbXMuY29tMB4XDTIxMDcwMzIzNTEyMFoXDTIyMDcwMzIzNTEyMFowgZkxCzAJ 7 | BgNVBAYTAlVTMREwDwYDVQQIDAhNaWNoaWdhbjEVMBMGA1UEBwwMQmF0dGxlIENy 8 | ZWVrMRMwEQYDVQQKDApWb2lkUmVhbG1zMQswCQYDVQQLDAJWUjEXMBUGA1UEAwwO 9 | Vm9pZFJlYWxtcy5jb20xJTAjBgkqhkiG9w0BCQEWFmJjYWlybnNAdm9pZHJlYWxt 10 | cy5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALnjtXLasaT5bFvEEmMH 11 | qdwSUSqFRS1NQQOvP6q3IkW0EyibekyBLF7BTvhdKPpGqELhUjGqpjpxWw8fQYiN 12 | kCirhQe4WyyM4Gy08Xi949IpklqWTFJOG9revuZ1SEaI1U/Zq8BcoiQ+OsnHOhe5 13 | FxhBexuty+O1VVtlfNdxdEnbAgMBAAEwDQYJKoZIhvcNAQELBQADgYEAayi0j54N 14 | bGNlBT80H350RxTkxWu56nijxA2oZX7oK0IZfmp6eeUJYhdGDvcq5RlYR9YpCl3u 15 | 55zEipjBGV/iggMi3/05ED3U7RHp/17H/kBxQ47cmwCkLsr1tXUQ8isLI4gPNvyw 16 | cRthgactlNTjVearXYQ6gRNB2VZLz1vAe2Y= 17 | -----END CERTIFICATE----- 18 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-33/server.csr: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIICEjCCAXsCAQAwgZkxCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhNaWNoaWdhbjEV 3 | MBMGA1UEBwwMQmF0dGxlIENyZWVrMRMwEQYDVQQKDApWb2lkUmVhbG1zMQswCQYD 4 | VQQLDAJWUjEXMBUGA1UEAwwOVm9pZFJlYWxtcy5jb20xJTAjBgkqhkiG9w0BCQEW 5 | FmJjYWlybnNAdm9pZHJlYWxtcy5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ 6 | AoGBALnjtXLasaT5bFvEEmMHqdwSUSqFRS1NQQOvP6q3IkW0EyibekyBLF7BTvhd 7 | KPpGqELhUjGqpjpxWw8fQYiNkCirhQe4WyyM4Gy08Xi949IpklqWTFJOG9revuZ1 8 | SEaI1U/Zq8BcoiQ+OsnHOhe5FxhBexuty+O1VVtlfNdxdEnbAgMBAAGgODAXBgkq 9 | hkiG9w0BCQcxCgwIcGFzc3dvcmQwHQYJKoZIhvcNAQkCMRAMDnZvaWRyZWFsbXMu 10 | Y29tMA0GCSqGSIb3DQEBCwUAA4GBABfj0WMicoxrW2RD8eVQmkMYOi2U8Kc3H6WF 11 | lcYtBL+vtr/JeGt7ZG+6MgqSQLM8vthIkjU+vpY2+LQvWfooMFZQ1dYDp7lYoqAK 12 | B00NG2lbc49H5QtuhQpSDH033E6QW1/GWUVU+jYnPIVTPHKChJD9nuSVPcwArI8L 13 | abzzwBtK 14 | -----END CERTIFICATE REQUEST----- 15 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-33/server.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIICXQIBAAKBgQC547Vy2rGk+WxbxBJjB6ncElEqhUUtTUEDrz+qtyJFtBMom3pM 3 | gSxewU74XSj6RqhC4VIxqqY6cVsPH0GIjZAoq4UHuFssjOBstPF4vePSKZJalkxS 4 | Thva3r7mdUhGiNVP2avAXKIkPjrJxzoXuRcYQXsbrcvjtVVbZXzXcXRJ2wIDAQAB 5 | AoGAGjeGUMONSGIxKSQXH8Zl63bd4axYHFKH99gQl6gqekAyb4i2D/Ir6tVCqP6i 6 | l+G9O2mB6SVTOmzgVdqnqHWmvggiOLdkbmEEx9snPBkQFAKnz7iGrh9inH4o8XFy 7 | NxaFfwfV5NufujNUfgKjDWSFUeA5j0NbjLaXfvZ+Mh87xCECQQDaaUpvMIDmIyOa 8 | mEotGq17IgxdaEOPXgpMU2V/ERcw5/mf6BhiLg+JUADrzhGRlSSp5m2FmmV2zWAk 9 | XCwbTrFxAkEA2eGUo0mWF0QzB9EZ83bFftVG7b0gOEgbf2hwv5t1rCoBPkDTZG6o 10 | Pr58/hGX/SrcwUekdylgRcgqugv2fkhKCwJBAK5ba56D3ALcfmnFtUF4kJFBxxky 11 | SOzEp/fyg44CuL7EEVUEVaLbHnABvBqCsSfFJjWzzC7h6KoEngGoy1UpZyECQQCe 12 | ajeKKZypOfroeg4mSHr75tH1VQcyJKtpjWQ8zClYjgntW3DXmuVVCWcTy3L4rctn 13 | 9FEOGtVWp1z5fG0yEBlVAkB09QCp1NrUtjFBDNjZgV901IyFXGOmNGBm8uZ+ewjb 14 | snlZQ5Y/yrWU6XoxuuXsrlnR/SluBfSYt5D1DuCQrvI/ 15 | -----END RSA PRIVATE KEY----- 16 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-33/server.key.org: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | Proc-Type: 4,ENCRYPTED 3 | DEK-Info: DES-EDE3-CBC,E54E52CECD3B51CF 4 | 5 | 8zNiFesgyExWp9UlUNUTVtddrXHrN/Z+RT3/6vl6zEdEy+2OJh6PrEYVVI80L8Lp 6 | 6+ulgDIXLXrdkwovZCqWdweVpeF6RzgVY/Mr+3h1UfbOhwibZN9WhQaqoRC+hdjA 7 | xQ2VEmA6O4OIYp3E+92Qzk/zGJkbXfngq2r+xNxKVFAMB0bjDYxcOdIKPFBOXbmo 8 | zsOkHjhr/ImO64XfjC8XpGjgt4o+5IoIOPDwpQl7JcIimcMRBPUZ6GmJSU9S8tDi 9 | erhLxmnXbZrbA1KiaNWGfn7kBSd6RlXBr83LOus17/em29PzMXsmacoRfUIaQU0a 10 | hYjtQGManx33hMNaGFK5YR3HM8TqbmBvtThTlqzih2nxbYftQUlhO3WKXuGOVMnr 11 | ylh1BOF2HTjgMEJLf4BBubcb0yjm9AzEyDn4VUFWgvkkOOCqn3pu3y+EwLdIrIjL 12 | YGWQOIXT3CQBQrTPzrgAt9DZK6xC3jet4qTipI8x0mkARuFhychWl8+dEEp9X7cR 13 | 1uTrsB9sCarnTR950bzpLr1L9xbf/quzPqK3xkh4ze/wGdO3bbk8Lpv3xBKv5hlf 14 | msCpgAS8HydNw5Pt5q9C02Lzqbzt5uLKRsEm0LjAp/tJTPJfkKYCJUk9CN3mrf7z 15 | CRb/3MpKMsJZF6VYWu7Gfte/xvFcaBUGWMN0MdTM3L15xqVnRlPhCO8N0kqaxI5A 16 | ceZ+IUiFcaN2HVWKoj5GdviEcKiVVf4t2m4B2uatm5GzFXFp+6X4rFtzE0srl5aa 17 | CF69aA/lMDlDmEmER4nBcxdQ2cdYgnkI4+wdHXgsvbSAfKe0EOfQog== 18 | -----END RSA PRIVATE KEY----- 19 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-34/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-4-34 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Network REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Network REQUIRED) 16 | 17 | add_executable(qt6ca-4-34 18 | main.cpp 19 | server.cpp 20 | server.h 21 | ) 22 | target_link_libraries(qt6ca-4-34 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Network) 23 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-34/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | What 3 | SSL Server 4 | 5 | Why 6 | We want to use the certificate 7 | 8 | How 9 | Server code 10 | 11 | Create a cert 12 | https://stackoverflow.com/questions/33198360/qt-with-qsslsocket-not-connecting-properly 13 | 14 | #Step 1: Generate a Private Key 15 | openssl genrsa -des3 -out server.key 1024 16 | 17 | #Step 2: Generate a CSR (Certificate Signing Request) 18 | #Common Name (eg, your name or your server's hostname) []:example.com 19 | openssl req -new -key server.key -out server.csr 20 | 21 | #Step 3: Remove Passphrase from Key 22 | cp server.key server.key.org 23 | openssl rsa -in server.key.org -out server.key 24 | 25 | #Step 4: Generating a Self-Signed Certificate 26 | openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt 27 | 28 | 29 | Test the connection 30 | openssl s_client -connect 127.0.0.1:2020 31 | 32 | open a web browser and navigate to 127.0.0.1:2020 33 | 34 | */ 35 | 36 | 37 | #include 38 | #include "server.h" 39 | 40 | int main(int argc, char *argv[]) 41 | { 42 | QCoreApplication a(argc, argv); 43 | 44 | Server server; 45 | server.setKey("/home/rootshell/Code/cert/server.key"); 46 | server.setCert("/home/rootshell/Code/cert/server.crt"); 47 | 48 | if(!server.listen(QHostAddress::Any, 2020)) 49 | { 50 | qInfo() << server.errorString(); 51 | } 52 | else 53 | { 54 | qInfo() << "Listening on " << server.serverAddress() << ":" << server.serverPort(); 55 | } 56 | 57 | return a.exec(); 58 | } 59 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-34/server.h: -------------------------------------------------------------------------------- 1 | #ifndef SERVER_H 2 | #define SERVER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | class Server : public QTcpServer 13 | { 14 | Q_OBJECT 15 | public: 16 | explicit Server(QObject *parent = nullptr); 17 | 18 | void setCert(QString value); 19 | void setKey(QString value); 20 | 21 | signals: 22 | 23 | public slots: 24 | void disconnected(); 25 | void readyRead(); 26 | void encrypted(); 27 | void encryptedBytesWritten(qint64 written); 28 | void modeChanged(QSslSocket::SslMode mode); 29 | void peerVerifyError(const QSslError &error); 30 | void sslErrors(const QList &errors); 31 | void socketError(QAbstractSocket::SocketError err); 32 | 33 | // QTcpServer interface 34 | protected: 35 | void incomingConnection(qintptr handle) Q_DECL_OVERRIDE; 36 | 37 | private: 38 | QString certPath; 39 | QString keyPath; 40 | 41 | }; 42 | 43 | #endif // SERVER_H 44 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-35/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-4-35 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Network REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Network REQUIRED) 16 | 17 | add_executable(qt6ca-4-35 18 | main.cpp 19 | server.cpp 20 | server.h 21 | ) 22 | target_link_libraries(qt6ca-4-35 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Network) 23 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-35/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | What 3 | SSL Server 4 | 5 | Why 6 | We want to use the certificate 7 | 8 | How 9 | Server code 10 | 11 | Create a cert 12 | https://stackoverflow.com/questions/33198360/qt-with-qsslsocket-not-connecting-properly 13 | 14 | #Step 1: Generate a Private Key 15 | openssl genrsa -des3 -out server.key 1024 16 | 17 | #Step 2: Generate a CSR (Certificate Signing Request) 18 | #Common Name (eg, your name or your server's hostname) []:example.com 19 | openssl req -new -key server.key -out server.csr 20 | 21 | #Step 3: Remove Passphrase from Key 22 | cp server.key server.key.org 23 | openssl rsa -in server.key.org -out server.key 24 | 25 | #Step 4: Generating a Self-Signed Certificate 26 | openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt 27 | 28 | 29 | Test the connection 30 | openssl s_client -connect 127.0.0.1:2020 31 | 32 | open a web browser and navigate to 127.0.0.1:2020 33 | 34 | */ 35 | 36 | 37 | #include 38 | #include "server.h" 39 | 40 | int main(int argc, char *argv[]) 41 | { 42 | QCoreApplication a(argc, argv); 43 | 44 | Server server; 45 | server.setKey("/home/rootshell/Code/cert/server.key"); 46 | server.setCert("/home/rootshell/Code/cert/server.crt"); 47 | 48 | if(!server.listen(QHostAddress::Any, 2020)) 49 | { 50 | qInfo() << server.errorString(); 51 | } 52 | else 53 | { 54 | qInfo() << "Listening on " << server.serverAddress() << ":" << server.serverPort(); 55 | } 56 | 57 | return a.exec(); 58 | } 59 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-35/server.h: -------------------------------------------------------------------------------- 1 | #ifndef SERVER_H 2 | #define SERVER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | class Server : public QTcpServer 13 | { 14 | Q_OBJECT 15 | public: 16 | explicit Server(QObject *parent = nullptr); 17 | 18 | void setCert(QString value); 19 | void setKey(QString value); 20 | 21 | signals: 22 | 23 | public slots: 24 | void disconnected(); 25 | void readyRead(); 26 | void encrypted(); 27 | void encryptedBytesWritten(qint64 written); 28 | void modeChanged(QSslSocket::SslMode mode); 29 | void peerVerifyError(const QSslError &error); 30 | void sslErrors(const QList &errors); 31 | void socketError(QAbstractSocket::SocketError err); 32 | 33 | // QTcpServer interface 34 | protected: 35 | void incomingConnection(qintptr handle) Q_DECL_OVERRIDE; 36 | 37 | private: 38 | QString certPath; 39 | QString keyPath; 40 | 41 | }; 42 | 43 | #endif // SERVER_H 44 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-assign/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-4-assign LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Network REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Network REQUIRED) 16 | 17 | add_executable(qt6ca-4-assign 18 | main.cpp 19 | ) 20 | target_link_libraries(qt6ca-4-assign Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Network) 21 | -------------------------------------------------------------------------------- /section 4/qt6ca-4-assign/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | QNetworkAccessManager in blocking mode 5 | QEventLoop can help 6 | 7 | Why 8 | Its Easy 9 | 10 | How 11 | Code 12 | 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | int main(int argc, char *argv[]) 22 | { 23 | QCoreApplication a(argc, argv); 24 | 25 | QNetworkAccessManager manager; 26 | QNetworkRequest request(QUrl("https://postman-echo.com/get")); 27 | QNetworkReply* reply = manager.get(request); 28 | 29 | //reply->waitForReadyRead(); 30 | QEventLoop loop; 31 | a.connect(reply,&QNetworkReply::finished,&loop,&QEventLoop::quit); 32 | loop.exec(); 33 | 34 | qInfo() << reply->readAll(); 35 | reply->deleteLater(); 36 | 37 | return a.exec(); 38 | } 39 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-10/myapp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(myapp LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) 16 | 17 | add_executable(myapp 18 | main.cpp 19 | ) 20 | add_library(mylib SHARED IMPORTED) # or STATIC instead of SHARED 21 | set_target_properties(mylib PROPERTIES 22 | IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/lib/libmylib.so" 23 | INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/inc" 24 | ) 25 | target_link_libraries(myapp mylib Qt${QT_VERSION_MAJOR}::Core) 26 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-10/myapp/inc/mylib.h: -------------------------------------------------------------------------------- 1 | #ifndef MYLIB_H 2 | #define MYLIB_H 3 | 4 | #include "mylib_global.h" 5 | #include 6 | 7 | class MYLIB_EXPORT Mylib 8 | { 9 | public: 10 | Mylib(); 11 | void test(); 12 | }; 13 | 14 | #endif // MYLIB_H 15 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-10/myapp/inc/mylib_global.h: -------------------------------------------------------------------------------- 1 | #ifndef MYLIB_GLOBAL_H 2 | #define MYLIB_GLOBAL_H 3 | 4 | #include 5 | 6 | #if defined(MYLIB_LIBRARY) 7 | # define MYLIB_EXPORT Q_DECL_EXPORT 8 | #else 9 | # define MYLIB_EXPORT Q_DECL_IMPORT 10 | #endif 11 | 12 | #endif // MYLIB_GLOBAL_H 13 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-10/myapp/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Use an external lib 5 | 6 | Why 7 | See how to use libs outside our normal project 8 | 9 | How 10 | Build the lib 11 | Modify the app Cmake 12 | Build the app 13 | :-1: error: library not found for -lmylib 14 | Correct the path 15 | 16 | copy the compiled lib and includes to the source dir 17 | Modyfy CMakeLists.txt 18 | 19 | add_library(mylib SHARED IMPORTED) # or STATIC instead of SHARED 20 | set_target_properties(mylib PROPERTIES 21 | IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/lib/libmylib.dylib" 22 | INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/inc" 23 | ) 24 | target_link_libraries(myapp mylib Qt${QT_VERSION_MAJOR}::Core) 25 | 26 | */ 27 | 28 | #include 29 | #include "inc/mylib_global.h" 30 | #include "inc/mylib.h" 31 | 32 | int main(int argc, char *argv[]) 33 | { 34 | QCoreApplication a(argc, argv); 35 | 36 | Mylib lib; 37 | lib.test(); 38 | 39 | return a.exec(); 40 | } 41 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-10/mylib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(mylib LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | set(CMAKE_AUTOUIC ON) 7 | set(CMAKE_AUTOMOC ON) 8 | set(CMAKE_AUTORCC ON) 9 | set(CMAKE_CXX_STANDARD 11) 10 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 11 | 12 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) 13 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) 14 | 15 | add_library(mylib SHARED 16 | mylib_global.h 17 | mylib.cpp 18 | mylib.h 19 | ) 20 | 21 | target_link_libraries(mylib PRIVATE Qt${QT_VERSION_MAJOR}::Core) 22 | 23 | target_compile_definitions(mylib PRIVATE MYLIB_LIBRARY) 24 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-10/mylib/mylib.cpp: -------------------------------------------------------------------------------- 1 | #include "mylib.h" 2 | 3 | Mylib::Mylib() 4 | { 5 | } 6 | 7 | void Mylib::test() 8 | { 9 | qInfo() << "Hello from my library!"; 10 | } 11 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-10/mylib/mylib.h: -------------------------------------------------------------------------------- 1 | #ifndef MYLIB_H 2 | #define MYLIB_H 3 | 4 | #include "mylib_global.h" 5 | #include 6 | 7 | class MYLIB_EXPORT Mylib 8 | { 9 | public: 10 | Mylib(); 11 | void test(); 12 | }; 13 | 14 | #endif // MYLIB_H 15 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-10/mylib/mylib_global.h: -------------------------------------------------------------------------------- 1 | #ifndef MYLIB_GLOBAL_H 2 | #define MYLIB_GLOBAL_H 3 | 4 | #include 5 | 6 | #if defined(MYLIB_LIBRARY) 7 | # define MYLIB_EXPORT Q_DECL_EXPORT 8 | #else 9 | # define MYLIB_EXPORT Q_DECL_IMPORT 10 | #endif 11 | 12 | #endif // MYLIB_GLOBAL_H 13 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-12/myapp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(myapp LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) 16 | 17 | add_executable(myapp 18 | main.cpp 19 | ) 20 | add_library(mylib STATIC IMPORTED) # or STATIC instead of SHARED 21 | set_target_properties(mylib PROPERTIES 22 | IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/lib/libmylib.a" 23 | INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/inc" 24 | ) 25 | target_link_libraries(myapp mylib Qt${QT_VERSION_MAJOR}::Core) 26 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-12/myapp/inc/mylib.h: -------------------------------------------------------------------------------- 1 | #ifndef MYLIB_H 2 | #define MYLIB_H 3 | 4 | #include 5 | 6 | class Mylib 7 | { 8 | public: 9 | Mylib(); 10 | void test(); 11 | }; 12 | 13 | #endif // MYLIB_H 14 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-12/myapp/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Use an static lib 5 | 6 | Why 7 | We want to link the lib directly into our binary 8 | 9 | How 10 | Build the lib in static 11 | Explain the ".a" file 12 | Copy it to /lib 13 | Copy the includes to the /inc 14 | Modify CMakeLists.txt 15 | 16 | ldd = linux 17 | otool -l = mac 18 | 19 | */ 20 | 21 | #include 22 | #include "inc/mylib.h" 23 | 24 | int main(int argc, char *argv[]) 25 | { 26 | QCoreApplication a(argc, argv); 27 | 28 | Mylib lib; 29 | lib.test(); 30 | 31 | return a.exec(); 32 | } 33 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-12/mylib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(mylib LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | set(CMAKE_AUTOUIC ON) 7 | set(CMAKE_AUTOMOC ON) 8 | set(CMAKE_AUTORCC ON) 9 | set(CMAKE_CXX_STANDARD 11) 10 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 11 | 12 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) 13 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) 14 | 15 | add_library(mylib STATIC 16 | mylib.cpp 17 | mylib.h 18 | ) 19 | 20 | target_link_libraries(mylib PRIVATE Qt${QT_VERSION_MAJOR}::Core) 21 | 22 | target_compile_definitions(mylib PRIVATE MYLIB_LIBRARY) 23 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-12/mylib/mylib.cpp: -------------------------------------------------------------------------------- 1 | #include "mylib.h" 2 | 3 | Mylib::Mylib() 4 | { 5 | } 6 | 7 | void Mylib::test() 8 | { 9 | qInfo() << "Hello from my STATIC library!"; 10 | } 11 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-12/mylib/mylib.h: -------------------------------------------------------------------------------- 1 | #ifndef MYLIB_H 2 | #define MYLIB_H 3 | 4 | #include 5 | 6 | class Mylib 7 | { 8 | public: 9 | Mylib(); 10 | void test(); 11 | }; 12 | 13 | #endif // MYLIB_H 14 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-13/myapp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(myapp LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) 16 | 17 | add_executable(myapp 18 | main.cpp 19 | plugin.h 20 | ) 21 | target_link_libraries(myapp Qt${QT_VERSION_MAJOR}::Core) 22 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-13/myapp/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Application plugins 5 | 6 | Why 7 | We want to extend our application 8 | 9 | How 10 | QPluginLoader 11 | Make the plugin 12 | Build it 13 | Include the Plugin.h file 14 | Add the compiled plugin to a sub folder called "plugins" in the build directory 15 | 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include "plugin.h" 25 | 26 | QStringList getPlugins(QString path) 27 | { 28 | QStringList plugins; 29 | 30 | QStringList filter; 31 | filter << "*.dll" << "*.so" << "*.dylib"; 32 | 33 | QDir dir(path); 34 | QFileInfoList list = dir.entryInfoList(filter); 35 | foreach(QFileInfo file, list) 36 | { 37 | plugins.append(file.filePath()); 38 | //Mac - if(!file.isSymLink()) plugins.append(file.filePath()); 39 | } 40 | 41 | return plugins; 42 | } 43 | 44 | void testPlugins(QStringList plugins) 45 | { 46 | foreach(QString file, plugins) 47 | { 48 | qInfo() << "Loading..." << file; 49 | 50 | QPluginLoader loader(file); 51 | if(!loader.load()) 52 | { 53 | qInfo() << "Error: " << loader.fileName() << " Error: " << loader.errorString(); 54 | continue; 55 | } 56 | 57 | qInfo() << "Loaded: " << loader.fileName(); 58 | Plugin* plugin = qobject_cast(loader.instance()); 59 | if(plugin) 60 | { 61 | plugin->test("Bryan"); 62 | loader.unload(); 63 | } 64 | else 65 | { 66 | qInfo() << "Could not cast: " << loader.fileName(); 67 | } 68 | } 69 | } 70 | 71 | int main(int argc, char *argv[]) 72 | { 73 | QCoreApplication a(argc, argv); 74 | 75 | qInfo() << "Hello Plugins"; 76 | QDir dir = QDir::current(); 77 | // dir.cdUp(); 78 | dir.cd("plugins"); // Plugins 79 | qInfo() << "Path: " << dir.path(); 80 | 81 | QStringList plugins = getPlugins(dir.path()); 82 | qInfo() << "Plugins: " << plugins; 83 | 84 | testPlugins(plugins); 85 | 86 | qInfo() << "Done!"; 87 | 88 | return a.exec(); 89 | } 90 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-13/myapp/plugin.h: -------------------------------------------------------------------------------- 1 | #ifndef PLUGIN_H 2 | #define PLUGIN_H 3 | 4 | #include 5 | #include 6 | 7 | class Plugin 8 | { 9 | public: 10 | //virtual ~Plugin() = 0; 11 | virtual void test(QString name) = 0; 12 | }; 13 | 14 | //Declare the interface 15 | Q_DECLARE_INTERFACE(Plugin,"com.voidrealms.plugin") 16 | 17 | #endif // PLUGIN_H 18 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-13/myplugin/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(myplugin LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | set(CMAKE_AUTOUIC ON) 7 | set(CMAKE_AUTOMOC ON) 8 | set(CMAKE_AUTORCC ON) 9 | set(CMAKE_CXX_STANDARD 11) 10 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 11 | 12 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) 13 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) 14 | 15 | add_library(myplugin SHARED 16 | myplugin.cpp 17 | myplugin.h 18 | plugin.h 19 | ) 20 | 21 | target_link_libraries(myplugin PRIVATE Qt${QT_VERSION_MAJOR}::Core) 22 | 23 | target_compile_definitions(myplugin PRIVATE MYPLUGIN_LIBRARY) 24 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-13/myplugin/myplugin.cpp: -------------------------------------------------------------------------------- 1 | #include "myplugin.h" 2 | 3 | 4 | MyPlugin::MyPlugin(QObject *parent) 5 | { 6 | Q_UNUSED(parent); 7 | qInfo() << "Plugin Constructed"; 8 | } 9 | 10 | MyPlugin::~MyPlugin() 11 | { 12 | qInfo() << "Plugin Deconstructed"; 13 | } 14 | 15 | 16 | void MyPlugin::test(QString name) 17 | { 18 | qInfo() << "Test from plugin: " << name; 19 | } 20 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-13/myplugin/myplugin.h: -------------------------------------------------------------------------------- 1 | #ifndef MYPLUGIN_H 2 | #define MYPLUGIN_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "plugin.h" 9 | 10 | class MyPlugin: public QObject, public Plugin 11 | { 12 | Q_OBJECT 13 | Q_PLUGIN_METADATA(IID "com.voidrealms.plugin") 14 | Q_INTERFACES(Plugin) 15 | 16 | public: 17 | explicit MyPlugin(QObject* parent = nullptr); 18 | ~MyPlugin(); 19 | 20 | signals: 21 | 22 | public slots: 23 | 24 | // Plugin interface 25 | public: 26 | void test(QString name) Q_DECL_OVERRIDE; // override 27 | }; 28 | 29 | #endif // MYPLUGIN_H 30 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-13/myplugin/myplugin_global.h: -------------------------------------------------------------------------------- 1 | #ifndef MYPLUGIN_GLOBAL_H 2 | #define MYPLUGIN_GLOBAL_H 3 | 4 | #include 5 | 6 | #if defined(MYPLUGIN_LIBRARY) 7 | # define MYPLUGIN_EXPORT Q_DECL_EXPORT 8 | #else 9 | # define MYPLUGIN_EXPORT Q_DECL_IMPORT 10 | #endif 11 | 12 | #endif // MYPLUGIN_GLOBAL_H 13 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-13/myplugin/plugin.h: -------------------------------------------------------------------------------- 1 | #ifndef PLUGIN_H 2 | #define PLUGIN_H 3 | 4 | #include 5 | #include 6 | 7 | class Plugin 8 | { 9 | public: 10 | //virtual ~Plugin() = 0; 11 | virtual void test(QString name) = 0; 12 | }; 13 | 14 | //Declare the interface 15 | Q_DECLARE_INTERFACE(Plugin,"com.voidrealms.plugin") 16 | 17 | #endif // PLUGIN_H 18 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-9/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | add_subdirectory(mylib) 4 | add_subdirectory(myapp) 5 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-9/myapp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(myapp LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) 16 | 17 | add_executable(myapp 18 | main.cpp 19 | ) 20 | target_link_libraries(myapp mylib Qt${QT_VERSION_MAJOR}::Core) 21 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-9/myapp/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Make a library 5 | 6 | Why 7 | We want to see how 8 | 9 | How 10 | CMake add sub dirs 11 | 12 | */ 13 | 14 | 15 | #include 16 | #include "../mylib/mylib_global.h" 17 | #include "../mylib/mylib.h" 18 | 19 | int main(int argc, char *argv[]) 20 | { 21 | QCoreApplication a(argc, argv); 22 | 23 | Mylib lib; 24 | lib.test(); 25 | 26 | 27 | return a.exec(); 28 | } 29 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-9/mylib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(mylib LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | set(CMAKE_AUTOUIC ON) 7 | set(CMAKE_AUTOMOC ON) 8 | set(CMAKE_AUTORCC ON) 9 | set(CMAKE_CXX_STANDARD 11) 10 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 11 | 12 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) 13 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) 14 | 15 | add_library(mylib SHARED 16 | mylib_global.h 17 | mylib.cpp 18 | mylib.h 19 | ) 20 | 21 | target_link_libraries(mylib PRIVATE Qt${QT_VERSION_MAJOR}::Core) 22 | 23 | target_compile_definitions(mylib PRIVATE MYLIB_LIBRARY) 24 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-9/mylib/mylib.cpp: -------------------------------------------------------------------------------- 1 | #include "mylib.h" 2 | 3 | Mylib::Mylib() 4 | { 5 | } 6 | 7 | void Mylib::test() 8 | { 9 | qInfo() << "Hello from my library!"; 10 | } 11 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-9/mylib/mylib.h: -------------------------------------------------------------------------------- 1 | #ifndef MYLIB_H 2 | #define MYLIB_H 3 | 4 | #include "mylib_global.h" 5 | #include 6 | 7 | class MYLIB_EXPORT Mylib 8 | { 9 | public: 10 | Mylib(); 11 | 12 | void test(); 13 | }; 14 | 15 | #endif // MYLIB_H 16 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-9/mylib/mylib_global.h: -------------------------------------------------------------------------------- 1 | #ifndef MYLIB_GLOBAL_H 2 | #define MYLIB_GLOBAL_H 3 | 4 | #include 5 | 6 | #if defined(MYLIB_LIBRARY) 7 | # define MYLIB_EXPORT Q_DECL_EXPORT 8 | #else 9 | # define MYLIB_EXPORT Q_DECL_IMPORT 10 | #endif 11 | 12 | #endif // MYLIB_GLOBAL_H 13 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-assign/cats/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(cats LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | set(CMAKE_AUTOUIC ON) 7 | set(CMAKE_AUTOMOC ON) 8 | set(CMAKE_AUTORCC ON) 9 | set(CMAKE_CXX_STANDARD 11) 10 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 11 | 12 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) 13 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) 14 | 15 | add_library(cats SHARED 16 | cats.cpp 17 | cats.h 18 | plugin.h 19 | ) 20 | 21 | target_link_libraries(cats PRIVATE Qt${QT_VERSION_MAJOR}::Core) 22 | 23 | target_compile_definitions(cats PRIVATE MYPLUGIN_LIBRARY) 24 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-assign/cats/cats.cpp: -------------------------------------------------------------------------------- 1 | #include "cats.h" 2 | 3 | 4 | Cats::Cats(QObject *parent) 5 | { 6 | Q_UNUSED(parent); 7 | qInfo() << "Plugin Constructed"; 8 | } 9 | 10 | Cats::~Cats() 11 | { 12 | qInfo() << "Plugin Deconstructed"; 13 | } 14 | 15 | 16 | void Cats::test(QString name) 17 | { 18 | qInfo() << "Cat says: " << name; 19 | } 20 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-assign/cats/cats.h: -------------------------------------------------------------------------------- 1 | #ifndef MYPLUGIN_H 2 | #define MYPLUGIN_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "plugin.h" 9 | 10 | class Cats: public QObject, public Plugin 11 | { 12 | Q_OBJECT 13 | Q_PLUGIN_METADATA(IID "com.voidrealms.cats") 14 | Q_INTERFACES(Plugin) 15 | 16 | public: 17 | explicit Cats(QObject* parent = nullptr); 18 | ~Cats(); 19 | 20 | signals: 21 | 22 | public slots: 23 | 24 | // Plugin interface 25 | public: 26 | void test(QString name) Q_DECL_OVERRIDE; // override 27 | }; 28 | 29 | #endif // MYPLUGIN_H 30 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-assign/cats/plugin.h: -------------------------------------------------------------------------------- 1 | #ifndef PLUGIN_H 2 | #define PLUGIN_H 3 | 4 | #include 5 | #include 6 | 7 | class Plugin 8 | { 9 | public: 10 | //virtual ~Plugin() = 0; 11 | virtual void test(QString name) = 0; 12 | }; 13 | 14 | //Declare the interface 15 | Q_DECLARE_INTERFACE(Plugin,"com.voidrealms.plugin") 16 | 17 | #endif // PLUGIN_H 18 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-assign/myapp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(myapp LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) 16 | 17 | add_executable(myapp 18 | main.cpp 19 | plugin.h 20 | ) 21 | target_link_libraries(myapp Qt${QT_VERSION_MAJOR}::Core) 22 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-assign/myapp/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Application plugins 5 | 6 | Why 7 | We want to extend our application 8 | 9 | How 10 | QPluginLoader 11 | Make the plugin 12 | Build it 13 | Include the Plugin.h file 14 | Add the compiled plugin to a sub folder called "plugins" in the build directory 15 | 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include "plugin.h" 25 | 26 | QStringList getPlugins(QString path) 27 | { 28 | QStringList plugins; 29 | 30 | QStringList filter; 31 | filter << "*.dll" << "*.so" << "*.dylib"; 32 | 33 | QDir dir(path); 34 | QFileInfoList list = dir.entryInfoList(filter); 35 | foreach(QFileInfo file, list) 36 | { 37 | plugins.append(file.filePath()); 38 | //Mac - if(!file.isSymLink()) plugins.append(file.filePath()); 39 | } 40 | 41 | return plugins; 42 | } 43 | 44 | void testPlugins(QStringList plugins) 45 | { 46 | foreach(QString file, plugins) 47 | { 48 | qInfo() << "Loading..." << file; 49 | 50 | QPluginLoader loader(file); 51 | if(!loader.load()) 52 | { 53 | qInfo() << "Error: " << loader.fileName() << " Error: " << loader.errorString(); 54 | continue; 55 | } 56 | 57 | qInfo() << "Loaded: " << loader.fileName(); 58 | Plugin* plugin = qobject_cast(loader.instance()); 59 | if(plugin) 60 | { 61 | plugin->test("Bryan"); 62 | loader.unload(); 63 | } 64 | else 65 | { 66 | qInfo() << "Could not cast: " << loader.fileName(); 67 | } 68 | } 69 | } 70 | 71 | int main(int argc, char *argv[]) 72 | { 73 | QCoreApplication a(argc, argv); 74 | 75 | qInfo() << "Hello Plugins"; 76 | QDir dir = QDir::current(); 77 | // dir.cdUp(); 78 | dir.cd("plugins"); // Plugins 79 | qInfo() << "Path: " << dir.path(); 80 | 81 | QStringList plugins = getPlugins(dir.path()); 82 | qInfo() << "Plugins: " << plugins; 83 | 84 | testPlugins(plugins); 85 | 86 | qInfo() << "Done!"; 87 | 88 | return a.exec(); 89 | } 90 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-assign/myapp/plugin.h: -------------------------------------------------------------------------------- 1 | #ifndef PLUGIN_H 2 | #define PLUGIN_H 3 | 4 | #include 5 | #include 6 | 7 | class Plugin 8 | { 9 | public: 10 | //virtual ~Plugin() = 0; 11 | virtual void test(QString name) = 0; 12 | }; 13 | 14 | //Declare the interface 15 | Q_DECLARE_INTERFACE(Plugin,"com.voidrealms.plugin") 16 | 17 | #endif // PLUGIN_H 18 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-assign/myplugin/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(myplugin LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | set(CMAKE_AUTOUIC ON) 7 | set(CMAKE_AUTOMOC ON) 8 | set(CMAKE_AUTORCC ON) 9 | set(CMAKE_CXX_STANDARD 11) 10 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 11 | 12 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) 13 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) 14 | 15 | add_library(myplugin SHARED 16 | myplugin.cpp 17 | myplugin.h 18 | plugin.h 19 | ) 20 | 21 | target_link_libraries(myplugin PRIVATE Qt${QT_VERSION_MAJOR}::Core) 22 | 23 | target_compile_definitions(myplugin PRIVATE MYPLUGIN_LIBRARY) 24 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-assign/myplugin/myplugin.cpp: -------------------------------------------------------------------------------- 1 | #include "myplugin.h" 2 | 3 | 4 | MyPlugin::MyPlugin(QObject *parent) 5 | { 6 | Q_UNUSED(parent); 7 | qInfo() << "Plugin Constructed"; 8 | } 9 | 10 | MyPlugin::~MyPlugin() 11 | { 12 | qInfo() << "Plugin Deconstructed"; 13 | } 14 | 15 | 16 | void MyPlugin::test(QString name) 17 | { 18 | qInfo() << "Test from plugin: " << name; 19 | } 20 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-assign/myplugin/myplugin.h: -------------------------------------------------------------------------------- 1 | #ifndef MYPLUGIN_H 2 | #define MYPLUGIN_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "plugin.h" 9 | 10 | class MyPlugin: public QObject, public Plugin 11 | { 12 | Q_OBJECT 13 | Q_PLUGIN_METADATA(IID "com.voidrealms.plugin") 14 | Q_INTERFACES(Plugin) 15 | 16 | public: 17 | explicit MyPlugin(QObject* parent = nullptr); 18 | ~MyPlugin(); 19 | 20 | signals: 21 | 22 | public slots: 23 | 24 | // Plugin interface 25 | public: 26 | void test(QString name) Q_DECL_OVERRIDE; // override 27 | }; 28 | 29 | #endif // MYPLUGIN_H 30 | -------------------------------------------------------------------------------- /section 5/qt6ca-5-assign/myplugin/plugin.h: -------------------------------------------------------------------------------- 1 | #ifndef PLUGIN_H 2 | #define PLUGIN_H 3 | 4 | #include 5 | #include 6 | 7 | class Plugin 8 | { 9 | public: 10 | //virtual ~Plugin() = 0; 11 | virtual void test(QString name) = 0; 12 | }; 13 | 14 | //Declare the interface 15 | Q_DECLARE_INTERFACE(Plugin,"com.voidrealms.plugin") 16 | 17 | #endif // PLUGIN_H 18 | -------------------------------------------------------------------------------- /section 6/qt6ca-6-5/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-6-5 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Sql REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Sql REQUIRED) 16 | 17 | add_executable(qt6ca-6-5 18 | main.cpp 19 | ) 20 | target_link_libraries(qt6ca-6-5 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Sql) 21 | -------------------------------------------------------------------------------- /section 6/qt6ca-6-6/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-6-6 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Sql REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Sql REQUIRED) 16 | 17 | add_executable(qt6ca-6-6 18 | main.cpp 19 | ) 20 | target_link_libraries(qt6ca-6-6 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Sql) 21 | -------------------------------------------------------------------------------- /section 6/qt6ca-6-6/main.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | 4 | What 5 | Inspecting the installed plugins 6 | 7 | Why 8 | We want to know whats installed 9 | 10 | How 11 | Example below 12 | 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | int main(int argc, char *argv[]) 22 | { 23 | QCoreApplication a(argc, argv); 24 | qInfo() << "Inspecting Drivers"; 25 | 26 | foreach(QString driver, QSqlDatabase::drivers()) 27 | { 28 | qInfo() << driver; 29 | 30 | QSqlDatabase db = QSqlDatabase::addDatabase(driver); 31 | QSqlDriver *obj = db.driver(); 32 | 33 | qInfo() << "Transactions: " << obj->hasFeature(QSqlDriver::DriverFeature::Transactions); 34 | qInfo() << "QuerySize: " << obj->hasFeature(QSqlDriver::DriverFeature::QuerySize); 35 | qInfo() << "BLOB: " << obj->hasFeature(QSqlDriver::DriverFeature::BLOB); 36 | qInfo() << "Unicode: " << obj->hasFeature(QSqlDriver::DriverFeature::Unicode); 37 | qInfo() << "PreparedQueries: " << obj->hasFeature(QSqlDriver::DriverFeature::PreparedQueries); 38 | qInfo() << "NamedPlaceholders: " << obj->hasFeature(QSqlDriver::DriverFeature::NamedPlaceholders); 39 | qInfo() << "PositionalPlaceholders: " << obj->hasFeature(QSqlDriver::DriverFeature::PositionalPlaceholders); 40 | qInfo() << "LastInsertId: " << obj->hasFeature(QSqlDriver::DriverFeature::LastInsertId); 41 | qInfo() << "BatchOperations: " << obj->hasFeature(QSqlDriver::DriverFeature::BatchOperations); 42 | qInfo() << "SimpleLocking: " << obj->hasFeature(QSqlDriver::DriverFeature::SimpleLocking); 43 | qInfo() << "LowPrecisionNumbers: " << obj->hasFeature(QSqlDriver::DriverFeature::LowPrecisionNumbers); 44 | qInfo() << "EventNotifications: " << obj->hasFeature(QSqlDriver::DriverFeature::EventNotifications); 45 | qInfo() << "FinishQuery: " << obj->hasFeature(QSqlDriver::DriverFeature::FinishQuery); 46 | qInfo() << "MultipleResultSets: " << obj->hasFeature(QSqlDriver::DriverFeature::MultipleResultSets); 47 | qInfo() << "CancelQuery: " << obj->hasFeature(QSqlDriver::DriverFeature::CancelQuery); 48 | 49 | qInfo() << ""; 50 | } 51 | return a.exec(); 52 | } 53 | -------------------------------------------------------------------------------- /section 6/qt6ca-6-7/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-6-7 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Sql REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Sql REQUIRED) 16 | 17 | add_executable(qt6ca-6-7 18 | main.cpp 19 | ) 20 | target_link_libraries(qt6ca-6-7 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Sql) 21 | -------------------------------------------------------------------------------- /section 6/qt6ca-6-7/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | QSqlDatabase and QSqlQuery 5 | 6 | Why 7 | We want the basics of how to work with MySql 8 | 9 | How 10 | Example below 11 | 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | 23 | int main(int argc, char *argv[]) 24 | { 25 | QCoreApplication a(argc, argv); 26 | 27 | qInfo() << "Opening the database"; 28 | QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL"); 29 | db.setHostName("localhost"); // 127.0.0.1 30 | db.setUserName("qt6ca"); //Change the username 31 | db.setPassword("qt6ca-password"); //Change the password 32 | 33 | if(!db.open()) 34 | { 35 | qInfo() << "Could not open connection!"; 36 | qInfo() << db.lastError().text(); 37 | } 38 | else 39 | { 40 | qInfo() << "Connected, lets make a query..."; 41 | QSqlQuery query; 42 | QString cmd = "SELECT name,age FROM voidrealms.users WHERE age > 40;"; 43 | 44 | if(!query.exec(cmd)) 45 | { 46 | qInfo() << db.lastError().text(); 47 | qInfo() << query.lastError().text(); 48 | } 49 | else 50 | { 51 | qInfo() << "Got query results: " << query.size(); 52 | while(query.next()) 53 | { 54 | QString name = query.value(0).toString(); 55 | int age = query.value(1).toInt(); 56 | 57 | qInfo() << " name: " << name << " is " << age; 58 | } 59 | } 60 | 61 | db.close(); 62 | qInfo() << "Disconnected"; 63 | 64 | } 65 | 66 | 67 | return a.exec(); 68 | } 69 | -------------------------------------------------------------------------------- /section 6/qt6ca-6-8/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-6-8 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Sql REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Sql REQUIRED) 16 | 17 | add_executable(qt6ca-6-8 18 | main.cpp 19 | user.cpp 20 | user.h 21 | ) 22 | target_link_libraries(qt6ca-6-8 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Sql) 23 | -------------------------------------------------------------------------------- /section 6/qt6ca-6-8/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Data class 5 | 6 | Why 7 | Its easy! 8 | 9 | How 10 | Code 11 | 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include "user.h" 20 | 21 | bool openDB(QSqlDatabase &db) 22 | { 23 | qInfo() << "Opening Database"; 24 | db.setHostName("localhost"); 25 | db.setUserName("qt6ca"); //Change the username 26 | db.setPassword("qt6ca-password"); //Change the password 27 | 28 | bool ok = db.open(); 29 | if(ok) 30 | { 31 | qInfo() << "Opened database connection!"; 32 | return true; 33 | } 34 | 35 | qInfo() << "Failed to open connection!"; 36 | qInfo() << db.lastError().text(); 37 | 38 | return false; 39 | } 40 | 41 | int createUser() 42 | { 43 | qInfo() << "Creating user"; 44 | User user; 45 | int id = 0; 46 | 47 | if(user.open()) 48 | { 49 | user.begin(); 50 | user.name = "Britney Dibel"; 51 | user.age = 26; 52 | user.save(); 53 | 54 | user.name = "Britney Crawford"; 55 | user.save(); 56 | user.commit(); 57 | 58 | id = user.id; 59 | 60 | } 61 | 62 | return id; 63 | } 64 | 65 | void loadUser(int id) 66 | { 67 | qInfo() << "Loading user:" << id; 68 | User user; 69 | if(user.open()) 70 | { 71 | user.load(id); 72 | qInfo() << "Loaded: " << user.name; 73 | } 74 | } 75 | 76 | 77 | int main(int argc, char *argv[]) 78 | { 79 | QCoreApplication a(argc, argv); 80 | 81 | QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL"); 82 | if(openDB(db)) 83 | { 84 | int id = createUser(); 85 | qInfo() << "Created: " << id; 86 | 87 | if(id > 0) loadUser(id); 88 | 89 | } 90 | 91 | QSqlDatabase::database().close(); 92 | 93 | 94 | return a.exec(); 95 | } 96 | -------------------------------------------------------------------------------- /section 6/qt6ca-6-8/user.cpp: -------------------------------------------------------------------------------- 1 | #include "user.h" 2 | 3 | User::User(QObject *parent) : QObject(parent) 4 | { 5 | create(); 6 | } 7 | 8 | void User::begin() 9 | { 10 | QSqlDatabase::database().transaction(); 11 | } 12 | 13 | void User::commit() 14 | { 15 | QSqlDatabase::database().commit(); 16 | } 17 | 18 | void User::rollback() 19 | { 20 | QSqlDatabase::database().rollback(); 21 | } 22 | 23 | bool User::open() 24 | { 25 | QSqlDatabase db = QSqlDatabase::database(); 26 | bool isOpen = db.isOpen(); 27 | 28 | qInfo() << "isOpen: " << isOpen; 29 | return isOpen; 30 | } 31 | 32 | void User::create() 33 | { 34 | id = 0; 35 | age = 0; 36 | name = ""; 37 | } 38 | 39 | void User::load(int value) 40 | { 41 | qInfo() << "Loading record: " << value; 42 | 43 | QSqlQuery query; 44 | QString cmd = "SELECT idusers,age,name FROM voidrealms.users where idusers = :id;"; 45 | query.prepare(cmd); 46 | query.bindValue(":id",value); 47 | 48 | bool ok = exec(query); 49 | 50 | if(ok) 51 | { 52 | while (query.next()) 53 | { 54 | QSqlRecord record = query.record(); 55 | id = record.value(0).toInt(); 56 | age = record.value(1).toInt(); 57 | name = record.value(2).toString(); 58 | 59 | qInfo() << "Loaded " << id; 60 | 61 | return; 62 | } 63 | } 64 | } 65 | 66 | void User::save() 67 | { 68 | if(id > 0) 69 | { 70 | update(); 71 | } 72 | else 73 | { 74 | insert(); 75 | } 76 | } 77 | 78 | void User::remove() 79 | { 80 | QSqlQuery query; 81 | QString cmd = "DELETE FROM voidrealms.users where idusers = :id"; 82 | query.prepare(cmd); 83 | query.bindValue(":id", id); 84 | 85 | exec(query); 86 | } 87 | 88 | bool User::insert() 89 | { 90 | qInfo() << "Inserting row"; 91 | QSqlQuery query; 92 | QString cmd = "INSERT INTO `voidrealms`.`users` (`name`,`age`)VALUES(:name,:age);"; 93 | query.prepare(cmd); 94 | query.bindValue(":name", name); 95 | query.bindValue(":age", age); 96 | 97 | bool ok = exec(query); 98 | 99 | if(ok) 100 | { 101 | id = query.lastInsertId().toInt(); 102 | qInfo() << "Inserted " << id; 103 | } 104 | else 105 | { 106 | id = 0; 107 | } 108 | 109 | return ok; 110 | } 111 | 112 | bool User::update() 113 | { 114 | qInfo() << "Inserting row"; 115 | QSqlQuery query; 116 | QString cmd = "UPDATE `voidrealms`.`users` SET `idusers` = :id, `name` = :name, `age` = :age WHERE `idusers` = :id;"; 117 | query.prepare(cmd); 118 | query.bindValue(":id", id); 119 | query.bindValue(":name", name); 120 | query.bindValue(":age", age); 121 | 122 | 123 | bool ok = exec(query); 124 | 125 | if(ok) 126 | { 127 | qInfo() << "Updated " << id; 128 | } 129 | 130 | 131 | return ok; 132 | } 133 | 134 | bool User::exec(QSqlQuery &query) 135 | { 136 | QSqlDatabase db = QSqlDatabase::database(); 137 | if(!db.isOpen()) 138 | { 139 | qInfo() << "The connection is not open!"; 140 | return false; 141 | } 142 | 143 | qInfo() << "Exec: " << query.executedQuery(); 144 | bool ok = query.exec(); 145 | 146 | if(!ok) 147 | { 148 | qInfo() << db.lastError().text(); 149 | qInfo() << query.lastError().text(); 150 | } 151 | 152 | return ok; 153 | } 154 | -------------------------------------------------------------------------------- /section 6/qt6ca-6-8/user.h: -------------------------------------------------------------------------------- 1 | #ifndef USER_H 2 | #define USER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | class User : public QObject 13 | { 14 | Q_OBJECT 15 | public: 16 | explicit User(QObject *parent = nullptr); 17 | 18 | int id; 19 | int age; 20 | QString name; 21 | 22 | void begin(); 23 | void commit(); 24 | void rollback(); 25 | bool open(); 26 | void create(); 27 | void load(int value); 28 | void save(); 29 | void remove(); 30 | 31 | 32 | signals: 33 | 34 | public slots: 35 | 36 | private: 37 | bool insert(); 38 | bool update(); 39 | bool exec(QSqlQuery &query); 40 | }; 41 | 42 | #endif // USER_H 43 | -------------------------------------------------------------------------------- /section 6/qt6ca-6-assign/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-6-assign LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Sql REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Sql REQUIRED) 16 | 17 | add_executable(qt6ca-6-assign 18 | main.cpp 19 | ) 20 | target_link_libraries(qt6ca-6-assign Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Sql) 21 | -------------------------------------------------------------------------------- /section 6/qt6ca-6-assign/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Assignment 5 | 6 | Why 7 | Practice what you have learned 8 | 9 | How 10 | List if the installed drivers 11 | 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | int main(int argc, char *argv[]) 21 | { 22 | QCoreApplication a(argc, argv); 23 | 24 | qInfo() << "Inspecting Drivers"; 25 | 26 | foreach(QString driver, QSqlDatabase::drivers()) 27 | { 28 | qInfo() << driver; 29 | 30 | QSqlDatabase db = QSqlDatabase::addDatabase(driver); 31 | QSqlDriver *obj = db.driver(); 32 | 33 | qInfo() << "Transactions: " << obj->hasFeature(QSqlDriver::DriverFeature::Transactions); 34 | 35 | 36 | qInfo() << ""; 37 | } 38 | 39 | return a.exec(); 40 | } 41 | -------------------------------------------------------------------------------- /section 7/qt6ca-7-3/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-7-3 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Test REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Test REQUIRED) 16 | 17 | add_executable(qt6ca-7-3 18 | main.cpp 19 | cat.h 20 | cat.cpp 21 | ) 22 | target_link_libraries(qt6ca-7-3 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Test) 23 | -------------------------------------------------------------------------------- /section 7/qt6ca-7-3/cat.cpp: -------------------------------------------------------------------------------- 1 | #include "cat.h" 2 | 3 | Cat::Cat(QObject *parent) : QObject(parent) 4 | { 5 | qInfo() << Q_FUNC_INFO; 6 | } 7 | 8 | void Cat::public_test() 9 | { 10 | qInfo() << Q_FUNC_INFO; 11 | 12 | } 13 | 14 | void Cat::test() 15 | { 16 | qInfo() << Q_FUNC_INFO; 17 | } 18 | 19 | void Cat::play() 20 | { 21 | qInfo() << Q_FUNC_INFO; 22 | } 23 | 24 | void Cat::meow() 25 | { 26 | qInfo() << Q_FUNC_INFO; 27 | } 28 | 29 | void Cat::sleep() 30 | { 31 | qInfo() << Q_FUNC_INFO; 32 | } 33 | 34 | void Cat::speak(QString value) 35 | { 36 | Q_UNUSED(value); 37 | qInfo() << Q_FUNC_INFO; 38 | } 39 | 40 | void Cat::private_test() 41 | { 42 | qInfo() << Q_FUNC_INFO; 43 | } 44 | -------------------------------------------------------------------------------- /section 7/qt6ca-7-3/cat.h: -------------------------------------------------------------------------------- 1 | #ifndef CAT_H 2 | #define CAT_H 3 | 4 | #include 5 | #include 6 | 7 | 8 | class Cat : public QObject 9 | { 10 | Q_OBJECT 11 | public: 12 | explicit Cat(QObject *parent = nullptr); 13 | void public_test(); //not called 14 | 15 | signals: 16 | 17 | public slots: 18 | 19 | void test(); //not called 20 | 21 | 22 | private slots: 23 | void play(); 24 | void meow(); 25 | void sleep(); 26 | void speak(QString value); //no param 27 | 28 | private: 29 | void private_test(); //not called 30 | }; 31 | 32 | #endif // CAT_H 33 | -------------------------------------------------------------------------------- /section 7/qt6ca-7-3/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Lets test 5 | 6 | Why 7 | To see how it works 8 | 9 | How 10 | Example 11 | 12 | */ 13 | 14 | #include 15 | #include 16 | #include "cat.h" 17 | 18 | int main(int argc, char *argv[]) 19 | { 20 | QCoreApplication a(argc, argv); 21 | 22 | Cat cat; 23 | #ifdef QT_DEBUG 24 | QTest::qExec(&cat); 25 | #endif 26 | return a.exec(); 27 | } 28 | -------------------------------------------------------------------------------- /section 7/qt6ca-7-4/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-7-4 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Test REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Test REQUIRED) 16 | 17 | add_executable(qt6ca-7-4 18 | main.cpp 19 | dog.cpp 20 | dog.h 21 | ) 22 | target_link_libraries(qt6ca-7-4 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Test) 23 | -------------------------------------------------------------------------------- /section 7/qt6ca-7-4/dog.cpp: -------------------------------------------------------------------------------- 1 | #include "dog.h" 2 | 3 | Dog::Dog(QObject *parent) : QObject(parent) 4 | { 5 | qInfo() << "Constructor"; 6 | } 7 | 8 | void Dog::initTestCase() 9 | { 10 | qInfo() << "initTestCase"; 11 | } 12 | 13 | void Dog::init() 14 | { 15 | qInfo() << "init"; 16 | } 17 | 18 | void Dog::cleanup() 19 | { 20 | qInfo() << "cleanup"; 21 | } 22 | 23 | void Dog::cleanupTestCase() 24 | { 25 | qInfo() << "cleanupTestCase"; 26 | } 27 | 28 | void Dog::bark() 29 | { 30 | qInfo() << "bark bark bark"; 31 | } 32 | 33 | void Dog::rollover() 34 | { 35 | qInfo() << "*rolls*"; 36 | } 37 | -------------------------------------------------------------------------------- /section 7/qt6ca-7-4/dog.h: -------------------------------------------------------------------------------- 1 | #ifndef DOG_H 2 | #define DOG_H 3 | 4 | #include 5 | #include 6 | 7 | class Dog : public QObject 8 | { 9 | Q_OBJECT 10 | public: 11 | explicit Dog(QObject *parent = nullptr); 12 | 13 | signals: 14 | 15 | public slots: 16 | 17 | private slots: 18 | //Called before the first test 19 | void initTestCase(); 20 | 21 | //Called before each test 22 | void init(); 23 | 24 | //Called after each test 25 | void cleanup(); 26 | 27 | //Called after the last test 28 | void cleanupTestCase(); 29 | 30 | //Our custom slot to be tested 31 | void bark(); 32 | 33 | //Another custom slot to test 34 | void rollover(); 35 | }; 36 | 37 | #endif // DOG_H 38 | -------------------------------------------------------------------------------- /section 7/qt6ca-7-4/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Basic testing 5 | 6 | Why 7 | Lets look deeper at testing 8 | 9 | How 10 | Example code 11 | 12 | */ 13 | 14 | #include 15 | #include 16 | #include "dog.h" 17 | 18 | int main(int argc, char *argv[]) 19 | { 20 | QCoreApplication a(argc, argv); 21 | 22 | Dog dog; 23 | QTest::qExec(&dog); 24 | 25 | return a.exec(); 26 | } 27 | -------------------------------------------------------------------------------- /section 7/qt6ca-7-5/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-7-5 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Test REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Test REQUIRED) 16 | 17 | add_executable(qt6ca-7-5 18 | main.cpp 19 | widget.cpp 20 | widget.h 21 | ) 22 | target_link_libraries(qt6ca-7-5 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Test) 23 | -------------------------------------------------------------------------------- /section 7/qt6ca-7-5/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Testing for failure 5 | 6 | Why 7 | This is the reason for testing 8 | 9 | How 10 | QFAIL QVERIFY QCOMPARE QWARN 11 | 12 | */ 13 | 14 | 15 | #include 16 | #include 17 | #include "widget.h" 18 | 19 | int main(int argc, char *argv[]) 20 | { 21 | QCoreApplication a(argc, argv); 22 | 23 | Widget widget; 24 | widget.setAge(46); 25 | QTest::qExec(&widget); 26 | 27 | return a.exec(); 28 | } 29 | -------------------------------------------------------------------------------- /section 7/qt6ca-7-5/widget.cpp: -------------------------------------------------------------------------------- 1 | #include "widget.h" 2 | 3 | Widget::Widget(QObject *parent) : QObject(parent) 4 | { 5 | age = 0; 6 | } 7 | 8 | void Widget::setAge(int value) 9 | { 10 | age = value; 11 | } 12 | 13 | void Widget::testFail() 14 | { 15 | QFAIL("NO REASON JUST FAIL!!!"); 16 | } 17 | 18 | void Widget::testAge() 19 | { 20 | if(!age) QFAIL("Age is not set!"); 21 | } 22 | 23 | void Widget::testWidget() 24 | { 25 | 26 | int value = 45; 27 | 28 | //Make sure the age is valid-------------- 29 | QVERIFY(age > 0 && age < 100); 30 | 31 | //Issue warnings 32 | if(age > 40) QWARN("Age is over 40!"); 33 | if(age < 21) QFAIL("Must be an adult!"); 34 | 35 | //Make sure they are the same--------------------- 36 | QCOMPARE(age, value); 37 | 38 | 39 | } 40 | -------------------------------------------------------------------------------- /section 7/qt6ca-7-5/widget.h: -------------------------------------------------------------------------------- 1 | #ifndef WIDGET_H 2 | #define WIDGET_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class Widget : public QObject 9 | { 10 | Q_OBJECT 11 | public: 12 | explicit Widget(QObject *parent = nullptr); 13 | 14 | void setAge(int value); 15 | 16 | signals: 17 | 18 | public slots: 19 | 20 | private slots: 21 | void testFail(); 22 | void testAge(); 23 | void testWidget(); 24 | 25 | private: 26 | int age; 27 | }; 28 | 29 | #endif // WIDGET_H 30 | -------------------------------------------------------------------------------- /section 7/qt6ca-7-6/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-7-6 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Test REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Test REQUIRED) 16 | 17 | add_executable(qt6ca-7-6 18 | main.cpp 19 | widget.cpp 20 | widget.h 21 | ) 22 | target_link_libraries(qt6ca-7-6 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Test) 23 | -------------------------------------------------------------------------------- /section 7/qt6ca-7-6/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Data driven tests 5 | 6 | Why 7 | We want to test data 8 | 9 | How 10 | QTEST_MAIN addColumn addRow QFETCH 11 | 12 | */ 13 | 14 | #include 15 | #include 16 | #include "widget.h" 17 | 18 | //Replaces the main function 19 | QTEST_MAIN(Widget); 20 | -------------------------------------------------------------------------------- /section 7/qt6ca-7-6/widget.cpp: -------------------------------------------------------------------------------- 1 | #include "widget.h" 2 | 3 | Widget::Widget(QObject *parent) : QObject(parent) 4 | { 5 | 6 | } 7 | 8 | void Widget::testAge_data() 9 | { 10 | qInfo() << "Generating data..."; 11 | 12 | QTest::addColumn("name"); 13 | QTest::addColumn("age"); 14 | 15 | QTest::addRow("Invalid") << "Bob" << 190; 16 | QTest::addRow("Old") << "Bryan" << 44; 17 | QTest::addRow("Young") << "Heather" << 25; 18 | QTest::addRow("Under age") << "Rango" << 14; 19 | QTest::addRow("Retired") << "Grandma" << 90; 20 | 21 | qInfo() << "Data generated!"; 22 | } 23 | 24 | void Widget::testAge() 25 | { 26 | QFETCH(QString,name); 27 | QFETCH(int, age); 28 | 29 | qInfo() << "Testing age " << name << " is " << age; 30 | 31 | if(age < 1 || age > 100) QFAIL("Invalid Age!"); 32 | if(age < 21) QFAIL("Must be an adult!"); 33 | if(age > 40) QWARN("Getting Old!"); 34 | if(age > 65) qInfo() << "This person is retired"; 35 | } 36 | -------------------------------------------------------------------------------- /section 7/qt6ca-7-6/widget.h: -------------------------------------------------------------------------------- 1 | #ifndef WIDGET_H 2 | #define WIDGET_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class Widget : public QObject 9 | { 10 | Q_OBJECT 11 | public: 12 | explicit Widget(QObject *parent = nullptr); 13 | 14 | signals: 15 | 16 | public slots: 17 | 18 | private slots: 19 | void testAge_data(); 20 | void testAge(); 21 | 22 | 23 | }; 24 | 25 | #endif // WIDGET_H 26 | -------------------------------------------------------------------------------- /section 7/qt6ca-7-7/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-7-7 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Test REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Test REQUIRED) 16 | 17 | add_executable(qt6ca-7-7 18 | main.cpp 19 | widget.cpp 20 | widget.h 21 | ) 22 | target_link_libraries(qt6ca-7-7 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Test) 23 | -------------------------------------------------------------------------------- /section 7/qt6ca-7-7/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Benchmarking 5 | 6 | Why 7 | We want to know what speed things run 8 | 9 | How 10 | QBENCHMARK 11 | 12 | */ 13 | 14 | #include 15 | #include "widget.h" 16 | 17 | QTEST_MAIN(Widget); 18 | -------------------------------------------------------------------------------- /section 7/qt6ca-7-7/widget.cpp: -------------------------------------------------------------------------------- 1 | #include "widget.h" 2 | 3 | Widget::Widget(QObject *parent) : QObject(parent) 4 | { 5 | 6 | } 7 | 8 | void Widget::testFor() 9 | { 10 | QVector list; 11 | list.fill(0,100); 12 | 13 | //Called multiple times! 14 | QBENCHMARK 15 | { 16 | for (int i = 0; i < list.size();i++) 17 | { 18 | //Do Stuff 19 | } 20 | } 21 | } 22 | 23 | void Widget::testForEach() 24 | { 25 | QVector list; 26 | list.fill(0,100); 27 | 28 | //Called multiple times! 29 | QBENCHMARK 30 | { 31 | foreach(int value, list) 32 | { 33 | //Do Stuff 34 | } 35 | } 36 | } 37 | 38 | void Widget::testString() 39 | { 40 | QString him = "Bryan"; 41 | QString her = "Tammy"; 42 | 43 | QBENCHMARK 44 | { 45 | int ret = him.compare(her); 46 | } 47 | } 48 | 49 | void Widget::testComp() 50 | { 51 | QString him = "Bryan"; 52 | QString her = "Tammy"; 53 | 54 | QBENCHMARK 55 | { 56 | QCOMPARE(him, her); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /section 7/qt6ca-7-7/widget.h: -------------------------------------------------------------------------------- 1 | #ifndef WIDGET_H 2 | #define WIDGET_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class Widget : public QObject 9 | { 10 | Q_OBJECT 11 | public: 12 | explicit Widget(QObject *parent = nullptr); 13 | 14 | signals: 15 | 16 | public slots: 17 | 18 | private slots: 19 | void testFor(); 20 | void testForEach(); 21 | void testString(); 22 | void testComp(); 23 | 24 | }; 25 | 26 | #endif // WIDGET_H 27 | -------------------------------------------------------------------------------- /section 7/qt6ca-7-8/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-7-8 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Test REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Test REQUIRED) 16 | 17 | add_executable(qt6ca-7-8 18 | main.cpp 19 | widget.cpp 20 | widget.h 21 | ) 22 | target_link_libraries(qt6ca-7-8 Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Test) 23 | -------------------------------------------------------------------------------- /section 7/qt6ca-7-8/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Skipping tests and expecting failue 5 | 6 | Why 7 | We live in the real word 8 | 9 | How 10 | QSKIP QEXPECT_FAIL 11 | 12 | */ 13 | 14 | #include 15 | #include "widget.h" 16 | 17 | //Update .Pro file: QT += testlib 18 | 19 | QTEST_MAIN(Widget); 20 | -------------------------------------------------------------------------------- /section 7/qt6ca-7-8/widget.cpp: -------------------------------------------------------------------------------- 1 | #include "widget.h" 2 | 3 | Widget::Widget(QObject *parent) : QObject(parent) 4 | { 5 | 6 | } 7 | 8 | void Widget::test() 9 | { 10 | QFETCH(int, value); 11 | 12 | //Skip 5 13 | if(value == 5) QSKIP("Skipping 5"); 14 | 15 | //Exits 16 | qInfo() << "Testing: " << value; 17 | } 18 | 19 | void Widget::test_data() 20 | { 21 | qInfo() << "Generating data..."; 22 | QTest::addColumn("value"); 23 | 24 | for (int i = 0; i < 10; i++) 25 | { 26 | QString name = QString::number(i); 27 | QByteArray ba = name.toLatin1(); 28 | const char *c_str = ba.data(); 29 | QTest::newRow(c_str) << i; 30 | } 31 | } 32 | 33 | void Widget::testFail() 34 | { 35 | int current = 6; 36 | int supported = 6; 37 | QCOMPARE(current,supported); 38 | 39 | //Test previous 40 | QEXPECT_FAIL("","Version 5 is not supported",Continue); 41 | QCOMPARE(current,5); //Will Fail 42 | } 43 | -------------------------------------------------------------------------------- /section 7/qt6ca-7-8/widget.h: -------------------------------------------------------------------------------- 1 | #ifndef WIDGET_H 2 | #define WIDGET_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class Widget : public QObject 9 | { 10 | Q_OBJECT 11 | public: 12 | explicit Widget(QObject *parent = nullptr); 13 | 14 | signals: 15 | 16 | public slots: 17 | 18 | private slots: 19 | void test(); 20 | void test_data(); 21 | void testFail(); 22 | 23 | }; 24 | 25 | #endif // WIDGET_H 26 | -------------------------------------------------------------------------------- /section 7/qt6ca-7-assign/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-7-assign LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Test REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Test REQUIRED) 16 | 17 | add_executable(qt6ca-7-assign 18 | main.cpp 19 | widget.cpp 20 | widget.h 21 | ) 22 | target_link_libraries(qt6ca-7-assign Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Test) 23 | -------------------------------------------------------------------------------- /section 7/qt6ca-7-assign/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Assignment 5 | 6 | Why 7 | Practice what you have learned 8 | 9 | How 10 | Example code 11 | 12 | */ 13 | 14 | #include 15 | #include "widget.h" 16 | 17 | QTEST_MAIN(Widget); 18 | -------------------------------------------------------------------------------- /section 7/qt6ca-7-assign/widget.cpp: -------------------------------------------------------------------------------- 1 | #include "widget.h" 2 | 3 | Widget::Widget(QObject *parent) : QObject(parent) 4 | { 5 | 6 | } 7 | 8 | void Widget::doMath(int max) 9 | { 10 | for (int i = 0; i < max; i++) 11 | { 12 | int h = max * i; 13 | Q_UNUSED(h); 14 | } 15 | } 16 | 17 | void Widget::testMath() 18 | { 19 | QBENCHMARK 20 | { 21 | int value = QRandomGenerator::global()->bounded(1000); 22 | qInfo() << "Value:" << value; 23 | doMath(value); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /section 7/qt6ca-7-assign/widget.h: -------------------------------------------------------------------------------- 1 | #ifndef WIDGET_H 2 | #define WIDGET_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class Widget : public QObject 10 | { 11 | Q_OBJECT 12 | public: 13 | explicit Widget(QObject *parent = nullptr); 14 | 15 | signals: 16 | 17 | public slots: 18 | void doMath(int max); 19 | 20 | private slots: 21 | void testMath(); 22 | 23 | }; 24 | 25 | #endif // WIDGET_H 26 | -------------------------------------------------------------------------------- /section 8/qt6ca-8-10/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-8-10 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) 16 | 17 | add_executable(qt6ca-8-10 18 | main.cpp 19 | ) 20 | target_link_libraries(qt6ca-8-10 Qt${QT_VERSION_MAJOR}::Core) 21 | -------------------------------------------------------------------------------- /section 8/qt6ca-8-10/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Build Qt Static 5 | 6 | Why 7 | Some people want to do things the hard way 8 | 9 | How 10 | 11 | Install the source 12 | https://www.youtube.com/watch?v=2qsR8Dw8uzA 13 | 14 | Dynamic Build Commands: 15 | ./configure -release -opensource -confirm-license -prefix /PATH/BUILD 16 | make -j8 17 | make install 18 | 19 | Static Build Commands: 20 | ./configure -release -static -opensource -confirm-license -prefix /PATH/BUILD-STATIC 21 | make -j8 22 | make install 23 | 24 | 25 | */ 26 | 27 | #include 28 | #include 29 | 30 | /* 31 | https://retifrav.github.io/blog/2018/02/17/build-qt-statically/ 32 | 33 | Can be frustrating 34 | Takes a long time 35 | Fully of bugs issues and show stoppers 36 | 37 | 38 | cd /home/rootshell/Applications 39 | mkdir build 40 | 41 | Copy the source 42 | 43 | /Src/configure -static -release -ltcg -optimize-size -no-pch -prefix "/-static" -skip webengine -nomake tools -nomake tests -nomake examples 44 | 45 | make -j8 46 | (30 minutes later) 47 | make -j8 install 48 | 49 | Copy to Qt Folder 50 | Setup a project and build dynamically 51 | Manage kits 52 | Add the Desktop Static Build 53 | Switch the kit to static and build 54 | ** Besure to set to local desktop 55 | ** Be sure to add the Qt version (static) or it will build dynamically 56 | 57 | Compiler - GCC 7 v86 64 58 | 59 | build static release 60 | run ldd and show the lack of depends and show the size difference 61 | 62 | ldd 63 | 64 | Show the size (Hello world is 2.5 mb) 65 | use UPX to compress 66 | 67 | ./upx -9 (About 1mb) 68 | 69 | 70 | */ 71 | 72 | int main(int argc, char *argv[]) 73 | { 74 | QCoreApplication a(argc, argv); 75 | 76 | #ifdef QT_DEBUG 77 | qInfo() << "Running in debug build"; 78 | #else 79 | qInfo() << "Running in release build"; 80 | #endif 81 | 82 | return a.exec(); 83 | } 84 | -------------------------------------------------------------------------------- /section 8/qt6ca-8-6/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-8-6 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) 16 | 17 | add_executable(qt6ca-8-6 18 | main.cpp 19 | ) 20 | target_link_libraries(qt6ca-8-6 Qt${QT_VERSION_MAJOR}::Core) 21 | -------------------------------------------------------------------------------- /section 8/qt6ca-8-6/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | A test application 5 | 6 | Why 7 | We need something to deploy 8 | 9 | How 10 | Build in release 11 | Explain debug vs release 12 | We will use the Release build to deploy 13 | 14 | */ 15 | 16 | #include 17 | #include 18 | 19 | int main(int argc, char *argv[]) 20 | { 21 | QCoreApplication a(argc, argv); 22 | 23 | QString build; 24 | 25 | #ifdef QT_DEBUG 26 | build = "debug"; 27 | #else 28 | build = "release"; 29 | #endif 30 | 31 | qInfo() << "Current build: " << build; 32 | 33 | return a.exec(); 34 | } 35 | -------------------------------------------------------------------------------- /section 8/qt6ca-8-7/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-8-7 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) 16 | 17 | #add_executable(qt6ca-8-7 18 | # main.cpp 19 | #) 20 | 21 | add_executable(qt6ca-8-7 MACOSX_BUNDLE 22 | main.cpp 23 | ) 24 | set_target_properties(qt6ca-8-7 PROPERTIES 25 | BUNDLE True 26 | MACOSX_BUNDLE_GUI_IDENTIFIER my.domain.style.identifier.qt6ca-8-7 27 | MACOSX_BUNDLE_BUNDLE_NAME qt6ca-8-7 28 | MACOSX_BUNDLE_BUNDLE_VERSION "0.1" 29 | MACOSX_BUNDLE_SHORT_VERSION_STRING "0.1" 30 | #MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/cmake/customtemplate.plist.in 31 | 32 | ) 33 | 34 | target_link_libraries(qt6ca-8-7 Qt${QT_VERSION_MAJOR}::Core) 35 | 36 | 37 | -------------------------------------------------------------------------------- /section 8/qt6ca-8-7/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Test app to deploy 5 | 6 | Why 7 | We want to distribute our app 8 | 9 | How 10 | 11 | Deploy on mac example 12 | 13 | https://doc.qt.io/qt-5/macos-deployment.html 14 | 15 | Compile in debug mode 16 | Compile in release mode 17 | 18 | Show how these are different applications, different sizes using the Get Info 19 | 20 | use otool to show the dependancies 21 | otool -L 22 | 23 | open a application - Calculator 24 | right click and "Show Package Contents" 25 | Talk about how they can be self contained and have an expected format 26 | 27 | Look in the pro file 28 | CONFIG -= app_bundle 29 | comment out and show the bundle being created, but it lacks the qt libs, use show contents on it 30 | #CONFIG -= app_bundle 31 | 32 | CMAKE 33 | set(CUR_TARGET myappname) 34 | add_executable(${CUR_TARGET} MACOSX_BUNDLE ${MY_SRC}) 35 | set_target_properties(${CUR_TARGET} PROPERTIES 36 | BUNDLE True 37 | MACOSX_BUNDLE_GUI_IDENTIFIER my.domain.style.identifier.${CUR_TARGET} 38 | MACOSX_BUNDLE_BUNDLE_NAME ${CUR_TARGET} 39 | MACOSX_BUNDLE_BUNDLE_VERSION "0.1" 40 | MACOSX_BUNDLE_SHORT_VERSION_STRING "0.1" 41 | MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/cmake/customtemplate.plist.in 42 | ) 43 | ----------------------- 44 | add_executable(qt6ca-8-7 MACOSX_BUNDLE 45 | main.cpp 46 | ) 47 | set_target_properties(qt6ca-8-7 PROPERTIES 48 | BUNDLE True 49 | MACOSX_BUNDLE_GUI_IDENTIFIER my.domain.style.identifier.qt6ca-8-7 50 | MACOSX_BUNDLE_BUNDLE_NAME qt6ca-8-7 51 | MACOSX_BUNDLE_BUNDLE_VERSION "0.1" 52 | MACOSX_BUNDLE_SHORT_VERSION_STRING "0.1" 53 | #MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/cmake/customtemplate.plist.in 54 | 55 | ) 56 | ----------------------- 57 | 58 | 59 | Look in /clang_64/bin/ 60 | 61 | show "macdeployqt" 62 | run clang_64/bin/macdeployqt -dmg 63 | 64 | Examine the app inside of the bundle 65 | otool -L 66 | Run the app from inside the bundle 67 | 68 | Run the app using open 69 | open -a Terminal 70 | 71 | */ 72 | 73 | #include 74 | #include 75 | 76 | 77 | int main(int argc, char *argv[]) 78 | { 79 | QCoreApplication a(argc, argv); 80 | 81 | #ifdef QT_DEBUG 82 | qDebug() << "Running a debug build"; 83 | #else 84 | qDebug() << "Running a release build"; 85 | #endif 86 | 87 | return a.exec(); 88 | } 89 | -------------------------------------------------------------------------------- /section 8/qt6ca-8-8/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-8-8 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) 16 | 17 | add_executable(qt6ca-8-8 18 | main.cpp 19 | ) 20 | target_link_libraries(qt6ca-8-8 Qt${QT_VERSION_MAJOR}::Core) 21 | -------------------------------------------------------------------------------- /section 8/qt6ca-8-8/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Deploy to linux 5 | 6 | Why 7 | This can get crazy... 8 | 9 | How 10 | Run LinuxQtDeploy 11 | https://github.com/probonopd/linuxdeployqt 12 | 13 | 14 | export LD_LIBRARY_PATH=/home/rootshell/Applications/Qt/6.1.1/gcc_64/lib/ 15 | ./linuxdeployqt-continuous-x86_64.AppImage ./build/qt6ca-8-8 -unsupported-allow-new-glibc 16 | 17 | copy the icon.png 18 | 19 | Make a desktop file (your_app.desktop) 20 | ------------------ 21 | [Desktop Entry] 22 | Type=Application 23 | Name=MyApp 24 | Comment=Qt Tutorial 25 | Exec=qt6ca-8-8 26 | Icon=icon 27 | Categories=Office; 28 | ------------------ 29 | 30 | Run app image 31 | https://github.com/AppImage/AppImageKit 32 | https://github.com/AppImage/AppImageKit/releases 33 | 34 | ./appimagetool-x86_64.AppImage ./build/ 35 | 36 | 37 | */ 38 | 39 | 40 | #include 41 | 42 | int main(int argc, char *argv[]) 43 | { 44 | QCoreApplication a(argc, argv); 45 | 46 | #ifdef QT_DEBUG 47 | qDebug() << "Running a debug build"; 48 | #else 49 | qDebug() << "Running a release build"; 50 | #endif 51 | 52 | return a.exec(); 53 | } 54 | -------------------------------------------------------------------------------- /section 8/qt6ca-8-9/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(qt6ca-8-9 LANGUAGES CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 11) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) 15 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) 16 | 17 | add_executable(qt6ca-8-9 18 | main.cpp 19 | ) 20 | target_link_libraries(qt6ca-8-9 Qt${QT_VERSION_MAJOR}::Core) 21 | -------------------------------------------------------------------------------- /section 8/qt6ca-8-9/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | What 4 | Deploy to Windows 5 | 6 | Why 7 | Its windows 8 | 9 | How 10 | 11 | make new app 12 | choose mingw x 64 13 | 14 | 15 | -------------------- 16 | #include 17 | #include 18 | 19 | int main(int argc, char *argv[]) 20 | { 21 | QCoreApplication a(argc, argv); 22 | 23 | #ifdef QT_DEBUG 24 | qInfo() << "Running in debug build"; 25 | #else 26 | qInfo() << "Running in release build"; 27 | #endif 28 | 29 | return a.exec(); 30 | } 31 | -------------------- 32 | 33 | build in release 34 | show the exe 35 | 36 | Run windeploy qt 37 | \mingw73_64\bin\windeployqt.exe "" 38 | 39 | Run it and show its still having issues 40 | Show Dependancy walker and show the yellow items 41 | 42 | Still missing 43 | LIBGCC_S_DW2-1.DLL 44 | LIBSTDC++-6.DLL 45 | 46 | Look in the Ming32Bit folder 47 | C:\Qt\5.12.2\mingw73_32\bin 48 | 49 | Copy the yellow libs 50 | Show the EXE runs 51 | 52 | // My favorite tool is INNO Setup 53 | 54 | */ 55 | 56 | 57 | #include 58 | #include 59 | 60 | int main(int argc, char *argv[]) 61 | { 62 | QCoreApplication a(argc, argv); 63 | 64 | #ifdef QT_DEBUG 65 | qInfo() << "Running in debug build"; 66 | #else 67 | qInfo() << "Running in release build"; 68 | #endif 69 | 70 | return a.exec(); 71 | } 72 | --------------------------------------------------------------------------------