1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
11 ** Licensees holding valid Qt Commercial licenses may use this file in
12 ** accordance with the Qt Commercial License Agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and Nokia.
16 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** If you are unsure which license is appropriate for your use, please
26 ** contact the sales department at http://qt.nokia.com/contact.
28 **************************************************************************/
30 #include "profileeditor.h"
32 #include "profilehighlighter.h"
33 #include "qt4projectmanager.h"
34 #include "qt4projectmanagerconstants.h"
35 #include "profileeditorfactory.h"
36 #include "addlibrarywizard.h"
38 #include <coreplugin/icore.h>
39 #include <coreplugin/actionmanager/actionmanager.h>
40 #include <coreplugin/uniqueidmanager.h>
41 #include <coreplugin/actionmanager/actioncontainer.h>
42 #include <texteditor/fontsettings.h>
43 #include <texteditor/texteditoractionhandler.h>
44 #include <texteditor/texteditorconstants.h>
45 #include <texteditor/texteditorsettings.h>
47 #include <QtCore/QFileInfo>
48 #include <QtCore/QDir>
49 #include <QtGui/QMenu>
51 using namespace Qt4ProjectManager;
52 using namespace Qt4ProjectManager::Internal;
55 // ProFileEditorEditable
58 ProFileEditorEditable::ProFileEditorEditable(ProFileEditor *editor)
59 : BaseTextEditorEditable(editor),
60 m_context(Qt4ProjectManager::Constants::C_PROFILEEDITOR,
61 TextEditor::Constants::C_TEXTEDITOR)
63 // m_contexts << uidm->uniqueIdentifier(Qt4ProjectManager::Constants::PROJECT_KIND);
66 Core::Context ProFileEditorEditable::context() const
71 Core::IEditor *ProFileEditorEditable::duplicate(QWidget *parent)
73 ProFileEditor *ret = new ProFileEditor(parent, qobject_cast<ProFileEditor*>(editor())->factory(),
74 qobject_cast<ProFileEditor*>(editor())->actionHandler());
75 ret->duplicateFrom(editor());
76 TextEditor::TextEditorSettings::instance()->initializeEditor(ret);
77 return ret->editableInterface();
80 QString ProFileEditorEditable::id() const
82 return QLatin1String(Qt4ProjectManager::Constants::PROFILE_EDITOR_ID);
86 // ProFileEditorEditor
89 ProFileEditor::ProFileEditor(QWidget *parent, ProFileEditorFactory *factory, TextEditor::TextEditorActionHandler *ah)
90 : BaseTextEditor(parent), m_factory(factory), m_ah(ah)
92 ProFileDocument *doc = new ProFileDocument();
93 doc->setMimeType(QLatin1String(Qt4ProjectManager::Constants::PROFILE_MIMETYPE));
94 setBaseTextDocument(doc);
96 ah->setupActions(this);
98 baseTextDocument()->setSyntaxHighlighter(new ProFileHighlighter);
99 m_commentDefinition.clearCommentStyles();
100 m_commentDefinition.setSingleLine(QString(QLatin1Char('#')));
103 ProFileEditor::~ProFileEditor()
107 void ProFileEditor::unCommentSelection()
109 Utils::unCommentSelection(this, m_commentDefinition);
112 static bool isValidFileNameChar(const QChar &c)
114 if (c.isLetterOrNumber()
115 || c == QLatin1Char('.')
116 || c == QLatin1Char('_')
117 || c == QLatin1Char('-')
118 || c == QLatin1Char('/')
119 || c == QLatin1Char('\\'))
124 ProFileEditor::Link ProFileEditor::findLinkAt(const QTextCursor &cursor,
125 bool /* resolveTarget */)
129 int lineNumber = 0, positionInBlock = 0;
130 convertPosition(cursor.position(), &lineNumber, &positionInBlock);
132 const QString block = cursor.block().text();
134 // check if the current position is commented out
135 const int hashPos = block.indexOf(QLatin1Char('#'));
136 if (hashPos >= 0 && hashPos < positionInBlock)
139 // find the beginning of a filename
141 int beginPos = positionInBlock - 1;
142 while (beginPos >= 0) {
143 QChar c = block.at(beginPos);
144 if (isValidFileNameChar(c)) {
152 // find the end of a filename
153 int endPos = positionInBlock;
154 while (endPos < block.count()) {
155 QChar c = block.at(endPos);
156 if (isValidFileNameChar(c)) {
164 if (buffer.isEmpty())
167 // remove trailing '\' since it can be line continuation char
168 if (buffer.at(buffer.size() - 1) == QLatin1Char('\\')) {
173 // if the buffer starts with $$PWD accept it
174 if (buffer.startsWith(QLatin1String("PWD/")) ||
175 buffer.startsWith(QLatin1String("PWD\\"))) {
176 if (beginPos > 0 && block.mid(beginPos - 1, 2) == QLatin1String("$$")) {
178 buffer = buffer.mid(4);
182 QDir dir(QFileInfo(file()->fileName()).absolutePath());
183 QString fileName = dir.filePath(buffer);
184 QFileInfo fi(fileName);
187 QDir subDir(fi.absoluteFilePath());
188 QString subProject = subDir.filePath(subDir.dirName() + QLatin1String(".pro"));
189 if (QFileInfo(subProject).exists())
190 fileName = subProject;
194 link.fileName = fileName;
195 link.begin = cursor.position() - positionInBlock + beginPos + 1;
196 link.end = cursor.position() - positionInBlock + endPos;
201 TextEditor::BaseTextEditorEditable *ProFileEditor::createEditableInterface()
203 return new ProFileEditorEditable(this);
206 void ProFileEditor::contextMenuEvent(QContextMenuEvent *e)
208 QMenu *menu = new QMenu();
210 Core::ActionManager *am = Core::ICore::instance()->actionManager();
211 Core::ActionContainer *mcontext = am->actionContainer(Qt4ProjectManager::Constants::M_CONTEXT);
212 QMenu *contextMenu = mcontext->menu();
214 foreach (QAction *action, contextMenu->actions())
215 menu->addAction(action);
217 appendStandardContextMenuActions(menu);
219 menu->exec(e->globalPos());
223 void ProFileEditor::setFontSettings(const TextEditor::FontSettings &fs)
225 TextEditor::BaseTextEditor::setFontSettings(fs);
226 ProFileHighlighter *highlighter = qobject_cast<ProFileHighlighter*>(baseTextDocument()->syntaxHighlighter());
230 static QVector<QString> categories;
231 if (categories.isEmpty()) {
232 categories << QLatin1String(TextEditor::Constants::C_TYPE)
233 << QLatin1String(TextEditor::Constants::C_KEYWORD)
234 << QLatin1String(TextEditor::Constants::C_COMMENT)
235 << QLatin1String(TextEditor::Constants::C_VISUAL_WHITESPACE);
238 const QVector<QTextCharFormat> formats = fs.toTextCharFormats(categories);
239 highlighter->setFormats(formats.constBegin(), formats.constEnd());
240 highlighter->rehighlight();
243 void ProFileEditor::addLibrary()
245 AddLibraryWizard wizard(file()->fileName(), this);
246 if (wizard.exec() != QDialog::Accepted)
249 TextEditor::BaseTextEditorEditable *editable = editableInterface();
250 const int endOfDoc = editable->position(TextEditor::ITextEditor::EndOfDoc);
251 editable->setCurPos(endOfDoc);
252 QString snippet = wizard.snippet();
254 // add extra \n in case the last line is not empty
256 editable->convertPosition(endOfDoc, &line, &column);
257 if (!editable->textAt(endOfDoc - column, column).simplified().isEmpty())
258 snippet = QLatin1Char('\n') + snippet;
260 editable->insert(snippet);
263 void ProFileEditor::jumpToFile()
265 openLink(findLinkAt(textCursor()));
272 ProFileDocument::ProFileDocument()
273 : TextEditor::BaseTextDocument()
277 QString ProFileDocument::defaultPath() const
279 QFileInfo fi(fileName());
280 return fi.absolutePath();
283 QString ProFileDocument::suggestedFileName() const
285 QFileInfo fi(fileName());
286 return fi.fileName();