[qet] [1907] Reworked the way project saving is presented to users. |
[ Thread Index |
Date Index
| More lists.tuxfamily.org/qet Archives
]
Revision: 1907
Author: xavier
Date: 2012-07-13 09:21:19 +0200 (Fri, 13 Jul 2012)
Log Message:
-----------
Reworked the way project saving is presented to users.
Modified Paths:
--------------
trunk/sources/projectview.cpp
trunk/sources/projectview.h
trunk/sources/qetdiagrameditor.cpp
trunk/sources/qetdiagrameditor.h
trunk/sources/qetproject.cpp
trunk/sources/qetproject.h
Added Paths:
-----------
trunk/sources/closediagramsdialog.cpp
trunk/sources/closediagramsdialog.h
trunk/sources/qetresult.cpp
trunk/sources/qetresult.h
Added: trunk/sources/closediagramsdialog.cpp
===================================================================
--- trunk/sources/closediagramsdialog.cpp (rev 0)
+++ trunk/sources/closediagramsdialog.cpp 2012-07-13 07:21:19 UTC (rev 1907)
@@ -0,0 +1,313 @@
+/*
+ Copyright 2006-2012 Xavier Guerrin
+ This file is part of QElectroTech.
+
+ QElectroTech is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ QElectroTech is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include "closediagramsdialog.h"
+#include "diagram.h"
+#include "qeticons.h"
+
+/**
+ Construct a dialog showing \a diagrams.
+ @param parent Parent QWidget
+*/
+CloseDiagramsDialog::CloseDiagramsDialog(const QList<Diagram *> &diagrams, QWidget *parent) :
+ QDialog(parent),
+ diagrams_list_(diagrams),
+ answer_(-1)
+{
+ initWidgets();
+ initLayout();
+}
+
+/**
+ Destructor
+*/
+CloseDiagramsDialog::~CloseDiagramsDialog() {
+}
+
+/**
+ @return the user answer once the dialog has been executed.
+*/
+int CloseDiagramsDialog::answer() const {
+ return(answer_);
+}
+
+/**
+ @return what the user wants to do with \a diagram
+ @see CloseDiagramsDialog::Actions
+*/
+int CloseDiagramsDialog::actionForDiagram(Diagram *diagram) {
+ if (QCheckBox *checkbox = getCheckBoxForDiagram(diagram)) {
+ if (!diagram -> undoStack().isClean()) {
+ return(checkbox -> isChecked() ? Save : DoNotSave);
+ } else if (!diagram -> wasWritten()) {
+ return(checkbox -> isChecked() ? Save : Remove);
+ }
+ }
+ return(Unknown);
+}
+
+/**
+ @return the list of diagrams for which users have chosen the \a action
+ action.
+*/
+QList<Diagram *> CloseDiagramsDialog::diagramsByAction(Actions action) {
+ QList<Diagram *> diagrams;
+ foreach (Diagram *diagram, diagrams_list_) {
+ if (actionForDiagram(diagram) == action) {
+ diagrams << diagram;
+ }
+ }
+ return(diagrams);
+}
+
+/**
+ Initialize widgets.
+*/
+void CloseDiagramsDialog::initWidgets() {
+ setWindowTitle(tr("Fermer un projet", "window title"));
+
+ connect(&show_mapper_, SIGNAL(mapped(int)), this, SLOT(requireShowDiagram(int)));
+
+ // label when diagrams were modified
+ informative_label1_ = new QLabel(
+ tr(
+ "Les sch\351mas ci-dessous contiennent des modifications non "
+ "enregistr\351es. Faut-il les sauvegarder ?",
+ "informative label"
+ )
+ );
+ informative_label1_ -> setWordWrap(true);
+
+ // label when no diagrams were modified
+ informative_label2_ = new QLabel(tr("Voulez-vous enregistrer le projet ?", "informative label"));
+ informative_label2_ -> setWordWrap(true);
+
+ // header labels
+ QLabel *state_label = new QLabel(tr("\311tat", "column header"));
+ QLabel *title_label = new QLabel(tr("Sch\351ma", "column header"));
+
+ // header checkbox in order to check/uncheck all diagrams
+ all_checkbox_ = new QCheckBox(tr("Action", "column header"));
+ all_checkbox_ -> setChecked(true);
+ connect(all_checkbox_, SIGNAL(stateChanged(int)), this, SLOT(topCheckBoxChangedState(int)));
+
+ // spacers inserted in the header row
+ QSpacerItem *spacer1 = new QSpacerItem(10, 10, QSizePolicy::Expanding, QSizePolicy::Minimum);
+ QSpacerItem *spacer2 = new QSpacerItem(25, 10, QSizePolicy::Preferred, QSizePolicy::Minimum);
+
+ buttons_ = new QDialogButtonBox(QDialogButtonBox::Save | QDialogButtonBox::Discard | QDialogButtonBox::Cancel);
+ connect(buttons_, SIGNAL(clicked(QAbstractButton *)), this, SLOT(storeAnswer(QAbstractButton *)));
+
+ // widget layout
+ diagrams_list_layout_ = new QGridLayout();
+ diagrams_list_layout_ -> addWidget(state_label, 0, 1, 1, 1, Qt::AlignCenter);
+ diagrams_list_layout_ -> addItem(spacer1, 0, 2);
+ diagrams_list_layout_ -> addWidget(title_label, 0, 3, 1, 1, Qt::AlignCenter);
+ diagrams_list_layout_ -> addItem(spacer2, 0, 4);
+ diagrams_list_layout_ -> addWidget(all_checkbox_, 0, 5, 1, 1, Qt::AlignCenter);
+
+ // widget
+ diagrams_list_widget_ = new QWidget();
+ diagrams_list_widget_ -> setLayout(diagrams_list_layout_);
+ diagrams_list_widget_ -> setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
+
+ // scroll area
+ diagrams_list_area_ = new QScrollArea();
+ diagrams_list_area_ -> setWidgetResizable(true);
+ diagrams_list_area_ -> setFrameStyle(QFrame::Plain | QFrame::NoFrame);
+
+ loadDiagramsList();
+ diagrams_list_area_ -> setWidget(diagrams_list_widget_);
+}
+
+/**
+ Initialize layout.
+*/
+void CloseDiagramsDialog::initLayout() {
+ setMinimumSize(650, 340);
+
+ QVBoxLayout *vlayout0 = new QVBoxLayout();
+ vlayout0 -> addWidget(informative_label1_);
+ vlayout0 -> addWidget(informative_label2_);
+ vlayout0 -> addWidget(diagrams_list_area_);
+ vlayout0 -> addWidget(buttons_);
+ setLayout(vlayout0);
+}
+
+/**
+ Create a visual list of all modified diagrams.
+*/
+void CloseDiagramsDialog::loadDiagramsList() {
+ if (diagrams_list_.count()) {
+ int row_id = 1;
+ foreach (Diagram *diagram, diagrams_list_) {
+ addDiagram(diagram, row_id);
+ ++ row_id;
+ }
+ informative_label2_ -> setVisible(false);
+ } else {
+ informative_label1_ -> setVisible(false);
+ diagrams_list_area_ -> setVisible(false);
+ }
+}
+
+/**
+ Add \a diagram to the \a row_id row of the visual list.
+*/
+void CloseDiagramsDialog::addDiagram(Diagram *diagram, int row_id) {
+ QLabel *diagram_title = new QLabel(diagramTitle(diagram));
+ QPushButton *diagram_show = new QPushButton(QET::Icons::ZoomOriginal, ""); // tr("Afficher ce sch\351ma", "button label")
+ show_mapper_.setMapping(diagram_show, row_id - 1);
+ connect(diagram_show, SIGNAL(released()), &show_mapper_, SLOT(map()));
+ QLabel *diagram_status = new QLabel(diagramStatus(diagram));
+ QCheckBox *diagram_checkbox = new QCheckBox(diagramAction(diagram));
+ diagram_checkbox -> setChecked(true);
+ connect(diagram_checkbox, SIGNAL(stateChanged(int)), this, SLOT(lambdaCheckBoxChangedState(int)));
+
+ diagrams_list_layout_ -> addWidget(diagram_show, row_id, 0, 1, 1, Qt::AlignCenter);
+ diagrams_list_layout_ -> addWidget(diagram_title, row_id, 1, 1, 1, Qt::AlignCenter);
+ diagrams_list_layout_ -> addWidget(diagram_status, row_id, 3, 1, 1, Qt::AlignCenter);
+ diagrams_list_layout_ -> addWidget(diagram_checkbox, row_id, 5, 1, 1, Qt::AlignCenter);
+}
+
+/**
+ @return the action checkbox for \a diagram, or 0 if no adequate checkbox could be found.
+*/
+QCheckBox *CloseDiagramsDialog::getCheckBoxForDiagram(Diagram *diagram) {
+ int diagram_index = diagrams_list_.indexOf(diagram);
+ if (diagram_index == -1) return(0);
+
+ // We add 1 because there is one row dedicated to column headers;
+ // 4 is the column containing checkboxes, see initWidgets().
+ QLayoutItem *item = diagrams_list_layout_ -> itemAtPosition(diagram_index + 1, 5);
+ if (!item) return(0);
+
+ QWidget *widget = item -> widget();
+ if (!widget) return(0);
+
+ return(static_cast<QCheckBox *>(widget));
+}
+
+/**
+ @return the title for \a diagram
+*/
+QString CloseDiagramsDialog::diagramTitle(Diagram *diagram) {
+ if (!diagram -> title().isEmpty()) {
+ return(diagram -> title());
+ }
+ return(tr("Sch\351ma sans titre", "fallback diagram title"));
+}
+
+/**
+ @return a string describing the status of \a diagram
+*/
+QString CloseDiagramsDialog::diagramStatus(Diagram *diagram) {
+ if (!diagram) return(QString());
+ if (!diagram -> undoStack().isClean()) {
+ return(tr("Modifi\351", "diagram status"));
+ } else if (!diagram -> wasWritten()) {
+ return(tr("Ajout\351, non modifi\351", "diagram status"));
+ } else {
+ return(QString());
+ }
+}
+
+/**
+ @return a string describing the effect of saving \a diagram (e.g. "Save" or
+ "Keep").
+*/
+QString CloseDiagramsDialog::diagramAction(Diagram *diagram) {
+ if (!diagram) return(QString());
+ if (!diagram -> undoStack().isClean()) {
+ return(tr("Enregistrer", "diagram action"));
+ } else if (!diagram -> wasWritten()) {
+ return(tr("Conserver", "diagram action"));
+ } else {
+ return(QString());
+ }
+}
+
+/**
+ Adjust the state of the header checkbox when a diagram checkbox was
+ switched to \a new_state.
+*/
+void CloseDiagramsDialog::lambdaCheckBoxChangedState(int new_state) {
+ bool state = new_state;
+
+ bool all_same_state = true;
+ foreach (Diagram *diagram, diagrams_list_) {
+ if (QCheckBox *checkbox = getCheckBoxForDiagram(diagram)) {
+ if (checkbox -> isChecked() != state) {
+ all_same_state = false;
+ break;
+ }
+ }
+ }
+
+ all_checkbox_ -> blockSignals(true);
+ if (all_same_state) {
+ all_checkbox_ -> setTristate(false);
+ all_checkbox_ -> setChecked(state);
+ } else {
+ all_checkbox_ -> setTristate(true);
+ all_checkbox_ -> setCheckState(Qt::PartiallyChecked);
+ }
+ all_checkbox_ -> blockSignals(false);
+ all_checkbox_ -> update();
+}
+
+/**
+ Adjust diagram checkboxes when the header checkbox was switched to \a
+ new_state.
+*/
+void CloseDiagramsDialog::topCheckBoxChangedState(int new_state) {
+ setCheckedAll((bool)new_state);
+}
+
+/**
+ Set all diagram checkboxes to the checked (true) or unchecked (false)
+ state.
+*/
+void CloseDiagramsDialog::setCheckedAll(bool checked) {
+ foreach (Diagram *diagram, diagrams_list_) {
+ if (QCheckBox *checkbox = getCheckBoxForDiagram(diagram)) {
+ if (checkbox -> isChecked() != checked) {
+ checkbox -> blockSignals(true);
+ checkbox -> setChecked(checked);
+ checkbox -> blockSignals(false);
+ }
+ }
+ }
+}
+
+/**
+ Find the diagram at \a diagram_index and emts the showDiagram() signal with
+ it.
+*/
+void CloseDiagramsDialog::requireShowDiagram(int diagram_index) {
+ Diagram *diagram = diagrams_list_.value(diagram_index);
+ if (!diagram) return;
+ emit(showDiagram(diagram));
+}
+
+/**
+ Store the user answer when the dialog is validated or rejected.
+*/
+void CloseDiagramsDialog::storeAnswer(QAbstractButton *button) {
+ answer_ = buttons_ -> buttonRole(button);
+ accept();
+}
Added: trunk/sources/closediagramsdialog.h
===================================================================
--- trunk/sources/closediagramsdialog.h (rev 0)
+++ trunk/sources/closediagramsdialog.h 2012-07-13 07:21:19 UTC (rev 1907)
@@ -0,0 +1,92 @@
+/*
+ Copyright 2006-2012 Xavier Guerrin
+ This file is part of QElectroTech.
+
+ QElectroTech is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ QElectroTech is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef CLOSE_DIAGRAMS_DIALOG_H
+#define CLOSE_DIAGRAMS_DIALOG_H
+#include <QDialog>
+#include <QSignalMapper>
+class QAbstractButton;
+class QDialogButtonBox;
+class QCheckBox;
+class QLabel;
+class QPushButton;
+class Diagram;
+class QGridLayout;
+class QScrollArea;
+
+/**
+ This class represents a dialog asking users whether they want to save
+ their modified project when it is being closed and what they wish to save
+ in it.
+*/
+class CloseDiagramsDialog : public QDialog {
+ Q_OBJECT
+ public:
+ enum Actions {
+ Unknown,
+ Save,
+ DoNotSave,
+ Remove
+ };
+
+ // Constructors, destructor
+ public:
+ CloseDiagramsDialog(const QList<Diagram *> &diagrams, QWidget *parent = 0);
+ virtual ~CloseDiagramsDialog();
+ private:
+ CloseDiagramsDialog(const CloseDiagramsDialog &);
+
+ // methods
+ public:
+ int answer() const;
+ int actionForDiagram(Diagram *);
+ QList<Diagram *> diagramsByAction(Actions);
+
+ private:
+ void initWidgets();
+ void initLayout();
+ void loadDiagramsList();
+ void addDiagram(Diagram *, int);
+ QCheckBox *getCheckBoxForDiagram(Diagram *);
+ QString diagramTitle(Diagram *);
+ QString diagramStatus(Diagram *);
+ QString diagramAction(Diagram *);
+
+ signals:
+ void showDiagram(Diagram *);
+
+ private slots:
+ void lambdaCheckBoxChangedState(int);
+ void topCheckBoxChangedState(int);
+ void setCheckedAll(bool);
+ void requireShowDiagram(int);
+ void storeAnswer(QAbstractButton *);
+
+ // attributes
+ private:
+ QList<Diagram *> diagrams_list_; ///< List of (modified or newly added) diagrams displayed by the dialog
+ QLabel *informative_label1_; ///< Informative label when there are modified diagrams
+ QLabel *informative_label2_; ///< Informative label when there is no modified diagram
+ QCheckBox *all_checkbox_; ///< Header checkbox to check/uncheck all other checkboxes
+ QScrollArea *diagrams_list_area_; ///< Scroll area to make the diagrams visual list fit in the dialog
+ QWidget *diagrams_list_widget_; ///< Scrolled widget
+ QGridLayout *diagrams_list_layout_; ///< Layout used to list diagrams
+ QDialogButtonBox *buttons_; ///< Buttons for users to input their final choice
+ int answer_; ///< Reflects the user answer once the diagram has been executed
+ QSignalMapper show_mapper_; ///< Signal mapper for the "show diagram" buttons to work
+};
+#endif
Modified: trunk/sources/projectview.cpp
===================================================================
--- trunk/sources/projectview.cpp 2012-07-10 00:11:12 UTC (rev 1906)
+++ trunk/sources/projectview.cpp 2012-07-13 07:21:19 UTC (rev 1907)
@@ -18,6 +18,7 @@
#include "projectview.h"
#include "qetproject.h"
#include "configdialog.h"
+#include "closediagramsdialog.h"
#include "projectconfigpages.h"
#include "diagramview.h"
#include "diagram.h"
@@ -94,6 +95,36 @@
}
/**
+ @return A list containing child diagrams matching provided \a options.
+*/
+QList<Diagram *> ProjectView::getDiagrams(ProjectSaveOptions options) {
+ QList<Diagram *> selection;
+ if ((options & AllDiagrams) == AllDiagrams) {
+ selection << project_ -> diagrams();
+ } else {
+ Diagram *current = 0;
+ if (DiagramView *view = currentDiagram()) {
+ current = view -> diagram();
+ }
+ if (options & CurrentDiagram) {
+ if (current) selection << current;
+ } else if (options & AllDiagramsButCurrent) {
+ selection = project_ -> diagrams();
+ selection.removeOne(current);
+ }
+ }
+
+ if (options & ModifiedDiagramsOnly) {
+ foreach (Diagram *diagram, selection) {
+ if (!diagram -> undoStack().isClean() || !diagram -> wasWritten()) continue;
+ selection.removeOne(diagram);
+ }
+ }
+
+ return(selection);
+}
+
+/**
@return le schema actuellement active
*/
DiagramView *ProjectView::currentDiagram() const {
@@ -106,35 +137,7 @@
@param qce Le QCloseEvent decrivant l'evenement
*/
void ProjectView::closeEvent(QCloseEvent *qce) {
- // si la vue n'est pas liee a un projet, on ferme directement
- if (!project_) {
- qce -> accept();
- emit(projectClosed(this));
- return;
- }
-
- // si le projet est comme neuf et n'est pas enregistre, on ferme directement
- if (!project_ -> projectWasModified() && project_ -> filePath().isEmpty()) {
- qce -> accept();
- emit(projectClosed(this));
- return;
- }
-
- bool can_close_project = true;
- if (!tryClosing()) {
- // l'utilisateur a refuse la fermeture du projet - on arrete la
- can_close_project = false;
- } else {
- // a ce stade, l'utilisateur a accepte la fermeture de tout le contenu du projet
- if (!project_ -> filePath().isEmpty()) {
- // si le projet a un chemin specifie, on l'enregistre et on le ferme
- can_close_project = project_ -> write();
- } else {
- // l'utilisateur n'enregistre pas son projet
- can_close_project = true;
- }
- }
-
+ bool can_close_project = tryClosing();
if (can_close_project) {
qce -> accept();
emit(projectClosed(this));
@@ -152,34 +155,46 @@
@see tryClosingDiagrams()
*/
bool ProjectView::tryClosing() {
+ if (!project_) return(true);
+
+ // First step: require external editors closing -- users may either cancel
+ // the whole closing process or save (and therefore add) content into this
+ // project. Of course, they may also discard them.
if (!tryClosingElementEditors()) {
return(false);
}
- if (!tryClosingDiagrams()) {
- return(false);
+ // Check how different the current situation is from a brand new, untouched project
+ if (project_ -> filePath().isEmpty() && !project_ -> projectWasModified()) {
+ return(true);
}
- // a ce stade, l'utilisateur a accepte de fermer tous les editeurs
- // d'elements et tous les schemas
- // on regarde s'il reste du contenu dans le projet
- if (project_ -> projectWasModified() && project_ -> filePath().isEmpty()) {
- // si oui, on propose a l'utilisateur d'enregistrer le projet
- QMessageBox::StandardButton answer = QET::MessageBox::question(
- this,
- tr("Enregistrer le projet en cours ?", "message box title"),
- QString(tr("Voulez-vous enregistrer le projet ?", "message box content")),
- QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
- QMessageBox::Cancel
- );
- if (answer == QMessageBox::Cancel) {
- return(false);
- } else if (answer == QMessageBox::Yes) {
- return(save());
- }
+ // Second step: users are presented with a dialog that enables them to
+ // choose whether they want to:
+ // - cancel the closing process,
+ // - discard all modifications,
+ // - or specify what is to be saved, i.e. they choose whether they wants to
+ // save/give up/remove diagrams considered as modified.
+ int user_input = tryClosingDiagrams();
+ if (user_input == QDialogButtonBox::RejectRole) {
+ return(false); // the closing process was cancelled
+ } else if (user_input == QDialogButtonBox::DestructiveRole) {
+ return(true); // all modifications were discarded
}
- return(true);
+ // Check how different the current situation is from a brand new, untouched project (yes , again)
+ if (project_ -> filePath().isEmpty() && !project_ -> projectWasModified()) {
+ return(true);
+ }
+
+ if (project_ -> filePath().isEmpty()) {
+ QString filepath = askUserForFilePath();
+ if (filepath.isEmpty()) return(false); // users may cancel the closing
+ }
+ QETResult result = project_ -> write();
+ updateWindowTitle();
+ if (!result.isOk()) emit(errorEncountered(result.errorMessage()));
+ return(result.isOk());
}
/**
@@ -215,49 +230,45 @@
l'utilisateur s'il souhaite l'enlever.
@return true si tous les schemas peuvent etre fermes, false sinon
*/
-bool ProjectView::tryClosingDiagrams() {
- if (!project_) return(true);
+int ProjectView::tryClosingDiagrams() {
+ if (!project_) return(QDialogButtonBox::DestructiveRole);
- foreach(DiagramView *diagram_view, diagrams()) {
- if (!diagram_view -> diagram() -> undoStack().isClean()) {
- // ce schema a ete modifie - on demande a l'utilisateur s'il veut l'enregistrer
- showDiagram(diagram_view -> diagram());
- QMessageBox::StandardButton answer = QET::MessageBox::question(
- this,
- tr("Enregistrer le sch\351ma en cours ?", "message box title"),
- QString(tr("Voulez-vous enregistrer le sch\351ma %1 ?", "message box content - %1 is a diagram title")).arg(diagram_view -> windowTitle()),
- QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
- QMessageBox::Cancel
- );
- if (answer == QMessageBox::Cancel) {
- return(false);
- } else if (answer == QMessageBox::Yes) {
- if (!save()) {
- return(false);
- }
- }
- } else if (!diagram_view -> diagram() -> wasWritten()) {
- // ce schema a ete ajoute mais pas modifie - on demande a l'utilisateur s'il veut le conserver
- showDiagram(diagram_view -> diagram());
- QMessageBox::StandardButton answer = QET::MessageBox::question(
- this,
- tr("Enregistrer le nouveau sch\351ma ?", "message box title"),
- tr("Ce sch\351ma a \351t\351 ajout\351 mais n'a \351t\351 ni modifi\351 ni enregistr\351. Voulez-vous le conserver ?", "message box content"),
- QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
- QMessageBox::Cancel
- );
- if (answer == QMessageBox::Cancel) {
- return(false);
- } else if (answer == QMessageBox::Yes) {
- if (!save()) {
- return(false);
- }
- } else if (answer == QMessageBox::No) {
- removeDiagram(diagram_view);
- }
+ QList<Diagram *> modified_diagrams = getDiagrams(AllDiagrams | ModifiedDiagramsOnly);
+ if (!modified_diagrams.count() && !project_ -> filePath().isEmpty()) {
+ // nothing was modified, and we have a filepath, i.e. everything was already
+ // saved, i.e we can close the project right now
+ return(QDialogButtonBox::DestructiveRole);
+ }
+
+ CloseDiagramsDialog close_dialog(modified_diagrams, this);
+ if (!project_ -> title().isEmpty()) {
+ close_dialog.setWindowTitle(
+ QString(
+ tr(
+ "Fermer le projet \"%1\"",
+ "project closing dialog title -- %1 is a project title"
+ )
+ ).arg(project_ -> title())
+ );
+ }
+ connect(&close_dialog, SIGNAL(showDiagram(Diagram*)), this, SLOT(showDiagram(Diagram*)));
+ if (close_dialog.exec() == QDialog::Rejected) {
+ return(QDialogButtonBox::RejectRole);
+ }
+
+ if (close_dialog.answer() == QDialogButtonBox::AcceptRole) {
+ // save diagrams the user marked as to be saved
+ QList<Diagram *> to_save = close_dialog.diagramsByAction(CloseDiagramsDialog::Save);
+ saveDiagrams(to_save);
+
+ // remove diagrams the user marked as to be removed
+ QList<Diagram *> to_close = close_dialog.diagramsByAction(CloseDiagramsDialog::Remove);
+ foreach (Diagram *diagram, to_close) {
+ removeDiagram(diagram);
}
}
- return(true);
+
+ return(close_dialog.answer());
}
/**
@@ -291,6 +302,15 @@
}
/**
+ @return the QETResult object to be returned when it appears this project
+ view is not associated to any project.
+*/
+QETResult ProjectView::noProjectResult() const {
+ QETResult no_project(tr("aucun projet affich\351", "error message"), false);
+ return(no_project);
+}
+
+/**
Ajoute un nouveau schema au ProjectView
*/
void ProjectView::addNewDiagram() {
@@ -530,58 +550,78 @@
}
/**
- Enregistre le projet dans un fichier.
+ Save project properties along with all modified diagrams.
@see filePath()
@see setFilePath()
- @return true si l'enregistrement a reussi, false sinon
+ @return a QETResult object reflecting the situation
*/
-bool ProjectView::save() {
- bool result = false;
- if (project_) {
- if (project_ -> filePath().isEmpty()) {
- // le projet n'est pas encore enregistre dans un fichier
- // save() equivaut alors a saveAs()
- return(saveAs());
- }
- // on enregistre le schema en cours
- if (DiagramView *current_view = currentDiagram()) {
- if (Diagram *diagram = current_view -> diagram()) {
- diagram -> write();
- result = true;
- }
- } else {
- // s'il n'y a pas de schema, on appelle directement la methode write()
- result = project_ -> write();
- }
+QETResult ProjectView::save() {
+ return(doSave(AllDiagrams | ModifiedDiagramsOnly));
+}
+
+/**
+ Ask users for a filepath in order to save the project.
+ @param options May be used to specify what should be saved; defaults to
+ all modified diagrams.
+ @return a QETResult object reflecting the situation; note that a valid
+ QETResult object is returned if the operation was cancelled.
+*/
+QETResult ProjectView::saveAs(ProjectSaveOptions options) {
+ if (!project_) return(noProjectResult());
+
+ QString filepath = askUserForFilePath();
+ if (filepath.isEmpty()) return(QETResult());
+ return(doSave(options));
+}
+
+/**
+ Save the current diagram.
+ @return A QETResult object reflecting the situation.
+*/
+QETResult ProjectView::saveCurrentDiagram() {
+ return(doSave(CurrentDiagram));
+}
+
+/**
+ Save project content according to \a options, then write the project file. May
+ call saveAs if no filepath was provided before.
+ @param options May be used to specify what should be saved (e.g. modified
+ diagrams only).
+ @return a QETResult object reflecting the situation; note that a valid
+ QETResult object is returned if the operation was cancelled.
+*/
+QETResult ProjectView::doSave(ProjectSaveOptions options) {
+ if (!project_) return(noProjectResult());
+
+ if (project_ -> filePath().isEmpty()) {
+ // The project has not been saved to a file yet,
+ // so save() actually means saveAs().
+ return(saveAs(options));
}
+
+ // look for diagrams matching the required save options
+ saveDiagrams(getDiagrams(options));
+
+ // write to file
+ QETResult result = project_ -> write();
updateWindowTitle();
return(result);
}
/**
- Save all diagrams in the project.
- @return False if something went wrong (no project, no filepath provided, write
- error), true otherwise.
+ Save \a diagrams without emitting the written() signal and without writing
+ the project file itself.
*/
-bool ProjectView::saveAll() {
- if (project_) {
- if (project_ -> filePath().isEmpty()) {
- QString filepath = askUserForFilePath();
- if (filepath.isEmpty()) return(false);
- }
- foreach (Diagram *diagram, project_ -> diagrams()) {
- // Diagram::write() emits the written() signal, which is connected to
- // QETProject::write() through QETProject::componentWritten(). We do not want
- // to write the project immediately, so we block this signal.
- diagram -> blockSignals(true);
- diagram -> write();
- diagram -> blockSignals(false);
- }
- bool writing = project_ -> write();
- updateWindowTitle();
- return(writing);
+void ProjectView::saveDiagrams(const QList<Diagram *> &diagrams) {
+ foreach (Diagram *diagram, diagrams) {
+ // Diagram::write() emits the written() signal, which is connected
+ // to QETProject::write() through QETProject::componentWritten().
+ // We do not want to write the project immediately, so we block
+ // this signal.
+ diagram -> blockSignals(true);
+ diagram -> write();
+ diagram -> blockSignals(false);
}
- return(false);
}
/**
@@ -653,20 +693,6 @@
}
/**
- Demande un nom de fichier a l'utilisateur pour enregistrer le projet
- Si aucun nom n'est entre, elle renvoie faux.
- Si le nom ne se termine pas par l'extension .qet, celle-ci est ajoutee.
- Si l'enregistrement reussit, le nom du fichier est conserve et la fonction renvoie true.
- Sinon, faux est renvoye.
- @return true si l'enregistrement a reussi, false sinon
-*/
-bool ProjectView::saveAs() {
- QString filepath = askUserForFilePath();
- if (filepath.isEmpty()) return(false);
- return(save());
-}
-
-/**
Initialize actions for this widget.
*/
void ProjectView::initActions() {
Modified: trunk/sources/projectview.h
===================================================================
--- trunk/sources/projectview.h 2012-07-10 00:11:12 UTC (rev 1906)
+++ trunk/sources/projectview.h 2012-07-13 07:21:19 UTC (rev 1907)
@@ -19,6 +19,7 @@
#define PROJECT_VIEW_H
#include <QtGui>
#include "templatelocation.h"
+#include "qetresult.h"
class QETProject;
class DiagramView;
class Diagram;
@@ -29,6 +30,17 @@
*/
class ProjectView : public QWidget {
Q_OBJECT
+
+ public:
+ enum ProjectSaveOption {
+ ModifiedDiagramsOnly = 1,
+ CurrentDiagram = 2,
+ AllDiagramsButCurrent = 4,
+ AllDiagrams = 6
+ };
+ Q_DECLARE_FLAGS(ProjectSaveOptions, ProjectSaveOption)
+
+
// constructeurs, destructeur
public:
ProjectView(QETProject *, QWidget * = 0);
@@ -41,6 +53,7 @@
QETProject *project();
void setProject(QETProject *);
QList<DiagramView *> diagrams() const;
+ QList<Diagram *> getDiagrams(ProjectSaveOptions options);
DiagramView *currentDiagram() const;
void closeEvent(QCloseEvent *);
@@ -61,9 +74,11 @@
void moveDiagramDown(Diagram *);
void printProject();
void exportProject();
- bool save();
- bool saveAs();
- bool saveAll();
+ QETResult save();
+ QETResult saveAs(ProjectSaveOptions = ProjectSaveOptions(AllDiagrams | ModifiedDiagramsOnly));
+ QETResult saveCurrentDiagram();
+ QETResult doSave(ProjectSaveOptions);
+ void saveDiagrams(const QList<Diagram *> &);
int cleanProject();
void updateWindowTitle();
void updateTabTitle(DiagramView *, const QString &);
@@ -77,6 +92,7 @@
void diagramActivated(DiagramView *);
void diagramOrderChanged(ProjectView *, int, int);
void projectClosed(ProjectView *);
+ void errorEncountered(const QString &);
// relayed signals
void findElementRequired(const ElementsLocation &);
void editElementRequired(const ElementsLocation &);
@@ -91,8 +107,9 @@
void rebuildDiagramsMap();
bool tryClosing();
bool tryClosingElementEditors();
- bool tryClosingDiagrams();
+ int tryClosingDiagrams();
QString askUserForFilePath(bool = true);
+ QETResult noProjectResult() const;
private slots:
void tabChanged(int);
@@ -113,4 +130,5 @@
QMap<int, DiagramView *> diagram_ids_;
QList<DiagramView *> diagrams_;
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(ProjectView::ProjectSaveOptions)
#endif
Modified: trunk/sources/qetdiagrameditor.cpp
===================================================================
--- trunk/sources/qetdiagrameditor.cpp 2012-07-10 00:11:12 UTC (rev 1906)
+++ trunk/sources/qetdiagrameditor.cpp 2012-07-13 07:21:19 UTC (rev 1907)
@@ -27,6 +27,7 @@
#include "qeticons.h"
#include "qetelementeditor.h"
#include "qetmessagebox.h"
+#include "qetresult.h"
#include "genericpanel.h"
/**
@@ -179,8 +180,8 @@
open_file = new QAction(QET::Icons::DocumentOpen, tr("&Ouvrir"), this);
close_file = new QAction(QET::Icons::DocumentClose, tr("&Fermer"), this);
save_file = new QAction(QET::Icons::DocumentSave, tr("&Enregistrer"), this);
- save_file_sous = new QAction(QET::Icons::DocumentSaveAs, tr("Enregistrer sous"), this);
- save_all = new QAction(QET::Icons::DocumentSaveAll, tr("&Enregistrer tous les sch\351mas"), this);
+ save_file_as = new QAction(QET::Icons::DocumentSaveAs, tr("Enregistrer sous"), this);
+ save_cur_diagram = new QAction(QET::Icons::DocumentSaveAll, tr("&Enregistrer tous les sch\351mas"), this);
import_diagram = new QAction(QET::Icons::DocumentImport, tr("&Importer"), this);
export_diagram = new QAction(QET::Icons::DocumentExport, tr("E&xporter"), this);
print = new QAction(QET::Icons::DocumentPrint, tr("Imprimer"), this);
@@ -273,9 +274,9 @@
new_file -> setStatusTip(tr("Cr\351e un nouveau sch\351ma", "status bar tip"));
open_file -> setStatusTip(tr("Ouvre un sch\351ma existant", "status bar tip"));
close_file -> setStatusTip(tr("Ferme le sch\351ma courant", "status bar tip"));
- save_file -> setStatusTip(tr("Enregistre le sch\351ma courant", "status bar tip"));
- save_file_sous -> setStatusTip(tr("Enregistre le sch\351ma courant avec un autre nom de fichier", "status bar tip"));
- save_all -> setStatusTip(tr("Enregistre tous les sch\351mas du projet courant", "status bar tip"));
+ save_file -> setStatusTip(tr("Enregistre le projet courant et tous ses sch\351mas", "status bar tip"));
+ save_file_as -> setStatusTip(tr("Enregistre le project courant avec un autre nom de fichier", "status bar tip"));
+ save_cur_diagram -> setStatusTip(tr("Enregistre tous les sch\351mas du projet courant", "status bar tip"));
import_diagram -> setStatusTip(tr("Importe un sch\351ma dans le sch\351ma courant", "status bar tip"));
export_diagram -> setStatusTip(tr("Exporte le sch\351ma courant dans un autre format", "status bar tip"));
print -> setStatusTip(tr("Imprime le sch\351ma courant", "status bar tip"));
@@ -356,9 +357,9 @@
connect(zoom_reset, SIGNAL(triggered()), this, SLOT(slot_zoomReset()) );
connect(print, SIGNAL(triggered()), this, SLOT(printDialog()) );
connect(export_diagram, SIGNAL(triggered()), this, SLOT(exportDialog()) );
- connect(save_file_sous, SIGNAL(triggered()), this, SLOT(saveAsDialog()) );
+ connect(save_file_as, SIGNAL(triggered()), this, SLOT(saveAs()) );
connect(save_file, SIGNAL(triggered()), this, SLOT(save()) );
- connect(save_all, SIGNAL(triggered()), this, SLOT(saveAll()) );
+ connect(save_cur_diagram, SIGNAL(triggered()), this, SLOT(saveCurrentDiagram()) );
connect(new_file, SIGNAL(triggered()), this, SLOT(newProject()) );
connect(open_file, SIGNAL(triggered()), this, SLOT(openProject()) );
connect(close_file, SIGNAL(triggered()), this, SLOT(closeCurrentProject()) );
@@ -421,8 +422,8 @@
menu_fichier -> addMenu(QETApp::projectsRecentFiles() -> menu());
connect(QETApp::projectsRecentFiles(), SIGNAL(fileOpeningRequested(const QString &)), this, SLOT(openRecentFile(const QString &)));
menu_fichier -> addAction(save_file);
- menu_fichier -> addAction(save_file_sous);
- menu_fichier -> addAction(save_all);
+ menu_fichier -> addAction(save_file_as);
+ menu_fichier -> addAction(save_cur_diagram);
menu_fichier -> addAction(close_file);
menu_fichier -> addSeparator();
//menu_fichier -> addAction(import_diagram);
@@ -504,8 +505,8 @@
main_bar -> addAction(new_file);
main_bar -> addAction(open_file);
main_bar -> addAction(save_file);
- main_bar -> addAction(save_file_sous);
- main_bar -> addAction(save_all);
+ main_bar -> addAction(save_file_as);
+ main_bar -> addAction(save_cur_diagram);
main_bar -> addAction(close_file);
main_bar -> addAction(print);
main_bar -> addSeparator();
@@ -561,45 +562,45 @@
Methode enregistrant le schema dans le dernier nom de fichier connu.
@return true si l'enregistrement a reussi, false sinon
*/
-bool QETDiagramEditor::save() {
+void QETDiagramEditor::save() {
if (ProjectView *project_view = currentProject()) {
- bool save_file = project_view -> save();
- if (save_file) {
+ QETResult save_file = project_view -> save();
+ if (save_file.isOk()) {
QETApp::projectsRecentFiles() -> fileWasOpened(project_view -> project() -> filePath());
+ } else {
+ showError(save_file);
}
- return(save_file);
}
- return(false);
}
/**
Cette methode demande un nom de fichier a l'utilisateur pour enregistrer le schema
@return true si l'enregistrement a reussi, false sinon
*/
-bool QETDiagramEditor::saveAsDialog() {
+void QETDiagramEditor::saveAs() {
if (ProjectView *project_view = currentProject()) {
- bool save_file = project_view -> saveAs();
- if (save_file) {
+ QETResult save_file = project_view -> saveAs();
+ if (save_file.isOk()) {
QETApp::projectsRecentFiles() -> fileWasOpened(project_view -> project() -> filePath());
+ } else {
+ showError(save_file);
}
- return(save_file);
}
- return(false);
}
/**
Methode enregistrant tous les schemas.
@return true si l'enregistrement a reussi, false sinon
*/
-bool QETDiagramEditor::saveAll() {
+void QETDiagramEditor::saveCurrentDiagram() {
if (ProjectView *project_view = currentProject()) {
- bool save_file = project_view -> saveAll();
- if (save_file) {
+ QETResult save_file = project_view -> saveCurrentDiagram();
+ if (save_file.isOk()) {
QETApp::projectsRecentFiles() -> fileWasOpened(project_view -> project() -> filePath());
+ } else {
+ showError(save_file);
}
- return(save_file);
}
- return(false);
}
/**
@@ -1044,8 +1045,8 @@
// actions ayant juste besoin d'un document ouvert
close_file -> setEnabled(opened_project);
save_file -> setEnabled(editable_project);
- save_file_sous -> setEnabled(opened_project);
- save_all -> setEnabled(editable_diagram);
+ save_file_as -> setEnabled(opened_project);
+ save_cur_diagram -> setEnabled(editable_diagram);
prj_edit_prop -> setEnabled(opened_project);
prj_add_diagram -> setEnabled(editable_project);
prj_del_diagram -> setEnabled(editable_project);
@@ -1197,6 +1198,9 @@
QETApp::instance(), SLOT(openTitleBlockTemplate(TitleBlockTemplateLocation, bool))
);
+ // display error messages sent by the project view
+ connect(project_view, SIGNAL(errorEncountered(QString)), this, SLOT(showError(const QString &)));
+
// affiche la fenetre
if (maximise) project_view -> showMaximized();
else project_view -> show();
@@ -1687,6 +1691,22 @@
}
/**
+ Show the error message contained in \a result.
+*/
+void QETDiagramEditor::showError(const QETResult &result) {
+ if (result.isOk()) return;
+ showError(result.errorMessage());
+}
+
+/**
+ Show the \a error message.
+*/
+void QETDiagramEditor::showError(const QString &error) {
+ if (error.isEmpty()) return;
+ QET::MessageBox::critical(this, tr("Erreur", "message box title"), error);
+}
+
+/**
@return Les proprietes par defaut pour le cartouche d'un schema
*/
TitleBlockProperties QETDiagramEditor::defaultTitleBlockProperties() {
Modified: trunk/sources/qetdiagrameditor.h
===================================================================
--- trunk/sources/qetdiagrameditor.h 2012-07-10 00:11:12 UTC (rev 1906)
+++ trunk/sources/qetdiagrameditor.h 2012-07-13 07:21:19 UTC (rev 1907)
@@ -24,6 +24,7 @@
#include "titleblockproperties.h"
#include "exportproperties.h"
class QETProject;
+class QETResult;
class ProjectView;
class Diagram;
class DiagramView;
@@ -83,9 +84,9 @@
public slots:
void printDialog();
void exportDialog();
- bool saveAsDialog();
- bool save();
- bool saveAll();
+ void save();
+ void saveAs();
+ void saveCurrentDiagram();
bool newProject();
bool openProject();
bool openRecentFile(const QString &);
@@ -147,6 +148,8 @@
void diagramWasRemoved(DiagramView *);
void findElementInPanel(const ElementsLocation &);
void editElementInEditor(const ElementsLocation &);
+ void showError(const QETResult &);
+ void showError(const QString &);
// attributs
public:
@@ -160,9 +163,9 @@
QAction *new_file; ///< Cree un nouveau schema
QAction *open_file; ///< OUvre un fichier
QAction *close_file; ///< Ferme le fichier
- QAction *save_file; ///< Enregistre le fichier
- QAction *save_file_sous; ///< Enregistrer le fichier sous un nom donne
- QAction *save_all; ///< Enregistre tous les schemas
+ QAction *save_file; ///< Save current project
+ QAction *save_file_as; ///< Save current project as a specific file
+ QAction *save_cur_diagram; ///< Save current diagram of the current project only
QAction *import_diagram; ///< Importe un schema existant (non implemente)
QAction *export_diagram; ///< Exporte le schema sous forme d'image
QAction *print; ///< Imprime le schema
Modified: trunk/sources/qetproject.cpp
===================================================================
--- trunk/sources/qetproject.cpp 2012-07-10 00:11:12 UTC (rev 1906)
+++ trunk/sources/qetproject.cpp 2012-07-13 07:21:19 UTC (rev 1907)
@@ -22,6 +22,7 @@
#include "elementscategory.h"
#include "qetapp.h"
#include "qetdiagrameditor.h"
+#include "qetresult.h"
#include "integrationmoveelementshandler.h"
#include "movetemplateshandler.h"
#include "basicmoveelementshandler.h"
@@ -468,17 +469,15 @@
@see setFilePath()
@return true si l'enregistrement a reussi, false sinon
*/
-bool QETProject::write() {
- // le chemin du fichier doit etre connu
+QETResult QETProject::write() {
+ // this operation requires a filepath
if (file_path_.isEmpty()) {
- qDebug() << qPrintable(QString("QETProject::write() : called without a known filepath [%1]").arg(QET::pointerString(this)));
- return(false);
+ return(QString("unable to save project to file: no filepath was specified"));
}
- // si le projet a ete ouvert en mode lecture seule et que le fichier n'est pas accessible en ecriture, on n'effectue pas l'enregistrement
+ // if the project was opened read-only and the file is still non-writable, do not save the project
if (isReadOnly() && !QFileInfo(file_path_).isWritable()) {
- qDebug() << qPrintable(QString("QETProject::write() : the file %1 was opened read-only and thus will not be written. [%2]").arg(file_path_).arg(QET::pointerString(this)));
- return(true);
+ return(QString("the file %1 was opened read-only and thus will not be written").arg(file_path_));
}
// realise l'export en XML du projet dans le document XML interne
@@ -488,11 +487,11 @@
QString error_message;
bool writing = QET::writeXmlFile(document_root_, file_path_, &error_message);
if (!writing) {
- qDebug() << qPrintable(QString("QETProject::write() : %1 [%2]").arg(error_message).arg(QET::pointerString(this)));
- } else {
- setModified(false);
+ return(error_message);
}
- return(writing);
+
+ setModified(false);
+ return(QETResult());
}
/**
@@ -1180,6 +1179,10 @@
return(true);
}
+ // the integration category must be empty
+ if (integ_cat -> categories().count()) return(true);
+ if (integ_cat -> elements().count()) return(true);
+
return(false);
}
@@ -1205,7 +1208,7 @@
if (diagrams_.count() != 1) return(true);
// dont la pile d'annulation est "clean"
- return(!(diagrams_[0] -> undoStack().isClean()));
+ return(!(diagrams_[0] -> undoStack().isClean() && !diagrams_[0] -> wasWritten()));
}
/**
Modified: trunk/sources/qetproject.h
===================================================================
--- trunk/sources/qetproject.h 2012-07-10 00:11:12 UTC (rev 1906)
+++ trunk/sources/qetproject.h 2012-07-13 07:21:19 UTC (rev 1907)
@@ -30,6 +30,7 @@
class ElementsCategory;
class ElementDefinition;
class ElementsLocation;
+class QETResult;
class TitleBlockTemplate;
class XmlElementsCollection;
class MoveElementsHandler;
@@ -98,7 +99,7 @@
void setDefaultConductorProperties(const ConductorProperties &);
QDomDocument toXml();
bool close();
- bool write();
+ QETResult write();
bool isReadOnly() const;
void setReadOnly(bool);
bool isEmpty() const;
Added: trunk/sources/qetresult.cpp
===================================================================
--- trunk/sources/qetresult.cpp (rev 0)
+++ trunk/sources/qetresult.cpp 2012-07-13 07:21:19 UTC (rev 1907)
@@ -0,0 +1,70 @@
+/*
+ Copyright 2006-2012 Xavier Guerrin
+ This file is part of QElectroTech.
+
+ QElectroTech is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ QElectroTech is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include "qetresult.h"
+
+/**
+ Construct a default "true" QET result without an error message.
+*/
+QETResult::QETResult() :
+ result_(true)
+{
+}
+
+/**
+ Construct a QET result embedding \a error_message and \a result (defaults
+ to false).
+*/
+QETResult::QETResult(const QString &error_message, bool result) :
+ result_(result),
+ error_message_(error_message)
+{
+}
+
+/**
+ Destructor
+*/
+QETResult::~QETResult() {
+}
+
+/**
+ @return the boolean value embedded within this result.
+*/
+bool QETResult::isOk() const {
+ return(result_);
+}
+
+/**
+ Embed \a result.
+*/
+void QETResult::setResult(bool result) {
+ result_ = result;
+}
+
+/**
+ @return the error message embedded within this result.
+*/
+QString QETResult::errorMessage() const {
+ return(error_message_);
+}
+
+/**
+ Embed \a error_message wihthin this result.
+*/
+void QETResult::setErrorMessage(const QString &error_message) {
+ error_message_ = error_message;
+}
Added: trunk/sources/qetresult.h
===================================================================
--- trunk/sources/qetresult.h (rev 0)
+++ trunk/sources/qetresult.h 2012-07-13 07:21:19 UTC (rev 1907)
@@ -0,0 +1,46 @@
+/*
+ Copyright 2006-2012 Xavier Guerrin
+ This file is part of QElectroTech.
+
+ QElectroTech is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ QElectroTech is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef QET_RESULT_H
+#define QET_RESULT_H
+#include <QString>
+
+/**
+ This class represents the result of a lambda operation. Technically, it is
+ a mere boolean+error message pair.
+*/
+class QETResult {
+ // Constructor, destructor
+ public:
+ QETResult();
+ QETResult(const QString &error_message, bool = false);
+ virtual ~QETResult();
+
+ // methods
+ public:
+ bool isOk() const;
+ void setResult(bool);
+ QString errorMessage() const;
+ void setErrorMessage(const QString &);
+
+ // attributes
+ private:
+ bool result_; ///< Embedded boolean value
+ QString error_message_; ///< Embedded error message, typically used to explain what failed to users
+};
+
+#endif