Qt ошибка: 'class Ui::MainWindow' has no member named 'actionSave'; did you mean 'actionNew'?

399
27 сентября 2021, 11:40

Столкнулся с интересной ошибкой. Пару минут назад собирал проект, всё работало. После того как залил его на git начала появляться ошибка

D:\Qt\Git\TextEditor\mainwindow.cpp:13: ошибка: 'class Ui::MainWindow' has no member named 'actionSave'; did you mean 'actionNew'? connect(ui->actionSave, SIGNAL(triggered()), this, SLOT(saveFile())); ^~~~~~~~~~ actionNew

Да, я понимаю, что git не причём, но факт остаётся фактом, я ничего не изменял! Просто компилятор перестал видеть большую часть действий (QtAction) а-ля actionCopy/actionCut хотя в QtDesigner они имеются... Подскажите пожалуйста, что я сделал не так своими ручками, что всё сломалось? Вот файлы проекта: main.cpp:

#include "mainwindow.h"
#include <QtCore>
#include <QtGui>
#include <QApplication>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    a.setApplicationName(APPLICATION_NAME);
    a.setApplicationVersion(APPLICATION_VERSION);
    a.setOrganizationName(ORGANIZATION_NAME);
    a.setOrganizationDomain(ORGANIZATION_DOMAIN);
    a.setWindowIcon(QIcon(":/icons/images/new.png"));
    MainWindow w;
    w.show();
    return a.exec();
}

mainwindow.h:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#define DEFAULT_FONT "Cooper Black"
#define DEFAULT_FONT_SIZE 12
#define APPLICATION_NAME "TextEditor"
#define APPLICATION_VERSION "0.1"
#define ORGANIZATION_NAME "MephiSoft"
#define ORGANIZATION_DOMAIN "mephi.ru"
#include <QMainWindow>
#include <QCloseEvent>
#include <QMessageBox>
#include <QPushButton>
#include <QFontDialog>
#include <QSettings>
#include <QTextStream>
#include <QFileInfo>
#include <QFileDialog>
#include <QDir>
#include <QStringBuilder>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    MainWindow(const QString& filename, QWidget *parent = 0);
    QSettings *settings;
private slots:
    void on_actionNew_triggered();
    void on_textEdit_textChanged();
    void closeEvent(QCloseEvent *);
    void on_actionSelectFont_triggered();
    void on_actionAbout_triggered();
    void on_actionOpen_triggered();
    bool saveFile();
    bool saveFileAs();
private:
    void documentModified();
    void connect_clipboard();
    void loadFile(const QString &);
    void setFileName(const QString &);
    QString m_fileName;
private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

mainwindow.cpp:

#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    connect(ui->actionClose, SIGNAL(triggered()), this, SLOT(close()));
    connect(ui->actionExit, SIGNAL(triggered()), qApp, SLOT(closeAllWindows()));
    connect_clipboard();
    connect(ui->actionSave, SIGNAL(triggered()), this, SLOT(saveFile()));
    connect(ui->actionSaveAs, SIGNAL(triggered()), this, SLOT(saveFileAs()));
    settings = new QSettings(ORGANIZATION_NAME, APPLICATION_NAME);
    QString viewFont = "viewFont";
    QFont default_font(DEFAULT_FONT, DEFAULT_FONT_SIZE);
    QFont last_font = qvariant_cast<QFont>(settings -> value(viewFont, default_font));
    ui -> textEdit -> setFont(last_font);
    m_fileName = QString();
    setFileName(m_fileName);
}
MainWindow::MainWindow(const QString& filename, QWidget *parent)
    : MainWindow(parent)
{
    m_fileName = filename;
    loadFile(m_fileName);
}

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

