6#include <qdesigner_utils_p.h>
17#include <pluginmanager_p.h>
18#include <qdesigner_formbuilder_p.h>
19#include <qdesigner_utils_p.h>
20#include <iconloader_p.h>
21#include <previewmanager_p.h>
22#include <codedialog_p.h>
23#include <qdesigner_formwindowmanager_p.h>
26#include <QtDesigner/abstractformeditor.h>
27#include <QtDesigner/abstractformwindow.h>
28#include <QtDesigner/abstractintegration.h>
29#include <QtDesigner/abstractlanguage.h>
30#include <QtDesigner/abstractmetadatabase.h>
31#include <QtDesigner/abstractformwindowmanager.h>
32#include <QtDesigner/abstractformwindowcursor.h>
33#include <QtDesigner/abstractformeditorplugin.h>
34#include <QtDesigner/qextensionmanager.h>
36#include <QtDesigner/private/shared_settings_p.h>
37#include <QtDesigner/private/formwindowbase_p.h>
39#include <QtWidgets/qstylefactory.h>
40#include <QtWidgets/qfiledialog.h>
41#include <QtWidgets/qmenu.h>
42#include <QtWidgets/qmessagebox.h>
43#include <QtWidgets/qmdisubwindow.h>
44#include <QtWidgets/qpushbutton.h>
45#include <QtWidgets/qstatusbar.h>
47#include <QtGui/qaction.h>
48#include <QtGui/qactiongroup.h>
49#include <QtGui/qevent.h>
50#include <QtGui/qicon.h>
51#include <QtGui/qimage.h>
52#include <QtGui/qpixmap.h>
53#include <QtGui/qscreen.h>
54#if defined(QT_PRINTSUPPORT_LIB)
55# include <QtPrintSupport/qtprintsupportglobal.h>
56# if QT_CONFIG(printer) && QT_CONFIG(printdialog)
57# include <QtPrintSupport/qprinter.h>
58# include <QtPrintSupport/qprintdialog.h>
62#include <QtGui/qpainter.h>
63#include <QtGui/qtransform.h>
64#include <QtGui/qcursor.h>
66#include <QtCore/qdir.h>
67#include <QtCore/qsize.h>
68#include <QtCore/qlibraryinfo.h>
69#include <QtCore/qbuffer.h>
70#include <QtCore/qpluginloader.h>
71#include <QtCore/qdebug.h>
72#include <QtCore/qtimer.h>
73#include <QtCore/qtextstream.h>
74#include <QtCore/qmetaobject.h>
75#include <QtCore/qfileinfo.h>
76#include <QtCore/qsavefile.h>
77#include <QtCore/qscopedpointer.h>
78#include <QtXml/qdom.h>
86using namespace Qt::StringLiterals;
91# define NONMODAL_PREVIEW
95 QAction * rc =
new QAction(parent);
96 rc->setSeparator(
true);
101 QActionGroup * rc =
new QActionGroup(parent);
102 rc->setExclusive(exclusive);
108 for (QAction *a : actions)
109 a->setShortcutContext(Qt::ApplicationShortcut);
114 return QDesignerActions::tr(
"Saved %1.").arg(fileName);
119 return QDesignerActions::tr(
"Designer UI files (*.%1);;All Files (*)").arg(extension);
123 const QDir& backupDir);
126 std::optional<QDir> alternativeDir = {})
128 QString contents = alternativeDir.has_value()
129 ? fixResourceFileBackupPath(fw, alternativeDir.value()) : fw->contents();
130 if (
auto *fwb = qobject_cast<
const qdesigner_internal::FormWindowBase *>(fw)) {
131 if (fwb->lineTerminatorMode() == qdesigner_internal::FormWindowBase::CRLFLineTerminator)
132 contents.replace(u'\n',
"\r\n"_L1);
134 return contents.toUtf8();
139 auto result =
new QFileDialog(parent, QDesignerActions::tr(
"Save Form As"),
140 dir, fileDialogFilters(extension));
141 result->setAcceptMode(QFileDialog::AcceptSave);
142 result->setDefaultSuffix(extension);
147 : QObject(workbench),
148 m_workbench(workbench),
151 m_backupTimer(
new QTimer(
this)),
152 m_fileActions(createActionGroup(
this)),
153 m_recentFilesActions(createActionGroup(
this)),
154 m_editActions(createActionGroup(
this)),
155 m_formActions(createActionGroup(
this)),
156 m_settingsActions(createActionGroup(
this)),
157 m_windowActions(createActionGroup(
this)),
158 m_toolActions(createActionGroup(
this,
true)),
159 m_editWidgetsAction(
new QAction(tr(
"Edit Widgets"),
this)),
160 m_newFormAction(
new QAction(qdesigner_internal::createIconSet(QIcon::ThemeIcon::DocumentNew,
162 tr(
"&New..."),
this)),
163 m_openFormAction(
new QAction(qdesigner_internal::createIconSet(QIcon::ThemeIcon::DocumentOpen,
165 tr(
"&Open..."),
this)),
166 m_saveFormAction(
new QAction(qdesigner_internal::createIconSet(QIcon::ThemeIcon::DocumentSave,
169 m_saveFormAsAction(
new QAction(QIcon::fromTheme(QIcon::ThemeIcon::DocumentSaveAs),
170 tr(
"Save &As..."),
this)),
171 m_saveAllFormsAction(
new QAction(tr(
"Save A&ll"),
this)),
172 m_saveFormAsTemplateAction(
new QAction(tr(
"Save As &Template..."),
this)),
173 m_closeFormAction(
new QAction(QIcon::fromTheme(QIcon::ThemeIcon::WindowClose),
174 tr(
"&Close"),
this)),
175 m_savePreviewImageAction(
new QAction(tr(
"Save &Image..."),
this)),
176 m_printPreviewAction(
new QAction(QIcon::fromTheme(QIcon::ThemeIcon::DocumentPrint),
177 tr(
"&Print..."),
this)),
178 m_quitAction(
new QAction(QIcon::fromTheme(QIcon::ThemeIcon::ApplicationExit),
180 m_viewCppCodeAction(
new QAction(tr(
"View &C++ Code..."),
this)),
181 m_viewPythonCodeAction(
new QAction(tr(
"View &Python Code..."),
this)),
182 m_minimizeAction(
new QAction(tr(
"&Minimize"),
this)),
183 m_bringAllToFrontSeparator(createSeparator(
this)),
184 m_bringAllToFrontAction(
new QAction(tr(
"Bring All to Front"),
this)),
185 m_windowListSeparatorAction(createSeparator(
this)),
186 m_preferencesAction(
new QAction(tr(
"Preferences..."),
this)),
187 m_appFontAction(
new QAction(tr(
"Additional Fonts..."),
this))
189 Q_ASSERT(m_core !=
nullptr);
190 qdesigner_internal::QDesignerFormWindowManager *ifwm = qobject_cast<qdesigner_internal::QDesignerFormWindowManager *>(m_core->formWindowManager());
192 m_previewManager = ifwm->previewManager();
193 m_previewFormAction = ifwm->action(QDesignerFormWindowManagerInterface::DefaultPreviewAction);
194 m_styleActions = ifwm->actionGroup(QDesignerFormWindowManagerInterface::StyledPreviewActionGroup);
195 connect(ifwm, &QDesignerFormWindowManagerInterface::formWindowSettingsChanged,
196 this, &QDesignerActions::formWindowSettingsChanged);
198 m_editWidgetsAction->setObjectName(u"__qt_edit_widgets_action"_s);
199 m_newFormAction->setObjectName(u"__qt_new_form_action"_s);
200 m_openFormAction->setObjectName(u"__qt_open_form_action"_s);
201 m_saveFormAction->setObjectName(u"__qt_save_form_action"_s);
202 m_saveFormAsAction->setObjectName(u"__qt_save_form_as_action"_s);
203 m_saveAllFormsAction->setObjectName(u"__qt_save_all_forms_action"_s);
204 m_saveFormAsTemplateAction->setObjectName(u"__qt_save_form_as_template_action"_s);
205 m_closeFormAction->setObjectName(u"__qt_close_form_action"_s);
206 m_quitAction->setObjectName(u"__qt_quit_action"_s);
207 m_previewFormAction->setObjectName(u"__qt_preview_form_action"_s);
208 m_viewCppCodeAction->setObjectName(u"__qt_preview_cpp_code_action"_s);
209 m_viewPythonCodeAction->setObjectName(u"__qt_preview_python_code_action"_s);
210 m_minimizeAction->setObjectName(u"__qt_minimize_action"_s);
211 m_bringAllToFrontAction->setObjectName(u"__qt_bring_all_to_front_action"_s);
212 m_preferencesAction->setObjectName(u"__qt_preferences_action"_s);
214 m_helpActions = createHelpActions();
220 QDesignerFormWindowManagerInterface *formWindowManager = m_core->formWindowManager();
221 Q_ASSERT(formWindowManager !=
nullptr);
226 m_newFormAction->setShortcut(QKeySequence::New);
227 connect(m_newFormAction, &QAction::triggered,
this, &QDesignerActions::createForm);
228 m_fileActions->addAction(m_newFormAction);
230 m_openFormAction->setShortcut(QKeySequence::Open);
231 connect(m_openFormAction, &QAction::triggered,
this, &QDesignerActions::slotOpenForm);
232 m_fileActions->addAction(m_openFormAction);
234 m_fileActions->addAction(createRecentFilesMenu());
235 m_fileActions->addAction(createSeparator(
this));
237 m_saveFormAction->setShortcut(QKeySequence::Save);
238 connect(m_saveFormAction, &QAction::triggered,
this,
239 QOverload<>::of(&QDesignerActions::saveForm));
240 m_fileActions->addAction(m_saveFormAction);
242 connect(m_saveFormAsAction, &QAction::triggered,
this,
243 QOverload<>::of(&QDesignerActions::saveFormAs));
244 m_fileActions->addAction(m_saveFormAsAction);
247 m_saveAllFormsAction->setShortcut(tr(
"ALT+CTRL+S"));
249 m_saveAllFormsAction->setShortcut(tr(
"CTRL+SHIFT+S"));
251 connect(m_saveAllFormsAction, &QAction::triggered,
this, &QDesignerActions::saveAllForms);
252 m_fileActions->addAction(m_saveAllFormsAction);
254 connect(m_saveFormAsTemplateAction, &QAction::triggered,
this, &QDesignerActions::saveFormAsTemplate);
255 m_fileActions->addAction(m_saveFormAsTemplateAction);
257 m_fileActions->addAction(createSeparator(
this));
259 m_printPreviewAction->setShortcut(QKeySequence::Print);
260 connect(m_printPreviewAction, &QAction::triggered,
this, &QDesignerActions::printPreviewImage);
261 m_fileActions->addAction(m_printPreviewAction);
262 m_printPreviewAction->setObjectName(u"__qt_print_action"_s);
264 connect(m_savePreviewImageAction, &QAction::triggered,
this, &QDesignerActions::savePreviewImage);
265 m_savePreviewImageAction->setObjectName(u"__qt_saveimage_action"_s);
266 m_fileActions->addAction(m_savePreviewImageAction);
267 m_fileActions->addAction(createSeparator(
this));
269 m_closeFormAction->setShortcut(QKeySequence::Close);
270 connect(m_closeFormAction, &QAction::triggered,
this, &QDesignerActions::closeForm);
271 m_fileActions->addAction(m_closeFormAction);
274 m_fileActions->addAction(createSeparator(
this));
276 m_quitAction->setShortcuts(QKeySequence::Quit);
277 m_quitAction->setMenuRole(QAction::QuitRole);
278 connect(m_quitAction, &QAction::triggered,
this, &QDesignerActions::shutdown);
279 m_fileActions->addAction(m_quitAction);
284 QAction *undoAction = formWindowManager->action(QDesignerFormWindowManagerInterface::UndoAction);
285 undoAction->setObjectName(u"__qt_undo_action"_s);
286 undoAction->setShortcut(QKeySequence::Undo);
287 m_editActions->addAction(undoAction);
289 QAction *redoAction = formWindowManager->action(QDesignerFormWindowManagerInterface::RedoAction);
290 redoAction->setObjectName(u"__qt_redo_action"_s);
291 redoAction->setShortcut(QKeySequence::Redo);
292 m_editActions->addAction(redoAction);
294 m_editActions->addAction(createSeparator(
this));
296#if QT_CONFIG(clipboard)
297 m_editActions->addAction(formWindowManager->action(QDesignerFormWindowManagerInterface::CutAction));
298 m_editActions->addAction(formWindowManager->action(QDesignerFormWindowManagerInterface::CopyAction));
299 m_editActions->addAction(formWindowManager->action(QDesignerFormWindowManagerInterface::PasteAction));
301 m_editActions->addAction(formWindowManager->action(QDesignerFormWindowManagerInterface::DeleteAction));
303 m_editActions->addAction(formWindowManager->action(QDesignerFormWindowManagerInterface::SelectAllAction));
305 m_editActions->addAction(createSeparator(
this));
307 m_editActions->addAction(formWindowManager->action(QDesignerFormWindowManagerInterface::LowerAction));
308 m_editActions->addAction(formWindowManager->action(QDesignerFormWindowManagerInterface::RaiseAction));
310 formWindowManager->action(QDesignerFormWindowManagerInterface::LowerAction)->setProperty(QDesignerActions::defaultToolbarPropertyName,
true);
311 formWindowManager->action(QDesignerFormWindowManagerInterface::RaiseAction)->setProperty(QDesignerActions::defaultToolbarPropertyName,
true);
317 m_editWidgetsAction->setCheckable(
true);
318 QList<QKeySequence> shortcuts;
319 shortcuts.append(QKeySequence(Qt::Key_F3));
320 shortcuts.append(QKeySequence(Qt::Key_Escape));
321 m_editWidgetsAction->setShortcuts(shortcuts);
322 QIcon fallback(m_core->resourceLocation() +
"/widgettool.png"_L1);
323 m_editWidgetsAction->setIcon(QIcon::fromTheme(u"designer-edit-widget"_s,
325 connect(m_editWidgetsAction, &QAction::triggered,
this, &QDesignerActions::editWidgetsSlot);
326 m_editWidgetsAction->setChecked(
true);
327 m_editWidgetsAction->setEnabled(
false);
329 m_toolActions->addAction(m_editWidgetsAction);
331 connect(formWindowManager, &qdesigner_internal::QDesignerFormWindowManager::activeFormWindowChanged,
332 this, &QDesignerActions::activeFormWindowChanged);
334 const QObjectList builtinPlugins = QPluginLoader::staticInstances()
335 + m_core->pluginManager()->instances();
336 for (QObject *plugin : builtinPlugins) {
337 if (QDesignerFormEditorPluginInterface *formEditorPlugin = qobject_cast<QDesignerFormEditorPluginInterface*>(plugin)) {
338 if (QAction *action = formEditorPlugin->action()) {
339 m_toolActions->addAction(action);
340 action->setProperty(QDesignerActions::defaultToolbarPropertyName,
true);
341 action->setCheckable(
true);
346 connect(m_preferencesAction, &QAction::triggered,
this, &QDesignerActions::showPreferencesDialog);
347 m_preferencesAction->setMenuRole(QAction::PreferencesRole);
348 m_settingsActions->addAction(m_preferencesAction);
350 connect(m_appFontAction, &QAction::triggered,
this, &QDesignerActions::showAppFontDialog);
351 m_settingsActions->addAction(m_appFontAction);
356 m_formActions->addAction(formWindowManager->action(QDesignerFormWindowManagerInterface::HorizontalLayoutAction));
357 m_formActions->addAction(formWindowManager->action(QDesignerFormWindowManagerInterface::VerticalLayoutAction));
358 m_formActions->addAction(formWindowManager->action(QDesignerFormWindowManagerInterface::SplitHorizontalAction));
359 m_formActions->addAction(formWindowManager->action(QDesignerFormWindowManagerInterface::SplitVerticalAction));
360 m_formActions->addAction(formWindowManager->action(QDesignerFormWindowManagerInterface::GridLayoutAction));
361 m_formActions->addAction(formWindowManager->action(QDesignerFormWindowManagerInterface::FormLayoutAction));
362 m_formActions->addAction(formWindowManager->action(QDesignerFormWindowManagerInterface::BreakLayoutAction));
363 m_formActions->addAction(formWindowManager->action(QDesignerFormWindowManagerInterface::AdjustSizeAction));
364 m_formActions->addAction(formWindowManager->action(QDesignerFormWindowManagerInterface::SimplifyLayoutAction));
365 m_formActions->addAction(createSeparator(
this));
367 formWindowManager->action(QDesignerFormWindowManagerInterface::HorizontalLayoutAction)->setProperty(QDesignerActions::defaultToolbarPropertyName,
true);
368 formWindowManager->action(QDesignerFormWindowManagerInterface::VerticalLayoutAction)->setProperty(QDesignerActions::defaultToolbarPropertyName,
true);
369 formWindowManager->action(QDesignerFormWindowManagerInterface::SplitHorizontalAction)->setProperty(QDesignerActions::defaultToolbarPropertyName,
true);
370 formWindowManager->action(QDesignerFormWindowManagerInterface::SplitVerticalAction)->setProperty(QDesignerActions::defaultToolbarPropertyName,
true);
371 formWindowManager->action(QDesignerFormWindowManagerInterface::GridLayoutAction)->setProperty(QDesignerActions::defaultToolbarPropertyName,
true);
372 formWindowManager->action(QDesignerFormWindowManagerInterface::FormLayoutAction)->setProperty(QDesignerActions::defaultToolbarPropertyName,
true);
373 formWindowManager->action(QDesignerFormWindowManagerInterface::BreakLayoutAction)->setProperty(QDesignerActions::defaultToolbarPropertyName,
true);
374 formWindowManager->action(QDesignerFormWindowManagerInterface::AdjustSizeAction)->setProperty(QDesignerActions::defaultToolbarPropertyName,
true);
376 m_previewFormAction->setShortcut(tr(
"CTRL+R"));
377 m_formActions->addAction(m_previewFormAction);
378 connect(m_previewManager, &qdesigner_internal::PreviewManager::firstPreviewOpened,
379 this, &QDesignerActions::updateCloseAction);
380 connect(m_previewManager, &qdesigner_internal::PreviewManager::lastPreviewClosed,
381 this, &QDesignerActions::updateCloseAction);
383 connect(m_viewCppCodeAction, &QAction::triggered,
this,
384 [
this] () {
this->viewCode(qdesigner_internal::UicLanguage::Cpp); });
385 connect(m_viewPythonCodeAction, &QAction::triggered,
this,
386 [
this] () {
this->viewCode(qdesigner_internal::UicLanguage::Python); });
389 if (qt_extension<QDesignerLanguageExtension *>(m_core->extensionManager(), m_core) ==
nullptr) {
390 m_formActions->addAction(m_viewCppCodeAction);
391 m_formActions->addAction(m_viewPythonCodeAction);
394 m_formActions->addAction(createSeparator(
this));
396 m_formActions->addAction(ifwm->action(QDesignerFormWindowManagerInterface::FormWindowSettingsDialogAction));
400 m_minimizeAction->setEnabled(
false);
401 m_minimizeAction->setCheckable(
true);
402 m_minimizeAction->setShortcut(tr(
"CTRL+M"));
403 connect(m_minimizeAction, &QAction::triggered, m_workbench, &QDesignerWorkbench::toggleFormMinimizationState);
404 m_windowActions->addAction(m_minimizeAction);
406 m_windowActions->addAction(m_bringAllToFrontSeparator);
407 connect(m_bringAllToFrontAction, &QAction::triggered, m_workbench, &QDesignerWorkbench::bringAllToFront);
408 m_windowActions->addAction(m_bringAllToFrontAction);
409 m_windowActions->addAction(m_windowListSeparatorAction);
416 fixActionContext(m_fileActions->actions());
417 fixActionContext(m_editActions->actions());
418 fixActionContext(m_toolActions->actions());
419 fixActionContext(m_formActions->actions());
420 fixActionContext(m_windowActions->actions());
421 fixActionContext(m_helpActions->actions());
423 activeFormWindowChanged(
core()->formWindowManager()->activeFormWindow());
425 m_backupTimer->start(180000);
426 connect(m_backupTimer, &QTimer::timeout,
this, &QDesignerActions::backupForms);
429 connect(formWindowManager, &QDesignerFormWindowManagerInterface::formWindowAdded,
430 this, &QDesignerActions::formWindowCountChanged);
431 connect(formWindowManager, &QDesignerFormWindowManagerInterface::formWindowRemoved,
432 this, &QDesignerActions::formWindowCountChanged);
433 formWindowCountChanged();
438 QActionGroup *helpActions = createActionGroup(
this);
440#ifndef QT_JAMBI_BUILD
441 QAction *mainHelpAction =
new QAction(tr(
"Qt Widgets Designer &Help"),
this);
442 mainHelpAction->setObjectName(u"__qt_designer_help_action"_s);
443 connect(mainHelpAction, &QAction::triggered,
this, &QDesignerActions::showDesignerHelp);
444 mainHelpAction->setShortcut(Qt::CTRL | Qt::Key_Question);
445 helpActions->addAction(mainHelpAction);
447 helpActions->addAction(createSeparator(
this));
448 QAction *widgetHelp =
new QAction(tr(
"Current Widget Help"),
this);
449 widgetHelp->setObjectName(u"__qt_current_widget_help_action"_s);
450 widgetHelp->setShortcut(Qt::Key_F1);
451 connect(widgetHelp, &QAction::triggered,
this, &QDesignerActions::showWidgetSpecificHelp);
452 helpActions->addAction(widgetHelp);
456 helpActions->addAction(createSeparator(
this));
457 QAction *aboutPluginsAction =
new QAction(tr(
"About Plugins"),
this);
458 aboutPluginsAction->setObjectName(u"__qt_about_plugins_action"_s);
459 aboutPluginsAction->setMenuRole(QAction::ApplicationSpecificRole);
460 connect(aboutPluginsAction, &QAction::triggered,
461 m_core->formWindowManager(), &QDesignerFormWindowManagerInterface::showPluginDialog);
462 helpActions->addAction(aboutPluginsAction);
464 QAction *aboutDesignerAction =
new QAction(tr(
"About Qt Widgets Designer"),
this);
465 aboutDesignerAction->setMenuRole(QAction::AboutRole);
466 aboutDesignerAction->setObjectName(u"__qt_about_designer_action"_s);
467 connect(aboutDesignerAction, &QAction::triggered,
this, &QDesignerActions::aboutDesigner);
468 helpActions->addAction(aboutDesignerAction);
470 QAction *aboutQtAction =
new QAction(tr(
"About Qt"),
this);
471 aboutQtAction->setMenuRole(QAction::AboutQtRole);
472 aboutQtAction->setObjectName(u"__qt_about_qt_action"_s);
473 connect(aboutQtAction, &QAction::triggered, qApp, &QApplication::aboutQt);
474 helpActions->addAction(aboutQtAction);
487 QDesignerLanguageExtension *lang
488 = qt_extension<QDesignerLanguageExtension *>(m_core->extensionManager(), m_core);
490 return lang->uiExtension();
496 m_recentMenu.reset(
new QMenu);
499 for (
int i = 0; i < MaxRecentFiles; ++i) {
500 act =
new QAction(
this);
501 act->setVisible(
false);
502 connect(act, &QAction::triggered,
this, &QDesignerActions::openRecentForm);
503 m_recentFilesActions->addAction(act);
504 m_recentMenu->addAction(act);
506 updateRecentFileActions();
507 m_recentMenu->addSeparator();
508 act =
new QAction(QIcon::fromTheme(QIcon::ThemeIcon::EditClear),
509 tr(
"Clear &Menu"),
this);
510 act->setObjectName(u"__qt_action_clear_menu_"_s);
511 connect(act, &QAction::triggered,
this, &QDesignerActions::clearRecentFiles);
512 m_recentFilesActions->addAction(act);
513 m_recentMenu->addAction(act);
515 act =
new QAction(QIcon::fromTheme(QIcon::ThemeIcon::DocumentOpenRecent),
516 tr(
"&Recent Forms"),
this);
517 act->setMenu(m_recentMenu.get());
522{
return m_toolActions; }
525{
return m_workbench; }
531{
return m_fileActions; }
534{
return m_editActions; }
537{
return m_formActions; }
540{
return m_settingsActions; }
543{
return m_windowActions; }
546{
return m_helpActions; }
549{
return m_styleActions; }
552{
return m_previewFormAction; }
555{
return m_viewCppCodeAction; }
560 QDesignerFormWindowManagerInterface *formWindowManager =
core()->formWindowManager();
561 for (
int i=0; i<formWindowManager->formWindowCount(); ++i) {
562 QDesignerFormWindowInterface *formWindow = formWindowManager->formWindow(i);
563 formWindow->editWidgets();
569 showNewFormDialog(QString());
577 dlg->setAttribute(Qt::WA_DeleteOnClose);
578 dlg->setAttribute(Qt::WA_ShowModal);
580 dlg->setGeometry(fixDialogRect(dlg->rect()));
592 const QString extension = uiExtension();
593 const QStringList fileNames = QFileDialog::getOpenFileNames(parent, tr(
"Open Form"),
594 m_openDirectory, fileDialogFilters(extension),
nullptr);
596 if (fileNames.isEmpty())
599 bool atLeastOne =
false;
600 for (
const QString &fileName : fileNames) {
601 if (readInForm(fileName) && !atLeastOne)
610 const QString extension = uiExtension();
612 QString dir = fw->fileName();
616 if (!m_saveDirectory.isEmpty()) {
617 dir = m_saveDirectory;
620 if (!m_openDirectory.isEmpty()) {
621 dir = m_openDirectory;
624 dir = QDir::current().absolutePath();
626 dir += QDir::separator();
627 dir +=
"untitled."_L1;
631 QScopedPointer<QFileDialog> saveAsDialog(createSaveAsDialog(fw, dir, extension));
632 if (saveAsDialog->exec() != QDialog::Accepted)
635 const QString saveFile = saveAsDialog->selectedFiles().constFirst();
636 saveAsDialog.reset();
638 fw->setFileName(saveFile);
644 if (QDesignerFormWindowInterface *fw =
core()->formWindowManager()->activeFormWindow()) {
646 showStatusBarMessage(savedMessage(QFileInfo(fw->fileName()).fileName()));
653 QDesignerFormWindowManagerInterface *formWindowManager =
core()->formWindowManager();
654 if (
const int totalWindows = formWindowManager->formWindowCount()) {
655 const auto separator =
", "_L1;
656 for (
int i = 0; i < totalWindows; ++i) {
657 QDesignerFormWindowInterface *fw = formWindowManager->formWindow(i);
658 if (fw && fw->isDirty()) {
659 formWindowManager->setActiveFormWindow(fw);
661 if (!fileNames.isEmpty())
662 fileNames += separator;
663 fileNames += QFileInfo(fw->fileName()).fileName();
671 if (!fileNames.isEmpty()) {
672 showStatusBarMessage(savedMessage(fileNames));
679 if (fw->fileName().isEmpty())
680 ret = saveFormAs(fw);
688 if (m_previewManager->previewCount()) {
693 if (QDesignerFormWindowInterface *fw =
core()->formWindowManager()->activeFormWindow())
694 if (
QWidget *parent = fw->parentWidget()) {
695 if (QMdiSubWindow *mdiSubWindow = qobject_cast<QMdiSubWindow *>(parent->parentWidget())) {
696 mdiSubWindow->close();
705 if (QDesignerFormWindowInterface *fw =
core()->formWindowManager()->activeFormWindow()) {
707 showStatusBarMessage(savedMessage(fw->fileName()));
713 if (QDesignerFormWindowInterface *fw =
core()->formWindowManager()->activeFormWindow()) {
721 QMessageBox::information(core()->topLevel(), tr(
"Designer"), tr(
"Feature not implemented yet!"));
726 m_previewManager->closeAllPreviews();
731 QDesignerFormWindowInterface *fw =
core()->formWindowManager()->activeFormWindow();
734 QString errorMessage;
735 if (!qdesigner_internal::CodeDialog::showCodeDialog(fw, language, fw, &errorMessage))
736 QMessageBox::warning(fw, tr(
"Code generation failed"), errorMessage);
741 QString fn = fileName;
744 QDesignerFormWindowManagerInterface *formWindowManager =
core()->formWindowManager();
745 const int totalWindows = formWindowManager->formWindowCount();
746 for (
int i = 0; i < totalWindows; ++i) {
747 QDesignerFormWindowInterface *w = formWindowManager->formWindow(i);
748 if (w->fileName() == fn) {
750 formWindowManager->setActiveFormWindow(w);
758 QString errorMessage;
761 m_openDirectory = QFileInfo(fn).absolutePath();
765 QMessageBox box(QMessageBox::Warning, tr(
"Read error"),
766 tr(
"%1\nDo you want to update the file location or generate a new form?").arg(errorMessage),
767 QMessageBox::Cancel, core()->topLevel());
769 QPushButton *updateButton = box.addButton(tr(
"&Update"), QMessageBox::ActionRole);
770 QPushButton *newButton = box.addButton(tr(
"&New Form"), QMessageBox::ActionRole);
772 if (box.clickedButton() == box.button(QMessageBox::Cancel))
775 if (box.clickedButton() == updateButton) {
776 const QString extension = uiExtension();
777 fn = QFileDialog::getOpenFileName(core()->topLevel(),
778 tr(
"Open Form"), m_openDirectory,
779 fileDialogFilters(extension),
nullptr);
783 }
else if (box.clickedButton() == newButton) {
786 QString newFormFileName;
787 const QFileInfo fInfo(fn);
788 if (!fInfo.exists()) {
790 const QString directory = fInfo.absolutePath();
791 if (QDir(directory).exists())
792 newFormFileName = directory + u'/' + fInfo.fileName();
794 showNewFormDialog(newFormFileName);
804 Q_ASSERT(fw && !saveFile.isEmpty());
807 const QStringList problems = fw->checkContents();
808 if (!problems.isEmpty())
809 QMessageBox::information(fw->window(), tr(
"Qt Widgets Designer"), problems.join(
"<br>"_L1));
814 QSaveFile f(saveFile);
815 while (!f.open(QFile::WriteOnly)) {
816 QMessageBox box(QMessageBox::Warning,
818 tr(
"Could not open file"),
819 QMessageBox::NoButton, fw);
821 box.setWindowModality(Qt::WindowModal);
822 box.setInformativeText(tr(
"The file %1 could not be opened."
824 "\nWould you like to retry or select a different file?")
825 .arg(f.fileName(), f.errorString()));
826 QPushButton *retryButton = box.addButton(QMessageBox::Retry);
827 retryButton->setDefault(
true);
828 QPushButton *switchButton = box.addButton(tr(
"Select New File"), QMessageBox::AcceptRole);
829 QPushButton *cancelButton = box.addButton(QMessageBox::Cancel);
832 if (box.clickedButton() == cancelButton)
834 if (box.clickedButton() == switchButton) {
835 QScopedPointer<QFileDialog> saveAsDialog(createSaveAsDialog(fw, QDir::currentPath(), uiExtension()));
836 if (saveAsDialog->exec() != QDialog::Accepted)
839 const QString fileName = saveAsDialog->selectedFiles().constFirst();
840 f.setFileName(fileName);
841 fw->setFileName(fileName);
845 f.write(formWindowContents(fw));
847 QMessageBox box(QMessageBox::Warning, tr(
"Save Form"),
848 tr(
"Could not write file"),
849 QMessageBox::Cancel, fw);
850 box.setWindowModality(Qt::WindowModal);
851 box.setInformativeText(tr(
"It was not possible to write the file %1 to disk."
853 .arg(f.fileName(), f.errorString()));
857 addRecentFile(saveFile);
858 m_saveDirectory = QFileInfo(f.fileName()).absolutePath();
861 fw->parentWidget()->setWindowModified(
false);
877 const bool enable = formWindow !=
nullptr;
878 m_saveFormAction->setEnabled(enable);
879 m_saveFormAsAction->setEnabled(enable);
880 m_saveAllFormsAction->setEnabled(enable);
881 m_saveFormAsTemplateAction->setEnabled(enable);
882 m_closeFormAction->setEnabled(enable);
883 m_savePreviewImageAction->setEnabled(enable);
884 m_printPreviewAction->setEnabled(enable);
886 m_editWidgetsAction->setEnabled(enable);
888 m_previewFormAction->setEnabled(enable);
889 m_viewCppCodeAction->setEnabled(enable);
890 m_viewPythonCodeAction->setEnabled(enable);
891 m_styleActions->setEnabled(enable);
894void QDesignerActions::formWindowSettingsChanged(QDesignerFormWindowInterface *fw)
897 window->updateChanged();
902 QStringList files = m_settings.recentFilesList();
903 auto existingEnd =
std::remove_if(files.begin(), files.end(),
904 [] (
const QString &f) {
return !QFileInfo::exists(f); });
905 if (existingEnd != files.end()) {
906 files.erase(existingEnd, files.end());
907 m_settings.setRecentFilesList(files);
910 const auto recentFilesActs = m_recentFilesActions->actions();
912 for (QAction *action : recentFilesActs) {
913 if (i < files.size()) {
914 const QString &file = files.at(i);
915 action->setText(QFileInfo(file).fileName());
916 action->setIconText(file);
917 action->setVisible(
true);
919 action->setVisible(
false);
927 if (
const QAction *action = qobject_cast<
const QAction *>(sender())) {
929 updateRecentFileActions();
935 m_settings.setRecentFilesList(QStringList());
936 updateRecentFileActions();
941 return m_recentFilesActions;
946 QStringList files = m_settings.recentFilesList();
947 files.removeAll(fileName);
948 files.prepend(fileName);
949 while (files.size() > MaxRecentFiles)
952 m_settings.setRecentFilesList(files);
953 updateRecentFileActions();
958 return m_openFormAction;
963 return m_closeFormAction;
968 return m_minimizeAction;
973 QString url = AssistantClient::designerManualUrl();
974 url +=
"qtdesigner-manual.html"_L1;
980 QString url = AssistantClient::documentUrl(manual);
987 QString errorMessage;
988 if (!m_assistantClient.showPage(url, &errorMessage))
989 QMessageBox::warning(core()->topLevel(), tr(
"Assistant"), errorMessage);
994 VersionDialog mb(
core()->topLevel());
995 mb.setWindowTitle(tr(
"About Qt Widgets Designer"));
997 QMessageBox messageBox(QMessageBox::Information, u"Easter Egg"_s,
998 u"Easter Egg"_s, QMessageBox::Ok, core()->topLevel());
999 messageBox.setInformativeText(u"The Easter Egg has been removed."_s);
1006 return m_editWidgetsAction;
1011 const QString helpId = core()->integration()->contextHelpId();
1013 if (helpId.isEmpty()) {
1018 QString errorMessage;
1019 const bool rc = m_assistantClient.activateIdentifier(helpId, &errorMessage);
1021 QMessageBox::warning(core()->topLevel(), tr(
"Assistant"), errorMessage);
1026 if (m_previewManager->previewCount()) {
1027 m_closeFormAction->setText(tr(
"&Close Preview"));
1029 m_closeFormAction->setText(tr(
"&Close"));
1036 if (!count || !ensureBackupDirectories())
1040 QMap<QString, QString> backupMap;
1041 QDir backupDir(m_backupPath);
1042 for (
int i = 0; i < count; ++i) {
1044 QDesignerFormWindowInterface *fwi = fw
->editor();
1046 QString formBackupName = m_backupPath +
"/backup"_L1 + QString::number(i) +
".bak"_L1;
1048 QString fwn = QDir::toNativeSeparators(fwi->fileName());
1050 fwn = fw->windowTitle();
1052 backupMap.insert(fwn, formBackupName);
1055 QSaveFile file(formBackupName);
1056 if (file.open(QFile::WriteOnly)) {
1057 file.write(formWindowContents(fw->editor(), backupDir));
1061 backupMap.remove(fwn);
1062 qdesigner_internal::designerWarning(tr(
"The backup file %1 could not be written: %2").
1063 arg(QDir::toNativeSeparators(file.fileName()),
1064 file.errorString()));
1068 if (!backupMap.isEmpty())
1069 m_settings.setBackup(backupMap);
1073 const QDir& backupDir)
1075 const QString content = fwi->contents();
1076 QDomDocument domDoc(u"backup"_s);
1077 if(!domDoc.setContent(content))
1080 const QDomNodeList list = domDoc.elementsByTagName(u"resources"_s);
1084 for (
int i = 0; i < list.count(); i++) {
1085 const QDomNode node = list.at(i);
1086 if (!node.isNull()) {
1087 const QDomElement element = node.toElement();
1088 if (!element.isNull() && element.tagName() ==
"resources"_L1) {
1089 QDomNode childNode = element.firstChild();
1090 while (!childNode.isNull()) {
1091 QDomElement childElement = childNode.toElement();
1092 if (!childElement.isNull() && childElement.tagName() ==
"include"_L1) {
1093 const QString attr = childElement.attribute(u"location"_s);
1094 const QString path = fwi->absoluteDir().absoluteFilePath(attr);
1095 childElement.setAttribute(u"location"_s, backupDir.relativeFilePath(path));
1097 childNode = childNode.nextSibling();
1104 return domDoc.toString();
1109 QRect frameGeometry;
1110 const QRect availableGeometry = core()->topLevel()->screen()->geometry();
1113 frameGeometry =
core()->topLevel()->frameGeometry();
1115 frameGeometry = availableGeometry;
1117 QRect dlgRect = rect;
1118 dlgRect.moveCenter(frameGeometry.center());
1121 dlgRect.moveBottom(qMin(dlgRect.bottom(), availableGeometry.bottom()));
1122 dlgRect.moveRight(qMin(dlgRect.right(), availableGeometry.right()));
1123 dlgRect.moveLeft(qMax(dlgRect.left(), availableGeometry.left()));
1124 dlgRect.moveTop(qMax(dlgRect.top(), availableGeometry.top()));
1132 QStatusBar *bar =
qDesigner->mainWindow()->statusBar();
1133 if (bar && !bar->isHidden())
1134 bar->showMessage(message, 3000);
1140 m_bringAllToFrontSeparator->setVisible(visible);
1141 m_bringAllToFrontAction->setVisible(visible);
1146 m_windowListSeparatorAction->setVisible(visible);
1151 if (m_backupPath.isEmpty())
1152 m_backupPath = qdesigner_internal::dataDirectory() + u"/backup"_s;
1155 const QDir backupDir(m_backupPath);
1157 if (!backupDir.exists()) {
1158 if (!backupDir.mkpath(m_backupPath)) {
1159 qdesigner_internal::designerWarning(tr(
"The backup directory %1 could not be created.")
1160 .arg(QDir::toNativeSeparators(m_backupPath)));
1171 preferencesDialog.exec();
1178 if (!m_appFontDialog)
1179 m_appFontDialog =
new AppFontDialog(core()->topLevel());
1180 m_appFontDialog->show();
1181 m_appFontDialog->raise();
1184QPixmap
QDesignerActions::createPreviewPixmap(QDesignerFormWindowInterface *fw)
1186 const QCursor oldCursor = core()->topLevel()->cursor();
1187 core()->topLevel()->setCursor(Qt::WaitCursor);
1189 QString errorMessage;
1190 const QPixmap pixmap = m_previewManager->createPreviewPixmap(fw, QString(), &errorMessage);
1191 core()->topLevel()->setCursor(oldCursor);
1192 if (pixmap.isNull()) {
1193 QMessageBox::warning(fw, tr(
"Preview failed"), errorMessage);
1202 if (settings.isCustomPreviewConfigurationEnabled())
1203 pc = settings.customPreviewConfiguration();
1209 const char *format =
"png";
1211 QDesignerFormWindowInterface *fw =
core()->formWindowManager()->activeFormWindow();
1216 const QString extension = QString::fromLatin1(format);
1217 const QString filter = tr(
"Image files (*.%1)").arg(extension);
1219 QString suggestion = fw->fileName();
1220 if (!suggestion.isEmpty())
1221 suggestion = QFileInfo(suggestion).baseName() + u'.' + extension;
1223 QFileDialog dialog(fw, tr(
"Save Image"), suggestion, filter);
1224 dialog.setAcceptMode(QFileDialog::AcceptSave);
1225 dialog.setDefaultSuffix(extension);
1228 if (dialog.exec() != QDialog::Accepted)
1230 const QString fileName = dialog.selectedFiles().constFirst();
1232 if (image.isNull()) {
1233 const QPixmap pixmap = createPreviewPixmap(fw);
1234 if (pixmap.isNull())
1237 image = pixmap.toImage();
1240 if (image.save(fileName, format)) {
1241 showStatusBarMessage(tr(
"Saved image %1.").arg(QFileInfo(fileName).fileName()));
1245 QMessageBox box(QMessageBox::Warning, tr(
"Save Image"),
1246 tr(
"The file %1 could not be written.").arg( fileName),
1247 QMessageBox::Retry|QMessageBox::Cancel, fw);
1248 if (box.exec() == QMessageBox::Cancel)
1255 const bool enabled = m_core->formWindowManager()->formWindowCount() == 0;
1257
1258
1259 static const QString disabledTip = tr(
"Please close all forms to enable the loading of additional fonts.");
1260 m_appFontAction->setEnabled(enabled);
1261 m_appFontAction->setStatusTip(enabled ? QString() : disabledTip);
1267 QDesignerFormWindowInterface *fw = core()->formWindowManager()->activeFormWindow();
1272 m_printer =
new QPrinter(QPrinter::HighResolution);
1274 m_printer->setFullPage(
false);
1277 const QPixmap pixmap = createPreviewPixmap(fw);
1278 if (pixmap.isNull())
1281 const QSizeF pixmapSize = pixmap.size();
1283 m_printer->setPageOrientation(pixmapSize.width() > pixmapSize.height() ?
1284 QPageLayout::Landscape : QPageLayout::Portrait);
1287 QPrintDialog dialog(m_printer, fw);
1291 const QCursor oldCursor = core()->topLevel()->cursor();
1292 core()->topLevel()->setCursor(Qt::WaitCursor);
1294 const double suggestedScaling =
static_cast<
double>(m_printer->physicalDpiX()) /
static_cast<
double>(fw->physicalDpiX());
1296 QPainter painter(m_printer);
1297 painter.setRenderHint(QPainter::SmoothPixmapTransform);
1300 const QRectF page = painter.viewport();
1301 const double maxScaling = qMin(page.size().width() / pixmapSize.width(), page.size().height() / pixmapSize.height());
1302 const double scaling = qMin(suggestedScaling, maxScaling);
1304 const double xOffset = page.left() + qMax(0.0, (page.size().width() - scaling * pixmapSize.width()) / 2.0);
1305 const double yOffset = page.top() + qMax(0.0, (page.size().height() - scaling * pixmapSize.height()) / 2.0);
1308 painter.translate(xOffset, yOffset);
1309 painter.scale(scaling, scaling);
1310 painter.drawPixmap(0, 0, pixmap);
1311 core()->topLevel()->setCursor(oldCursor);
1313 showStatusBarMessage(tr(
"Printed %1.").arg(QFileInfo(fw->fileName()).fileName()));
QActionGroup * helpActions() const
QActionGroup * fileActions() const
QActionGroup * settingsActions() const
QAction * minimizeAction() const
QActionGroup * styleActions() const
~QDesignerActions() override
QActionGroup * editActions() const
bool writeOutForm(QDesignerFormWindowInterface *formWindow, const QString &fileName, bool check=true)
QString uiExtension() const
QActionGroup * formActions() const
bool openForm(QWidget *parent)
QDesignerFormEditorInterface * core() const
QActionGroup * toolActions() const
QAction * previewFormAction() const
QActionGroup * windowActions() const
bool readInForm(const QString &fileName)
QAction * closeFormAction() const
void setWindowListSeparatorVisible(bool visible)
bool saveForm(QDesignerFormWindowInterface *fw)
QAction * editWidgets() const
QAction * openFormAction() const
QAction * viewCodeAction() const
QDesignerWorkbench * workbench() const
void helpRequested(const QString &manual, const QString &document)
static const char * defaultToolbarPropertyName
void setBringAllToFrontVisible(bool visible)
QActionGroup * recentFilesActions() const
QDesignerSettings(QDesignerFormEditorInterface *core)
int formWindowCount() const
QDesignerFormEditorInterface * core() const
QDesignerFormWindow * formWindow(int index) const
void updateBackup(QDesignerFormWindowInterface *fwi)
Auxiliary methods to store/retrieve settings.
static QByteArray formWindowContents(const QDesignerFormWindowInterface *fw, std::optional< QDir > alternativeDir={})
static QString fixResourceFileBackupPath(const QDesignerFormWindowInterface *fwi, const QDir &backupDir)
static QString fileDialogFilters(const QString &extension)
static QString savedMessage(const QString &fileName)
static QAction * createSeparator(QObject *parent)
QFileDialog * createSaveAsDialog(QWidget *parent, const QString &dir, const QString &extension)
static QActionGroup * createActionGroup(QObject *parent, bool exclusive=false)
static void fixActionContext(const QList< QAction * > &actions)