diff options
author | Lars Knoll <lars.knoll@nokia.com> | 2009-03-23 09:18:55 (GMT) |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2009-03-23 09:18:55 (GMT) |
commit | e5fcad302d86d316390c6b0f62759a067313e8a9 (patch) | |
tree | c2afbf6f1066b6ce261f14341cf6d310e5595bc1 /tools/designer/src/lib/shared/qdesigner_promotiondialog.cpp | |
download | Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.zip Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.gz Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.bz2 |
Long live Qt 4.5!
Diffstat (limited to 'tools/designer/src/lib/shared/qdesigner_promotiondialog.cpp')
-rw-r--r-- | tools/designer/src/lib/shared/qdesigner_promotiondialog.cpp | 452 |
1 files changed, 452 insertions, 0 deletions
diff --git a/tools/designer/src/lib/shared/qdesigner_promotiondialog.cpp b/tools/designer/src/lib/shared/qdesigner_promotiondialog.cpp new file mode 100644 index 0000000..8453c16 --- /dev/null +++ b/tools/designer/src/lib/shared/qdesigner_promotiondialog.cpp @@ -0,0 +1,452 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/* +TRANSLATOR qdesigner_internal::QDesignerPromotionDialog +*/ + +#include "qdesigner_promotiondialog_p.h" +#include "promotionmodel_p.h" +#include "iconloader_p.h" +#include "widgetdatabase_p.h" +#include "signalslotdialog_p.h" + +#include <QtDesigner/QDesignerFormEditorInterface> +#include <QtDesigner/QDesignerFormWindowInterface> +#include <QtDesigner/QDesignerPromotionInterface> +#include <QtDesigner/QDesignerWidgetDataBaseItemInterface> +#include <abstractdialoggui_p.h> + +#include <QtCore/QTimer> +#include <QtGui/QVBoxLayout> +#include <QtGui/QHBoxLayout> +#include <QtGui/QFormLayout> +#include <QtGui/QDialogButtonBox> +#include <QtGui/QTreeView> +#include <QtGui/QHeaderView> +#include <QtGui/QPushButton> +#include <QtGui/QItemSelectionModel> +#include <QtGui/QItemSelection> +#include <QtGui/QComboBox> +#include <QtGui/QLineEdit> +#include <QtGui/QCheckBox> +#include <QtGui/QRegExpValidator> +#include <QtGui/QLabel> +#include <QtGui/QSpacerItem> +#include <QtGui/QMenu> +#include <QtGui/QAction> + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + // PromotionParameters + struct PromotionParameters { + QString m_baseClass; + QString m_className; + QString m_includeFile; + }; + + // NewPromotedClassPanel + NewPromotedClassPanel::NewPromotedClassPanel(const QStringList &baseClasses, + int selectedBaseClass, + QWidget *parent) : + QGroupBox(parent), + m_baseClassCombo(new QComboBox), + m_classNameEdit(new QLineEdit), + m_includeFileEdit(new QLineEdit), + m_globalIncludeCheckBox(new QCheckBox), + m_addButton(new QPushButton(tr("Add"))) + { + setTitle(tr("New Promoted Class")); + setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Maximum); + QHBoxLayout *hboxLayout = new QHBoxLayout(this); + + m_classNameEdit->setValidator(new QRegExpValidator(QRegExp(QLatin1String("[_a-zA-Z:][:_a-zA-Z0-9]*")), m_classNameEdit)); + connect(m_classNameEdit, SIGNAL(textChanged(QString)), this, SLOT(slotNameChanged(QString))); + connect(m_includeFileEdit, SIGNAL(textChanged(QString)), this, SLOT(slotIncludeFileChanged(QString))); + + m_baseClassCombo->setEditable(false); + m_baseClassCombo->addItems(baseClasses); + if (selectedBaseClass != -1) + m_baseClassCombo->setCurrentIndex(selectedBaseClass); + + // Grid + QFormLayout *formLayout = new QFormLayout(); + formLayout->addRow(tr("Base class name:"), m_baseClassCombo); + formLayout->addRow(tr("Promoted class name:"), m_classNameEdit); + formLayout->addRow(tr("Header file:"), m_includeFileEdit); + formLayout->addRow(tr("Global include"), m_globalIncludeCheckBox); + hboxLayout->addLayout(formLayout); + hboxLayout->addItem(new QSpacerItem(15, 0, QSizePolicy::Fixed, QSizePolicy::Ignored)); + // Button box + QVBoxLayout *buttonLayout = new QVBoxLayout(); + + m_addButton->setAutoDefault(false); + connect(m_addButton, SIGNAL(clicked()), this, SLOT(slotAdd())); + m_addButton->setEnabled(false); + buttonLayout->addWidget(m_addButton); + + QPushButton *resetButton = new QPushButton(tr("Reset")); + resetButton->setAutoDefault(false); + connect(resetButton, SIGNAL(clicked()), this, SLOT(slotReset())); + + buttonLayout->addWidget(resetButton); + buttonLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::Expanding)); + hboxLayout->addLayout(buttonLayout); + + enableButtons(); + } + + void NewPromotedClassPanel::slotAdd() { + bool ok = false; + emit newPromotedClass(promotionParameters(), &ok); + if (ok) + slotReset(); + } + + void NewPromotedClassPanel::slotReset() { + const QString empty; + m_classNameEdit->setText(empty); + m_includeFileEdit->setText(empty); + m_globalIncludeCheckBox->setCheckState(Qt::Unchecked); + } + + void NewPromotedClassPanel::grabFocus() { + m_classNameEdit->setFocus(Qt::OtherFocusReason); + } + + void NewPromotedClassPanel::slotNameChanged(const QString &className) { + // Suggest a name + if (!className.isEmpty()) { + QString suggestedHeader = className.toLower().replace(QLatin1String("::"), QString(QLatin1Char('_'))); + suggestedHeader += QLatin1String(".h"); + + const bool blocked = m_includeFileEdit->blockSignals(true); + m_includeFileEdit->setText(suggestedHeader); + m_includeFileEdit->blockSignals(blocked); + } + enableButtons(); + } + + void NewPromotedClassPanel::slotIncludeFileChanged(const QString &){ + enableButtons(); + } + + void NewPromotedClassPanel::enableButtons() { + const bool enabled = !m_classNameEdit->text().isEmpty() && !m_includeFileEdit->text().isEmpty(); + m_addButton->setEnabled(enabled); + m_addButton->setDefault(enabled); + } + + PromotionParameters NewPromotedClassPanel::promotionParameters() const { + PromotionParameters rc; + rc.m_baseClass = m_baseClassCombo->currentText(); + rc.m_className = m_classNameEdit->text(); + rc.m_includeFile = buildIncludeFile(m_includeFileEdit->text(), + m_globalIncludeCheckBox->checkState() == Qt::Checked ? IncludeGlobal : IncludeLocal); + return rc; + } + + void NewPromotedClassPanel::chooseBaseClass(const QString &baseClass) { + const int index = m_baseClassCombo->findText (baseClass); + if (index != -1) + m_baseClassCombo->setCurrentIndex (index); + } + + // --------------- QDesignerPromotionDialog + QDesignerPromotionDialog::QDesignerPromotionDialog(QDesignerFormEditorInterface *core, + QWidget *parent, + const QString &promotableWidgetClassName, + QString *promoteTo) : + QDialog(parent), + m_mode(promotableWidgetClassName.isEmpty() || promoteTo == 0 ? ModeEdit : ModeEditChooseClass), + m_promotableWidgetClassName(promotableWidgetClassName), + m_core(core), + m_promoteTo(promoteTo), + m_promotion(core->promotion()), + m_model(new PromotionModel(core)), + m_treeView(new QTreeView), + m_buttonBox(0), + m_removeButton(new QPushButton(createIconSet(QString::fromUtf8("minus.png")), QString())) + { + m_buttonBox = createButtonBox(); + setModal(true); + setWindowTitle(tr("Promoted Widgets")); + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); + + QVBoxLayout *vboxLayout = new QVBoxLayout(this); + + // tree view group + QGroupBox *treeViewGroup = new QGroupBox(); + treeViewGroup->setTitle(tr("Promoted Classes")); + QVBoxLayout *treeViewVBoxLayout = new QVBoxLayout(treeViewGroup); + // tree view + m_treeView->setModel (m_model); + m_treeView->setMinimumWidth(450); + m_treeView->setContextMenuPolicy(Qt::CustomContextMenu); + + connect(m_treeView->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), + this, SLOT(slotSelectionChanged(QItemSelection, QItemSelection))); + + connect(m_treeView, SIGNAL(customContextMenuRequested(QPoint)), + this, SLOT(slotTreeViewContextMenu(QPoint))); + + QHeaderView *headerView = m_treeView->header(); + headerView->setResizeMode(QHeaderView::ResizeToContents); + treeViewVBoxLayout->addWidget(m_treeView); + // remove button + QHBoxLayout *hboxLayout = new QHBoxLayout(); + hboxLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Ignored)); + + m_removeButton->setAutoDefault(false); + connect(m_removeButton, SIGNAL(clicked()), this, SLOT(slotRemove())); + m_removeButton->setEnabled(false); + hboxLayout->addWidget(m_removeButton); + treeViewVBoxLayout->addLayout(hboxLayout); + vboxLayout->addWidget(treeViewGroup); + // Create new panel: Try to be smart and preselect a base class. Default to QFrame + const QStringList &baseClassNameList = baseClassNames(m_promotion); + int preselectedBaseClass = -1; + if (m_mode == ModeEditChooseClass) { + preselectedBaseClass = baseClassNameList.indexOf(m_promotableWidgetClassName); + } + if (preselectedBaseClass == -1) + preselectedBaseClass = baseClassNameList.indexOf(QLatin1String("QFrame")); + + NewPromotedClassPanel *newPromotedClassPanel = new NewPromotedClassPanel(baseClassNameList, preselectedBaseClass); + connect(newPromotedClassPanel, SIGNAL(newPromotedClass(PromotionParameters, bool *)), this, SLOT(slotNewPromotedClass(PromotionParameters, bool *))); + connect(this, SIGNAL(selectedBaseClassChanged(QString)), + newPromotedClassPanel, SLOT(chooseBaseClass(QString))); + vboxLayout->addWidget(newPromotedClassPanel); + // button box + vboxLayout->addWidget(m_buttonBox); + // connect model + connect(m_model, SIGNAL(includeFileChanged(QDesignerWidgetDataBaseItemInterface*, QString)), + this, SLOT(slotIncludeFileChanged(QDesignerWidgetDataBaseItemInterface*, QString))); + + connect(m_model, SIGNAL(classNameChanged(QDesignerWidgetDataBaseItemInterface*, QString)), + this, SLOT(slotClassNameChanged(QDesignerWidgetDataBaseItemInterface*, QString))); + + // focus + if (m_mode == ModeEditChooseClass) + newPromotedClassPanel->grabFocus(); + + slotUpdateFromWidgetDatabase(); + } + + QDialogButtonBox *QDesignerPromotionDialog::createButtonBox() { + QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Close); + + connect(buttonBox , SIGNAL(accepted()), this, SLOT(slotAcceptPromoteTo())); + buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Promote")); + buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + + connect(buttonBox , SIGNAL(rejected()), this, SLOT(reject())); + return buttonBox; + } + + void QDesignerPromotionDialog::slotUpdateFromWidgetDatabase() { + m_model->updateFromWidgetDatabase(); + m_treeView->expandAll(); + m_removeButton->setEnabled(false); + } + + void QDesignerPromotionDialog::delayedUpdateFromWidgetDatabase() { + QTimer::singleShot(0, this, SLOT(slotUpdateFromWidgetDatabase())); + } + + const QStringList &QDesignerPromotionDialog::baseClassNames(const QDesignerPromotionInterface *promotion) { + typedef QList<QDesignerWidgetDataBaseItemInterface *> WidgetDataBaseItemList; + static QStringList rc; + if (rc.empty()) { + // Convert the item list into a string list. + const WidgetDataBaseItemList dbItems = promotion->promotionBaseClasses(); + const WidgetDataBaseItemList::const_iterator cend = dbItems.constEnd(); + for (WidgetDataBaseItemList::const_iterator it = dbItems.constBegin() ; it != cend; ++it) { + rc.push_back( (*it)->name()); + } + } + return rc; + } + + void QDesignerPromotionDialog::slotAcceptPromoteTo() { + Q_ASSERT(m_mode == ModeEditChooseClass); + unsigned flags; + // Ok pressed: Promote to selected class + if (QDesignerWidgetDataBaseItemInterface *dbItem = databaseItemAt(m_treeView->selectionModel()->selection(), flags)) { + if (flags & CanPromote) { + *m_promoteTo = dbItem ->name(); + accept(); + } + } + } + + void QDesignerPromotionDialog::slotRemove() { + unsigned flags; + QDesignerWidgetDataBaseItemInterface *dbItem = databaseItemAt(m_treeView->selectionModel()->selection(), flags); + if (!dbItem || (flags & Referenced)) + return; + + QString errorMessage; + if (m_promotion->removePromotedClass(dbItem->name(), &errorMessage)) { + slotUpdateFromWidgetDatabase(); + } else { + displayError(errorMessage); + } + } + + void QDesignerPromotionDialog::slotSelectionChanged(const QItemSelection &selected, const QItemSelection &) { + // Enable deleting non-referenced items + unsigned flags; + const QDesignerWidgetDataBaseItemInterface *dbItem = databaseItemAt(selected, flags); + m_removeButton->setEnabled(dbItem && !(flags & Referenced)); + // In choose mode, can we promote to the class? + if (m_mode == ModeEditChooseClass) { + const bool enablePromoted = flags & CanPromote; + m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(enablePromoted); + m_buttonBox->button(QDialogButtonBox::Ok)->setDefault(enablePromoted); + } + // different base? + if (dbItem) { + const QString baseClass = dbItem->extends(); + if (baseClass != m_lastSelectedBaseClass) { + m_lastSelectedBaseClass = baseClass; + emit selectedBaseClassChanged(m_lastSelectedBaseClass); + } + } + } + + QDesignerWidgetDataBaseItemInterface *QDesignerPromotionDialog::databaseItemAt(const QItemSelection &selected, unsigned &flags) const { + flags = 0; + const QModelIndexList indexes = selected.indexes(); + if (indexes.empty()) + return 0; + + bool referenced; + QDesignerWidgetDataBaseItemInterface *dbItem = m_model->databaseItemAt(indexes.front(), &referenced); + + if (dbItem) { + if (referenced) + flags |= Referenced; + // In choose mode, can we promote to the class? + if (m_mode == ModeEditChooseClass && dbItem && dbItem->isPromoted() && dbItem->extends() == m_promotableWidgetClassName) + flags |= CanPromote; + + } + return dbItem; + } + + void QDesignerPromotionDialog::slotNewPromotedClass(const PromotionParameters &p, bool *ok) { + QString errorMessage; + *ok = m_promotion->addPromotedClass(p.m_baseClass, p.m_className, p.m_includeFile, &errorMessage); + if (*ok) { + // update and select + slotUpdateFromWidgetDatabase(); + const QModelIndex newClassIndex = m_model->indexOfClass(p.m_className); + if (newClassIndex.isValid()) { + m_treeView->selectionModel()->select(newClassIndex, QItemSelectionModel::SelectCurrent|QItemSelectionModel::Rows); + } + } else { + displayError(errorMessage); + } + } + + void QDesignerPromotionDialog::slotIncludeFileChanged(QDesignerWidgetDataBaseItemInterface *dbItem, const QString &includeFile) { + if (includeFile.isEmpty()) { + delayedUpdateFromWidgetDatabase(); + return; + } + + if (dbItem->includeFile() == includeFile) + return; + + QString errorMessage; + if (!m_promotion->setPromotedClassIncludeFile(dbItem->name(), includeFile, &errorMessage)) { + displayError(errorMessage); + delayedUpdateFromWidgetDatabase(); + } + } + + void QDesignerPromotionDialog::slotClassNameChanged(QDesignerWidgetDataBaseItemInterface *dbItem, const QString &newName) { + if (newName.isEmpty()) { + delayedUpdateFromWidgetDatabase(); + return; + } + const QString oldName = dbItem->name(); + if (newName == oldName) + return; + + QString errorMessage; + if (!m_promotion->changePromotedClassName(oldName , newName, &errorMessage)) { + displayError(errorMessage); + delayedUpdateFromWidgetDatabase(); + } + } + + void QDesignerPromotionDialog::slotTreeViewContextMenu(const QPoint &pos) { + unsigned flags; + const QDesignerWidgetDataBaseItemInterface *dbItem = databaseItemAt(m_treeView->selectionModel()->selection(), flags); + if (!dbItem) + return; + + QMenu menu; + QAction *signalSlotAction = menu.addAction(tr("Change signals/slots...")); + connect(signalSlotAction, SIGNAL(triggered()), this, SLOT(slotEditSignalsSlots())); + + menu.exec(m_treeView->viewport()->mapToGlobal(pos)); + } + + void QDesignerPromotionDialog::slotEditSignalsSlots() { + unsigned flags; + const QDesignerWidgetDataBaseItemInterface *dbItem = databaseItemAt(m_treeView->selectionModel()->selection(), flags); + if (!dbItem) + return; + + SignalSlotDialog::editPromotedClass(m_core, dbItem->name(), this); + } + + void QDesignerPromotionDialog::displayError(const QString &message) { + m_core->dialogGui()->message(this, QDesignerDialogGuiInterface::PromotionErrorMessage, QMessageBox::Warning, + tr("%1 - Error").arg(windowTitle()), message, QMessageBox::Close); + } +} // namespace qdesigner_internal + +QT_END_NAMESPACE |