File indexing completed on 2024-04-21 15:24:34
0001 /* 0002 SPDX-FileCopyrightText: 2013 Sven Brauch <svenbrauch@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0005 */ 0006 0007 #include "docfilemanagerwidget.h" 0008 #include "kcm_docfiles.h" 0009 #include "docfilewizard.h" 0010 #include <interfaces/idocumentcontroller.h> 0011 #include <interfaces/icore.h> 0012 0013 #include <QBoxLayout> 0014 #include <QFileSystemModel> 0015 #include <QDialogButtonBox> 0016 #include <QTreeView> 0017 #include <QPushButton> 0018 #include <QSplitter> 0019 #include <QLabel> 0020 #include <QTextEdit> 0021 #include <QUrl> 0022 #include <QDebug> 0023 #include <QTemporaryFile> 0024 #include <QStandardPaths> 0025 #include <QDesktopServices> 0026 #include <QIcon> 0027 0028 #include <KMessageBox> 0029 #include <KLocalizedString> 0030 #include <KTextEditor/Document> 0031 0032 DocfileManagerWidget::DocfileManagerWidget(QWidget* parent) 0033 : QWidget(parent) 0034 { 0035 QString dir = docfilePath(); 0036 if ( dir.isEmpty() ) { 0037 KMessageBox::error(this, i18n("Failed to find a valid data directory for kdevpythonsupport.")); 0038 return; 0039 } 0040 0041 // construct the tree view which displays the currently installed files 0042 QFileSystemModel* model = new QFileSystemModel(this); 0043 model->setRootPath(dir); 0044 filesTreeView = new QTreeView; 0045 filesTreeView->setSelectionMode(QAbstractItemView::MultiSelection); 0046 filesTreeView->setModel(model); 0047 filesTreeView->setRootIndex(model->index(dir)); 0048 0049 // construct the buttons for up/download 0050 QVBoxLayout* buttonsLayout = new QVBoxLayout; 0051 QPushButton* generateButton = new QPushButton(i18n("Generate...")); 0052 generateButton->setIcon(QIcon::fromTheme("tools-wizard")); 0053 QPushButton* importButton = new QPushButton(i18n("Import From Editor")); 0054 importButton->setToolTip(i18n("Copy the contents of the active editor window " 0055 "to a new file in the documentation directory")); 0056 buttonsLayout->addWidget(generateButton); 0057 buttonsLayout->addWidget(importButton); 0058 QObject::connect(generateButton, &QAbstractButton::clicked, this, &DocfileManagerWidget::runWizard); 0059 QObject::connect(importButton, &QAbstractButton::clicked, this, &DocfileManagerWidget::copyEditorContents); 0060 0061 // construct the buttons for the remaining actions 0062 QFrame* separator = new QFrame(); 0063 separator->setFrameShape(QFrame::HLine); 0064 QFrame* separator2 = new QFrame(); 0065 separator2->setFrameShape(QFrame::HLine); 0066 QPushButton* openFileManagerButton = new QPushButton(i18n("Open File Manager")); 0067 openFileManagerButton->setIcon(QIcon::fromTheme(QStringLiteral("system-file-manager"))); 0068 QPushButton* openTextEditorButton = new QPushButton(i18nc("Edit selected files", "Edit Selected")); 0069 openTextEditorButton->setIcon(QIcon::fromTheme(QStringLiteral("document-edit"))); 0070 QPushButton* searchPathsButton = new QPushButton(i18n("Search Paths...")); 0071 searchPathsButton->setIcon(QIcon::fromTheme(QStringLiteral("search"))); 0072 buttonsLayout->addWidget(separator); 0073 buttonsLayout->addWidget(openFileManagerButton); 0074 buttonsLayout->addWidget(openTextEditorButton); 0075 buttonsLayout->addWidget(separator2); 0076 buttonsLayout->addWidget(searchPathsButton); 0077 QObject::connect(openFileManagerButton, &QAbstractButton::clicked, this, &DocfileManagerWidget::openDocfilePath); 0078 QObject::connect(openTextEditorButton, &QAbstractButton::clicked, this, &DocfileManagerWidget::openSelectedInTextEditor); 0079 QObject::connect(searchPathsButton, &QAbstractButton::clicked, this, &DocfileManagerWidget::showSearchPaths); 0080 0081 buttonsLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Expanding)); 0082 0083 // arrange the results nicely around a splitter 0084 QSplitter* splitter = new QSplitter; 0085 QWidget* w = new QWidget; 0086 w->setLayout(buttonsLayout); 0087 splitter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); 0088 splitter->addWidget(filesTreeView); 0089 splitter->addWidget(w); 0090 splitter->setSizes(QList<int>() << 800 << 100); 0091 0092 setLayout(new QVBoxLayout); 0093 layout()->addWidget(splitter); 0094 layout()->setContentsMargins(0, 0, 0, 0); 0095 } 0096 0097 void DocfileManagerWidget::showSearchPaths() 0098 { 0099 QStringList dirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, "kdevpythonsupport/documentation_files", QStandardPaths::LocateDirectory); 0100 QLabel* dirsMessageLabel = new QLabel(i18nc("displays a list of search paths below", 0101 "Paths searched for documentation by kdev-python (in this order):")); 0102 QTextEdit* paths = new QTextEdit; 0103 paths->setPlainText(dirs.join("\n")); 0104 paths->setReadOnly(true); 0105 0106 QDialog* message = new QDialog(this); 0107 message->setLayout(new QVBoxLayout); 0108 message->layout()->addWidget(dirsMessageLabel); 0109 message->layout()->addWidget(paths); 0110 QWidget* closeWidget = new QWidget; 0111 QPushButton* closeButton = new QPushButton("Close"); 0112 closeWidget->setLayout(new QHBoxLayout); 0113 closeWidget->layout()->addItem(new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Expanding)); 0114 closeWidget->layout()->addWidget(closeButton); 0115 message->layout()->addWidget(closeWidget); 0116 0117 QObject::connect(closeButton, &QAbstractButton::clicked, message, &QWidget::close); 0118 message->resize(600, 200); 0119 message->exec(); 0120 } 0121 0122 void DocfileManagerWidget::openDocfilePath() 0123 { 0124 if ( QDir(docfilePath()).exists() ) { 0125 QDesktopServices::openUrl(QUrl::fromLocalFile(docfilePath())); 0126 } 0127 } 0128 0129 void DocfileManagerWidget::copyEditorContents() 0130 { 0131 KDevelop::IDocumentController* documentController = KDevelop::ICore::self()->documentController(); 0132 if ( documentController->activeDocument() ) { 0133 if ( KTextEditor::Document* doc = documentController->activeDocument()->textDocument() ) { 0134 auto dialog = new QDialog(this); 0135 auto buttonbox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, dialog); 0136 connect(buttonbox->button(QDialogButtonBox::Ok), &QPushButton::clicked, 0137 dialog, &QDialog::accept); 0138 connect(buttonbox->button(QDialogButtonBox::Cancel), &QPushButton::clicked, 0139 dialog, &QDialog::reject); 0140 dialog->setLayout(new QVBoxLayout); 0141 dialog->layout()->addWidget(new QLabel(i18n("Enter a relative target path to copy %1 to:", doc->url().path()))); 0142 QLineEdit* lineEdit = new QLineEdit; 0143 lineEdit->setText(doc->documentName()); 0144 dialog->layout()->addWidget(lineEdit); 0145 dialog->layout()->addWidget(new QLabel(i18n("This path must match what you use in Python to import " 0146 "this module. For example, enter \"numpy/fft.py\" for numpy.fft"))); 0147 dialog->layout()->addWidget(new QLabel(i18n("After copying, you will be editing the new document."))); 0148 dialog->layout()->addWidget(buttonbox); 0149 if ( dialog->exec() == QDialog::Accepted ) { 0150 auto target = QUrl::fromLocalFile(docfilePath() + "/" + lineEdit->text()); 0151 // TODO QUrl: cleanPath? 0152 QDir d(target.url()); 0153 if ( ! d.exists() ) { 0154 d.mkpath(d.absolutePath()); 0155 } 0156 doc->saveAs(target); 0157 } 0158 } 0159 } 0160 } 0161 0162 void DocfileManagerWidget::openSelectedInTextEditor() 0163 { 0164 const QList<QUrl> selected = selectedItems(); 0165 if ( selected.isEmpty() ) { 0166 KMessageBox::information(this, i18n("Please select at least one file from the list for editing.")); 0167 } 0168 foreach ( const QUrl& item, selected ) { 0169 KDevelop::ICore::self()->documentController()->openDocument(item); 0170 } 0171 } 0172 0173 QString DocfileManagerWidget::docfilePath() 0174 { 0175 // finds a local directory which is contained in the dirs searched by the parser, code 0176 // and creates it if it doesn't exist 0177 QString path = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/" + "kdevpythonsupport/documentation_files/"; 0178 QDir dir(path); 0179 dir.mkpath(path); 0180 return path; 0181 } 0182 0183 const QList<QUrl> DocfileManagerWidget::selectedItems() const 0184 { 0185 const QModelIndexList items = filesTreeView->selectionModel()->selectedRows(); 0186 QList<QUrl> urls; 0187 const QFileSystemModel* fsmodel = qobject_cast<QFileSystemModel*>(filesTreeView->model()); 0188 foreach ( const QModelIndex& index, items ) { 0189 urls << QUrl::fromLocalFile(fsmodel->filePath(index)); 0190 } 0191 return urls; 0192 } 0193 0194 void DocfileManagerWidget::runWizard() 0195 { 0196 DocfileWizard wizard(docfilePath(), this); 0197 wizard.exec(); 0198 } 0199 0200 #include "moc_docfilemanagerwidget.cpp"