File indexing completed on 2024-04-28 05:49:36
0001 /* 0002 SPDX-FileCopyrightText: 2022 Christoph Cullmann <cullmann@kde.org> 0003 SPDX-FileCopyrightText: 2022 Waqar Ahmed <waqar.17a@gmail.com> 0004 SPDX-License-Identifier: MIT 0005 */ 0006 0007 #include "ktexteditor_utils.h" 0008 #include "diagnostics/diagnosticview.h" 0009 #include "diffwidget.h" 0010 0011 #include <QDir> 0012 #include <QFontDatabase> 0013 #include <QIcon> 0014 #include <QMimeDatabase> 0015 #include <QPointer> 0016 #include <QScrollBar> 0017 #include <QVariant> 0018 0019 #include <KActionCollection> 0020 #include <KLocalizedString> 0021 #include <KTextEditor/Application> 0022 #include <KTextEditor/Editor> 0023 #include <KTextEditor/MainWindow> 0024 #include <KTextEditor/Plugin> 0025 #include <KTextEditor/View> 0026 #include <KXMLGUIFactory> 0027 0028 namespace Utils 0029 { 0030 0031 class KateScrollBarRestorerPrivate 0032 { 0033 public: 0034 explicit KateScrollBarRestorerPrivate(KTextEditor::View *view) 0035 { 0036 // Find KateScrollBar 0037 const auto scrollBars = view->findChildren<QScrollBar *>(); 0038 kateScrollBar = [scrollBars] { 0039 for (auto scrollBar : scrollBars) { 0040 if (qstrcmp(scrollBar->metaObject()->className(), "KateScrollBar") == 0) { 0041 return scrollBar; 0042 } 0043 } 0044 return static_cast<QScrollBar *>(nullptr); 0045 }(); 0046 0047 if (kateScrollBar) { 0048 oldScrollValue = kateScrollBar->value(); 0049 } 0050 } 0051 0052 void restore() 0053 { 0054 if (restored) { 0055 return; 0056 } 0057 0058 if (kateScrollBar) { 0059 kateScrollBar->setValue(oldScrollValue); 0060 } 0061 restored = true; 0062 } 0063 0064 ~KateScrollBarRestorerPrivate() 0065 { 0066 restore(); 0067 } 0068 0069 private: 0070 QPointer<QScrollBar> kateScrollBar = nullptr; 0071 int oldScrollValue = 0; 0072 bool restored = false; 0073 }; 0074 0075 KateScrollBarRestorer::KateScrollBarRestorer(KTextEditor::View *view) 0076 : d(new KateScrollBarRestorerPrivate(view)) 0077 { 0078 } 0079 0080 void KateScrollBarRestorer::restore() 0081 { 0082 d->restore(); 0083 } 0084 0085 KateScrollBarRestorer::~KateScrollBarRestorer() 0086 { 0087 delete d; 0088 } 0089 0090 QFont editorFont() 0091 { 0092 if (KTextEditor::Editor::instance()) { 0093 return KTextEditor::Editor::instance()->font(); 0094 } 0095 qWarning() << __func__ << "Editor::instance() is null! falling back to system fixed font"; 0096 return QFontDatabase::systemFont(QFontDatabase::FixedFont); 0097 } 0098 0099 KATE_PRIVATE_EXPORT KTextEditor::Range getVisibleRange(KTextEditor::View *view) 0100 { 0101 Q_ASSERT(view); 0102 auto doc = view->document(); 0103 auto first = view->firstDisplayedLine(); 0104 auto last = view->lastDisplayedLine(); 0105 auto lastLineLen = doc->line(last).size(); 0106 return KTextEditor::Range(first, 0, last, lastLineLen); 0107 } 0108 0109 QIcon iconForDocument(KTextEditor::Document *doc) 0110 { 0111 // simple modified indicator if modified 0112 QIcon icon; 0113 if (doc->isModified()) { 0114 icon = QIcon::fromTheme(QStringLiteral("modified")); 0115 } 0116 0117 // else mime-type icon 0118 else { 0119 icon = QIcon::fromTheme(QMimeDatabase().mimeTypeForName(doc->mimeType()).iconName()); 0120 } 0121 0122 // ensure we always have a valid icon 0123 if (icon.isNull()) { 0124 icon = QIcon::fromTheme(QStringLiteral("text-plain")); 0125 } 0126 return icon; 0127 } 0128 0129 QAction *toolviewShowAction(KTextEditor::MainWindow *mainWindow, const QString &toolviewName) 0130 { 0131 Q_ASSERT(mainWindow); 0132 0133 const auto clients = mainWindow->guiFactory()->clients(); 0134 static const QString prefix = QStringLiteral("kate_mdi_toolview_"); 0135 auto it = std::find_if(clients.begin(), clients.end(), [](const KXMLGUIClient *c) { 0136 return c->componentName() == QStringLiteral("toolviewmanager"); 0137 }); 0138 0139 if (it == clients.end()) { 0140 qWarning() << Q_FUNC_INFO << "Unexpected unable to find toolviewmanager KXMLGUIClient, toolviewName: " << toolviewName; 0141 return nullptr; 0142 } 0143 return (*it)->actionCollection()->action(prefix + toolviewName); 0144 } 0145 0146 QWidget *toolviewForName(KTextEditor::MainWindow *mainWindow, const QString &toolviewName) 0147 { 0148 QWidget *toolView = nullptr; 0149 QMetaObject::invokeMethod(mainWindow->parent(), "toolviewForName", Qt::DirectConnection, Q_RETURN_ARG(QWidget *, toolView), Q_ARG(QString, toolviewName)); 0150 return toolView; 0151 } 0152 0153 void showMessage(const QString &message, const QIcon &icon, const QString &category, MessageType type, KTextEditor::MainWindow *mainWindow) 0154 { 0155 Q_ASSERT(type >= MessageType::Log && type <= MessageType::Error); 0156 QVariantMap msg; 0157 static const QString msgToString[] = { 0158 QStringLiteral("Log"), 0159 QStringLiteral("Info"), 0160 QStringLiteral("Warning"), 0161 QStringLiteral("Error"), 0162 }; 0163 msg.insert(QStringLiteral("type"), msgToString[type]); 0164 msg.insert(QStringLiteral("category"), category); 0165 msg.insert(QStringLiteral("categoryIcon"), icon); 0166 msg.insert(QStringLiteral("text"), message); 0167 showMessage(msg, mainWindow); 0168 } 0169 0170 void showMessage(const QVariantMap &map, KTextEditor::MainWindow *mainWindow) 0171 { 0172 if (!mainWindow) { 0173 mainWindow = KTextEditor::Editor::instance()->application()->activeMainWindow(); 0174 } 0175 QMetaObject::invokeMethod(mainWindow->parent(), "showMessage", Qt::DirectConnection, Q_ARG(QVariantMap, map)); 0176 } 0177 0178 void showDiff(const QByteArray &diff, const DiffParams ¶ms, KTextEditor::MainWindow *mainWindow) 0179 { 0180 DiffWidgetManager::openDiff(diff, params, mainWindow); 0181 } 0182 0183 void addWidget(QWidget *widget, KTextEditor::MainWindow *mainWindow) 0184 { 0185 QMetaObject::invokeMethod(mainWindow->parent(), "addWidget", Qt::DirectConnection, Q_ARG(QWidget *, widget)); 0186 } 0187 0188 void activateWidget(QWidget *widget, KTextEditor::MainWindow *mainWindow) 0189 { 0190 QMetaObject::invokeMethod(mainWindow->parent(), "activateWidget", Qt::DirectConnection, Q_ARG(QWidget *, widget)); 0191 } 0192 0193 QWidgetList widgets(KTextEditor::MainWindow *mainWindow) 0194 { 0195 QWidgetList ret; 0196 QMetaObject::invokeMethod(mainWindow->parent(), "widgets", Qt::DirectConnection, Q_RETURN_ARG(QWidgetList, ret)); 0197 return ret; 0198 } 0199 0200 void insertWidgetInStatusbar(QWidget *widget, KTextEditor::MainWindow *mainWindow) 0201 { 0202 QMetaObject::invokeMethod(mainWindow->parent(), "insertWidgetInStatusbar", Qt::DirectConnection, Q_ARG(QWidget *, widget)); 0203 } 0204 0205 void addPositionToHistory(const QUrl &url, KTextEditor::Cursor c, KTextEditor::MainWindow *mainWindow) 0206 { 0207 QMetaObject::invokeMethod(mainWindow->parent(), "addPositionToHistory", Qt::DirectConnection, Q_ARG(QUrl, url), Q_ARG(KTextEditor::Cursor, c)); 0208 } 0209 0210 QString projectBaseDirForDocument(KTextEditor::Document *doc) 0211 { 0212 QString baseDir; 0213 if (QObject *plugin = KTextEditor::Editor::instance()->application()->plugin(QStringLiteral("kateprojectplugin"))) { 0214 QMetaObject::invokeMethod(plugin, "projectBaseDirForDocument", Q_RETURN_ARG(QString, baseDir), Q_ARG(KTextEditor::Document *, doc)); 0215 } 0216 return baseDir; 0217 } 0218 0219 QVariantMap projectMapForDocument(KTextEditor::Document *doc) 0220 { 0221 QVariantMap projectMap; 0222 if (QObject *plugin = KTextEditor::Editor::instance()->application()->plugin(QStringLiteral("kateprojectplugin"))) { 0223 QMetaObject::invokeMethod(plugin, "projectMapForDocument", Q_RETURN_ARG(QVariantMap, projectMap), Q_ARG(KTextEditor::Document *, doc)); 0224 } 0225 return projectMap; 0226 } 0227 0228 QString niceFileNameWithPath(const QUrl &url) 0229 { 0230 // we want some filename @ folder output to have chance to keep important stuff even on elide 0231 if (url.isLocalFile()) { 0232 // perhaps shorten the path 0233 const QString homePath = QDir::homePath(); 0234 QString path = url.toString(QUrl::RemoveFilename | QUrl::PreferLocalFile | QUrl::StripTrailingSlash); 0235 if (path.startsWith(homePath)) { 0236 path = QLatin1String("~") + path.right(path.length() - homePath.length()); 0237 } 0238 return url.fileName() + QStringLiteral(" @ ") + path; 0239 } 0240 return url.toDisplayString(); 0241 } 0242 }