/* 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 . */ #include "closediagramsdialog.h" #include "diagram.h" #include "qeticons.h" /** Construct a dialog showing \a diagrams. @param parent Parent QWidget */ CloseDiagramsDialog::CloseDiagramsDialog(const QList &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 CloseDiagramsDialog::diagramsByAction(Actions action) { QList 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 QString action_label_text = tr("Action", "column header"); QLabel *action_label = new QLabel(action_label_text); all_checkbox_ = new QCheckBox(action_label_text); all_checkbox_ -> setToolTip(tr("Cocher ou d\351cocher toutes les cases \340 cocher", "checbox tooltip")); all_checkbox_ -> setChecked(true); connect(all_checkbox_, SIGNAL(stateChanged(int)), this, SLOT(topCheckBoxChangedState(int))); QWidget *header_widget = diagrams_list_.count() > 1 ? static_cast(all_checkbox_) : static_cast(action_label); Qt::Alignment header_alignment = diagrams_list_.count() > 1 ? Qt::AlignLeft : Qt::AlignCenter; // 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(title_label, 0, 1, 1, 1, Qt::AlignCenter); diagrams_list_layout_ -> addItem(spacer1, 0, 2); diagrams_list_layout_ -> addWidget(state_label, 0, 3, 1, 1, Qt::AlignCenter); diagrams_list_layout_ -> addItem(spacer2, 0, 4); diagrams_list_layout_ -> addWidget(header_widget, 0, 5, 1, 1, header_alignment); // 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() { if (diagrams_list_.count()) { 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, ""); diagram_show -> setToolTip(tr("Afficher ce sch\351ma", "button tooltip")); 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::AlignLeft); } /** @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(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(); }