void MainWindow::on_actionNew_triggered()
{
    MainWindow* w1 = new MainWindow;
    w1 -> show();
}
void MainWindow::on_textEdit_textChanged()
{
    documentModified();
}
void MainWindow::documentModified()
{
    setWindowModified(true);
}
void MainWindow::closeEvent(QCloseEvent *e)
{
    if (! this -> isWindowModified()) e -> accept();
    else{
        QString title = tr("TextEditor");
        QString text = tr("Сохранить изменения в файле %1?").arg(m_fileName);
        QString save = tr("Сохранить");
        QString no_save = tr("Не сохранять");
        QString cancel = tr("Отмена");
        QMessageBox messageBox(QMessageBox::Question,
                    title,
                    text,
                    QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel,
                    this);
        messageBox.setButtonText(QMessageBox::Save, save);
        messageBox.setButtonText(QMessageBox::Discard, no_save);
        messageBox.setButtonText(QMessageBox::Cancel, cancel);
        int res = messageBox.exec();
        switch(res){
            case QMessageBox::Save:
            {
                bool result;
                if (m_fileName.isNull()) result = saveFileAs();
                else result = saveFile();
                result ? e -> accept(): e -> ignore();
                break;
            }
            case QMessageBox::Discard:
                e -> accept();
                break;
            case QMessageBox::Cancel:
                e -> ignore();
                break;
        }
    }
}
void MainWindow::on_actionSelectFont_triggered()
{
    bool ok;
    QString viewFont = "viewFont";
    QFont last_font = qvariant_cast<QFont>(settings -> value(viewFont));
    QFont font = QFontDialog::getFont(&ok, last_font, this);
    if (ok){
        ui->textEdit->setFont(font);
        settings -> setValue(viewFont, font);
    }
}
void MainWindow::connect_clipboard(){
    ui->actionCopy->setEnabled(false);
    ui->actionCut->setEnabled(false);
    ui->actionUndo->setEnabled(false);
    ui->actionRedo->setEnabled(false);
    connect(ui->actionAboutQt, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
    connect(ui->actionCut, SIGNAL(triggered()), ui->textEdit, SLOT(cut()));
    connect(ui->actionCopy, SIGNAL(triggered()), ui->textEdit, SLOT(copy()));
    connect(ui->actionPaste, SIGNAL(triggered()), ui->textEdit, SLOT(paste()));
    connect(ui->actionUndo, SIGNAL(triggered()), ui->textEdit, SLOT(undo()));
    connect(ui->actionRedo, SIGNAL(triggered()), ui->textEdit, SLOT(redo()));
    connect(ui->textEdit, SIGNAL(copyAvailable(bool)), ui->actionCopy, SLOT(setEnabled(bool)));
    connect(ui->textEdit, SIGNAL(copyAvailable(bool)), ui->actionCut, SLOT(setEnabled(bool)));
    connect(ui->textEdit, SIGNAL(undoAvailable(bool)), ui->actionUndo, SLOT(setEnabled(bool)));
    connect(ui->textEdit, SIGNAL(redoAvailable(bool)), ui->actionRedo, SLOT(setEnabled(bool)));
}
void MainWindow::on_actionAbout_triggered()
{
    QString title = QString("О программе");
    QString done_by = QString("Выполнил: Чудновец Иван Владимирович\nГруппа: Б17-511");
    QMessageBox::about(this, title, done_by);
}
void MainWindow::loadFile(const QString &fileName){
    QFile file(fileName);
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)){
        QMessageBox::warning(this, tr("Ошибка"), tr("Ошибка: не удалось открыть файл."));
        setFileName(QString());
    }
    else{
        QTextStream in(&file);
        ui->textEdit->setText(in.readAll());
        file.close();
        setFileName(fileName);
        this -> setWindowModified(false);
    }
}
void MainWindow::setFileName(const QString &fileName){
    m_fileName = fileName;
    QString title = QString("%1[*] - %2")
            .arg(m_fileName.isNull()?"Новый документ":QFileInfo(m_fileName).fileName())
            .arg(QApplication::applicationName());
    this ->setWindowTitle(title);
}
void MainWindow::on_actionOpen_triggered()
{
    QString fileName = QFileDialog::getOpenFileName(this,
            "Открыть документ", QDir::currentPath(), "Text documents (*.txt)");
    if (fileName.isNull()) return;
    else{
        if (!this->isWindowModified()){
            loadFile(fileName);
        }
        else{
            MainWindow* w = new MainWindow(fileName);
            w -> show();
        }
    }
}
bool MainWindow::saveFileAs(){
    QString fileName = QFileDialog::getSaveFileName(this, "Сохранить документ",
          m_fileName.isNull()?QDir::currentPath():m_fileName, "Text documents (*.txt)");
    if (fileName.isNull())return false;
    setFileName(fileName);
    return saveFile();
}
bool MainWindow::saveFile(){
    if (m_fileName.isNull())return saveFileAs();
    QFile file(m_fileName);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)){
        QMessageBox::warning(this, tr("Ошибка"), tr("Ошибка: не удалось открыть файл."));
        setFileName(QString());
        return false;
    }
    QTextStream in(&file);
    in << ui->textEdit->toPlainText();
    file.close();
    this ->setWindowModified(false);
    return true;
}

