Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
codedialog.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
4#include "codedialog_p.h"
6#include "iconloader_p.h"
7
8#include <texteditfindwidget_p.h>
9
10#include <QtWidgets/qapplication.h>
11#if QT_CONFIG(clipboard)
12#include <QtGui/qclipboard.h>
13#endif
14#include <QtWidgets/qdialogbuttonbox.h>
15#include <QtWidgets/qfiledialog.h>
16#include <QtWidgets/qmessagebox.h>
17#include <QtWidgets/qpushbutton.h>
18#include <QtWidgets/qtextedit.h>
19#include <QtWidgets/qtoolbar.h>
20#include <QtWidgets/qboxlayout.h>
21
22#include <QtGui/qaction.h>
23#include <QtGui/qevent.h>
24#include <QtGui/qfontdatabase.h>
25#include <QtGui/qfontmetrics.h>
26#include <QtGui/qicon.h>
27
28#include <QtCore/qdebug.h>
29#include <QtCore/qdir.h>
30#include <QtCore/qmimedatabase.h>
31#include <QtCore/qtemporaryfile.h>
32
34
35using namespace Qt::StringLiterals;
36
37namespace qdesigner_internal {
38// ----------------- CodeDialogPrivate
47
48CodeDialog::CodeDialogPrivate::CodeDialogPrivate()
49 : m_textEdit(new QTextEdit)
50 , m_findWidget(new TextEditFindWidget)
51{
52}
53
54// ----------------- CodeDialog
55CodeDialog::CodeDialog(QWidget *parent) :
56 QDialog(parent),
57 m_impl(new CodeDialogPrivate)
58{
59 QVBoxLayout *vBoxLayout = new QVBoxLayout;
60
61 // Edit tool bar
62 QToolBar *toolBar = new QToolBar;
63
64 const QIcon saveIcon = createIconSet(QIcon::ThemeIcon::DocumentSave,
65 "filesave.png"_L1);
66 QAction *saveAction = toolBar->addAction(saveIcon, tr("Save..."));
67 connect(saveAction, &QAction::triggered, this, &CodeDialog::slotSaveAs);
68
69#if QT_CONFIG(clipboard)
70 const QIcon copyIcon = createIconSet(QIcon::ThemeIcon::EditCopy,
71 "editcopy.png"_L1);
72 QAction *copyAction = toolBar->addAction(copyIcon, tr("Copy All"));
73 connect(copyAction, &QAction::triggered, this, &CodeDialog::copyAll);
74#endif
75
76 toolBar->addAction(m_impl->m_findWidget->createFindAction(toolBar));
77
78 vBoxLayout->addWidget(toolBar);
79
80 // Edit
81 m_impl->m_textEdit->setReadOnly(true);
82 const auto font = QFontDatabase::systemFont(QFontDatabase::SystemFont::FixedFont);
83 const int editorWidth = QFontMetrics(font, this).averageCharWidth() * 100;
84 m_impl->m_textEdit->setFont(font);
85 m_impl->m_textEdit->setMinimumSize(QSize(
86 qMax(editorWidth, m_impl->m_findWidget->minimumSize().width()),
87 500));
88 vBoxLayout->addWidget(m_impl->m_textEdit);
89
90 // Find
91 m_impl->m_findWidget->setTextEdit(m_impl->m_textEdit);
92 vBoxLayout->addWidget(m_impl->m_findWidget);
93
94 // Button box
95 QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Close);
96 connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
97
98 // Disable auto default
99 QPushButton *closeButton = buttonBox->button(QDialogButtonBox::Close);
100 closeButton->setAutoDefault(false);
101 vBoxLayout->addWidget(buttonBox);
102
103 setLayout(vBoxLayout);
104}
105
106CodeDialog::~CodeDialog()
107{
108 delete m_impl;
109}
110
111void CodeDialog::setCode(const QString &code)
112{
113 m_impl->m_textEdit->setPlainText(code);
114}
115
116QString CodeDialog::code() const
117{
118 return m_impl->m_textEdit->toPlainText();
119}
120
121void CodeDialog::setFormFileName(const QString &f)
122{
123 m_impl->m_formFileName = f;
124}
125
126QString CodeDialog::formFileName() const
127{
128 return m_impl->m_formFileName;
129}
130
131void CodeDialog::setMimeType(const QString &m)
132{
133 m_impl->m_mimeType = m;
134}
135
136bool CodeDialog::generateCode(const QDesignerFormWindowInterface *fw,
137 UicLanguage language,
138 QString *code,
139 QString *errorMessage)
140{
141 // Generate temporary file name similar to form file name
142 // (for header guards)
143 QString tempPattern = QDir::tempPath();
144 if (!tempPattern.endsWith(QDir::separator())) // platform-dependant
145 tempPattern += QDir::separator();
146 const QString fileName = fw->fileName();
147 if (fileName.isEmpty()) {
148 tempPattern += "designer"_L1;
149 } else {
150 tempPattern += QFileInfo(fileName).baseName();
151 }
152 tempPattern += "XXXXXX.ui"_L1;
153 // Write to temp file
154 QTemporaryFile tempFormFile(tempPattern);
155
156 tempFormFile.setAutoRemove(true);
157 if (!tempFormFile.open()) {
158 *errorMessage = tr("A temporary form file could not be created in %1.").arg(QDir::tempPath());
159 return false;
160 }
161 const QString tempFormFileName = tempFormFile.fileName();
162 tempFormFile.write(fw->contents().toUtf8());
163 if (!tempFormFile.flush()) {
164 *errorMessage = tr("The temporary form file %1 could not be written.").arg(tempFormFileName);
165 return false;
166 }
167 tempFormFile.close();
168 // Run uic
169 QByteArray rc;
170 if (!runUIC(tempFormFileName, language, rc, *errorMessage))
171 return false;
172 *code = QString::fromUtf8(rc);
173 return true;
174}
175
176bool CodeDialog::showCodeDialog(const QDesignerFormWindowInterface *fw,
177 UicLanguage language,
178 QWidget *parent,
179 QString *errorMessage)
180{
181 QString code;
182 if (!generateCode(fw, language, &code, errorMessage))
183 return false;
184
185 auto dialog = new CodeDialog(parent);
186 dialog->setModal(false);
187 dialog->setAttribute(Qt::WA_DeleteOnClose);
188 dialog->setCode(code);
189 dialog->setFormFileName(fw->fileName());
190 QLatin1StringView languageName;
191 switch (language) {
192 case UicLanguage::Cpp:
193 languageName = "C++"_L1;
194 dialog->setMimeType(u"text/x-chdr"_s);
195 break;
196 case UicLanguage::Python:
197 languageName = "Python"_L1;
198 dialog->setMimeType(u"text/x-python"_s);
199 break;
200 }
201 dialog->setWindowTitle(tr("%1 - [%2 Code]").
202 arg(fw->mainContainer()->windowTitle(), languageName));
203 dialog->show();
204 return true;
205}
206
207void CodeDialog::slotSaveAs()
208{
209 // build the default relative name 'ui_sth.h'
210 QMimeDatabase mimeDb;
211 const QString suffix = mimeDb.mimeTypeForName(m_impl->m_mimeType).preferredSuffix();
212
213 // file dialog
214 QFileDialog fileDialog(this, tr("Save Code"));
215 fileDialog.setMimeTypeFilters(QStringList(m_impl->m_mimeType));
216 fileDialog.setAcceptMode(QFileDialog::AcceptSave);
217 fileDialog.setDefaultSuffix(suffix);
218 const QString uiFile = formFileName();
219 if (!uiFile.isEmpty()) {
220 QFileInfo uiFi(uiFile);
221 fileDialog.setDirectory(uiFi.absolutePath());
222 fileDialog.selectFile("ui_"_L1 + uiFi.baseName()
223 + '.'_L1 + suffix);
224 }
225
226 while (true) {
227 if (fileDialog.exec() != QDialog::Accepted)
228 break;
229 const QString fileName = fileDialog.selectedFiles().constFirst();
230
231 QFile file(fileName);
232 if (!file.open(QIODevice::WriteOnly|QIODevice::Text)) {
233 warning(tr("The file %1 could not be opened: %2")
234 .arg(fileName, file.errorString()));
235 continue;
236 }
237 file.write(code().toUtf8());
238 if (!file.flush()) {
239 warning(tr("The file %1 could not be written: %2")
240 .arg(fileName, file.errorString()));
241 continue;
242 }
243 file.close();
244 break;
245 }
246}
247
248void CodeDialog::warning(const QString &msg)
249{
250 QMessageBox::warning(
251 this, tr("%1 - Error").arg(windowTitle()),
252 msg, QMessageBox::Close);
253}
254
255#if QT_CONFIG(clipboard)
256void CodeDialog::copyAll()
257{
258 QApplication::clipboard()->setText(code());
259}
260#endif
261
262} // namespace qdesigner_internal
263
264QT_END_NAMESPACE
A search bar that is commonly added below the searchable text.
Combined button and popup list for selecting options.