1 /**************************************************************************** 2 ** 3 ** Copyright (C) 2015 The Qt Company Ltd. 4 ** Contact: http://www.qt.io/licensing/ 5 ** 6 ** This file is part of the Qt Designer of the Qt Toolkit. 7 ** 8 ** $QT_BEGIN_LICENSE:LGPL$ 9 ** Commercial License Usage 10 ** Licensees holding valid commercial Qt licenses may use this file in 11 ** accordance with the commercial license agreement provided with the 12 ** Software or, alternatively, in accordance with the terms contained in 13 ** a written agreement between you and The Qt Company. For licensing terms 14 ** and conditions see http://www.qt.io/terms-conditions. For further 15 ** information use the contact form at http://www.qt.io/contact-us. 16 ** 17 ** GNU Lesser General Public License Usage 18 ** Alternatively, this file may be used under the terms of the GNU Lesser 19 ** General Public License version 2.1 or version 3 as published by the Free 20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and 21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the 22 ** following information to ensure the GNU Lesser General Public License 23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and 24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 25 ** 26 ** As a special exception, The Qt Company gives you certain additional 27 ** rights. These rights are described in The Qt Company LGPL Exception 28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 29 ** 30 ** GNU General Public License Usage 31 ** Alternatively, this file may be used under the terms of the GNU 32 ** General Public License version 3.0 as published by the Free Software 33 ** Foundation and appearing in the file LICENSE.GPL included in the 34 ** packaging of this file. Please review the following information to 35 ** ensure the GNU General Public License version 3.0 requirements will be 36 ** met: http://www.gnu.org/copyleft/gpl.html. 37 ** 38 ** $QT_END_LICENSE$ 39 ** 40 ****************************************************************************/ 41 42 #include "promotionmodel_p.h" 43 #include "widgetdatabase_p.h" 44 45 #include <QtDesigner/QDesignerWidgetDataBaseInterface> 46 #include <QtDesigner/QDesignerPromotionInterface> 47 #include <QtDesigner/QDesignerFormEditorInterface> 48 49 #include <QtGui/QStandardItem> 50 #include <QtCore/QCoreApplication> 51 52 QT_BEGIN_NAMESPACE 53 54 namespace { 55 typedef QList<QStandardItem *> StandardItemList; 56 57 // Model columns. 58 enum { ClassNameColumn, IncludeFileColumn, IncludeTypeColumn, ReferencedColumn, NumColumns }; 59 60 // Create a model row. modelRow()61 StandardItemList modelRow() { 62 StandardItemList rc; 63 for (int i = 0; i < NumColumns; i++) { 64 rc.push_back(new QStandardItem()); 65 } 66 return rc; 67 } 68 69 // Create a model row for a base class (read-only, cannot be selected). baseModelRow(const QDesignerWidgetDataBaseItemInterface * dbItem)70 StandardItemList baseModelRow(const QDesignerWidgetDataBaseItemInterface *dbItem) { 71 StandardItemList rc = modelRow(); 72 73 rc[ClassNameColumn]->setText(dbItem->name()); 74 for (int i = 0; i < NumColumns; i++) { 75 rc[i]->setFlags(Qt::ItemIsEnabled); 76 } 77 return rc; 78 } 79 80 // Create an editable model row for a promoted class. promotedModelRow(const QDesignerWidgetDataBaseInterface * widgetDataBase,QDesignerWidgetDataBaseItemInterface * dbItem,bool referenced=false)81 StandardItemList promotedModelRow(const QDesignerWidgetDataBaseInterface *widgetDataBase, 82 QDesignerWidgetDataBaseItemInterface *dbItem, 83 bool referenced = false) { 84 85 const int index = widgetDataBase->indexOf(dbItem); 86 87 // Associate user data: database index and enabled flag 88 QVariantList userDataList; 89 userDataList.push_back(QVariant(index)); 90 userDataList.push_back(QVariant(referenced)); 91 const QVariant userData(userDataList); 92 93 StandardItemList rc = modelRow(); 94 // name 95 rc[ClassNameColumn]->setText(dbItem->name()); 96 rc[ClassNameColumn]->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled|Qt::ItemIsEditable); 97 rc[ClassNameColumn]->setData(userData); 98 // header 99 const qdesigner_internal::IncludeSpecification spec = qdesigner_internal::includeSpecification(dbItem->includeFile()); 100 rc[IncludeFileColumn]->setText(spec.first); 101 rc[IncludeFileColumn]->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled|Qt::ItemIsEditable); 102 rc[IncludeFileColumn]->setData(userData); 103 // global include 104 rc[IncludeTypeColumn]->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled|Qt::ItemIsEditable|Qt::ItemIsUserCheckable); 105 rc[IncludeTypeColumn]->setData(userData); 106 rc[IncludeTypeColumn]->setCheckState(spec.second == qdesigner_internal::IncludeGlobal ? Qt::Checked : Qt::Unchecked); 107 // referenced 108 rc[ReferencedColumn]->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); 109 rc[ClassNameColumn]->setData(userData); 110 if (!referenced) { 111 //: Usage of promoted widgets 112 static const QString notUsed = QCoreApplication::translate("PromotionModel", "Not used"); 113 rc[ReferencedColumn]->setText(notUsed); 114 } 115 return rc; 116 } 117 } 118 119 namespace qdesigner_internal { 120 PromotionModel(QDesignerFormEditorInterface * core)121 PromotionModel::PromotionModel(QDesignerFormEditorInterface *core) : 122 m_core(core) 123 { 124 connect(this, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(slotItemChanged(QStandardItem*))); 125 } 126 initializeHeaders()127 void PromotionModel::initializeHeaders() { 128 setColumnCount(NumColumns); 129 QStringList horizontalLabels(tr("Name")); 130 horizontalLabels += tr("Header file"); 131 horizontalLabels += tr("Global include"); 132 horizontalLabels += tr("Usage"); 133 setHorizontalHeaderLabels (horizontalLabels); 134 } 135 updateFromWidgetDatabase()136 void PromotionModel::updateFromWidgetDatabase() { 137 typedef QDesignerPromotionInterface::PromotedClasses PromotedClasses; 138 139 clear(); 140 initializeHeaders(); 141 142 // retrieve list of pairs from DB and convert into a tree structure. 143 // Set the item index as user data on the item. 144 const PromotedClasses promotedClasses = m_core->promotion()->promotedClasses(); 145 146 if (promotedClasses.empty()) 147 return; 148 149 const QSet<QString> usedPromotedClasses = m_core->promotion()->referencedPromotedClassNames(); 150 151 QDesignerWidgetDataBaseInterface *widgetDataBase = m_core->widgetDataBase(); 152 QDesignerWidgetDataBaseItemInterface *baseClass = 0; 153 QStandardItem *baseItem = 0; 154 155 const PromotedClasses::const_iterator bcend = promotedClasses.constEnd(); 156 for (PromotedClasses::const_iterator it = promotedClasses.constBegin(); it != bcend; ++it) { 157 // Start a new base class? 158 if (baseClass != it->baseItem) { 159 baseClass = it->baseItem; 160 const StandardItemList baseRow = baseModelRow(it->baseItem); 161 baseItem = baseRow.front(); 162 appendRow(baseRow); 163 } 164 Q_ASSERT(baseItem); 165 // Append derived 166 baseItem->appendRow(promotedModelRow(widgetDataBase, it->promotedItem, usedPromotedClasses.contains(it->promotedItem->name()))); 167 } 168 } 169 slotItemChanged(QStandardItem * changedItem)170 void PromotionModel::slotItemChanged(QStandardItem * changedItem) { 171 // Retrieve DB item 172 bool referenced; 173 QDesignerWidgetDataBaseItemInterface *dbItem = databaseItem(changedItem, &referenced); 174 Q_ASSERT(dbItem); 175 // Change header or type 176 switch (changedItem->column()) { 177 case ClassNameColumn: 178 emit classNameChanged(dbItem, changedItem->text()); 179 break; 180 case IncludeTypeColumn: 181 case IncludeFileColumn: { 182 // Get both file and type items via parent. 183 const QStandardItem *baseClassItem = changedItem->parent(); 184 const QStandardItem *fileItem = baseClassItem->child(changedItem->row(), IncludeFileColumn); 185 const QStandardItem *typeItem = baseClassItem->child(changedItem->row(), IncludeTypeColumn); 186 emit includeFileChanged(dbItem, buildIncludeFile(fileItem->text(), typeItem->checkState() == Qt::Checked ? IncludeGlobal : IncludeLocal)); 187 } 188 break; 189 } 190 } 191 databaseItemAt(const QModelIndex & index,bool * referenced) const192 QDesignerWidgetDataBaseItemInterface *PromotionModel::databaseItemAt(const QModelIndex &index, bool *referenced) const { 193 if (const QStandardItem *item = itemFromIndex (index)) 194 return databaseItem(item, referenced); 195 196 *referenced = false; 197 return 0; 198 } 199 databaseItem(const QStandardItem * item,bool * referenced) const200 QDesignerWidgetDataBaseItemInterface *PromotionModel::databaseItem(const QStandardItem * item, bool *referenced) const { 201 // Decode user data associated with item. 202 const QVariant data = item->data(); 203 if (data.type() != QVariant::List) { 204 *referenced = false; 205 return 0; 206 } 207 208 const QVariantList dataList = data.toList(); 209 const int index = dataList[0].toInt(); 210 *referenced = dataList[1].toBool(); 211 return m_core->widgetDataBase()->item(index); 212 } 213 indexOfClass(const QString & className) const214 QModelIndex PromotionModel::indexOfClass(const QString &className) const { 215 const StandardItemList matches = findItems (className, Qt::MatchFixedString|Qt::MatchCaseSensitive|Qt::MatchRecursive); 216 return matches.empty() ? QModelIndex() : indexFromItem (matches.front()); 217 } 218 } // namespace qdesigner_internal 219 220 QT_END_NAMESPACE 221