Для тех, кто не верит, что все action'ы на месте:

И, наконец, mainwindow.ui:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>800</width>
    <height>600</height>
   </rect>
  </property>
  <property name="sizePolicy">
   <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
    <horstretch>0</horstretch>
    <verstretch>0</verstretch>
   </sizepolicy>
  </property>
  <property name="windowTitle">
   <string>TextEditor[*]</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QVBoxLayout" name="verticalLayout">
    <item>
     <widget class="QTextEdit" name="textEdit"/>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>800</width>
     <height>21</height>
    </rect>
   </property>
   <widget class="QMenu" name="menu">
    <property name="title">
     <string>&amp;Файл</string>
    </property>
    <addaction name="actionNew"/>
    <addaction name="actionOpen"/>
    <addaction name="actionSave"/>
    <addaction name="actionSaveAs"/>
    <addaction name="separator"/>
    <addaction name="actionClose"/>
    <addaction name="separator"/>
    <addaction name="actionExit"/>
   </widget>
   <widget class="QMenu" name="menu_2">
    <property name="title">
     <string>Вид</string>
    </property>
    <addaction name="actionSelectFont"/>
   </widget>
   <widget class="QMenu" name="menu_3">
    <property name="title">
     <string>Помощь</string>
    </property>
    <addaction name="actionAbout"/>
    <addaction name="separator"/>
    <addaction name="actionAboutQt"/>
   </widget>
   <widget class="QMenu" name="menu_4">
    <property name="title">
     <string>Редактирование</string>
    </property>
    <addaction name="actionCut"/>
    <addaction name="actionCopy"/>
    <addaction name="actionPaste"/>
    <addaction name="actionUndo"/>
    <addaction name="actionRedo"/>
   </widget>
   <addaction name="menu"/>
   <addaction name="menu_4"/>
   <addaction name="menu_2"/>
   <addaction name="menu_3"/>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
  <widget class="QToolBar" name="toolBar">
   <property name="windowTitle">
    <string>toolBar</string>
   </property>
   <attribute name="toolBarArea">
    <enum>TopToolBarArea</enum>
   </attribute>
   <attribute name="toolBarBreak">
    <bool>false</bool>
   </attribute>
   <addaction name="actionNew"/>
   <addaction name="actionSave"/>
   <addaction name="separator"/>
   <addaction name="actionCopy"/>
   <addaction name="actionPaste"/>
   <addaction name="actionCut"/>
   <addaction name="actionUndo"/>
   <addaction name="actionRedo"/>
  </widget>
  <action name="actionNew">
   <property name="icon">
    <iconset resource="icons.qrc">
     <normaloff>:/icons/images/new.png</normaloff>:/icons/images/new.png</iconset>
   </property>
   <property name="text">
    <string>Создать</string>
   </property>
   <property name="toolTip">
    <string>Создать новый документ</string>
   </property>
   <property name="shortcut">
    <string>Ctrl+N</string>
   </property>
  </action>
  <action name="actionClose">
   <property name="text">
    <string>Закрыть</string>
   </property>
   <property name="toolTip">
    <string>Закрыть текущее окно</string>
   </property>
   <property name="shortcut">
    <string>Ctrl+W</string>
   </property>
  </action>
  <action name="actionExit">
   <property name="text">
    <string>Выход</string>
   </property>
   <property name="toolTip">
    <string>Завершить работу</string>
   </property>
  </action>
  <action name="actionSelectFont">
   <property name="text">
    <string>Выбрать шрифт...</string>
   </property>
   <property name="toolTip">
    <string>Выбор шрифта текста</string>
   </property>
  </action>
  <action name="actionAbout">
   <property name="text">
    <string>О программе</string>
   </property>
  </action>
  <action name="actionAboutQt">
   <property name="text">
    <string>О Qt</string>
   </property>
  </action>
  <action name="actionCut">
   <property name="icon">
    <iconset resource="icons.qrc">
     <normaloff>:/icons/images/cut.png</normaloff>:/icons/images/cut.png</iconset>
   </property>
   <property name="text">
    <string>Вырезать</string>
   </property>
   <property name="toolTip">
    <string>Вырезать</string>
   </property>
   <property name="shortcut">
    <string>Ctrl+X</string>
   </property>
  </action>
  <action name="actionCopy">
   <property name="icon">
    <iconset resource="icons.qrc">
     <normaloff>:/icons/images/copy.png</normaloff>:/icons/images/copy.png</iconset>
   </property>
   <property name="text">
    <string>Копировать</string>
   </property>
   <property name="toolTip">
    <string>Копировать</string>
   </property>
   <property name="shortcut">
    <string>Ctrl+C</string>
   </property>
  </action>
  <action name="actionPaste">
   <property name="icon">
    <iconset resource="icons.qrc">
     <normaloff>:/icons/images/paste.png</normaloff>:/icons/images/paste.png</iconset>
   </property>
   <property name="text">
    <string>Вставить</string>
   </property>
   <property name="toolTip">
    <string>Вставить</string>
   </property>
   <property name="shortcut">
    <string>Ctrl+V</string>
   </property>
  </action>
  <action name="actionUndo">
   <property name="icon">
    <iconset resource="icons.qrc">
     <normaloff>:/icons/images/editundo.png</normaloff>:/icons/images/editundo.png</iconset>
   </property>
   <property name="text">
    <string>Отменить</string>
   </property>
   <property name="toolTip">
    <string>Отмена последнего действия </string>
   </property>
   <property name="shortcut">
    <string>Ctrl+Z</string>
   </property>
  </action>
  <action name="actionRedo">
   <property name="icon">
    <iconset resource="icons.qrc">
     <normaloff>:/icons/images/editredo.png</normaloff>:/icons/images/editredo.png</iconset>
   </property>
   <property name="text">
    <string>Повторить</string>
   </property>
   <property name="toolTip">
    <string>Повтор последнего действия</string>
   </property>
   <property name="shortcut">
    <string>Ctrl+Y</string>
   </property>
  </action>
  <action name="actionOpen">
   <property name="icon">
    <iconset resource="icons.qrc">
     <normaloff>:/icons/images/open.png</normaloff>:/icons/images/open.png</iconset>
   </property>
   <property name="text">
    <string>Открыть...</string>
   </property>
   <property name="toolTip">
    <string>Открыть документ</string>
   </property>
   <property name="shortcut">
    <string>Ctrl+O</string>
   </property>
  </action>
  <action name="actionSave">
   <property name="icon">
    <iconset resource="icons.qrc">
     <normaloff>:/icons/images/save.png</normaloff>:/icons/images/save.png</iconset>
   </property>
   <property name="text">
    <string>Сохранить...</string>
   </property>
   <property name="toolTip">
    <string>Сохранить документ</string>
   </property>
   <property name="shortcut">
    <string>Ctrl+S</string>
   </property>
  </action>
  <action name="actionSaveAs">
   <property name="text">
    <string>Сохранить как...</string>
   </property>
   <property name="toolTip">
    <string>Сохранить документ как</string>
   </property>
   <property name="shortcut">
    <string>Ctrl+Shift+S</string>
   </property>
  </action>
 </widget>
 <resources>
  <include location="icons.qrc"/>
 </resources>
 <connections/>
</ui>
Answer 1

Попробуйте перезапустить QMake. Для этого в контекстном меню выберите

Сборка -> Очистить все

Если это не поможет, удалите папку build-* в директории с папкой проекта

READ ALSO
Ускорение Сишниго ввода/вывода

Ускорение Сишниго ввода/вывода

Если в программе используется Сишный ввод/вывод (scanf(), printf()), то рассинхронизация потоков (std::ios_base::sync_with_stdio(false)) может увеличить производительность?...

95
Что означает данное выражение?

Что означает данное выражение?

Помогите пожалуйста понять данный код

102
перекомпилируйте с параметром -fPIC

перекомпилируйте с параметром -fPIC

Работаю над проектом(состоящий из нескольких подпроектов) Cmake с использование библиотеки wxWidgets, некоторые проекты не могут собраться по причине:

61