Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

More std lib function



  • hello,
    I have a program from youtube (watch?v=UvUZoS_HaGY) witch is running there, but when try to compile it on my personal computer, then I get following error message std::pair<_T1,_T2>::first has incomplete type, referring to
    the penultimate line of notesmanager.h.
    std::unordered_map<int, std::pair<Note, std::unique_ptr<QTextDocument>>> notes;
    I can't find the error, it's because in the .pro file is required c++17.
    My pc is running under Kubuntu 20.04, Creator 14.3.2 (Qt 5.15.1)
    Does somebody has any idea?
    Thanks

    the code:
    // notes.pro
    ////////////

    QT += core gui

    greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

    CONFIG += c++17

    You can make your code fail to compile if it uses deprecated APIs.

    In order to do so, uncomment the following line.

    #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000

    disables all the APIs deprecated before Qt 6.0.0

    SOURCES +=
    main.cpp
    mainwindow.cpp
    noteslistwidget.cpp
    notesmanager.cpp
    notewidget.cpp

    HEADERS +=
    mainwindow.h
    note.h
    noteslistwidget.h
    notesmanager.h
    notewidget.h

    FORMS +=
    mainwindow.ui
    noteslistwidget.ui

    Default rules for deployment.

    qnx: target.path = /tmp/$${TARGET}/bin
    else: unix:!android: target.path = /opt/$${TARGET}/bin
    !isEmpty(target.path): INSTALLS += target

    // main.cpp
    ///////////

    #include "mainwindow.h"
    #include "notesmanager.h"

    #include <QApplication>

    int main(int argc, char *argv[])
    {
    QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps, true);
    QApplication::setAttribute(Qt::AA_EnableHighDpiScaling,true);

    QApplication a(argc, argv);
    NotesManager manager;
    MainWindow w(manager);
    
    w.show();
    return a.exec();
    

    }

    //mainwindow.cpp
    ////////////////

    #include "mainwindow.h"
    #include "ui_mainwindow.h"

    #include "notesmanager.h"
    #include "note.h"
    #include "noteslistwidget.h"

    #include <QPushButton>
    #include <QMessageBox>

    #include <algorithm>

    MainWindow::MainWindow(NotesManager &manager, QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::MainWindow)
    , notesManager(manager)
    {
    ui->setupUi(this);
    makeConnections();
    init();
    }

    MainWindow::~MainWindow()
    {
    delete ui;
    }

    void MainWindow::on_newNoteBtn_clicked()
    {
    notesManager.createNewNote();
    }

    void MainWindow::on_removeNoteBtn_clicked()
    {
    removeNote(ui->notesListWidget->currentNoteId());
    }

    // handle NotesManager signals
    void MainWindow::onNewNoteCreated(int id)
    {
    addNoteToList(notesManager.note(id));
    }

    void MainWindow::onNoteContentChanged(int id)
    {
    ui->notesListWidget->updateCurrentNote(notesManager.note(id));
    }

    // handle NotesListWidget signals
    void MainWindow::onSelectedNoteChanged(int id)
    {
    auto *document = notesManager.noteDocument(id);
    if(document)
    {
    ui->textEdit->setDocument(document);
    // auto cursor = ui->textEdit->textCursor();
    // cursor.movePosition(QTextCursor::End);
    // ui->textEdit->setTextCursor(cursor);
    }
    }

    void MainWindow::onRemoveNote(int id)
    {
    removeNote(id);
    }

    void MainWindow::addNoteToList(const Note &note)
    {
    ui->notesListWidget->addNote(note);
    }

    void MainWindow::removeNote(int id)
    {
    QString noteTitle = notesManager.note(id).title;
    auto pressedBtn = QMessageBox::information(this,"remove note?",
    QString("Are you sure you want to remove %0?").arg(noteTitle),
    QMessageBox::Yes|QMessageBox::No,QMessageBox::Yes);

    if(pressedBtn == QMessageBox::Yes)
    {
        if(notesManager.count() ==1)
            ui->textEdit->setDocument(nullptr);
    
        ui->notesListWidget->removeCurrentNote();
        notesManager.removeNote(id);
    }
    

    }

    void MainWindow::init()
    {
    auto notesList = notesManager.noteCollection();
    std::sort(notesList.begin(), notesList.end(),
    [](const Note &left, const Note &right)
    {
    return left.lastModified < right.lastModified;
    });
    for(auto &note : notesList)
    addNoteToList(note);
    }

    void MainWindow::makeConnections()
    {
    connect(ui->newNoteBtn, &QPushButton::click, this, &MainWindow::on_newNoteBtn_clicked);
    connect(ui->removeNoteBtn, &QPushButton::click, this, &MainWindow::on_removeNoteBtn_clicked);

    connect(&notesManager, &NotesManager::newNoteCreated,this, &MainWindow::onNewNoteCreated);
    connect(&notesManager, &NotesManager::noteContendChanged, this, &MainWindow::onNoteContentChanged);
    
    connect(ui->notesListWidget, &NotesListWidget::selectedNoteChanged, this, &MainWindow::onSelectedNoteChanged);
    

    }

    //MainWindow.h
    //////////////

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H

    #include <QWidget>
    #include <QPushButton>

    QT_BEGIN_NAMESPACE
    namespace Ui { class MainWindow; }
    QT_END_NAMESPACE

    class NotesManager;
    class Note;

    class MainWindow : public QWidget
    {
    Q_OBJECT

    public:
    MainWindow(NotesManager &manageNr, QWidget *parent = nullptr);
    ~MainWindow();

    private slots:
    // handle signal for ui
    void on_newNoteBtn_clicked();
    void on_removeNoteBtn_clicked();

    // handle NotesManager signals
    void onNewNoteCreated(int id);
    void onNoteContentChanged(int id);
    
    // handle NotesListWidget signals
    void onSelectedNoteChanged(int id);
    void onRemoveNote(int id);
    

    private:
    void addNoteToList(const Note &note);
    void removeNote(int id);

    void init();
    void makeConnections();
    Ui::MainWindow *ui;
    NotesManager &notesManager;
    

    };
    #endif // MAINWINDOW_H

    //mainwindow.ui
    ///////////////

    <?xml version="1.0" encoding="UTF-8"?>
    <ui version="4.0">
    <class>MainWindow</class>
    <widget class="QWidget" name="MainWindow">
    <property name="geometry">
    <rect>
    <x>0</x>
    <y>0</y>
    <width>800</width>
    <height>600</height>
    </rect>
    </property>
    <property name="windowTitle">
    <string>MainWindow</string>
    </property>
    <layout class="QVBoxLayout" name="verticalLayout" stretch="0,1">
    <item>
    <layout class="QHBoxLayout" name="horizontalLayout">
    <item>
    <widget class="QPushButton" name="newNoteBtn">
    <property name="text">
    <string>New</string>
    </property>
    </widget>
    </item>
    <item>
    <widget class="QPushButton" name="removeNoteBtn">
    <property name="text">
    <string>Delete</string>
    </property>
    </widget>
    </item>
    <item>
    <spacer name="horizontalSpacer">
    <property name="orientation">
    <enum>Qt::Horizontal</enum>
    </property>
    <property name="sizeHint" stdset="0">
    <size>
    <width>40</width>
    <height>20</height>
    </size>
    </property>
    </spacer>
    </item>
    </layout>
    </item>
    <item>
    <widget class="QSplitter" name="splitter">
    <property name="orientation">
    <enum>Qt::Horizontal</enum>
    </property>
    <property name="childrenCollapsible">
    <bool>false</bool>
    </property>
    <widget class="NotesListWidget" name="notesListWidget" native="true"/>
    <widget class="QTextEdit" name="textEdit"/>
    </widget>
    </item>
    </layout>
    </widget>
    <customwidgets>
    <customwidget>
    <class>NotesListWidget</class>
    <extends>QWidget</extends>
    <header>noteslistwidget.h</header>
    <container>1</container>
    </customwidget>
    </customwidgets>
    <resources/>
    <connections/>
    </ui>

    //note.h
    ////////
    #pragma once

    #include <QString>
    #include <QDateTime>

    struct Note
    {
    int id;
    QString title;
    QString content;
    QDateTime lastModified;

    };

    //noteslistwidget.cpp
    ///////////////////

    #include "noteslistwidget.h"
    #include "ui_noteslistwidget.h"

    #include "note.h"

    NotesListWidget::NotesListWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::NotesListWidget)
    {
    ui->setupUi(this);
    connect(ui->noteList, &QListWidget::itemSelectionChanged,
    this, &NotesListWidget::onItemSlectionChanged);
    }

    NotesListWidget::~NotesListWidget()
    {
    delete ui;
    }
    void NotesListWidget::addNote(const Note &note)
    {
    auto *item = new QListWidgetItem();
    ui->noteList->insertItem(0, item);

    setupNoteItem(note, item);
    

    }
    void NotesListWidget::removeCurrentNote()
    {
    auto *currentItem = ui->noteList->currentItem();
    if(currentItem != nullptr)
    {
    delete currentItem;
    }
    }
    void NotesListWidget::updateCurrentNote(const Note &note)
    {
    if(ui->noteList->currentRow() !=0 )
    {
    moveCurrenItemToTop(note);
    }
    }

    int NotesListWidget::currentNoteId()
    {
    auto *currentItem = ui->noteList->currentItem();
    int noteId =currentItem->data(Qt::UserRole).toInt();
    return noteId;
    }

    void NotesListWidget::onItemSlectionChanged()
    {
    auto *currentItem = ui->noteList->currentItem();
    if(currentItem)
    {
    int id = currentNoteId();
    emit selectedNoteChanged(id);
    }
    }
    void NotesListWidget::moveCurrenItemToTop(const Note &note)
    {
    blockSignals(true);
    auto *item = ui->noteList->takeItem(ui->noteList->currentRow());

    ui->noteList->insertItem(0,item);
    setupNoteItem(note, item);
    blockSignals(false);
    

    }
    void NotesListWidget::setupNoteItem(const Note &note, QListWidgetItem *item)
    {
    item->setText(note.title);
    item->setData(Qt::UserRole, note.id);
    ui->noteList->setCurrentItem(item);
    }

    // notesListWidget.h
    ////////////////////
    #pragma once

    #include <QWidget>

    namespace Ui {
    class NotesListWidget;
    }

    struct Note;
    class QListWidgetItem;

    class NotesListWidget : public QWidget
    {
    Q_OBJECT

    public:
    explicit NotesListWidget(QWidget *parent = nullptr);
    ~NotesListWidget();

    void addNote(const Note &note);
    void removeCurrentNote();
    void updateCurrentNote(const Note &note);
    
    int currentNoteId();
    

    signals:
    void selectedNoteChanged(int id);

    private:
    void onItemSlectionChanged();

    void moveCurrenItemToTop(const Note &note);
    void setupNoteItem(const Note &note, QListWidgetItem *item);
    

    private:
    Ui::NotesListWidget *ui;
    };

    //noteslistwidget.ui
    ////////////////////

    <?xml version="1.0" encoding="UTF-8"?>
    <ui version="4.0">
    <class>NotesListWidget</class>
    <widget class="QWidget" name="NotesListWidget">
    <property name="geometry">
    <rect>
    <x>0</x>
    <y>0</y>
    <width>261</width>
    <height>579</height>
    </rect>
    </property>
    <property name="windowTitle">
    <string>Form</string>
    </property>
    <layout class="QVBoxLayout" name="verticalLayout">
    <item>
    <widget class="QListWidget" name="noteList"/>
    </item>
    </layout>
    </widget>
    <resources/>
    <connections/>
    </ui>

    //notesmanager.cpp
    //////////////////

    #include "notesmanager.h"
    #include "note.h"

    #include <QTextDocument>
    #include <QSignalMapper>

    int nextNoteId();

    NotesManager::NotesManager(QObject *parent) : QObject(parent)
    {
    mapChangedSignalToNoteId = new QSignalMapper(this);
    connect(mapChangedSignalToNoteId, &QSignalMapper::mappedInt,
    this, &NotesManager::onNoteContentChanged);

    readNotes();  
    
    if(notes.size() ==0)
        createNewNote();
    

    }

    NotesManager::~NotesManager()
    {
    writeNotes();
    }

    void NotesManager::createNewNote()
    {
    int id = nextNoteId();
    auto &[note, textDocument] = notes[id];
    note.id = id;
    note.title = "new Note";
    note.lastModified = QDateTime::currentDateTime();
    textDocument = createNewTextDocument(note);

    emit newNoteCreated(id);

    }

    void NotesManager::removeNote(int id)
    {
    notes.erase(id);

    if(notes.empty())
        createNewNote();
    

    }

    void NotesManager::renameNote(int id, const QString &newTitle)
    {
    // todo
    // Q_UNUSED(id);
    // Q_UNUSED(newTitle);

       auto found = notes.find(id);
       if(found !=notes.end())
       {
           auto &[note, textDocument] = found->second;
           note.title = newTitle;
           note.lastModified = QDateTime::currentDateTime();
       }
    

    }

    const Note &NotesManager::note(int id) const
    {
    return notes.at(id).first;
    }

    QTextDocument *NotesManager::noteDocument(int id) const
    {
    auto found = notes.find(id);
    if(found != notes.end())
    {
    return found->second.second.get();
    }
    return nullptr;
    }

    std::vector<std::reference_wrapper<Note>>NotesManager::noteCollection()
    {
    std::vector<std::reference_wrapper<Note>> out;
    for(auto &i : notes)
    {
    auto &[note, QTextDocument] =i.second;
    note.content = QTextDocument.toPainText();
    out.push_back(note);
    }
    return out;
    }

    size_t NotesManager::count() const
    {
    return notes.size();
    }

    void NotesManager::onNoteContentChanged(int id)
    {
    notes.at(id).first.lastModified =QDateTime::currentDateTime();
    emit noteContendChanged(id);
    }

    void NotesManager::readNotes()
    {
    // todo
    }

    void NotesManager::writeNotes()
    {
    // todo
    }
    std::unique_ptr<QTextDocument> NotesManager::createNewTextDocument(const Note &note)
    {
    auto textDocument =std::make_unique<QTextDocument>(note.content);
    connect(textDocument.get(), &QTextDocument::contentsChange,
    mapChangedSignalToNoteId, qOverload<>(&QSignalMapper::map));
    mapChangedSignalToNoteId->setMapping(textDocument.get(),note.id);

    return textDocument;
    

    }
    int nextNoteId()
    {
    static int id = 0;
    return ++id;
    }

    //notesmanager.h
    ////////////////

    #pragma once
    #include <QObject>

    #include <unordered_map>
    #include <vector>
    #include <utility>
    #include <memory>

    struct Note;

    class QTextDocument;
    class QSignalMapper;

    class NotesManager : public QObject

    {
    Q_OBJECT
    public:
    explicit NotesManager(QObject *parent = nullptr);
    ~NotesManager();

    void createNewNote();
    void removeNote(int id);
    void renameNote(int id, const QString &newTitle);
    
    const Note &note(int id) const;
    QTextDocument *noteDocument(int id) const;
    std::vector<std::reference_wrapper<Note>> noteCollection();
    size_t count() const;
    

    signals:
    void newNoteCreated(int id);
    void noteContendChanged(int id);

    private:
    void onNoteContentChanged(int id);
    void readNotes();
    void writeNotes();
    std::unique_ptr<QTextDocument> createNewTextDocument(const Note &note);

    private:
    std::unordered_map<int, std::pair<Note, std::unique_ptr<QTextDocument>>> notes;
    QSignalMapper *mapChangedSignalToNoteId =nullptr;
    };

    //////////////////////
    // end notes.cpp


  • Lifetime Qt Champion


Log in to reply