2013-10-02 4 views
1

XML 파일에서 개체를 읽고 싶습니다. 파일을 열 수 없거나 파일 콘텐츠를로드 할 수없는 경우 2 가지 예외를 처리해야합니다. (잘못 formated) 파일 및 예외에 대한 2 개의 clases에서 내용을 읽을 다음 함수를 작성했습니다. 문제는 내가 응용 프로그램을 실행할 때 예외가 있다는 것을 나타내는 frindly 메시지 대신 XML 형식이 다른 파일을로드하려고 할 때 디버그 오류가 발생합니다. abort()가 호출되었습니다. 나는 잘하지 못하고 있니?Qt C++ QException 문제 : 디버그 오류

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

} 
return a.exec(); 
} 

답변

2

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); 
     } 
    } 

    } 
} 

주요 기능의 읽기 기능

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); 
    } 
    } 

호출이 예외는 특히 그들이 QCoreApplication::notify()에 도달 할 것, 이벤트 루프에서 실행되는 코드에서 발생한다. 이 것은 간접적 인 운영 체제 이벤트 루프 호출을 통해 a.exec()에서 간접적으로 호출됩니다.

따라서 a.exec()을 try/catch로 감쌀 수 없습니다. 코드와

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를 사용하는 비명이다 : 다음과 같이 QCoreApplication::notify() 다시 구현해야합니다. 파일을 열고 닫는 것을 나타내는 상태와 예를 들어 중간 상태를 가져야합니다. "저장되지 않은 변경 사항"대화 상자가 나타납니다. 그러면 코드 주위에 ui->actionXYZ->setEnabled(true)이 깔려 있지 않습니다. 당신이 fileOpen 상태를 가정하면, 다음

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

을 할 파일이 열려있을 때, 당신은 상태 머신의 신호 전환에 부착 된 신호를 방출한다. 상태 머신이 나머지 작업을 수행합니다 - 사용자 등에 대한 작업을 활성화/비활성화합니다.