File indexing completed on 2024-05-12 04:37:46
0001 /* 0002 SPDX-FileCopyrightText: 2008 Aleix Pol <aleixpol@gmail.com> 0003 SPDX-FileCopyrightText: 2009 Ramón Zarazúa <killerfox512+kde@gmail.com> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "applychangeswidget.h" 0009 0010 #include <KTextEditor/Document> 0011 0012 #include <KParts/PartLoader> 0013 #include <KParts/ReadWritePart> 0014 0015 #include <QAction> 0016 #include <QDialogButtonBox> 0017 #include <QDir> 0018 #include <QLabel> 0019 #include <QMimeType> 0020 #include <QMimeDatabase> 0021 #include <QPushButton> 0022 #include <QSplitter> 0023 #include <QTemporaryFile> 0024 #include <QTabWidget> 0025 #include <QVBoxLayout> 0026 0027 #include "coderepresentation.h" 0028 #include <interfaces/icore.h> 0029 #include <interfaces/idocumentcontroller.h> 0030 0031 namespace KDevelop { 0032 class ApplyChangesWidgetPrivate 0033 { 0034 public: 0035 0036 explicit ApplyChangesWidgetPrivate(ApplyChangesWidget* p) 0037 : parent(p) 0038 , m_index(0) {} 0039 ~ApplyChangesWidgetPrivate() 0040 { 0041 qDeleteAll(m_temps); 0042 } 0043 0044 void createEditPart(const KDevelop::IndexedString& url); 0045 0046 ApplyChangesWidget* const parent; 0047 int m_index; 0048 QList<KParts::ReadWritePart*> m_editParts; 0049 QList<QTemporaryFile*> m_temps; 0050 QList<IndexedString> m_files; 0051 QTabWidget* m_documentTabs; 0052 QLabel* m_info; 0053 }; 0054 0055 ApplyChangesWidget::ApplyChangesWidget(QWidget* parent) 0056 : QDialog(parent) 0057 , d_ptr(new ApplyChangesWidgetPrivate(this)) 0058 { 0059 Q_D(ApplyChangesWidget); 0060 0061 setSizeGripEnabled(true); 0062 0063 auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); 0064 auto mainLayout = new QVBoxLayout(this); 0065 auto okButton = buttonBox->button(QDialogButtonBox::Ok); 0066 okButton->setDefault(true); 0067 okButton->setShortcut(Qt::CTRL | Qt::Key_Return); 0068 connect(buttonBox, &QDialogButtonBox::accepted, this, &ApplyChangesWidget::accept); 0069 connect(buttonBox, &QDialogButtonBox::rejected, this, &ApplyChangesWidget::reject); 0070 0071 auto* w = new QWidget(this); 0072 d->m_info = new QLabel(w); 0073 d->m_documentTabs = new QTabWidget(w); 0074 connect(d->m_documentTabs, &QTabWidget::currentChanged, 0075 this, &ApplyChangesWidget::indexChanged); 0076 0077 auto* l = new QVBoxLayout(w); 0078 l->addWidget(d->m_info); 0079 l->addWidget(d->m_documentTabs); 0080 0081 mainLayout->addWidget(w); 0082 mainLayout->addWidget(buttonBox); 0083 0084 resize(QSize(800, 400)); 0085 } 0086 0087 ApplyChangesWidget::~ApplyChangesWidget() = default; 0088 0089 bool ApplyChangesWidget::hasDocuments() const 0090 { 0091 Q_D(const ApplyChangesWidget); 0092 0093 return d->m_editParts.size() > 0; 0094 } 0095 0096 KTextEditor::Document* ApplyChangesWidget::document() const 0097 { 0098 Q_D(const ApplyChangesWidget); 0099 0100 return qobject_cast<KTextEditor::Document*>(d->m_editParts.value(d->m_index)); 0101 } 0102 0103 void ApplyChangesWidget::setInformation(const QString& info) 0104 { 0105 Q_D(ApplyChangesWidget); 0106 0107 d->m_info->setText(info); 0108 } 0109 0110 void ApplyChangesWidget::addDocuments(const IndexedString& original) 0111 { 0112 Q_D(ApplyChangesWidget); 0113 0114 int idx = d->m_files.indexOf(original); 0115 if (idx < 0) { 0116 auto* w = new QWidget; 0117 d->m_documentTabs->addTab(w, original.str()); 0118 d->m_documentTabs->setCurrentWidget(w); 0119 0120 d->m_files.insert(d->m_index, original); 0121 d->createEditPart(original); 0122 } else { 0123 d->m_index = idx; 0124 } 0125 } 0126 0127 bool ApplyChangesWidget::applyAllChanges() 0128 { 0129 Q_D(ApplyChangesWidget); 0130 0131 /// @todo implement safeguard in case a file saving fails 0132 0133 bool ret = true; 0134 for (int i = 0; i < d->m_files.size(); ++i) 0135 if (d->m_editParts[i]->saveAs(d->m_files[i].toUrl())) { 0136 IDocument* doc = ICore::self()->documentController()->documentForUrl(d->m_files[i].toUrl()); 0137 if (doc && doc->state() == IDocument::Dirty) 0138 doc->reload(); 0139 } else 0140 ret = false; 0141 0142 return ret; 0143 } 0144 } 0145 0146 namespace KDevelop { 0147 void ApplyChangesWidgetPrivate::createEditPart(const IndexedString& file) 0148 { 0149 QWidget* widget = m_documentTabs->currentWidget(); 0150 Q_ASSERT(widget); 0151 0152 auto* m = new QVBoxLayout(widget); 0153 auto* v = new QSplitter(widget); 0154 m->addWidget(v); 0155 0156 QUrl url = file.toUrl(); 0157 0158 QMimeType mimetype = QMimeDatabase().mimeTypeForUrl(url); 0159 0160 auto* part = 0161 KParts::PartLoader::createPartInstanceForMimeType<KParts::ReadWritePart>(mimetype.name(), widget, widget); 0162 auto* document = qobject_cast<KTextEditor::Document*>(part); 0163 Q_ASSERT(document); 0164 0165 Q_ASSERT(document->action("file_save")); 0166 document->action("file_save")->setEnabled(false); 0167 0168 m_editParts.insert(m_index, part); 0169 0170 //Open the best code representation, even if it is artificial 0171 CodeRepresentation::Ptr repr = createCodeRepresentation(file); 0172 if (!repr->fileExists()) { 0173 const QString templateName = QDir::tempPath() + QLatin1Char('/') + 0174 url.fileName().split(QLatin1Char('.')).last(); 0175 auto* temp(new QTemporaryFile(templateName)); 0176 temp->open(); 0177 temp->write(repr->text().toUtf8()); 0178 temp->close(); 0179 0180 url = QUrl::fromLocalFile(temp->fileName()); 0181 0182 m_temps << temp; 0183 } 0184 m_editParts[m_index]->openUrl(url); 0185 0186 v->addWidget(m_editParts[m_index]->widget()); 0187 v->setSizes(QList<int> {400, 100}); 0188 } 0189 0190 void ApplyChangesWidget::indexChanged(int newIndex) 0191 { 0192 Q_D(ApplyChangesWidget); 0193 0194 Q_ASSERT(newIndex != -1); 0195 d->m_index = newIndex; 0196 } 0197 0198 void ApplyChangesWidget::updateDiffView(int index) 0199 { 0200 Q_D(ApplyChangesWidget); 0201 0202 d->m_index = index == -1 ? d->m_index : index; 0203 } 0204 } 0205 0206 #include "moc_applychangeswidget.cpp"