Qt C ++ QException问题:调试错误

时间:2013-10-02 18:44:11

标签: c++ qt

我想从XML文件中读取对象,我需要处理2个异常:当无法打开文件时以及无法加载文件内容时。 (格式不正确)我编写了以下函数来读取文件中的内容和2个异常的clases。问题是,当我运行我的应用程序并且我尝试加载具有不同格式的文件然后XML,而不是通知存在异常的frindly消息时,我有一个调试错误:调用abort()。我做得不好? 阅读功能

QList<Vehicle> VehicleHelper::readVehicles(QString fileName){
QList<Vehicle> vehicles;
Vehicle newVehicle;
QFile file(fileName);
QDomDocument document;
if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){
    throw FileCannotBeOpenException();
}
else{
    if(!document.setContent(&file)){
        throw InvalidXMLContentException();
    }
    file.close();
}

QDomElement root = document.firstChildElement();
QDomNodeList carElements = root.elementsByTagName("Car");
for(int i = 0; i < carElements.size(); i++){

    QDomNode carNode = carElements.at(i);

    QDomElement carElement = carNode.toElement();
    QString carID = carElement.attribute("ID");

    //if the idNumber is null, generate one
    if(carID.isEmpty()){
        QUuid newId = Vehicle::generateID();
        newVehicle.setVehicleId(newId);
    }
    else {
        QUuid id;
        try{
            id = QUuid::QUuid(carID);
        } catch(QException &ex){
            continue;
        }


        newVehicle.setVehicleId(id);
    }
  }

函数的调用

void MainWindow::on_actionOpen_triggered()
{
if(isModified){
    QMessageBox msgBox;
    QString message = "There are unsaved changes! Do you proceed? ";
    msgBox.setWindowTitle("Save Changes");
    msgBox.setText(message);
    msgBox.addButton("Don't save",QMessageBox::NoRole);
    msgBox.addButton(QMessageBox::Save);
    msgBox.addButton(QMessageBox::Cancel);
    msgBox.setIcon(QMessageBox::Question);
    int result = msgBox.exec();
    if(result == QMessageBox::Save){
        VehicleHelper::writeVehicles(cars,filename);
        msgBox.close();
    } else {
        QString fileName = QFileDialog::getOpenFileName(this,"Open file");
        if(!fileName.isEmpty()){
            setFileName(fileName);
            QFile file(fileName);
            try {
                cars = VehicleHelper::readVehicles(fileName);
            } catch(FileCannotBeOpenException &ex) {
                QMessageBox msgBox;
                msgBox.setIcon(QMessageBox::Critical);
                msgBox.setWindowTitle("Message!");
                msgBox.setText("Failed to open file");
                msgBox.setDefaultButton(QMessageBox::Ok);
                msgBox.exec();
                return;

            } catch(InvalidXMLContentException &ex){
                QMessageBox msgBox;
                msgBox.setIcon(QMessageBox::Critical);
                msgBox.setWindowTitle("Message!");
                msgBox.setText("Failed to load data!");
                msgBox.setDefaultButton(QMessageBox::Ok);
                msgBox.exec();
                return;
            }

            setTakenNumbersList(cars);
            //set data to the table view
            populate(cars);
       }
    }
 } else {
    QString fileName = QFileDialog::getOpenFileName(this,"Open file");
    if(!fileName.isEmpty()){
        setFileName(fileName);
        QFile file(fileName);
        if(file.open(QFile::ReadOnly | QFile::Text)){
            cars = VehicleHelper::readVehicles(fileName);
            setTakenNumbersList(cars);
            file.close();

            //set data to the table view
            populate(cars);

            ui->actionAdd->setEnabled(true);
            ui->actionBy_name->setEnabled(true);
            ui->actionBy_registration_date->setEnabled(true);
            ui->actionBy_registration_number->setEnabled(true);
            ui->actionBy_revision_date->setEnabled(true);
            ui->actionBy_type->setEnabled(true);
            ui->actionClear_Search->setEnabled(true);
            ui->actionDelete->setEnabled(true);
            ui->actionEdit->setEnabled(true);
            ui->actionSave->setEnabled(true);
            ui->actionSave_As->setEnabled(true);
        }
     }

    }
 }

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
try{
    w.show();
} catch(QException &ex){

}
return a.exec();
}

1 个答案:

答案 0 :(得分:2)

从事件循环中运行的代码抛出异常,特别是它们将到达QCoreApplication::notify()。这个是通过介入的操作系统事件循环调用从a.exec()间接调用的。

因此,您不能仅仅将a.exec()包装在try / catch中。您必须按以下方式重新实施QCoreApplication::notify()

class MyApplication : public QApplication
{
public:
   MyApplication(int & c, char ** a) : QApplication(c,a) {}
   virtual bool notify(QObject * obj, QEvent * ev) {
      bool rc = true;
      try {
         rc = QApplication::notify(obj, ev);
      }
      catch (QException &ex) {
         ...
      }
      return rc;
   }
};

int main(...) {
   MyApplication app(...);
   ...
}

您的代码的另一个问题是它尖叫使用State Machine Framework。你应该有代表文件打开和关闭的状态,以及例如中间状态。显示“未保存的更改”对话框。然后你不会在代码周围散布ui->actionXYZ->setEnabled(true)。假设你有一个fileOpen州,你就有了

fileOpen->assignProperty(ui->actionBy_name, "setEnabled", true);
...

然后,当文件打开时,您会发出一个信号,该信号附加到状态机中的信号转换。状态机将完成剩下的工作 - 它将为您启用/禁用操作等。