📄 widgetbox.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.**** This file is part of the Qt Designer of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.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 GNU** General Public Licensing requirements will be met:** http://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "widgetbox.h"// sdk#include <QtDesigner/QtDesigner>// shared#include <pluginmanager_p.h>#include <sheet_delegate_p.h>#include <iconloader_p.h>#include <QtGui/QtGui>#include <QtCore/qdebug.h>#include "widgetbox_dnditem.h"#define SCRATCHPAD_ITEM 1#define CUSTOM_ITEM 2#ifndef Q_MOC_RUNusing namespace qdesigner_internal;#endif/********************************************************************************* Tools*/static QDomElement childElement(QDomNode node, const QString &tag, const QString &attr_name, const QString &attr_value){ if (node.isElement()) { QDomElement elt = node.toElement(); if (elt.tagName() == tag) { if (attr_name.isEmpty()) return elt; if (elt.hasAttribute(attr_name)) { if (attr_value.isEmpty()) return elt; if (elt.attribute(attr_name) == attr_value) return elt; } } } QDomNode child = node.firstChild(); for (; !child.isNull(); child = child.nextSibling()) { QDomElement elt = childElement(child, tag, attr_name, attr_value); if (!elt.isNull()) return elt; } return QDomElement();}typedef QList<QDomElement> ElementList;static void _childElementList(QDomNode node, const QString &tag, const QString &attr_name, const QString &attr_value, ElementList *result){ if (node.isElement()) { QDomElement elt = node.toElement(); if (elt.tagName() == tag) { if (attr_name.isEmpty()) { result->append(elt); } else if (elt.hasAttribute(attr_name)) { if (attr_value.isEmpty()) result->append(elt); else if (elt.attribute(attr_name) == attr_value) result->append(elt); } } } QDomNode child = node.firstChild(); for (; !child.isNull(); child = child.nextSibling()) _childElementList(child, tag, attr_name, attr_value, result);}static QString domToString(const QDomElement &elt){ QString result; QTextStream stream(&result, QIODevice::WriteOnly); elt.save(stream, 2); stream.flush(); return result;}static QDomDocument stringToDom(const QString &xml){ QDomDocument result; result.setContent(xml); return result;}static DomWidget *xmlToUi(QString xml){ QDomDocument doc; QString err_msg; int err_line, err_col; if (!doc.setContent(xml, &err_msg, &err_line, &err_col)) { qWarning("xmlToUi: parse failed:\n%s\n:%d:%d: %s", xml.toUtf8().constData(), err_line, err_col, err_msg.toUtf8().constData()); return 0; } QDomElement dom_elt = doc.firstChildElement(); if (dom_elt.nodeName() != QLatin1String("widget")) { qWarning("xmlToUi: invalid root element:\n%s", xml.toUtf8().constData()); return 0; } DomWidget *widget = new DomWidget; widget->read(dom_elt); return widget;}/********************************************************************************* WidgetBoxItemDelegate*/namespace qdesigner_internal {class WidgetBoxItemDelegate : public SheetDelegate{public: WidgetBoxItemDelegate(QTreeWidget *tree, QWidget *parent = 0) : SheetDelegate(tree, parent) {} QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;};/********************************************************************************* WidgetBoxTreeView*/class WidgetBoxTreeView : public QTreeWidget{ Q_OBJECTpublic: typedef QDesignerWidgetBoxInterface::Widget Widget; typedef QDesignerWidgetBoxInterface::Category Category; typedef QDesignerWidgetBoxInterface::CategoryList CategoryList; WidgetBoxTreeView(QDesignerFormEditorInterface *core, QWidget *parent = 0); ~WidgetBoxTreeView(); int categoryCount() const; Category category(int cat_idx) const; void addCategory(const Category &cat); void removeCategory(int cat_idx); int widgetCount(int cat_idx) const; Widget widget(int cat_idx, int wgt_idx) const; void addWidget(int cat_idx, const Widget &wgt); void removeWidget(int cat_idx, int wgt_idx); void dropWidgets(const QList<QDesignerDnDItemInterface*> &item_list); void setFileName(const QString &file_name); QString fileName() const; bool load(); bool save();signals: void pressed(const QString dom_xml, const QPoint &global_mouse_pos);protected: void contextMenuEvent(QContextMenuEvent *e);private slots: void handleMousePress(QTreeWidgetItem *item); void removeCurrentItem(); void editCurrentItem(); void updateItemData(QTreeWidgetItem *item); void deleteScratchpad();private: QDesignerFormEditorInterface *m_core; QString m_file_name; mutable QHash<QString, QIcon> m_pluginIcons; CategoryList domToCateogryList(const QDomDocument &doc) const; Category domToCategory(const QDomElement &cat_elt) const; CategoryList loadCustomCategoryList() const; QDomDocument categoryListToDom(const CategoryList &cat_list) const; QTreeWidgetItem *widgetToItem(const Widget &wgt, QTreeWidgetItem *parent, bool editable = false); Widget itemToWidget(const QTreeWidgetItem *item) const; int indexOfCategory(const QString &name) const; int indexOfScratchpad(); QString widgetDomXml(const Widget &widget) const; QString qtify(const QString &name) const;};} // namespace qdesigner_internalQWidget *WidgetBoxItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const{ QWidget *result = SheetDelegate::createEditor(parent, option, index); QLineEdit *line_edit = qobject_cast<QLineEdit*>(result); if (line_edit == 0) return result; line_edit->setValidator(new QRegExpValidator(QRegExp(QLatin1String("[_a-zA-Z][_a-zA-Z0-9]*")), line_edit)); return result;}WidgetBoxTreeView::WidgetBoxTreeView(QDesignerFormEditorInterface *core, QWidget *parent) : QTreeWidget(parent){ setFocusPolicy(Qt::NoFocus); setItemDelegate(new WidgetBoxItemDelegate(this, this)); setRootIsDecorated(false); setColumnCount(1); header()->hide(); header()->setResizeMode(QHeaderView::Stretch); m_core = core; connect(this, SIGNAL(itemPressed(QTreeWidgetItem*,int)), this, SLOT(handleMousePress(QTreeWidgetItem*))); connect(this, SIGNAL(itemChanged(QTreeWidgetItem*,int)), this, SLOT(updateItemData(QTreeWidgetItem*))); setEditTriggers(QAbstractItemView::AnyKeyPressed);}WidgetBoxTreeView::~WidgetBoxTreeView(){ QSettings settings; settings.beginGroup(QLatin1String("WidgetBox")); QStringList open_cat; for (int i = 0; i < categoryCount(); ++i) { QTreeWidgetItem *cat_item = topLevelItem(i); if (isItemExpanded(cat_item)) open_cat.append(cat_item->text(0)); } settings.setValue(QLatin1String("open categories"), open_cat); settings.endGroup();}QString WidgetBoxTreeView::qtify(const QString &name) const{ QString qname = name; Q_ASSERT(name.isEmpty() == false); if (qname.count() > 1 && qname.at(1).toUpper() == qname.at(1) && (qname.at(0) == QLatin1Char('Q') || qname.at(0) == QLatin1Char('K'))) qname = qname.mid(1); int i=0; while (i < qname.length()) { if (qname.at(i).toLower() != qname.at(i)) qname[i] = qname.at(i).toLower(); else break; ++i; } return qname;}QString WidgetBoxTreeView::widgetDomXml(const Widget &widget) const{ QString domXml = widget.domXml(); if (domXml.isEmpty()) { QString defaultVarName = qtify(widget.name()); QString typeStr = widget.type() == Widget::Default ? QLatin1String("default") : QLatin1String("custom"); domXml = QString::fromUtf8("<widget class=\"%1\" name=\"%2\" type=\"%3\"/>") .arg(widget.name()) .arg(defaultVarName) .arg(typeStr); } return domXml;}void WidgetBoxTreeView::setFileName(const QString &file_name){ m_file_name = file_name;}QString WidgetBoxTreeView::fileName() const{ return m_file_name;}bool WidgetBoxTreeView::save(){ if (fileName().isEmpty()) return false; QFile file(fileName()); if (!file.open(QIODevice::WriteOnly)) return false; CategoryList cat_list; for (int i = 0; i < categoryCount(); ++i) cat_list.append(category(i)); QDomDocument doc = categoryListToDom(cat_list); QTextStream stream(&file); doc.save(stream, 4); return true;}void WidgetBoxTreeView::handleMousePress(QTreeWidgetItem *item){ if (item == 0) return; if (item->parent() == 0) { setItemExpanded(item, !isItemExpanded(item)); return; } QDesignerWidgetBoxInterface::Widget wgt = qvariant_cast<QDesignerWidgetBoxInterface::Widget>(item->data(0, Qt::UserRole)); if (wgt.isNull()) return; emit pressed(widgetDomXml(wgt), QCursor::pos());}int WidgetBoxTreeView::indexOfScratchpad(){ for (int i = 0; i < topLevelItemCount(); ++i) { if (topLevelItem(i)->data(0, Qt::UserRole).toInt() == SCRATCHPAD_ITEM) return i; } QTreeWidgetItem *scratch_item = new QTreeWidgetItem(this); scratch_item->setText(0, tr("Scratchpad")); scratch_item->setData(0, Qt::UserRole, SCRATCHPAD_ITEM); return categoryCount() - 1;}int WidgetBoxTreeView::indexOfCategory(const QString &name) const{ for (int i = 0; i < topLevelItemCount(); ++i) { if (topLevelItem(i)->text(0) == name) return i; } return -1;}bool WidgetBoxTreeView::load(){ QString name = fileName(); QFile f(name); if (!f.open(QIODevice::ReadOnly)) { return false; } QString error_msg; int line, col; QDomDocument doc; if (!doc.setContent(&f, &error_msg, &line, &col)) { qWarning("WidgetBox: failed to parse \"%s\": on line %d: %s", name.toUtf8().constData(), line, error_msg.toUtf8().constData()); return false; } CategoryList cat_list = domToCateogryList(doc); if (cat_list.isEmpty()) return false; // make sure the scratchpad is always at the end int scratch_idx = -1; for (int i = 0; i < cat_list.size(); ++i) { if (cat_list.at(i).type() == Category::Scratchpad) { scratch_idx = i; break; } } clear(); foreach(Category cat, cat_list) { if (cat.type() != Category::Scratchpad) addCategory(cat); } CategoryList custom_cat_list = loadCustomCategoryList(); foreach (Category cat, custom_cat_list) addCategory(cat); if (scratch_idx != -1) addCategory(cat_list.at(scratch_idx)); // Restore which items are expanded QSettings settings; settings.beginGroup(QLatin1String("WidgetBox")); QStringList closed_cat; for (int i = 0; i < topLevelItemCount(); ++i) { QTreeWidgetItem *item = topLevelItem(i); if (!isItemExpanded(item)) closed_cat.append(item->text(0)); } closed_cat = settings.value(QLatin1String("Closed categories"), closed_cat).toStringList(); for (int i = 0; i < closed_cat.size(); ++i) { int cat_idx = indexOfCategory(closed_cat[i]); if (cat_idx == -1) continue; QTreeWidgetItem *item = topLevelItem(cat_idx); if (item == 0) continue; setItemExpanded(item, false); } settings.endGroup(); return true;}QDomDocument WidgetBoxTreeView::categoryListToDom(const CategoryList &cat_list) const{ QDomDocument doc; QDomElement root = doc.createElement(QLatin1String("widgetbox")); doc.appendChild(root); foreach (Category cat, cat_list) { QDomElement cat_elt = doc.createElement(QLatin1String("category")); root.appendChild(cat_elt); cat_elt.setAttribute(QLatin1String("name"), cat.name()); if (cat.type() == Category::Scratchpad) cat_elt.setAttribute(QLatin1String("type"), QLatin1String("scratchpad")); for (int i = 0; i < cat.widgetCount(); ++i) { Widget wgt = cat.widget(i); if (wgt.type() == Widget::Custom) continue; DomWidget *dom_wgt = xmlToUi(widgetDomXml(wgt)); QDomElement wgt_elt = dom_wgt->write(doc); wgt_elt.setAttribute(QLatin1String("name"), wgt.name()); QString iconName = wgt.iconName();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -