From 9f509f9aa2a1066a223bfd23fb54862f9c988b78 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Sat, 15 Jun 2019 19:36:55 -0400 Subject: TextEditor now has a dynamic toolbar --- src/modinfodialog.cpp | 31 --------------- src/modinfodialog.h | 5 --- src/modinfodialog.ui | 68 ++++----------------------------- src/texteditor.cpp | 102 ++++++++++++++++++++++++++++++++++++++++++++++++-- src/texteditor.h | 29 +++++++++++++- 5 files changed, 132 insertions(+), 103 deletions(-) (limited to 'src') diff --git a/src/modinfodialog.cpp b/src/modinfodialog.cpp index db5b5fd0..169623ad 100644 --- a/src/modinfodialog.cpp +++ b/src/modinfodialog.cpp @@ -361,14 +361,9 @@ ModInfoDialog::ModInfoDialog(ModInfo::Ptr modInfo, const DirectoryEntry *directo m_textFileEditor.reset(new TextEditor(ui->textFileView)); - connect( - m_textFileEditor.get(), &TextEditor::changed, - [&](bool b){ onTextFileChanged(b); }); - ui->tabTextSplitter->setSizes({200, 1}); ui->tabTextSplitter->setStretchFactor(0, 0); ui->tabTextSplitter->setStretchFactor(1, 1); - setTextFileWordWrap(true); // refresh everything but the conflict lists, which are done in exec() because // they depend on restoring the state to some widgets; this refresh has to be @@ -1092,7 +1087,6 @@ void ModInfoDialog::on_textFileList_currentItemChanged( void ModInfoDialog::openTextFile(const QString &fileName) { m_textFileEditor->load(fileName); - ui->textFileSave->setEnabled(false); } void ModInfoDialog::openIniFile(const QString &fileName) @@ -1169,26 +1163,9 @@ void ModInfoDialog::on_saveButton_clicked() saveCurrentIniFile(); } -void ModInfoDialog::on_textFileSave_clicked() -{ - saveCurrentTextFile(); -} - -void ModInfoDialog::on_textFileWordWrap_clicked() -{ - setTextFileWordWrap(!m_textFileEditor->wordWrap()); -} - -void ModInfoDialog::setTextFileWordWrap(bool b) -{ - m_textFileEditor->wordWrap(b); - ui->textFileWordWrap->setChecked(b); -} - void ModInfoDialog::saveCurrentTextFile() { m_textFileEditor->save(); - ui->textFileSave->setEnabled(false); } @@ -1211,20 +1188,12 @@ void ModInfoDialog::saveCurrentIniFile() ui->saveButton->setEnabled(false); } - void ModInfoDialog::on_iniFileView_textChanged() { QPushButton* saveButton = findChild("saveButton"); saveButton->setEnabled(true); } - -void ModInfoDialog::onTextFileChanged(bool b) -{ - ui->textFileSave->setEnabled(b); -} - - void ModInfoDialog::on_activateESP_clicked() { QListWidget *activeESPList = findChild("activeESPList"); diff --git a/src/modinfodialog.h b/src/modinfodialog.h index 85226f45..42ef990d 100644 --- a/src/modinfodialog.h +++ b/src/modinfodialog.h @@ -220,15 +220,12 @@ private slots: void on_saveButton_clicked(); void on_activateESP_clicked(); void on_deactivateESP_clicked(); - void on_textFileSave_clicked(); - void on_textFileWordWrap_clicked(); void on_visitNexusLabel_linkActivated(const QString &link); void on_modIDEdit_editingFinished(); void on_sourceGameEdit_currentIndexChanged(int); void on_versionEdit_editingFinished(); void on_customUrlLineEdit_editingFinished(); void on_iniFileView_textChanged(); - void onTextFileChanged(bool b); void on_tabWidget_currentChanged(int index); void on_primaryCategoryBox_currentIndexChanged(int index); void on_categoriesTree_itemChanged(QTreeWidgetItem *item, int column); @@ -351,8 +348,6 @@ private: std::vector createGotoActions( const QList& selection); - - void setTextFileWordWrap(bool b); }; #endif // MODINFODIALOG_H diff --git a/src/modinfodialog.ui b/src/modinfodialog.ui index 4a29f6e4..513506a7 100644 --- a/src/modinfodialog.ui +++ b/src/modinfodialog.ui @@ -46,67 +46,13 @@ A list of text-files in the mod directory like readmes. - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Save - - - - - - - Word wrap - - - true - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - - - - - - + + + + + + + diff --git a/src/texteditor.cpp b/src/texteditor.cpp index eef74246..9de2b9c1 100644 --- a/src/texteditor.cpp +++ b/src/texteditor.cpp @@ -1,15 +1,18 @@ #include "texteditor.h" #include "utility.h" +#include TextEditor::TextEditor(QPlainTextEdit* edit) - : m_edit(edit), m_dirty(false) + : m_edit(edit), m_toolbar(*this), m_dirty(false) { + setupToolbar(); + m_edit->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); wordWrap(true); QObject::connect( m_edit->document(), &QTextDocument::modificationChanged, - [&](bool b){ onChanged(b); }); + [&](bool b){ onModified(b); }); } bool TextEditor::load(const QString& filename) @@ -69,8 +72,99 @@ bool TextEditor::dirty() const return m_dirty; } -void TextEditor::onChanged(bool b) +void TextEditor::onModified(bool b) { dirty(b); - emit changed(b); + emit modified(b); +} + +void TextEditor::setupToolbar() +{ + auto* widget = wrapEditWidget(); + if (!widget) { + return; + } + + auto* layout = new QVBoxLayout(widget); + + // adding toolbar and edit + layout->addWidget(m_toolbar.widget()); + layout->addWidget(m_edit); + + // make the edit stretch + layout->setStretch(0, 0); + layout->setStretch(1, 1); + + // visuals + layout->setContentsMargins(0, 0, 0, 0); + widget->show(); +} + +QWidget* TextEditor::wrapEditWidget() +{ + auto widget = std::make_unique(); + + // wrapping the QPlainTextEdit into a new widget so the toolbar can be + // displayed above it + + if (auto* parentLayout=m_edit->parentWidget()->layout()) { + // the edit's parent has a regular layout, replace the edit by the new + // widget and delete the QLayoutItem that's returned as it's not needed + delete parentLayout->replaceWidget(m_edit, widget.get()); + } else if (auto* splitter=qobject_cast(m_edit->parentWidget())) { + // the edit's parent is a QSplitter, which doesn't have a layout; replace + // the edit by using its index in the splitter + splitter->replaceWidget(splitter->indexOf(m_edit), widget.get()); + } else { + // unknown parent + qCritical("TextEditor: cannot wrap edit widget to display a toolbar"); + return nullptr; + } + + return widget.release(); +} + + +TextEditorToolbar::TextEditorToolbar(TextEditor& editor) : + m_editor(editor), + m_widget(new QWidget), + m_save(new QAction(QObject::tr("&Save"))), + m_wordWrap(new QAction(QObject::tr("&Word wrap"))) +{ + QObject::connect(m_save, &QAction::triggered, [&]{ onSave(); }); + QObject::connect(m_wordWrap, &QAction::triggered, [&]{ onWordWrap(); }); + + auto* layout = new QHBoxLayout(m_widget); + layout->setContentsMargins(0, 0, 0, 0); + layout->setAlignment(Qt::AlignLeft); + + auto* b = new QToolButton; + b->setDefaultAction(m_save); + layout->addWidget(b); + + b = new QToolButton; + b->setDefaultAction(m_wordWrap); + layout->addWidget(b); + + QObject::connect(&m_editor, &TextEditor::modified, [&](bool b){ onTextModified(b); }); +} + +QWidget* TextEditorToolbar::widget() +{ + return m_widget; +} + +void TextEditorToolbar::onTextModified(bool b) +{ + m_save->setEnabled(b); +} + +void TextEditorToolbar::onSave() +{ + m_editor.save(); +} + +void TextEditorToolbar::onWordWrap() +{ + m_editor.wordWrap(!m_editor.wordWrap()); } diff --git a/src/texteditor.h b/src/texteditor.h index 25a15ad7..10f6c4de 100644 --- a/src/texteditor.h +++ b/src/texteditor.h @@ -3,6 +3,27 @@ #include +class TextEditor; + +class TextEditorToolbar +{ +public: + TextEditorToolbar(TextEditor& editor); + + QWidget* widget(); + +private: + TextEditor& m_editor; + QWidget* m_widget; + QAction* m_save; + QAction* m_wordWrap; + + void onTextModified(bool b); + void onSave(); + void onWordWrap(); +}; + + class TextEditor : public QObject { Q_OBJECT @@ -21,16 +42,20 @@ public: bool dirty() const; signals: - void changed(bool b); + void modified(bool b); private: QPlainTextEdit* m_edit; + TextEditorToolbar m_toolbar; QString m_filename; QString m_encoding; bool m_dirty; - void onChanged(bool b); + void onModified(bool b); void dirty(bool b); + + void setupToolbar(); + QWidget* wrapEditWidget(); }; #endif // MO_TEXTEDITOR_H -- cgit v1.3.1