diff --git a/src/abbreviationmanager.cpp b/src/abbreviationmanager.cpp index 77c7a2da..f0486584 100644 --- a/src/abbreviationmanager.cpp +++ b/src/abbreviationmanager.cpp @@ -1,179 +1,179 @@ /******************************************************************************** * Copyright (C) 2007 by Holger Danielsson (holger.danielsson@versanet.de) * * 2008 - 2010 by Michel Ludwig (michel.ludwig@kdemail.net) * *********************************************************************************/ /************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "abbreviationmanager.h" #include -#include #include "codecompletion.h" #include "kileinfo.h" +#include "utilities.h" namespace KileAbbreviation { Manager::Manager(KileInfo* kileInfo, QObject *parent) : QObject(parent), m_kileInfo(kileInfo), m_abbreviationsDirty(false) { setObjectName("KileAbbreviation::Manager"); - m_localAbbreviationFile = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + '/' + "complete/abbreviation/" + "kile-abbrevs.cwl"; + m_localAbbreviationFile = KileUtilities::writableLocation(QStandardPaths::AppDataLocation) + '/' + "complete/abbreviation/" + "kile-abbrevs.cwl"; QDir testDir(m_localAbbreviationFile); if (!testDir.exists()) { testDir.mkpath(m_localAbbreviationFile); } } Manager::~Manager() { } const AbbreviationMap& Manager::getAbbreviationMap() { return m_abbreviationMap; } void Manager::updateLocalAbbreviation(const QString& text, const QString& replacement) { if(text.isEmpty() || replacement.isEmpty()) { return; } AbbreviationMap::iterator it = m_abbreviationMap.find(text); if(it != m_abbreviationMap.end()) { StringBooleanPair pair = it.value(); if(pair.first == replacement) { return; } m_abbreviationMap.erase(it); } m_abbreviationMap[text] = createLocalAbbreviationPair(replacement); m_abbreviationsDirty = true; emit(abbreviationsChanged()); } void Manager::removeLocalAbbreviation(const QString& text) { AbbreviationMap::iterator it = m_abbreviationMap.find(text); if(it == m_abbreviationMap.end()) { return; } StringBooleanPair pair = it.value(); if(isLocalAbbreviation(pair)) { m_abbreviationMap.erase(it); m_abbreviationsDirty = true; } emit(abbreviationsChanged()); } void Manager::readAbbreviationFiles() { if(m_abbreviationsDirty) { saveLocalAbbreviations(); } m_abbreviationMap.clear(); QStringList list = m_kileInfo->codeCompletionManager()->readCWLFiles(KileConfig::completeAbbrev(), "abbreviation"); addAbbreviationListToMap(list, true); // read local wordlist list = m_kileInfo->codeCompletionManager()->readCWLFile(m_localAbbreviationFile, true); addAbbreviationListToMap(list, false); emit(abbreviationsChanged()); } void Manager::saveLocalAbbreviations() { if(!m_abbreviationsDirty) { return; } KILE_DEBUG_MAIN; // create the file QFile abbreviationFile(m_localAbbreviationFile); if(!abbreviationFile.open(QIODevice::WriteOnly)) { KMessageBox::error(m_kileInfo->mainWindow(), i18n("Could not save the local abbreviation list.\nError code %1.", QString::number(abbreviationFile.error())), i18n("Saving Problem")); return; } QTextStream stream(&abbreviationFile); stream << "# abbreviation mode: editable abbreviations\n"; //QTextCodec *codec = QTextCodec::codecForName(m_ki->activeTextDocument()->encoding().ascii()); // stream.setCodec(codec); for(AbbreviationMap::iterator i = m_abbreviationMap.begin(); i != m_abbreviationMap.end(); ++i) { StringBooleanPair pair = i.value(); if(!pair.second) { stream << QString(i.key()).replace('=', "\\=") << '=' << pair.first << '\n'; } } abbreviationFile.close(); m_abbreviationsDirty = false; } void Manager::addAbbreviationListToMap(const QStringList& list, bool global) { // a '=' symbol in the left-hand side is encoded by '\=' for(QStringList::const_iterator i = list.begin(); i != list.end(); ++i) { QString entry = *i; int delimiter = entry.indexOf(QRegExp("[^\\\\]=")); if(delimiter < 0) { continue; } QString left = entry.left(delimiter + 1); // [^\\\\]= has length 2. left.replace("\\=", "="); QString right = entry.mid(delimiter + 2); // [^\\\\]= has length 2. if(right.isEmpty()) { continue; } m_abbreviationMap[left] = StringBooleanPair(right, global); } } QStringList Manager::getAbbreviationTextMatches(const QString& text) const { QStringList toReturn; for(AbbreviationMap::const_iterator i = m_abbreviationMap.begin(); i != m_abbreviationMap.end(); ++i) { if(i.key().startsWith(text)) { toReturn.append(i.value().first); } } return toReturn; } QString Manager::getAbbreviationTextMatch(const QString& text) const { return m_abbreviationMap[text].first; } bool Manager::abbreviationStartsWith(const QString& text) const { for(AbbreviationMap::const_iterator i = m_abbreviationMap.begin(); i != m_abbreviationMap.end(); ++i) { if(i.key().startsWith(text)) { return true; } } return false; } bool Manager::isAbbreviationDefined(const QString& text) const { return m_abbreviationMap.find(text) != m_abbreviationMap.end(); } } diff --git a/src/codecompletion.cpp b/src/codecompletion.cpp index 871ec06c..eec9dfe2 100644 --- a/src/codecompletion.cpp +++ b/src/codecompletion.cpp @@ -1,1150 +1,1150 @@ /********************************************************************************************** Copyright (C) 2004-2007 by Holger Danielsson (holger.danielsson@versanet.de) 2008-2016 by Michel Ludwig (michel.ludwig@kdemail.net) ***********************************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "codecompletion.h" #include #include #include #include -#include #include #include #include #include #include "kiledebug.h" #include "abbreviationmanager.h" #include "documentinfo.h" #include "editorextension.h" #include "kiledocmanager.h" #include "kileinfo.h" #include "kileviewmanager.h" #include "kileconfig.h" +#include "utilities.h" namespace KileCodeCompletion { LaTeXCompletionModel::LaTeXCompletionModel(QObject *parent, KileCodeCompletion::Manager *manager, KileDocument::EditorExtension *editorExtension) : KTextEditor::CodeCompletionModel(parent), m_codeCompletionManager(manager), m_editorExtension(editorExtension), m_currentView(Q_NULLPTR) { setHasGroups(false); } LaTeXCompletionModel::~LaTeXCompletionModel() { } void LaTeXCompletionModel::completionInvoked(KTextEditor::View *view, const KTextEditor::Range &range, InvocationType invocationType) { if(!range.isValid() || (invocationType == AutomaticInvocation && !KileConfig::completeAuto())) { beginResetModel(); m_completionList.clear(); endResetModel(); return; } Q_UNUSED(invocationType); m_currentView = view; KILE_DEBUG_CODECOMPLETION << "building model..."; buildModel(view, range); } KTextEditor::Range LaTeXCompletionModel::updateCompletionRange(KTextEditor::View *view, const KTextEditor::Range &range) { KILE_DEBUG_CODECOMPLETION << "updating model..." << view << range; KTextEditor::Range newRange = completionRange(view, view->cursorPosition()); if(newRange.isValid()) { buildModel(view, newRange); } return newRange; } static inline bool isSpecialLaTeXCommandCharacter(const QChar& c) { return (c == '{' || c == '[' || c == '*' || c == ']' || c == '}'); } static inline int specialLaTeXCommandCharacterOrdering(const QChar& c) { switch(c.unicode()) { case '{': return 1; case '[': return 2; case ']': return 3; case '}': return 4; case '*': return 5; default: // does nothing break; } return 4; // must be 'isLetterOrNumber()' now } static bool laTeXCommandLessThan(const QString& s1, const QString& s2) { for(int i = 0; i < s1.length(); ++i) { if(i >= s2.length()) { return false; } const QChar c1 = s1.at(i); const QChar c2 = s2.at(i); if(c1 == c2) { continue; } if(c1.isLetterOrNumber()) { if(isSpecialLaTeXCommandCharacter(c2)) { return false; } else { return (c1 < c2); } } else if(isSpecialLaTeXCommandCharacter(c1)) { if(isSpecialLaTeXCommandCharacter(c2)) { return (specialLaTeXCommandCharacterOrdering(c1) < specialLaTeXCommandCharacterOrdering(c2)); } else if(c2.isLetterOrNumber()) { return true; } else { return (c1 < c2); } } } return true; } void LaTeXCompletionModel::buildModel(KTextEditor::View *view, const KTextEditor::Range &range) { QString completionString = view->document()->text(range); KILE_DEBUG_CODECOMPLETION << "Text in completion range: " << completionString; m_completionList.clear(); if(completionString.startsWith('\\')) { m_completionList = m_codeCompletionManager->getLaTeXCommands(); m_completionList += m_codeCompletionManager->getLocallyDefinedLaTeXCommands(view); } else { KTextEditor::Cursor latexCommandStart = determineLaTeXCommandStart(view->document(), view->cursorPosition()); if(!latexCommandStart.isValid()) { return; } QString leftSubstring = view->document()->text(KTextEditor::Range(latexCommandStart, view->cursorPosition())); // check whether we are supposed to build a model for reference or citation completion int citationIndex = leftSubstring.indexOf(m_codeCompletionManager->m_citeRegExp); int referenceIndex = leftSubstring.indexOf(m_codeCompletionManager->m_referencesRegExp); if(referenceIndex != -1) { //FIXME: the retrieval of labels and BibTeX entries has to be revised! m_completionList = m_codeCompletionManager->m_ki->allLabels(); } else if(citationIndex != -1) { m_completionList = m_codeCompletionManager->m_ki->allBibItems(); } } beginResetModel(); filterModel(completionString); std::sort(m_completionList.begin(), m_completionList.end(), laTeXCommandLessThan); endResetModel(); } KTextEditor::Cursor LaTeXCompletionModel::determineLaTeXCommandStart(KTextEditor::Document *doc, const KTextEditor::Cursor& position) const { QString line = doc->line(position.line()); // QRegExp completionStartRegExp("((\\s|^)?)((\\\\\\w*)|(\\w+))$"); // QRegExp completionStartRegExp("((\\\\\\w*)|([^\\\\]\\b\\w+))$"); // QRegExp completionStartRegExp("(\\\\\\w*)[^\\\\]*$"); // TeX allows '.' characters inside citation labels (bug 266670) QRegExp completionStartRegExp("(\\\\([\\s\\{\\}\\[\\]\\w,.=\"'~:]|(\\&)|(\\$)|(\\%)(\\#)(\\_)|(\\{)|(\\})|(\\backslash)|(\\^)|(\\[)|(\\]))*)$"); completionStartRegExp.setMinimal(true); QString leftSubstring = line.left(position.column()); KILE_DEBUG_CODECOMPLETION << "leftSubstring: " << leftSubstring; int startPos = completionStartRegExp.lastIndexIn(leftSubstring); if(startPos >= 0) { return KTextEditor::Cursor(position.line(), startPos); } else { return KTextEditor::Cursor::invalid(); } } bool LaTeXCompletionModel::isWithinLaTeXCommand(KTextEditor::Document *doc, const KTextEditor::Cursor& commandStart, const KTextEditor::Cursor& cursorPosition) const { QString commandText = doc->text(KTextEditor::Range(commandStart, cursorPosition)); int numOpenSquareBrackets = commandText.count(QRegExp("[^\\\\]\\[")); int numClosedSquareBrackets = commandText.count(QRegExp("[^\\\\]\\]")); int numOpenCurlyBrackets = commandText.count(QRegExp("[^\\\\]\\{")); int numClosedCurlyBrackets = commandText.count(QRegExp("[^\\\\]\\}")); if(numOpenSquareBrackets != numClosedSquareBrackets || numOpenCurlyBrackets != numClosedCurlyBrackets) { return true; } if(numOpenSquareBrackets == 0 && numOpenCurlyBrackets == 0 && commandText.count(' ') == 0) { return true; } return false; } KTextEditor::Range LaTeXCompletionModel::completionRange(KTextEditor::View *view, const KTextEditor::Cursor &position) { bool latexCompletion = true; QString line = view->document()->line(position.line()); KTextEditor::Cursor startCursor = position; KTextEditor::Cursor endCursor = position; QRegExp completionEndRegExp("\\W|\\b|\\\\"); int cursorPos = position.column(); KTextEditor::Cursor latexCommandStart = determineLaTeXCommandStart(view->document(), position); KILE_DEBUG_CODECOMPLETION << "LaTeX command start " << latexCommandStart; if(!latexCommandStart.isValid() || !isWithinLaTeXCommand(view->document(), latexCommandStart, position)) { return KTextEditor::Range::invalid(); } QString completionString = view->document()->text(KTextEditor::Range(latexCommandStart, position)); KILE_DEBUG_CODECOMPLETION << "completionString " << completionString; //check whether we are completing a citation of reference if(completionString.indexOf(m_codeCompletionManager->m_citeRegExp) != -1 || completionString.indexOf(m_codeCompletionManager->m_referencesRegExp) != -1) { KILE_DEBUG_CODECOMPLETION << "found citation or reference!"; int openBracketIndex = completionString.indexOf('{'); if(openBracketIndex != -1) { // TeX allows '.' characters inside citation labels (bug 266670) QRegExp labelListRegExp("\\s*(([:.\\w]+)|([:.\\w]+(\\s*,\\s*[:.\\w]*)+))"); labelListRegExp.setMinimal(false); int column = openBracketIndex + 1; KILE_DEBUG_CODECOMPLETION << "open bracket column + 1: " << column; KILE_DEBUG_CODECOMPLETION << labelListRegExp.indexIn(completionString, openBracketIndex + 1); if(labelListRegExp.indexIn(completionString, openBracketIndex + 1) == openBracketIndex + 1 && labelListRegExp.matchedLength() + openBracketIndex + 1 == completionString.length()) { QRegExp lastCommaRegExp(",\\s*"); int lastCommaIndex = lastCommaRegExp.lastIndexIn(completionString); if(lastCommaIndex >= 0) { KILE_DEBUG_CODECOMPLETION << "last comma found at: " << lastCommaIndex; column = lastCommaIndex + lastCommaRegExp.matchedLength(); } } KILE_DEBUG_CODECOMPLETION << labelListRegExp.errorString(); startCursor.setColumn(latexCommandStart.column() + column); latexCompletion = false; } else { startCursor = latexCommandStart; } } else { startCursor = latexCommandStart; } int endPos = line.indexOf(completionEndRegExp, cursorPos); KILE_DEBUG_CODECOMPLETION << "endPos" << endPos; if(endPos >= 0) { endCursor.setColumn(endPos); } KTextEditor::Range completionRange(startCursor, endCursor); int rangeLength = endCursor.column() - startCursor.column(); if(latexCompletion && KileConfig::completeAuto() && rangeLength < KileConfig::completeAutoThreshold() + 1) { // + 1 for the command backslash KILE_DEBUG_CODECOMPLETION << "not reached the completion threshold yet"; return KTextEditor::Range::invalid(); } KILE_DEBUG_CODECOMPLETION << "returning completion range: " << completionRange; return completionRange; } bool LaTeXCompletionModel::shouldStartCompletion(KTextEditor::View *view, const QString &insertedText, bool userInsertion, const KTextEditor::Cursor &position) { Q_UNUSED(view); Q_UNUSED(position); if(!KileConfig::completeAuto()) { return false; } if(insertedText.isEmpty()) { return false; } if(insertedText.endsWith('{')) { return true; } else { return CodeCompletionModelControllerInterface::shouldStartCompletion(view, insertedText, userInsertion, position); } } bool LaTeXCompletionModel::shouldAbortCompletion(KTextEditor::View *view, const KTextEditor::Range &range, const QString ¤tCompletion) { Q_UNUSED(currentCompletion); if(view->cursorPosition() < range.start() || view->cursorPosition() > range.end() || m_completionList.size() == 0) { return true; } return false; } QString LaTeXCompletionModel::filterString(KTextEditor::View *view, const KTextEditor::Range &range, const KTextEditor::Cursor &position) { Q_UNUSED(position); KILE_DEBUG_CODECOMPLETION << "range: " << range; KILE_DEBUG_CODECOMPLETION << "text: " << (range.isValid() ? view->document()->text(range) : "(invalid range)"); return ""; } QVariant LaTeXCompletionModel::data(const QModelIndex& index, int role) const { switch(role) { case Qt::DisplayRole: if(index.column() != KTextEditor::CodeCompletionModel::Name) { return QVariant(); } return m_completionList.at(index.row()); case InheritanceDepth: return index.row(); } return QVariant(); } QModelIndex LaTeXCompletionModel::index(int row, int column, const QModelIndex &parent) const { if (row < 0 || row >= m_completionList.count() || column < 0 || column >= ColumnCount || parent.isValid()) { return QModelIndex(); } return createIndex(row, column); } int LaTeXCompletionModel::rowCount(const QModelIndex &parent) const { if(parent.isValid()) { return 0; } return m_completionList.size(); } void LaTeXCompletionModel::filterModel(const QString& text) { QMutableStringListIterator it(m_completionList); while(it.hasNext()) { QString string = it.next(); if(!string.startsWith(text)) { it.remove(); } } } void LaTeXCompletionModel::executeCompletionItem(KTextEditor::View *view, const KTextEditor::Range& word, const QModelIndex &index) const { KTextEditor::Document *document = view->document(); KTextEditor::Cursor startCursor = word.start(); const static QRegExp reEnv = QRegExp("^\\\\(begin|end)[^a-zA-Z]+"); int cursorXPos = -1, cursorYPos = -1; QString completionText = data(index.sibling(index.row(), Name), Qt::DisplayRole).toString(); QString textToInsert; int envIndex = reEnv.indexIn(completionText); if(completionText != "\\begin{}" && envIndex != -1) { // we are completing an environment QString prefix; prefix = document->text(KTextEditor::Range(startCursor.line(), 0, startCursor.line(), word.start().column())); textToInsert = buildEnvironmentCompletedText(completionText, prefix, cursorYPos, cursorXPos); KILE_DEBUG_CODECOMPLETION << cursorYPos << ", " << cursorXPos; } else { textToInsert = buildRegularCompletedText(stripParameters(completionText), cursorYPos, cursorXPos, true); } // if there are brackets present immediately after 'word' (for example, due to auto-bracketing of // the editor), we still have to remove them QString replaceText = document->text(word); const int numberOfOpenSimpleBrackets = replaceText.count('('); const int numberOfOpenSquareBrackets = replaceText.count('['); const int numberOfOpenCurlyBrackets = replaceText.count('{'); const int numberOfClosedSimpleBrackets = replaceText.count(')'); const int numberOfClosedSquareBrackets = replaceText.count(']'); const int numberOfClosedCurlyBrackets = replaceText.count('}'); const int numberOfClosedBracketsLeft = (numberOfOpenSimpleBrackets - numberOfClosedSimpleBrackets) + (numberOfOpenSquareBrackets - numberOfClosedSquareBrackets) + (numberOfOpenCurlyBrackets - numberOfClosedCurlyBrackets); if(numberOfOpenSimpleBrackets >= numberOfClosedSimpleBrackets && numberOfOpenSquareBrackets >= numberOfClosedSquareBrackets && numberOfOpenCurlyBrackets >= numberOfClosedCurlyBrackets && document->lineLength(word.end().line()) >= word.end().column() + numberOfClosedBracketsLeft) { KTextEditor::Range bracketRange = KTextEditor::Range(word.end(), numberOfClosedBracketsLeft); QString bracketText = document->text(bracketRange); if(bracketText.count(")") == (numberOfOpenSimpleBrackets - numberOfClosedSimpleBrackets) && bracketText.count("]") == (numberOfOpenSquareBrackets - numberOfClosedSquareBrackets) && bracketText.count("}") == (numberOfOpenCurlyBrackets - numberOfClosedCurlyBrackets)) { document->removeText(bracketRange); } } // now do the real completion document->replaceText(word, textToInsert); //HACK, but it's impossible to do this otherwise if(KileConfig::completeCursor() && (cursorXPos > 0 || cursorYPos > 0) && m_currentView && document->views().contains(m_currentView)) { m_currentView->setCursorPosition(KTextEditor::Cursor(startCursor.line() + (cursorYPos >= 0 ? cursorYPos : 0), startCursor.column() + (cursorXPos >= 0 ? cursorXPos : 0))); } } QString LaTeXCompletionModel::filterLatexCommand(const QString &text, int &cursorYPos, int &cursorXPos) { const static QRegExp reEnv = QRegExp("^\\\\(begin|end)[^a-zA-Z]+"); cursorXPos = -1, cursorYPos = -1; QString textToInsert; int envIndex = reEnv.indexIn(text); if(text != "\\begin{}" && envIndex != -1) { textToInsert = buildEnvironmentCompletedText(text, QString(), cursorYPos, cursorXPos); } else { textToInsert = buildRegularCompletedText(stripParameters(text), cursorYPos, cursorXPos, true); } return textToInsert; } // strip all names enclosed in braces // consider also beamer like stuff [<...>] and <...> QString LaTeXCompletionModel::stripParameters(const QString &text) const { QString s; bool ignore = false; for(int i = 0; i < text.length(); ++i) { QChar c = text[i]; switch(c.unicode()) { case '[': case '{': case '(': case '<': s += c; ignore = true; break; case ']': case '}': case ')': case '>': s += c; ignore = false; break; case ',': s += c; break; default: if(!ignore) { s += c; } break; } } return s; } QString LaTeXCompletionModel::buildRegularCompletedText(const QString &text, int &cursorYPos, int &cursorXPos, bool checkGroup) const { bool setCursor = true, setBullets = true; bool foundgroup = false; QString s; cursorXPos = -1; cursorYPos = -1; for(int i = 0; i < text.length(); ++i) { QChar c = text[i]; switch(c.unicode()) { case '<': case '{': case '(': case '[': // insert character s += c; if(cursorXPos < 0) { // remember position after first brace if(c == '[' && (i + 1) < text.length() && text[i + 1] == '<') { cursorXPos = i + 2; s += text[i + 1]; i++; }// special handling for '[<' else { cursorXPos = i + 1; } // insert bullet, if this is no cursorposition if((!setCursor) && setBullets && !(c == '[' && (i + 1) < text.length() && text[i + 1] == '<')) { s += s_bullet; } } // insert bullets after following braces else if(setBullets && !(c == '[' && (i + 1) < text.length() && text[i + 1] == '<')) { s += s_bullet; } break; case '>': case '}': case ')': case ']': // insert character s += c; break; case ',': // insert character s += c; // insert bullet? if(setBullets) { s += s_bullet; } break; case '.': // if the last character is a point of a range operator, // it will be replaced by a space or a bullet surrounded by spaces if(checkGroup && (s.right(1) == ".")) { foundgroup = true; s.truncate(s.length() - 1); if(setBullets) { s += ' ' + s_bullet + ' '; } else { s += ' '; } } else { s += c; } break; default: // insert all other characters s += c; break; } } // some more work with groups and bullets if(s.length() >= 2 && checkGroup && foundgroup && (setBullets | setCursor)) { int pos = 0; // search for braces, brackets and parens switch(s[1].unicode()) { case 'l': if(s.left(6) == "\\left ") { pos = 5; } break; case 'b': if(s.left(6) == "\\bigl ") { pos = 5; } else if(s.left(7) == "\\biggl ") { pos = 6; } break; case 'B' : if(s.left(6) == "\\Bigl ") { pos = 5; } else if(s.left(7) == "\\Biggl ") { pos = 6; } break; } // update cursorposition and set bullet if(pos > 0) { if(setCursor) { cursorXPos = pos; } if(setBullets) { if(!setCursor) { s.insert(pos, s_bullet); } s.append(s_bullet); } } } return s; } QString LaTeXCompletionModel::buildEnvironmentCompletedText(const QString &text, const QString &prefix, int &ypos, int &xpos) const { static QRegExp reEnv = QRegExp("^\\\\(begin|end)\\{([^\\}]*)\\}([^\\\\]*)(.*)"); if(reEnv.indexIn(text) == -1) { return text; } QString parameter = stripParameters(reEnv.cap(3)); QString start = reEnv.cap(1); QString envname = reEnv.cap(2); QString remainder = reEnv.cap(4); QString whitespace = buildWhiteSpaceString(prefix); QString envIndent = m_editorExtension->autoIndentEnvironment(); QString s = "\\" + start + "{" + envname + "}" + parameter + "\n"; s += whitespace; if(start != "end") { s += envIndent; } if(!remainder.isEmpty()) { s += remainder + ' '; } if(KileConfig::completeBullets() && !parameter.isEmpty()) { s += s_bullet; } if(KileConfig::completeCloseEnv() && start != "end") { s += '\n' + whitespace + "\\end{" + envname + "}\n"; } if(parameter.isEmpty()) { ypos = 1; xpos = envIndent.length() + ((!remainder.isEmpty()) ? remainder.length() + 1 : 0); } else { ypos = 0; if(parameter.left(2) == "[<") { xpos = 10 + envname.length(); } else { xpos = 9 + envname.length(); } } return s; } QString LaTeXCompletionModel::buildWhiteSpaceString(const QString &s) const { QString whitespace = s; for(int i = 0; i < whitespace.length(); ++i) { if(!whitespace[i].isSpace()) { whitespace[i] = ' '; } } return whitespace; } AbbreviationCompletionModel::AbbreviationCompletionModel(QObject *parent, KileAbbreviation::Manager *manager) : KTextEditor::CodeCompletionModel(parent), m_abbreviationManager(manager) { setHasGroups(false); } AbbreviationCompletionModel::~AbbreviationCompletionModel() { } QModelIndex AbbreviationCompletionModel::index(int row, int column, const QModelIndex &parent) const { if (row < 0 || row >= m_completionList.count() || column < 0 || column >= ColumnCount || parent.isValid()) { return QModelIndex(); } return createIndex(row, column); } QVariant AbbreviationCompletionModel::data(const QModelIndex& index, int role) const { if(index.column() != KTextEditor::CodeCompletionModel::Name) { return QVariant(); } switch(role) { case Qt::DisplayRole: return m_completionList.at(index.row()); } return QVariant(); } int AbbreviationCompletionModel::rowCount(const QModelIndex &parent) const { if(parent.isValid()) { return 0; } return m_completionList.size(); } bool AbbreviationCompletionModel::shouldStartCompletion(KTextEditor::View *view, const QString &insertedText, bool userInsertion, const KTextEditor::Cursor &position) { Q_UNUSED(view); Q_UNUSED(userInsertion); Q_UNUSED(position); int len = insertedText.length(); QRegExp whitespace(" |\t"); whitespace.setMinimal(true); int pos = insertedText.lastIndexOf(whitespace, -1); // 'pos' is less than or equal to 'len - 1' QString searchText = (pos >= 0 && pos < len) ? insertedText.right(len - pos - 1) : insertedText; return (KileConfig::completeAutoAbbrev() && m_abbreviationManager->abbreviationStartsWith(searchText)); } bool AbbreviationCompletionModel::shouldAbortCompletion(KTextEditor::View *view, const KTextEditor::Range &range, const QString ¤tCompletion) { Q_UNUSED(currentCompletion); if(view->cursorPosition() < range.start() || view->cursorPosition() > range.end() || m_completionList.size() == 0) { return true; } return false; } void AbbreviationCompletionModel::completionInvoked(KTextEditor::View *view, const KTextEditor::Range &range, InvocationType invocationType) { if(!range.isValid() || (invocationType == AutomaticInvocation && !KileConfig::completeAutoAbbrev())) { beginResetModel(); m_completionList.clear(); endResetModel(); return; } KILE_DEBUG_CODECOMPLETION << "building model..."; buildModel(view, range, (invocationType == UserInvocation || invocationType == ManualInvocation)); } KTextEditor::Range AbbreviationCompletionModel::updateCompletionRange(KTextEditor::View *view, const KTextEditor::Range &range) { if(!range.isValid()) { beginResetModel(); m_completionList.clear(); endResetModel(); return range; } KILE_DEBUG_CODECOMPLETION << "updating model..."; KTextEditor::Range newRange = completionRange(view, view->cursorPosition()); if(newRange.isValid()) { buildModel(view, newRange); } return newRange; } KTextEditor::Range AbbreviationCompletionModel::completionRange(KTextEditor::View *view, const KTextEditor::Cursor &position) { QString insertedText = view->document()->line(position.line()).left(position.column()); int len = insertedText.length(); QRegExp whitespace(" |\t"); whitespace.setMinimal(true); int pos = insertedText.lastIndexOf(whitespace,-1); QString searchText = (pos>=0 && posdocument(); document->replaceText(word, completionText); // look if there is a %C-wish to place the cursor if (completionText.indexOf("%C") >= 0) { KTextEditor::Range searchrange = KTextEditor::Range(word.start(),document->lines()+1,0); QVector rangevec = document->searchText(searchrange,"%C"); if (rangevec.size() >= 1) { KTextEditor::Range range = rangevec.at(0); document->removeText(range); if (view) { view->setCursorPosition(range.start()); } } } } void AbbreviationCompletionModel::buildModel(KTextEditor::View *view, const KTextEditor::Range &range, bool singleMatchMode) { beginResetModel(); m_completionList.clear(); endResetModel(); QString text = view->document()->text(range); KILE_DEBUG_CODECOMPLETION << text; if(text.isEmpty()) { return; } if(singleMatchMode && m_abbreviationManager->isAbbreviationDefined(text)) { m_completionList << m_abbreviationManager->getAbbreviationTextMatch(text); executeCompletionItem(view, range, index(0, 0)); } else { m_completionList = m_abbreviationManager->getAbbreviationTextMatches(text); m_completionList.sort(); if(m_completionList.size() == 1 && m_abbreviationManager->isAbbreviationDefined(text)) { executeCompletionItem(view, range, index(0, 0)); } } } Manager::Manager(KileInfo *info, QObject *parent) : QObject(parent), m_ki(info) { m_firstConfig = true; } Manager::~Manager() { } QStringList Manager::getLaTeXCommands() const { return m_texWordList; } QStringList Manager::getLocallyDefinedLaTeXCommands(KTextEditor::View *view) const { //FIXME: the retrieval of these commands has to be revised! KileDocument::TextInfo *textInfo = m_ki->docManager()->textInfoFor(view->document()); if(!textInfo) { return QStringList(); } return m_ki->allNewCommands(textInfo); } void Manager::readConfig(KConfig *config) { Q_UNUSED(config); KILE_DEBUG_CODECOMPLETION << "======================"; // reading the wordlists is only necessary at the first start // and when the list of files changes if(m_firstConfig || KileConfig::completeChangedLists() || KileConfig::completeChangedCommands()) { KILE_DEBUG_CODECOMPLETION << " setting regexp for references..."; buildReferenceCitationRegularExpressions(); KILE_DEBUG_CODECOMPLETION << " read wordlists..."; // wordlists for Tex/Latex mode QStringList files = KileConfig::completeTex(); m_texWordList = readCWLFiles(files, "tex"); addUserDefinedLaTeXCommands(m_texWordList); // wordlist for dictionary mode files = KileConfig::completeDict(); m_dictWordList = readCWLFiles(files, "dictionary"); m_dictWordList.sort(); // remember changed lists // FIXME: remove these hacks m_firstConfig = false; KileConfig::setCompleteChangedLists(false); KileConfig::setCompleteChangedCommands(false); } } void Manager::startLaTeXCompletion(KTextEditor::View *view) { if(!view) { view = m_ki->viewManager()->currentTextView(); if(!view) { return; } } KileDocument::TextInfo *textInfo = m_ki->docManager()->textInfoFor(view->document()); KileDocument::LaTeXInfo *latexInfo = dynamic_cast(textInfo); if(!latexInfo) { return; } latexInfo->startLaTeXCompletion(view); } void Manager::textInserted(KTextEditor::View* view, const KTextEditor::Cursor& /* position */, const QString& text) { // auto insert '$' if the user just typed a '$' character if (KileConfig::autoInsertDollar() && text == "$") { // code completion seems to be never active, so there is no need to // check KTextEditor::CodeCompletionInterface::isCompletionActive() KTextEditor::Cursor currentCursorPos = view->cursorPosition(); view->document()->insertText(currentCursorPos, "$"); view->setCursorPosition(currentCursorPos); } } void Manager::startLaTeXEnvironment(KTextEditor::View *view) { if(!view) { view = m_ki->viewManager()->currentTextView(); if(!view) { return; } } KTextEditor::Cursor cursor = view->cursorPosition(); QString line = view->document()->line(cursor.line()).left(cursor.column()); QRegExp regexp("\\\\b|\\\\be|\\\\beg|\\\\begi|\\\\begin|\\\\begin\\{|\\\\begin\\{([a-zA-z]*)"); int pos = regexp.lastIndexIn(line); if(pos >= 0) { view->document()->replaceText(KTextEditor::Range(cursor.line(), pos, cursor.line(), cursor.column()), "\\begin{"+regexp.cap(1)); } else { // environment completion will start with "\begin{en" when the cursor is placed // after the following strings: // en // x=en // it en // =en // it=en // en // but it will start with "\begin{" in the following situations: // \en // it\en // \aen QRegExp re("(^|[^\\\\A-Za-z])([a-zA-Z]+)$"); pos = re.indexIn(line); if(pos >= 0) { view->document()->replaceText(KTextEditor::Range(cursor.line(), re.pos(2), cursor.line(), cursor.column()), "\\begin{" + re.cap(2)); } else { view->document()->insertText(cursor, "\\begin{"); } } startLaTeXCompletion(view); } void Manager::startAbbreviationCompletion(KTextEditor::View *view) { if(!view) { view = m_ki->viewManager()->currentTextView(); if(!view) { return; } } KileDocument::TextInfo *textInfo = m_ki->docManager()->textInfoFor(view->document()); if(!textInfo) { return; } textInfo->startAbbreviationCompletion(view); } void Manager::buildReferenceCitationRegularExpressions() { // build list of references QString references = getCommandsString(KileDocument::CmdAttrReference); references.replace('*', "\\*"); m_referencesRegExp.setPattern("^\\\\(" + references + ")\\{"); m_referencesExtRegExp.setPattern("^\\\\(" + references + ")\\{[^\\{\\}\\\\]+,$"); // build list of citations QString citations = getCommandsString(KileDocument::CmdAttrCitations); citations.replace('*',"\\*"); m_citeRegExp.setPattern("^\\\\(((c|C|noc)(ite|itep|itet|itealt|itealp|iteauthor|iteyear|iteyearpar|itetext))" + citations + ")\\{"); m_citeExtRegExp.setPattern("^\\\\(((c|C|noc)(ite|itep|itet|itealt|itealp|iteauthor|iteyear|iteyearpar|itetext))" + citations + ")\\{[^\\{\\}\\\\]+,$"); } QString Manager::getCommandsString(KileDocument::CmdAttribute attrtype) { QStringList cmdlist; QStringList::ConstIterator it; // get info about user-defined references KileDocument::LatexCommands *cmd = m_ki->latexCommands(); cmd->commandList(cmdlist, attrtype, false); // build list of references QString commands; for(it = cmdlist.constBegin(); it != cmdlist.constEnd(); ++it) { if(cmd->isStarredEnv(*it) ) { commands += '|' + (*it).mid(1) + '*'; } commands += '|' + (*it).mid(1); } return commands; } void Manager::addUserDefinedLaTeXCommands(QStringList &wordlist) { QStringList cmdlist; QStringList::ConstIterator it; KileDocument::LatexCmdAttributes attr; // get info about user-defined commands and environments KileDocument::LatexCommands *cmd = m_ki->latexCommands(); cmd->commandList(cmdlist, KileDocument::CmdAttrNone, true); // add entries to wordlist for(it = cmdlist.constBegin(); it != cmdlist.constEnd(); ++it) { if(cmd->commandAttributes(*it, attr)) { QString command,eos; QStringList entrylist; if(attr.type < KileDocument::CmdAttrLabel) { // environment command = "\\begin{" + (*it); eos = '}'; } else { // command command = (*it); // eos.clear(); } // get all possibilities into a stringlist entrylist.append(command + eos); if(!attr.option.isEmpty()) { entrylist.append(command + eos + "[option]"); } if(attr.starred) { entrylist.append(command + '*' + eos); if (!attr.option.isEmpty()) { entrylist.append(command + '*' + eos + "[option]"); } } // finally append entries to wordlist QStringList::ConstIterator itentry; for(itentry = entrylist.constBegin(); itentry != entrylist.constEnd(); ++itentry) { QString entry = (*itentry); if(!attr.parameter.isEmpty()) { entry += "{param}"; } if(attr.type == KileDocument::CmdAttrList) { entry += "\\item"; } wordlist.append(entry); } } } } QStringList Manager::readCWLFile(const QString &filename, bool fullPathGiven) { QStringList toReturn; - QString file = fullPathGiven ? filename : QStandardPaths::locate(QStandardPaths::DataLocation, "complete/" + filename); + QString file = fullPathGiven ? filename : KileUtilities::locate(QStandardPaths::AppDataLocation, "complete/" + filename); if(file.isEmpty()) { return toReturn; } QFile f(file); if(f.open(QIODevice::ReadOnly)) { // file opened successfully QTextStream t(&f); // use a text stream while(!t.atEnd()) { // until end of file... QString s = t.readLine().trimmed(); // line of text excluding '\n' if(!(s.isEmpty() || s.at(0) == '#')) { toReturn.append(s); } } f.close(); } return toReturn; } QStringList Manager::readCWLFiles(const QStringList &files, const QString &dir) { // read wordlists from files QStringList wordlist; for(int i = 0; i < files.count(); ++i) { QString cwlfile = validCwlFile(files[i]); if( !cwlfile.isEmpty() ) { wordlist += readCWLFile(dir + '/' + cwlfile + ".cwl"); } } return wordlist; } QString Manager::validCwlFile(const QString &filename) { return (filename.at(0) == '1') ? filename.right( filename.length()-2 ) : QString(); } // find local and global cwl files: global files are not added, // if there is already a local file with this name. We fill a map // with filename as key and filepath as value. static void getCwlFiles(QMap &map, const QString &dir) { QStringList files = QDir(dir, "*.cwl").entryList(); for (QStringList::ConstIterator it = files.constBegin(); it != files.constEnd(); ++it) { QString filename = QFileInfo(*it).fileName(); if(!map.contains(filename)) { map[filename] = dir + '/' + (*it); } } } QMap Manager::getAllCwlFiles(const QString &localCwlPath, const QString &globalCwlPath) { // get a sorted list of all cwl files from both directories // Local files are preferred over global ones. QMap fileMap; getCwlFiles(fileMap, localCwlPath); getCwlFiles(fileMap, globalCwlPath); return fileMap; } QPair Manager::getCwlBaseDirs() { - QString localDir = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') + "complete"; + QString localDir = KileUtilities::writableLocation(QStandardPaths::AppDataLocation) + QLatin1Char('/') + "complete"; QString globalDir; - const QStringList dirs = QStandardPaths::locateAll(QStandardPaths::DataLocation, "complete", QStandardPaths::LocateDirectory); + const QStringList dirs = KileUtilities::locateAll(QStandardPaths::AppDataLocation, "complete", QStandardPaths::LocateDirectory); for(QStringList::ConstIterator it = dirs.constBegin(); it != dirs.constEnd(); ++it) { if((*it) != localDir) { globalDir = (*it); break; } } // we ensure that the directory strings end in '/' if(!localDir.endsWith('/')) { localDir += '/'; } if(!globalDir.endsWith('/')) { globalDir += '/'; } return QPair(localDir, globalDir); } } diff --git a/src/configtester.cpp b/src/configtester.cpp index 33072f9f..35ce3e71 100644 --- a/src/configtester.cpp +++ b/src/configtester.cpp @@ -1,825 +1,825 @@ /************************************************************************************* Copyright (C) 2004 by Jeroen Wijnhout (Jeroen.Wijnhout@kdemail.net) - 2012-2018 by Michel Ludwig (michel.ludwig@kdemail.net) + 2012-2019 by Michel Ludwig (michel.ludwig@kdemail.net) *************************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "configtester.h" #include #include #include #include #include #include #include #include #include #include #include -#include #include "documentinfo.h" #include "kiledebug.h" #include "kiledocmanager.h" #include "kiletoolmanager.h" #include "kileinfo.h" #include "kileconfig.h" #include "kiletool.h" #include "kiletool_enums.h" #include "kileversion.h" +#include "utilities.h" ConfigTest::ConfigTest(const QString& testGroup, const QString &name, bool isCritical) : m_testGroup(testGroup) , m_name(name) , m_isCritical(isCritical) , m_isSilent(false) , m_status(NotRun) { } ConfigTest::~ConfigTest() { } int ConfigTest::status() const { return m_status; } QString ConfigTest::name() const { return m_name; } QString ConfigTest::testGroup() const { return m_testGroup; } QString ConfigTest::resultText() const { return m_resultText; } void ConfigTest::addDependency(ConfigTest *test) { m_dependencyTestList.push_back(test); } bool ConfigTest::allDependenciesSucceeded() const { Q_FOREACH(ConfigTest *test, m_dependencyTestList) { if(test->status() != Success) { return false; } } return true; } bool ConfigTest::isCritical() const { return m_isCritical; } bool ConfigTest::isSilent() const { return m_isSilent; } void ConfigTest::setSilent(bool b) { m_isSilent = b; } void ConfigTest::setName(const QString& name) { m_name = name; } Tester::Tester(KileInfo *kileInfo, QObject *parent) : QObject(parent), m_ki(kileInfo), m_tempDir(Q_NULLPTR), m_testsDone(0) { m_tempDir = new QTemporaryDir(); setupTests(); m_nextTestIterator = m_testList.begin(); } Tester::~Tester() { if (m_tempDir) m_tempDir->remove(); delete m_tempDir; qDeleteAll(m_testList); } void Tester::runTests() { const QString& destinationDirectory = m_tempDir->path(); const QString& testDirectory = #ifdef Q_OS_WIN - QStandardPaths::locate(QStandardPaths::AppDataLocation, "kile/test", QStandardPaths::LocateDirectory); + KileUtilities::locate(QStandardPaths::AppDataLocation, "kile/test", QStandardPaths::LocateDirectory); #else - QStandardPaths::locate(QStandardPaths::AppDataLocation, "test", QStandardPaths::LocateDirectory); + KileUtilities::locate(QStandardPaths::AppDataLocation, "test", QStandardPaths::LocateDirectory); #endif KIO::CopyJob *copyJob = KIO::copyAs(QUrl::fromLocalFile(testDirectory), QUrl::fromLocalFile(destinationDirectory), KIO::HideProgressInfo | KIO::Overwrite); connect(copyJob, SIGNAL(result(KJob*)), this, SLOT(handleFileCopyResult(KJob*))); emit(percentageDone(0)); } void Tester::handleFileCopyResult(KJob* job) { if(job->error()) { emit(finished(false)); } else { startNextTest(); } } void Tester::addResult(const QString &tool, ConfigTest* testResult) { m_results[tool].push_back(testResult); } QStringList Tester::testGroups() { return m_results.keys(); } QList Tester::resultForGroup(const QString & tool) { return m_results[tool]; } // 'isCritical' is set to true iff one tool that failed was critical int Tester::statusForGroup(const QString &testGroup, bool *isCritical) { if(isCritical) { *isCritical = false; } QList tests = m_results[testGroup]; int status = ConfigTest::Success; for(int i = 0; i < tests.count(); ++i) { if(tests[i]->status() == ConfigTest::Failure) { if(isCritical && tests[i]->isCritical()) { *isCritical = true; } status = ConfigTest::Failure; } } return status; } void Tester::startNextTest() { KILE_DEBUG_MAIN; if(m_nextTestIterator != m_testList.end()) { m_currentTest = *m_nextTestIterator; ++m_nextTestIterator; if(!m_currentTest->allDependenciesSucceeded()) { QTimer::singleShot(0, this, SLOT(startNextTest())); return; } // we want events to be handled inbetween tests -> QueuedConnection connect(m_currentTest, SIGNAL(testComplete(ConfigTest*)), this, SLOT(handleTestComplete(ConfigTest*)), Qt::QueuedConnection); m_currentTest->call(); } else { emit(percentageDone(100)); emit(finished(true)); } } void Tester::handleTestComplete(ConfigTest *test) { KILE_DEBUG_MAIN; if(!test->isSilent()) { addResult(test->testGroup(), test); } ++m_testsDone; emit(percentageDone((m_testsDone / (float) m_testList.size()) * 100.0)); startNextTest(); } TestToolInKileTest::TestToolInKileTest(const QString& testGroup, KileInfo *kileInfo, const QString& toolName, const QString& filePath, bool isCritical) : ConfigTest(testGroup, i18n("Running in Kile"), isCritical), m_ki(kileInfo), m_toolName(toolName), m_filePath(filePath) { } TestToolInKileTest::~TestToolInKileTest() { } void TestToolInKileTest::call() { KileDocument::TextInfo *textInfo = m_ki->docManager()->fileOpen(QUrl::fromLocalFile(m_filePath)); if(!textInfo) { reportFailure(); return; } m_documentUrl = textInfo->url(); KileTool::Base *tool = m_ki->toolManager()->createTool(m_toolName, QString(), false); if(!tool) { m_ki->docManager()->fileClose(m_documentUrl); m_status = Failure; m_resultText = i18n("Tool not found.\n" "Kile is not configured correctly. Go to Settings->Configure Kile->Tools " "and either fix the problem or change to the default settings." ); emit(testComplete(this)); return; } // We don't want the tool to spawn subtools (especially, for LaTeX-style tools). // If we did, we might come into the situation that a subtool is launched before the // parsing is complete, which could trigger a "root document not found" error message. tool->setEntry("autoRun", "no"); connect(tool, SIGNAL(done(KileTool::Base*,int,bool)), this, SLOT(handleToolExit(KileTool::Base*,int,bool)), Qt::UniqueConnection); connect(tool, SIGNAL(failedToRun(KileTool::Base*,int)), this, SLOT(reportFailure())); m_ki->toolManager()->run(tool); } void TestToolInKileTest::reportSuccess() { m_ki->docManager()->fileClose(m_documentUrl); m_documentUrl.clear(); m_status = Success; m_resultText = i18n("Passed"); emit(testComplete(this)); } void TestToolInKileTest::reportFailure() { m_ki->docManager()->fileClose(m_documentUrl); m_documentUrl.clear(); m_status = Failure; m_resultText = i18n("Failed"); emit(testComplete(this)); } void TestToolInKileTest::handleToolExit(KileTool::Base *tool, int status, bool childToolSpawned) { Q_UNUSED(tool); Q_UNUSED(childToolSpawned); if(status == KileTool::Success) { reportSuccess(); } else { reportFailure(); } } OkularVersionTest::OkularVersionTest(const QString& testGroup, bool isCritical) : ConfigTest(testGroup, i18n("Version"), isCritical) { } OkularVersionTest::~OkularVersionTest() { } void OkularVersionTest::call() { KPluginLoader pluginLoader(OKULAR_LIBRARY_NAME); KPluginFactory *factory = pluginLoader.factory(); if (!factory) { m_status = Failure; } else { KParts::ReadOnlyPart *part = factory->create(); Okular::ViewerInterface *viewerInterface = dynamic_cast(part); if(!viewerInterface) { // OkularPart doesn't provide the ViewerInterface m_status = Failure; } else { m_status = Success; // it seems that the version of OkularPart cannot be detected, so we don't try it m_resultText = i18n("Embedding of Okular is supported"); } delete part; } delete factory; emit(testComplete(this)); } FindProgramTest::FindProgramTest(const QString& testGroup, const QString& programName, bool isCritical) : ConfigTest(testGroup, i18n("Binary"), isCritical), m_programName(programName) { } FindProgramTest::~FindProgramTest() { } void FindProgramTest::call() { QString execPath = QStandardPaths::findExecutable(m_programName); #ifdef Q_OS_WIN if(execPath.isEmpty()) { execPath = QStandardPaths::findExecutable(m_programName, QStringList(QCoreApplication::applicationDirPath())); } #endif bool thisIsWindowsConvertExe = false; #ifdef Q_OS_WIN QFileInfo execPathInfo(execPath); thisIsWindowsConvertExe = (m_programName == "convert") && (execPathInfo.dir().dirName() == "system32"); #endif if(execPath.isEmpty() || thisIsWindowsConvertExe) { m_status = Failure; if(!m_additionalFailureMessage.isEmpty()) { if(isCritical()) { m_resultText = i18nc("additional failure message given as argument", "Could not find the binary for this essential tool. %1", m_additionalFailureMessage); } else { m_resultText = i18nc("additional failure message given as argument", "No executable '%1' found. %2", m_programName, m_additionalFailureMessage); } } else { if(isCritical()) { m_resultText = i18n("Could not find the binary for this essential tool"); } else { m_resultText = i18n("No executable '%1' found", m_programName); } } } else { m_status = Success; m_resultText = i18nc("executable => path", "Found (%1 => %2)", m_programName, execPath); } emit(testComplete(this)); } void FindProgramTest::setAdditionalFailureMessage(const QString& s) { m_additionalFailureMessage = s; } ProgramTest::ProgramTest(const QString& testGroup, const QString& programName, const QString& workingDir, const QString& arg0, const QString& arg1, const QString& arg2, bool isCritical) : ConfigTest(testGroup, i18n("Simple Test"), isCritical), m_testProcess(Q_NULLPTR), m_programName(programName), m_workingDir(workingDir), m_arg0(arg0), m_arg1(arg1), m_arg2(arg2) { } ProgramTest::~ProgramTest() { delete m_testProcess; } void ProgramTest::call() { m_testProcess = new KProcess(); m_testProcess->setWorkingDirectory(m_workingDir); QStringList argList; if(!m_arg0.isEmpty()) { argList << m_arg0; } if(!m_arg1.isEmpty()) { argList << m_arg1; } if(!m_arg2.isEmpty()) { argList << m_arg2; } m_testProcess->setProgram(m_programName, argList); if (!KileConfig::teXPaths().isEmpty()) { m_testProcess->setEnv("TEXINPUTS", KileInfo::expandEnvironmentVars(KileConfig::teXPaths() + ":$TEXINPUTS")); } connect(m_testProcess, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(handleTestProcessFinished(int,QProcess::ExitStatus))); connect(m_testProcess, SIGNAL(error(QProcess::ProcessError)), this, SLOT(handleTestProcessError(QProcess::ProcessError))); m_testProcess->start(); } void ProgramTest::handleTestProcessFinished(int exitCode, QProcess::ExitStatus exitStatus) { m_testProcess->deleteLater(); m_testProcess = Q_NULLPTR; if(exitStatus == QProcess::NormalExit && exitCode == 0) { processFinishedSuccessfully(); } else { reportFailure(); } } void ProgramTest::processFinishedSuccessfully() { reportSuccess(); } void ProgramTest::handleTestProcessError(QProcess::ProcessError error) { Q_UNUSED(error); m_testProcess->deleteLater(); m_testProcess = Q_NULLPTR; reportFailure(); } void ProgramTest::reportSuccess() { m_resultText = i18n("Passed"); m_status = Success; emit(testComplete(this)); } void ProgramTest::reportFailure() { if(isCritical()) { m_resultText = i18n("This essential tool does not work; please check your installation."); } else { m_resultText = i18n("Failed"); } m_status = Failure; emit(testComplete(this)); } LaTeXSrcSpecialsSupportTest::LaTeXSrcSpecialsSupportTest(const QString& testGroup, const QString& workingDir, const QString& fileBaseName) : ProgramTest(testGroup, "latex", workingDir, "-src-specials", "--interaction=nonstopmode", fileBaseName + ".tex", false), m_fileBaseName(fileBaseName) { setName(i18n("Source Specials Switch")); } LaTeXSrcSpecialsSupportTest::~LaTeXSrcSpecialsSupportTest() { } void LaTeXSrcSpecialsSupportTest::processFinishedSuccessfully() { // before we can report success, we still have to perform the // following check: // src-specials are supported if the created file contains source // information (LaTeX doesn't report unknown command line flags as // errors). Hence, we now check whether the created file contains // the string 'src:'. QFile file(m_workingDir + '/' + m_fileBaseName + ".dvi"); if (!file.open(QIODevice::ReadOnly)) { reportFailure(); return; } // we read everything as it's a small file QByteArray array = file.readAll(); file.close(); if(!array.contains("src:")) { reportFailure(); return; } reportSuccess(); } void LaTeXSrcSpecialsSupportTest::reportSuccess() { m_resultText = i18n("Supported, use the 'Modern' configuration for (La)TeX to auto-enable inverse and forward search capabilities."); m_status = Success; emit(testComplete(this)); } void LaTeXSrcSpecialsSupportTest::reportFailure() { m_resultText = i18n("Not supported, use the srcltx package to enable the inverse and forward search capabilities."); m_status = Failure; emit(testComplete(this)); } SyncTeXSupportTest::SyncTeXSupportTest(const QString& testGroup, const QString& toolName, const QString& workingDir, const QString& fileBaseName) : ProgramTest(testGroup, toolName, workingDir, "-synctex=1", "--interaction=nonstopmode", fileBaseName + ".tex", false), m_fileBaseName(fileBaseName) { setName(i18n("SyncTeX Support")); } SyncTeXSupportTest::~SyncTeXSupportTest() { } void SyncTeXSupportTest::reportSuccess() { m_resultText = i18n("Supported, use the 'Modern' configuration for PDFLaTeX and XeLaTeX to auto-enable inverse and forward search capabilities."); m_status = Success; emit(testComplete(this)); } void SyncTeXSupportTest::reportFailure() { m_resultText = i18n("Not supported"); m_status = Failure; emit(testComplete(this)); } void SyncTeXSupportTest::processFinishedSuccessfully() { // before we can report success, we still have to check // whether a .synctex.gz file has been generated QFile file(m_workingDir + '/' + m_fileBaseName + ".synctex.gz"); if (!file.exists()) { reportFailure(); return; } reportSuccess(); } void Tester::installConsecutivelyDependentTests(ConfigTest *t1, ConfigTest *t2, ConfigTest *t3, ConfigTest *t4) { if(!t1) { return; } m_testList << t1; if(!t2) { return; } t2->addDependency(t1); m_testList << t2; if(!t3) { return; } t3->addDependency(t2); m_testList << t3; if(!t4) { return; } t4->addDependency(t3); m_testList << t4; } void Tester::setupTests() { /* testFile=test_plain.tex echo "opening $basedir/$testFile" $openDoc"$basedir/$testFile" echo "starting test: TeX" setTool TeX tool="tex --interaction=nonstopmode" setKey mustpass "where,basic,kile" setKey executable tex setKey where `which tex` setKey version `getTeXVersion tex` performTest basic "$tool test_plain.tex" performKileTest kile "run TeX" */ installConsecutivelyDependentTests( new FindProgramTest("TeX", "tex", true), new ProgramTest("TeX", "tex", m_tempDir->path(), "--interaction=nonstopmode", "test_plain.tex", "", true), new TestToolInKileTest("TeX", m_ki, "TeX", m_tempDir->path() + '/' + "test_plain.tex", true)); /* echo "starting test: PDFTeX" setTool PDFTeX tool="pdftex --interaction=nonstopmode" setKey mustpass "" setKey executable pdftex setKey where `which pdftex` performTest basic "$tool test_plain.tex" performKileTest kile "run PDFTeX" $closeDoc */ installConsecutivelyDependentTests( new FindProgramTest("PDFTeX", "pdftex", false), new ProgramTest("PDFTeX", "pdftex", m_tempDir->path(), "--interaction=nonstopmode", "test_plain.tex", "", false), new TestToolInKileTest("PDFTeX", m_ki, "PDFTeX", m_tempDir->path() + '/' + "test_plain.tex", false)); /* testFileBase="test" testFile=$testFileBase.tex echo "opening $basedir/$testFile" $openDoc"$basedir/$testFile" echo "starting test: LaTeX" setTool LaTeX tool="latex --interaction=nonstopmode" setKey mustpass "where,basic,kile" setKey executable latex setKey where `which latex` performTest basic "$tool $testFile" performKileTest kile "run LaTeX" performTest src "$tool -src $testFile" */ ProgramTest *latexProgramTest = new ProgramTest("LaTeX", "latex", m_tempDir->path(), "--interaction=nonstopmode", "test.tex", "", true); m_laTeXSrcSpecialsSupportTest = new LaTeXSrcSpecialsSupportTest("LaTeX", m_tempDir->path(), "test"); installConsecutivelyDependentTests( new FindProgramTest("LaTeX", "latex", true), latexProgramTest, new TestToolInKileTest("LaTeX", m_ki, "LaTeX", m_tempDir->path() + '/' + "test.tex", true), m_laTeXSrcSpecialsSupportTest); /* echo "starting test: PDFLaTeX" setTool PDFLaTeX setKey mustpass "" setKey executable pdflatex setKey where `which pdflatex` performTest basic "pdflatex $testFile" performKileTest kile "run PDFLaTeX" */ m_pdfLaTeXSyncTeXSupportTest = new SyncTeXSupportTest("PDFLaTeX", "pdflatex", m_tempDir->path(), "test"); installConsecutivelyDependentTests( new FindProgramTest("PDFLaTeX", "pdflatex", false), new ProgramTest("PDFLaTeX", "pdflatex", m_tempDir->path(), "--interaction=nonstopmode", "test.tex", "", false), new TestToolInKileTest("PDFLaTeX", m_ki, "PDFLaTeX", m_tempDir->path() + '/' + "test.tex", false), m_pdfLaTeXSyncTeXSupportTest); /* echo "starting test: DVItoPS" setTool DVItoPS setKey mustpass "" setKey executable dvips setKey where `which dvips` if [ -r $testFileBase.dvi ]; then performKileTest kile "run DVItoPS"; fi */ TestToolInKileTest *dvipsKileTest = new TestToolInKileTest("DVItoPS", m_ki, "DVItoPS", m_tempDir->path() + '/' + "test.tex", false); dvipsKileTest->addDependency(latexProgramTest); installConsecutivelyDependentTests( new FindProgramTest("DVItoPS", "dvips", false), dvipsKileTest); /* echo "starting test: DVItoPDF" setTool DVItoPDF setKey mustpass "" setKey executable dvipdfmx setKey where `which dvipdfmx` if [ -r $testFileBase.dvi ]; then performKileTest kile "run DVItoPDF"; fi */ TestToolInKileTest *dvipdfmxKileTest = new TestToolInKileTest("DVItoPDF", m_ki, "DVItoPDF", m_tempDir->path() + '/' + "test.tex", false); dvipdfmxKileTest->addDependency(latexProgramTest); installConsecutivelyDependentTests( new FindProgramTest("DVItoPDF", "dvipdfmx", false), dvipdfmxKileTest); /* echo "starting test: PStoPDF" setTool PStoPDF setKey mustpass "" setKey executable ps2pdf setKey where `which ps2pdf` if [ -r $testFileBase.ps ]; then performKileTest kile "run PStoPDF"; fi $closeDoc */ TestToolInKileTest *ps2pdfKileTest = new TestToolInKileTest("PStoPDF", m_ki, "PStoPDF", m_tempDir->path() + '/' + "test.tex", false); ps2pdfKileTest->addDependency(dvipsKileTest); installConsecutivelyDependentTests( new FindProgramTest("PStoPDF", "ps2pdf", false), ps2pdfKileTest); /* echo "starting test: BibTeX" setTool BibTeX setKey mustpass "" setKey executable bibtex setKey where `which bibtex` if [ -r "test.dvi" ] #LaTeX is working then testFileBase=test_bib testFile=$testFileBase.tex $openDoc"$basedir/$testFile" latex --interaction=nonstopmode $testFile performTest basic "bibtex $testFileBase" performKileTest kile "run BibTeX" $closeDoc fi */ TestToolInKileTest *latexForBibTeX = new TestToolInKileTest("BibTeX", m_ki, "LaTeX", m_tempDir->path() + '/' + "test_bib.tex", false); latexForBibTeX->addDependency(latexProgramTest); latexForBibTeX->setSilent(true); ProgramTest *bibtexProgramTest = new ProgramTest("BibTeX", "bibtex", m_tempDir->path(), "test_bib", "", "", false); bibtexProgramTest->addDependency(latexForBibTeX); TestToolInKileTest *bibtexKileTest = new TestToolInKileTest("BibTeX", m_ki, "BibTeX", m_tempDir->path() + '/' + "test_bib.tex", false); bibtexKileTest->addDependency(latexProgramTest); installConsecutivelyDependentTests( new FindProgramTest("BibTeX", "bibtex", false), latexForBibTeX, bibtexProgramTest, bibtexKileTest); /* echo "starting test: MakeIndex" setTool MakeIndex setKey mustpass "" setKey executable makeindex setKey where `which makeindex` if [ -r "test.dvi" ] #LaTeX is working then testFileBase=test_index testFile=$testFileBase.tex $openDoc"$basedir/$testFile" latex --interaction=nonstopmode $testFile performTest basic "makeindex $testFileBase" performKileTest kile "run MakeIndex" $closeDoc fi */ TestToolInKileTest *latexForMakeIndex = new TestToolInKileTest("MakeIndex", m_ki, "LaTeX", m_tempDir->path() + '/' + "test_index.tex", false); latexForMakeIndex->addDependency(latexProgramTest); latexForMakeIndex->setSilent(true); ProgramTest *makeIndexProgramTest = new ProgramTest("MakeIndex", "makeindex", m_tempDir->path(), "test_index", "", "", false); makeIndexProgramTest->addDependency(latexProgramTest); TestToolInKileTest *makeindexKileTest = new TestToolInKileTest("MakeIndex", m_ki, "MakeIndex", m_tempDir->path() + '/' + "test_index.tex", false); makeindexKileTest->addDependency(latexProgramTest); installConsecutivelyDependentTests( new FindProgramTest("MakeIndex", "makeindex", false), latexForMakeIndex, makeIndexProgramTest, makeindexKileTest); /* echo "starting test: Okular" setTool Okular setKey mustpass "where" setKey executable okular setKey version `getOkularVersion okular` performTest okular "isTheOkularVersionRecentEnough" setKey where `which okular` */ m_okularVersionTest = new OkularVersionTest("Okular", false); installConsecutivelyDependentTests( new FindProgramTest("Okular", "okular", false), m_okularVersionTest); /* echo "starting test: Acroread" setTool Acroread setKey mustpass "" setKey executable acroread setKey where `which acroread` */ /* echo "starting test: DVItoPNG" setTool DVItoPNG setKey mustpass "" setKey executable dvipng setKey where `which dvipng` */ FindProgramTest *dvipngProgramTest = new FindProgramTest("DVItoPNG", "dvipng", false); dvipngProgramTest->setAdditionalFailureMessage(i18n("PNG previews cannot be used for mathgroups in the bottom preview pane")); m_testList << dvipngProgramTest; /* echo "starting test: Convert" setTool Convert setKey mustpass "" setKey executable convert setKey where `which convert` */ FindProgramTest *convertProgramTest = new FindProgramTest("Convert", "convert", false); convertProgramTest->setAdditionalFailureMessage(i18n("PNG previews cannot be used with conversions 'dvi->ps->png' and 'pdf->png' in the bottom preview pane")); m_testList << convertProgramTest; } bool Tester::isSyncTeXSupportedForPDFLaTeX() { return (m_pdfLaTeXSyncTeXSupportTest->status() == ConfigTest::Success); } bool Tester::isViewerModeSupportedInOkular() { return (m_okularVersionTest->status() == ConfigTest::Success); } bool Tester::areSrcSpecialsSupportedForLaTeX() { return (m_laTeXSrcSpecialsSupportTest->status() == ConfigTest::Success); } diff --git a/src/convert.cpp b/src/convert.cpp index edc88ece..d6cd8bbb 100644 --- a/src/convert.cpp +++ b/src/convert.cpp @@ -1,346 +1,346 @@ /************************************************************************************* begin : Sun Feb 29 2004 copyright : (C) 2004 by Jeroen Wijnhout (Jeroen.Wijnhout@kdemail.net) *************************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "convert.h" #include #include -#include #include #include #include #include #include "kiledebug.h" +#include "utilities.h" QMap ConvertMap::g_maps; bool ConvertMap::create(const QString & encoding) { KILE_DEBUG_MAIN << "\tlooking for map for " << encoding; ConvertMap * map = g_maps[encoding]; if(!map) { KILE_DEBUG_MAIN << "\tcreating a map for " << encoding; map = new ConvertMap(encoding); // FIXME This will never be deleted if load() succeeds... if(map->load()) { g_maps[encoding] = map; } else { delete map; map = Q_NULLPTR; } map = g_maps[encoding]; } return (map != Q_NULLPTR); } QString ConvertMap::encodingNameFor(const QString & name) { QString std; for(int i = 0; i < name.length(); ++i) { if(!name[i].isSpace()) { std += name[i]; } } std = std.toLower(); if(std.startsWith(QLatin1String("iso8859-"))) { return "latin" + std.right(1); } if(std.startsWith(QLatin1String("cp"))) { return "cp" + std.right(4); } return name; } QString ConvertMap::isoNameFor(const QString & name) { QString std; for(int i = 0; i < name.length(); ++i) { if(!name[i].isSpace()) { std += name[i]; } } std = std.toLower(); if(std.startsWith(QLatin1String("latin"))) { return "ISO 8859-" + std.right(1); } if(std.startsWith(QLatin1String("cp"))) { return "cp " + std.right(4); } return name; } ConvertMap::ConvertMap(const QString& enc) { m_aliases.append(encodingNameFor(enc)); m_aliases.append(isoNameFor(enc)); } void ConvertMap::addPair(QChar c, const QString& enc) { m_toASCII[c] = commandIsTerminated(enc) ? enc : enc + "{}" ; m_toEncoding[enc] = c; } bool ConvertMap::commandIsTerminated(const QString & command) { static QRegExp reCommandSequences("\\\\([a-zA-Z]+|\\\"|\\')$"); return (reCommandSequences.indexIn(command) == -1); } bool ConvertMap::load() { static QRegExp reMap("^(.*):(.*)"); //makeMap(encoding()); //if map already exists, replace it - QFile qf(QStandardPaths::locate(QStandardPaths::DataLocation, "encodings/" + encoding() + ".enc")); + QFile qf(KileUtilities::locate(QStandardPaths::AppDataLocation, "encodings/" + encoding() + ".enc")); if(qf.open(QIODevice::ReadOnly)) { QTextStream stream(&qf); QTextCodec *codec = QTextCodec::codecForName(isoName().toLatin1()); if(codec) { stream.setCodec(codec); } while(!stream.atEnd()) { //parse the line if(stream.readLine().indexOf(reMap) != -1) { addPair(reMap.cap(1)[0], reMap.cap(2)); } } qf.close(); return true; } return false; } //BEGIN ConvertIO classes ConvertIO::ConvertIO(KTextEditor::Document *doc) : m_doc(doc), m_text(QString()), m_line(QString()), m_nLine(0) { } QString & ConvertIO::currentLine() { return m_line; } void ConvertIO::nextLine() { m_line = m_doc->line(m_nLine++); } void ConvertIO::writeText() { m_doc->setText(m_text); } int ConvertIO::current() { return m_nLine; } bool ConvertIO::done() { return current() == m_doc->lines(); } ConvertIOFile::ConvertIOFile(KTextEditor::Document *doc, const QUrl &url) : ConvertIO(doc), m_url(url) { } void ConvertIOFile::writeText() { QFile qf(m_url.toLocalFile()); if(qf.open(QIODevice::WriteOnly)) { //read the file QTextStream stream(&qf); stream << m_text; qf.close(); } else { qWarning() << "Could not open " << m_url.toLocalFile(); } } ConvertBase::ConvertBase(const QString & encoding, ConvertIO * io) : m_io(io), m_encoding(encoding), m_map(Q_NULLPTR) { } //END ConvertIO classes //BEGIN ConvertBase QString ConvertBase::mapNext(int &i) { return (QString)m_io->currentLine()[i++]; } bool ConvertBase::convert() { if(!setMap()) { return false; } m_io->text().clear(); do { m_io->nextLine(); int i = 0; while(i < m_io->currentLine().length()) { m_io->text() += mapNext(i); } if(!m_io->done()) { m_io->text() += '\n'; } } while(!m_io->done()); m_io->writeText(); return true; } bool ConvertBase::setMap() { //create map (or use existing) if(ConvertMap::create(m_encoding)) { m_map = ConvertMap::mapFor(m_encoding); } else { m_map = Q_NULLPTR; } return (m_map != Q_NULLPTR); } //END ConvertBase //BEGIN ConvertEncToASCII QString ConvertEncToASCII::mapNext(int &i) { return m_map->canDecode(m_io->currentLine()[i]) ? m_map->toASCII(m_io->currentLine()[i++]) : (QString)m_io->currentLine()[i++]; } //END ConvertEncToASCII //BEGIN ConvertASCIIToEnc //i is the position of the '\' QString ConvertASCIIToEnc::nextSequence(int &i) { //get first two characters QString seq = (QString)m_io->currentLine()[i++]; if(m_io->currentLine()[i].isLetter()) { while(m_io->currentLine()[i].isLetter()) { seq += (QString)m_io->currentLine()[i++]; } } else { return seq + (QString)m_io->currentLine()[i++]; } return seq; } bool ConvertASCIIToEnc::isModifier(const QString& seq) { static QRegExp reModifier("\\\\([cHkruv]|\"|\'|\\^|`|~|=|\\.)"); return reModifier.exactMatch(seq); } QString ConvertASCIIToEnc::getSequence(int &i) { QString seq = nextSequence(i); static QRegExp reBraces("\\{([a-zA-Z]?)\\}"); if(isModifier(seq)) { KILE_DEBUG_MAIN << "\tisModifier true : " << seq; if(seq[seq.length() - 1].isLetter()) { seq += ' '; } while(m_io->currentLine()[i].isSpace()) { ++i; } if(m_io->currentLine().mid(i, 2) == "{}") { i = i + 2; } if(m_io->currentLine()[i] == '\\') { seq += nextSequence(i); } else { if(reBraces.exactMatch(m_io->currentLine().mid(i, 3))) { KILE_DEBUG_MAIN << "\tbraces detected"; i = i + 3; seq += reBraces.cap(1); } else { QChar nextChar = m_io->currentLine()[i++]; if(!nextChar.isSpace()) { seq += (QString)nextChar; } } } } else if(m_map->canEncode(seq)) { if(m_io->currentLine().mid(i, 2) == "{}") { i = i + 2; } else if(m_io->currentLine()[i].isSpace()) { ++i; } } return seq; } QString ConvertASCIIToEnc::mapNext(int &i) { if(m_io->currentLine()[i] == '\\') { QString seq = getSequence(i); KILE_DEBUG_MAIN << "'\tsequence: " << seq; if(m_map->canEncode(seq)) { KILE_DEBUG_MAIN << "\tcan encode this"; //if ( m_io->currentLine().mid(i, 2) == "{}" ) i = i + 2; return m_map->toEncoding(seq); } else { return seq; } } return ConvertBase::mapNext(i); } //END ConvertASCIIToEnc diff --git a/src/dialogs/managetemplatesdialog.cpp b/src/dialogs/managetemplatesdialog.cpp index 42cd8f0d..1cb7bdad 100644 --- a/src/dialogs/managetemplatesdialog.cpp +++ b/src/dialogs/managetemplatesdialog.cpp @@ -1,341 +1,341 @@ /***************************************************************************************** begin : Sun Apr 27 2003 copyright : (C) 2003 by Jeroen Wijnhout (wijnhout@science.uva.nl) 2007 by Michel Ludwig (michel.ludwig@kdemail.net) *****************************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "dialogs/managetemplatesdialog.h" #include #include #include #include #include #include #include #include -#include #include #include #include #include #include #include #include #include #include #include #include "kiledebug.h" #include "kileextensions.h" #include "kileinfo.h" #include "templates.h" +#include "utilities.h" class TemplateListViewItem : public QTreeWidgetItem { public: TemplateListViewItem(QTreeWidget* parent, QTreeWidgetItem* preceding, const QString& mode, const KileTemplate::Info& info) : QTreeWidgetItem(parent, preceding), m_info(info) { setText(0, mode); setText(1, info.name); setText(2, KileInfo::documentTypeToString(info.type)); } virtual ~TemplateListViewItem() { } KileTemplate::Info getTemplateInfo() { return m_info; } protected: KileTemplate::Info m_info; }; // dialog to create a template ManageTemplatesDialog::ManageTemplatesDialog(KileTemplate::Manager *templateManager, const QUrl &sourceURL, const QString &caption, QWidget *parent, const char *name) : QDialog(parent) , m_templateManager(templateManager) , m_sourceURL(sourceURL) { setObjectName(name); setWindowTitle(caption); setModal(true); QVBoxLayout *mainLayout = new QVBoxLayout; setLayout(mainLayout); m_templateType = KileDocument::Extensions().determineDocumentType(sourceURL); QWidget *page = new QWidget(this); page->setObjectName("managetemplates_mainwidget"); mainLayout->addWidget(page); QGridLayout *topLayout = new QGridLayout(); topLayout->setMargin(0); page->setLayout(topLayout); topLayout->addWidget(new QLabel(i18n("Name:"), page), 0, 0); QString fileName = m_sourceURL.fileName(); //remove the extension int dotPos = fileName.lastIndexOf('.'); if (dotPos >= 0) { fileName = fileName.mid(0, dotPos); } m_nameEdit = new QLineEdit(fileName, page); mainLayout->addWidget(m_nameEdit); topLayout->addWidget(m_nameEdit, 0, 1); topLayout->addWidget(new QLabel(i18n("Type: %1", KileInfo::documentTypeToString(m_templateType)), page), 0, 2); topLayout->addWidget(new QLabel(i18n("Icon:"), page), 1, 0); - m_iconEdit = new QLineEdit(QStandardPaths::locate(QStandardPaths::DataLocation, "pics/type_Default.png"), page); + m_iconEdit = new QLineEdit(KileUtilities::locate(QStandardPaths::AppDataLocation, "pics/type_Default.png"), page); mainLayout->addWidget(m_iconEdit); topLayout->addWidget(m_iconEdit, 1, 1); QPushButton *iconbut = new QPushButton(i18n("Select..."), page); mainLayout->addWidget(iconbut); topLayout->addWidget(iconbut, 1, 2); m_templateList = new QTreeWidget(page); mainLayout->addWidget(m_templateList); m_templateList->setSortingEnabled(false); m_templateList->setHeaderLabels(QStringList() << i18nc("marked", "M") << i18n("Existing Templates") << i18n("Document Type")); m_templateList->setAllColumnsShowFocus(true); m_templateList->setRootIsDecorated(false); populateTemplateListView(m_templateType); topLayout->addWidget(m_templateList, 2, 0, 1, 3); m_showAllTypesCheckBox = new QCheckBox(i18n("Show all the templates"), page); mainLayout->addWidget(m_showAllTypesCheckBox); m_showAllTypesCheckBox->setChecked(false); connect(m_showAllTypesCheckBox, &QCheckBox::toggled, this, &ManageTemplatesDialog::updateTemplateListView); topLayout->addWidget(m_showAllTypesCheckBox, 3, 0, 1, 2); QPushButton *clearSelectionButton = new QPushButton(page); mainLayout->addWidget(clearSelectionButton); clearSelectionButton->setIcon(QIcon::fromTheme("edit-clear-locationbar")); int buttonSize = clearSelectionButton->sizeHint().height(); clearSelectionButton->setFixedSize(buttonSize, buttonSize); clearSelectionButton->setToolTip(i18n("Clear Selection")); connect(clearSelectionButton, &QPushButton::clicked, this, &ManageTemplatesDialog::clearSelection); topLayout->addWidget(clearSelectionButton, 3, 2, Qt::AlignRight); topLayout->addWidget(new QLabel(i18n("Select an existing template if you want to overwrite it with your new template.\nNote that you cannot overwrite templates marked with an asterisk:\nif you do select such a template, a new template with the same name\nwill be created in a location you have write access to."), page), 4, 0, 1, 3); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel); QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok); okButton->setDefault(true); okButton->setShortcut(Qt::CTRL | Qt::Key_Return); mainLayout->addWidget(buttonBox); connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); connect(m_templateList, &QTreeWidget::itemClicked, this, &ManageTemplatesDialog::slotSelectedTemplate); connect(iconbut, &QPushButton::clicked, this, &ManageTemplatesDialog::slotSelectIcon); connect(this, &QDialog::accepted, this, &ManageTemplatesDialog::addTemplate); } // dialog to remove a template ManageTemplatesDialog::ManageTemplatesDialog(KileTemplate::Manager *templateManager, const QString &caption, QWidget *parent, const char *name) : QDialog(parent) , m_templateManager(templateManager) , m_templateType(KileDocument::Undefined) , m_showAllTypesCheckBox(Q_NULLPTR) { setObjectName(name); setWindowTitle(caption); setModal(true); QVBoxLayout *mainLayout = new QVBoxLayout(); mainLayout->setMargin(0); setLayout(mainLayout); m_templateList = new QTreeWidget(this); m_templateList->setSortingEnabled(false); m_templateList->setHeaderLabels(QStringList() << i18nc("marked", "M") << i18n("Existing Templates") << i18n("Document Type")); m_templateList->setAllColumnsShowFocus(true); m_templateList->setRootIsDecorated(false); populateTemplateListView(KileDocument::Undefined); mainLayout->addWidget(m_templateList); mainLayout->addWidget(new QLabel(i18n("Please select the template that you want to remove.\nNote that you cannot delete templates marked with an asterisk (for which you lack the necessary deletion permissions)."), this)); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel); QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok); okButton->setDefault(true); okButton->setShortcut(Qt::CTRL | Qt::Key_Return); mainLayout->addWidget(buttonBox); connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); connect(this, &QDialog::accepted, this, &ManageTemplatesDialog::removeTemplate); } ManageTemplatesDialog::~ManageTemplatesDialog() { } void ManageTemplatesDialog::updateTemplateListView(bool showAllTypes) { populateTemplateListView((showAllTypes ? KileDocument::Undefined : m_templateType)); } void ManageTemplatesDialog::clearSelection() { m_templateList->clearSelection(); } void ManageTemplatesDialog::populateTemplateListView(KileDocument::Type type) { m_templateManager->scanForTemplates(); KileTemplate::TemplateList templateList = m_templateManager->getTemplates(type); QString mode; QTreeWidgetItem* previousItem = Q_NULLPTR; m_templateList->clear(); for (KileTemplate::TemplateListIterator i = templateList.begin(); i != templateList.end(); ++i) { KileTemplate::Info info = *i; QFileInfo iconFileInfo(info.icon); mode = (QFileInfo(info.path).isWritable() && (!iconFileInfo.exists() || iconFileInfo.isWritable())) ? " " : "*"; if ((type == KileDocument::Undefined) || (info.type == type)) { previousItem = new TemplateListViewItem(m_templateList, previousItem, mode, info); } } m_templateList->resizeColumnToContents(0); m_templateList->resizeColumnToContents(1); } void ManageTemplatesDialog::slotSelectedTemplate(QTreeWidgetItem *item) { TemplateListViewItem *templateItem = dynamic_cast(item); if (templateItem) { KileTemplate::Info info = templateItem->getTemplateInfo(); m_nameEdit->setText(info.name); m_iconEdit->setText(info.icon); } } void ManageTemplatesDialog::slotSelectIcon() { KIconDialog *dlg = new KIconDialog(); QString res = dlg->openDialog(); KIconLoader kil; if (!res.isNull()) { m_iconEdit->setText(kil.iconPath(res, -KIconLoader::SizeLarge, false)); } } void ManageTemplatesDialog::addTemplate() { QString templateName = (m_nameEdit->text()).trimmed(); if (templateName.isEmpty()) { KMessageBox::error(this, i18n("The template name that you have entered is invalid.\nPlease enter a new name.")); return; } QString icon = (m_iconEdit->text()).trimmed(); QUrl iconURL = QUrl::fromUserInput(icon); if (icon.isEmpty()) { KMessageBox::error(this, i18n("Please choose an icon first.")); return; } KIO::StatJob* statJob = KIO::stat(iconURL, KIO::StatJob::SourceSide, 0); KJobWidgets::setWindow(statJob, this); statJob->exec(); if (statJob->error()) { KMessageBox::error(this, i18n("The icon file: %1\ndoes not seem to exist. Please choose a new icon.", icon)); return; } statJob = KIO::stat(m_sourceURL, KIO::StatJob::SourceSide, 0); KJobWidgets::setWindow(statJob, this); statJob->exec(); if (statJob->error()) { KMessageBox::error(this, i18n("The file: %1\ndoes not seem to exist. Maybe you forgot to save the file?", m_sourceURL.toString())); return; } QTreeWidgetItem* item = m_templateList->currentItem(); if (!item && m_templateManager->searchForTemplate(templateName, m_templateType)) { KMessageBox::error(this, i18n("A template named \"%1\" already exists.\nPlease remove it first.", templateName)); return; } bool returnValue; if (item) { TemplateListViewItem *templateItem = dynamic_cast(item); Q_ASSERT(templateItem); KileTemplate::Info templateInfo = templateItem->getTemplateInfo(); if (KMessageBox::warningYesNo(this, i18n("You are about to replace the template \"%1\"; are you sure?", templateInfo.name)) == KMessageBox::No) { reject(); return; } returnValue = m_templateManager->replace(templateInfo, m_sourceURL, templateName, iconURL); } else { returnValue = m_templateManager->add(m_sourceURL, templateName, iconURL); } if (!returnValue) { KMessageBox::error(this, i18n("Failed to create the template.")); reject(); return; } } bool ManageTemplatesDialog::removeTemplate() { QTreeWidgetItem* item = m_templateList->currentItem(); if (!item) { KMessageBox::information(this, i18n("Please select a template that should be removed.")); return true; } TemplateListViewItem *templateItem = dynamic_cast(item); Q_ASSERT(templateItem); KileTemplate::Info templateInfo = templateItem->getTemplateInfo(); KIO::StatJob* statJob = KIO::stat(QUrl::fromUserInput(templateInfo.path), KIO::StatJob::DestinationSide, 0); KIO::StatJob* statJob2 = KIO::stat(QUrl::fromUserInput(templateInfo.icon), KIO::StatJob::DestinationSide, 0); KJobWidgets::setWindow(statJob, this); KJobWidgets::setWindow(statJob2, this); statJob->exec(); statJob2->exec(); if ((statJob->error() && statJob2->error()) || !QFileInfo(templateInfo.icon).exists()) { KMessageBox::error(this, i18n("Sorry, but you do not have the necessary permissions to remove the selected template.")); return false; } if (KMessageBox::warningYesNo(this, i18n("You are about to remove the template \"%1\"; are you sure?", templateInfo.name)) == KMessageBox::No) { return false; } if (!m_templateManager->remove(templateInfo)) { KMessageBox::error(this, i18n("The template could not be removed.")); reject(); return false; } return true; } diff --git a/src/dialogs/usermenu/usermenudialog.cpp b/src/dialogs/usermenu/usermenudialog.cpp index f1dd2159..dc0ccbe8 100644 --- a/src/dialogs/usermenu/usermenudialog.cpp +++ b/src/dialogs/usermenu/usermenudialog.cpp @@ -1,996 +1,995 @@ /*********************************************************************************** Copyright (C) 2011-2012 by Holger Danielsson (holger.danielsson@versanet.de) (C) 2018 by Michel Ludwig (michel.ludwig@kdemail.net) ***********************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include #include #include #include #include -#include #include #include #include #include #include #include #include #include "dialogs/usermenu/usermenudialog.h" #include "dialogs/usermenu/usermenutree.h" #include "dialogs/usermenu/usermenuitem.h" #include "usermenu/usermenu.h" #include "kiledebug.h" #include "utilities.h" namespace KileMenu { #define CHOOSABLE_MENUTYPES 3 UserMenuDialog::UserMenuDialog(KConfig *config, KileInfo *ki, KileMenu::UserMenu *userMenu, const QString &xmlfile, QWidget *parent) : KileDialog::Wizard(config, parent, Q_NULLPTR, i18n("Edit User Menu")) , m_ki(ki) , m_userMenu(userMenu) { QWidget *page = new QWidget(); QVBoxLayout *mainLayout = new QVBoxLayout; setLayout(mainLayout); m_UserMenuDialog.setupUi(page); m_menutree = m_UserMenuDialog.m_twUserMenu; m_menutree->setHeaderLabels(QStringList() << i18n("Menu Entry") << i18n("Shortcut")); // Indexes must be identical to MenuType. Only the first three of them are choosable (see CHOOSABLE_MENUTYPES) m_listMenutypes << i18n("Text") << i18n("Insert file contents") << i18n("Execute program") << i18n("Separator") << i18n("Submenu"); // some text m_UserMenuDialog.m_teText->setWhatsThis(i18n("Text, which will be inserted, if the action is executed. Some placeholders are available:
  • %M - selected (marked) text
  • %C - cursor position
  • %B - bullet
  • %E - indentation in environments
  • %R - select label from list
  • %T - select citation key from list
")); m_UserMenuDialog.m_teText->setToolTip(i18n("Available placeholders:\n%M: Selected (marked) text\n%C: Cursor position\n%B: Bullet\n%E: Indentation in environments\n%R: Select label from list\n%T: Select citation key from list\n%S: Source file name without extension")); // search for all action collections (needed for shortcut conflicts) QList allCollections; foreach (KXMLGUIClient *client, m_ki->mainWindow()->guiFactory()->clients()) { KILE_DEBUG_MAIN << "collection count: " << client->actionCollection()->count() ; allCollections += client->actionCollection(); } m_UserMenuDialog.m_keyChooser->setCheckActionCollections(allCollections); KILE_DEBUG_MAIN << "total collections: " << allCollections.count(); m_UserMenuDialog.m_pbInsertBelow->setIcon(QIcon::fromTheme("usermenu-insert-below.png")); m_UserMenuDialog.m_pbInsertSubmenu->setIcon(QIcon::fromTheme("usermenu-submenu-below.png")); m_UserMenuDialog.m_pbInsertSeparator->setIcon(QIcon::fromTheme("usermenu-separator-below.png")); m_UserMenuDialog.m_pbDelete->setIcon(QIcon::fromTheme("usermenu-delete.png")); m_UserMenuDialog.m_pbUp->setIcon(QIcon::fromTheme("usermenu-up.png")); m_UserMenuDialog.m_pbDown->setIcon(QIcon::fromTheme("usermenu-down.png")); m_UserMenuDialog.m_pbIconDelete->setIcon(QIcon::fromTheme("edit-clear-locationbar-rtl.png")); connect(m_UserMenuDialog.m_pbInsertBelow, &QPushButton::clicked, this, &UserMenuDialog::slotInsertMenuItem); connect(m_UserMenuDialog.m_pbInsertSubmenu, &QPushButton::clicked, this, &UserMenuDialog::slotInsertSubmenu); connect(m_UserMenuDialog.m_pbInsertSeparator, &QPushButton::clicked, this, &UserMenuDialog::slotInsertSeparator); connect(m_UserMenuDialog.m_pbUp, &QPushButton::clicked, this, &UserMenuDialog::slotUp); connect(m_UserMenuDialog.m_pbDown, &QPushButton::clicked, this, &UserMenuDialog::slotDown); connect(m_UserMenuDialog.m_pbDelete, &QPushButton::clicked, this, &UserMenuDialog::slotDelete); connect(m_menutree, &QTreeWidget::currentItemChanged, this, &UserMenuDialog::slotCurrentItemChanged); connect(m_UserMenuDialog.m_pbMenuentryType, &QPushButton::clicked, this, &UserMenuDialog::slotMenuentryTypeClicked); connect(m_UserMenuDialog.m_leMenuEntry, &KLineEdit::textEdited, this, &UserMenuDialog::slotMenuentryTextChanged); connect(m_UserMenuDialog.m_urlRequester, &KUrlRequester::textChanged, this, &UserMenuDialog::slotUrlTextChanged); connect(m_UserMenuDialog.m_urlRequester, &KUrlRequester::urlSelected, this, [=]() { setModified(); }); connect(m_UserMenuDialog.m_leParameter, &KLineEdit::textEdited, this, [=]() { setModified(); }); connect(m_UserMenuDialog.m_teText, &QPlainTextEdit::textChanged, this, [=]() { setModified(); }); connect(m_UserMenuDialog.m_pbIcon, &QPushButton::clicked, this, &UserMenuDialog::slotIconClicked); connect(m_UserMenuDialog.m_pbIconDelete, &QPushButton::clicked, this, &UserMenuDialog::slotIconDeleteClicked); connect(m_UserMenuDialog.m_keyChooser, &KKeySequenceWidget::keySequenceChanged, this, &UserMenuDialog::slotKeySequenceChanged); connect(m_UserMenuDialog.m_cbNeedsSelection, &QCheckBox::stateChanged, this, &UserMenuDialog::slotSelectionStateChanged); connect(m_UserMenuDialog.m_cbContextMenu, &QCheckBox::stateChanged, this, &UserMenuDialog::slotCheckboxStateChanged); connect(m_UserMenuDialog.m_cbReplaceSelection, &QCheckBox::stateChanged, this, &UserMenuDialog::slotCheckboxStateChanged); connect(m_UserMenuDialog.m_cbSelectInsertion, &QCheckBox::stateChanged, this, &UserMenuDialog::slotCheckboxStateChanged); connect(m_UserMenuDialog.m_cbInsertOutput, &QCheckBox::stateChanged, this, &UserMenuDialog::slotCheckboxStateChanged); connect(m_UserMenuDialog.m_pbInstall, &QPushButton::clicked, this, &UserMenuDialog::slotInstallClicked); connect(m_UserMenuDialog.m_pbNew, &QPushButton::clicked, this, &UserMenuDialog::slotNewClicked); connect(m_UserMenuDialog.m_pbLoad, &QPushButton::clicked, this, &UserMenuDialog::slotLoadClicked); connect(m_UserMenuDialog.m_pbSave, &QPushButton::clicked, this, &UserMenuDialog::slotSaveClicked); connect(m_UserMenuDialog.m_pbSaveAs, &QPushButton::clicked, this, &UserMenuDialog::slotSaveAsClicked); // set context menu handler for the menutree m_menutree->setContextMenuPolicy(Qt::CustomContextMenu); connect(m_menutree, &QWidget::customContextMenuRequested, this, &UserMenuDialog::slotCustomContextMenuRequested); // adjust some widths const int w = m_UserMenuDialog.m_pbInsertBelow->sizeHint().width(); m_UserMenuDialog.m_pbUp->setMinimumWidth(w); m_UserMenuDialog.m_pbDown->setMinimumWidth(w); m_UserMenuDialog.m_lbIconChosen->setMinimumWidth(m_UserMenuDialog.m_pbIcon->sizeHint().width()); setFocusProxy(m_menutree); setModal(false); // TODO: currently all dialog actions are in an extra widget // for usability some of those actions should be connect to the main dialog controls, // e.g. automatic install when pressing OK buttonBox()->clear(); buttonBox()->addButton(QDialogButtonBox::Close); buttonBox()->addButton(QDialogButtonBox::Help); mainLayout->addWidget(page); mainLayout->addWidget(buttonBox()); connect(buttonBox(), &QDialogButtonBox::helpRequested, this, &UserMenuDialog::slotShowHelp); KILE_DEBUG_MAIN << "start dialog with xmfile " << xmlfile; if (!xmlfile.isEmpty() && QFile::exists(xmlfile)) { m_modified = false; loadXmlFile(xmlfile,true); } else { startDialog(); } resize(minimumSize()); } void UserMenuDialog::startDialog() { initDialog(); m_modified = false; setXmlFile(QString(), false); updateDialogButtons(); m_UserMenuDialog.m_pbNew->setEnabled(false); } void UserMenuDialog::initDialog() { updateTreeButtons(); QTreeWidgetItem *current = m_menutree->currentItem(); if (current) { m_menutree->setCurrentItem(current); } // init first entry m_currentIcon.clear(); showMenuentryData(dynamic_cast(current)); } void UserMenuDialog::setXmlFile(const QString &filename, bool installed) { m_currentXmlInstalled = installed; m_currentXmlFile = filename; m_UserMenuDialog.m_lbXmlFile->setText(i18n("File:") + QLatin1String(" ") + QFileInfo(m_currentXmlFile).fileName()); if (m_currentXmlInstalled) { m_UserMenuDialog.m_lbXmlInstalled->show(); } else { m_UserMenuDialog.m_lbXmlInstalled->hide(); } } void UserMenuDialog::setModified() { if (!m_modified) { m_modified = true; } updateDialogButtons(); } void UserMenuDialog::updateDialogButtons() { bool installedFile = (!m_currentXmlFile.isEmpty()); bool menutreeState = !m_menutree->isEmpty(); bool installState = !m_modified && installedFile && !m_currentXmlInstalled; bool saveState = m_modified && installedFile; bool saveAsState = m_modified || (!m_modified && installedFile && m_currentXmlInstalled); m_UserMenuDialog.m_pbInstall->setEnabled(installState && menutreeState); m_UserMenuDialog.m_pbSave->setEnabled(saveState && menutreeState); m_UserMenuDialog.m_pbSaveAs->setEnabled(saveAsState && menutreeState); m_UserMenuDialog.m_pbNew->setEnabled(true); } void UserMenuDialog::slotShowHelp() { const QString message = i18n("

You can create, change and install a user-defined menu, which will appear as a part of Kile's menu. " "To create or change this menu, use the six buttons on the left side. " "Even more possible actions are available in the context menu of already existing menu items.

" "

Like a standard menu, three different kinds of menu items are available:

" "
    " "
  • standard entries, which are assigned to an action
  • " "
  • submenus, which contain more menu items
  • " "
  • separators, to get a visible structure of all entries
  • " "
" "

Each standard menu item is assigned to one of three action types:

" "
    " "
  • insert text: this action will insert your text at the current cursor position. " "Some metachars are available: %M, %C, %B, %E, %R, %T, %S: " "see the What's This or Tool Tip feature of this widget to get more information.
  • " "
  • file content: inserts the complete contents of a given file (metachars are also available)
  • " "
  • run an external program: The output of this program can be inserted into the opened document. " "Metachar %M is also possible in the commandline of this program, as the selected text will be saved in a temporary file. " "Use %M for the filename of this temporary file.
  • " "
" "

If some important information for an action is missing, menu items are colored red. " "More information is available using the What's this feature of most widgets.

"); KMessageBox::information(this, message, i18n("UserMenu Dialog")); } ///////////////////////////// Button slots (Install/New) ////////////////////////////// void UserMenuDialog::slotInstallClicked() { KILE_DEBUG_MAIN << "install " << m_currentXmlFile << "..."; if (!m_modified && !m_currentXmlFile.isEmpty()) { m_userMenu->installXmlFile(m_currentXmlFile); setXmlFile(m_currentXmlFile,true); updateDialogButtons(); } } void UserMenuDialog::slotNewClicked() { KILE_DEBUG_MAIN << "start new menutree ... "; if (!m_menutree->isEmpty() && m_modified) { if (KMessageBox::questionYesNo(this, i18n("Current menu tree was modified, but not saved.\nDiscard this tree?")) == KMessageBox::No) { return; } } m_menutree->clear(); m_modified = false; startDialog(); // includes updating of buttons } ///////////////////////////// Button slots (Load) ////////////////////////////// void UserMenuDialog::slotLoadClicked() { KILE_DEBUG_MAIN << "load xml file "; if (!m_menutree->isEmpty() && m_modified) { if (KMessageBox::questionYesNo(this, i18n("Current menu tree was modified, but not saved.\nDiscard this tree?")) == KMessageBox::No) { return; } } QString directory = UserMenu::selectUserMenuDir(); QString filter = i18n("User Menu Files (*.xml)"); QString filename = QFileDialog::getOpenFileName(this, i18n("Select Menu File"), directory, filter); if (filename.isEmpty()) { return; } if (QFile::exists(filename)) { loadXmlFile(filename,false); // includes updating of buttons } else { KMessageBox::error(this, i18n("File '%1' does not exist.", filename)); } } void UserMenuDialog::loadXmlFile(const QString &filename, bool installed) { KILE_DEBUG_MAIN << "load xml started ..."; m_menutree->readXml(filename); initDialog(); m_modified = false; setXmlFile(filename,installed); updateDialogButtons(); KILE_DEBUG_MAIN << "load xml finished ..."; } ///////////////////////////// Button slots (Save) ////////////////////////////// void UserMenuDialog::slotSaveClicked() { if (saveClicked()) { m_modified = false; if (m_currentXmlInstalled) { slotInstallClicked(); // includes all updates } else { setXmlFile(m_currentXmlFile,false); } updateDialogButtons(); } } bool UserMenuDialog::saveClicked() { if (m_currentXmlFile.isEmpty()) { return false; } KILE_DEBUG_MAIN << "save menutree: " << m_currentXmlFile; // read current entry QTreeWidgetItem *current = m_menutree->currentItem(); if (current) { KILE_DEBUG_MAIN << "read current item ..."; readMenuentryData( dynamic_cast(current) ); } if (saveCheck() == false) { return false; } // force to save file in local directory - QStringList dirs = QStandardPaths::locateAll(QStandardPaths::DataLocation, "usermenu", QStandardPaths::LocateDirectory); + QStringList dirs = KileUtilities::locateAll(QStandardPaths::AppDataLocation, "usermenu", QStandardPaths::LocateDirectory); if (dirs.size() > 1) { if (m_currentXmlFile.startsWith(dirs[1])) { m_currentXmlFile.replace(dirs[1],dirs[0]); KILE_DEBUG_MAIN << "change filename to local directory:" << m_currentXmlFile; } } // save file m_menutree->writeXml(m_currentXmlFile); return true; } void UserMenuDialog::slotSaveAsClicked() { const QString filename = saveAsClicked(); if (!filename.isEmpty()) { // set new state: current file is not installed anymore m_modified = false; setXmlFile(filename,false); updateDialogButtons(); } } QString UserMenuDialog::saveAsClicked() { KILE_DEBUG_MAIN << "menutree should be saved as ..."; // read current entry QTreeWidgetItem *current = m_menutree->currentItem(); if (current) { KILE_DEBUG_MAIN << "read current item ..."; readMenuentryData(dynamic_cast(current)); } if (saveCheck() == false) { return QString(); } - const QString directory = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') + "usermenu/"; + const QString directory = KileUtilities::writableLocation(QStandardPaths::AppDataLocation) + QLatin1Char('/') + "usermenu/"; const QString filter = i18n("User Menu Files (*.xml)"); QString filename = QFileDialog::getSaveFileName(this, i18n("Save Menu File"), directory, filter); if (filename.isEmpty()) { return QString(); } if (QFile::exists(filename)) { if (KMessageBox::questionYesNo(this, i18n("File '%1' does already exist.\nOverwrite this file?", filename)) == KMessageBox::No) { return QString(); } } // save file m_menutree->writeXml(filename); return filename; } bool UserMenuDialog::saveCheck() { if (m_menutree->errorCheck() == false) { if (KMessageBox::questionYesNo(this, i18n("The menu tree contains some errors and installing this file may lead to unpredictable results.\nDo you really want to save this file?")) == KMessageBox::No) { return false; } } return true; } ///////////////////////////// Button slots (left widget) ////////////////////////////// void UserMenuDialog::slotCustomContextMenuRequested(const QPoint &pos) { m_menutree->contextMenuRequested(pos); updateAfterDelete(); } void UserMenuDialog::slotInsertMenuItem() { if (m_menutree->insertMenuItem(m_menutree->currentItem())) { updateTreeButtons(); setModified(); } } void UserMenuDialog::slotInsertSubmenu() { QTreeWidgetItem *current = m_menutree->currentItem(); if (current && m_menutree->insertSubmenu(current)) { updateTreeButtons(); setModified(); } } void UserMenuDialog::slotInsertSeparator() { QTreeWidgetItem *current = m_menutree->currentItem(); if (current && m_menutree->insertSeparator(current)) { updateTreeButtons(); setModified(); } } void UserMenuDialog::slotDelete() { QTreeWidgetItem *current = m_menutree->currentItem(); if (current) { m_menutree->itemDelete(current); updateAfterDelete(); } } void UserMenuDialog::slotUp() { QTreeWidgetItem *current = m_menutree->currentItem(); if (current) { m_menutree->itemUp(); updateTreeButtons(); setModified(); } } void UserMenuDialog::slotDown() { QTreeWidgetItem *current = m_menutree->currentItem(); if (current) { m_menutree->itemDown(); updateTreeButtons(); setModified(); } } void UserMenuDialog::updateTreeButtons() { UserMenuItem *current = dynamic_cast(m_menutree->currentItem()); if (current) { bool state = (current->menutype() == UserMenuData::Separator) ? false : true; m_UserMenuDialog.m_pbInsertSeparator->setEnabled(state); m_UserMenuDialog.m_pbDelete->setEnabled(true); bool upstate = (m_menutree->indexOfTopLevelItem(current) == 0) ? false : true; m_UserMenuDialog.m_pbUp->setEnabled(upstate); bool downstate = (m_menutree->itemBelow(current)) ? true : false; if (!downstate && current->parent()) { downstate = true; } m_UserMenuDialog.m_pbDown->setEnabled(downstate); } else { m_UserMenuDialog.m_pbInsertSeparator->setEnabled(false); m_UserMenuDialog.m_pbDelete->setEnabled(false); m_UserMenuDialog.m_pbUp->setEnabled(false); m_UserMenuDialog.m_pbDown->setEnabled(false); } } void UserMenuDialog::updateAfterDelete() { if (m_menutree->isEmpty()) { initDialog(); } updateTreeButtons(); setModified(); } ////////////////////////////// TreeWidget slots (left widget) ////////////////////////////// void UserMenuDialog::slotCurrentItemChanged(QTreeWidgetItem *current,QTreeWidgetItem *previous) { QString from = (previous) ? previous->text(0) : "---"; QString to = (current) ? current->text(0) : "---"; KILE_DEBUG_MAIN << "currentItemChanged: from=" << from << " to=" << to; bool modifiedState = m_modified; bool installState = m_UserMenuDialog.m_pbInstall->isEnabled(); bool saveState = m_UserMenuDialog.m_pbSave->isEnabled(); bool saveAsState = m_UserMenuDialog.m_pbSaveAs->isEnabled(); // read old data readMenuentryData(dynamic_cast(previous)); // set new data showMenuentryData(dynamic_cast(current)); // update buttons for treewidget updateTreeButtons(); // restore saved states m_modified = modifiedState; m_UserMenuDialog.m_pbInstall->setEnabled(installState); m_UserMenuDialog.m_pbSave->setEnabled(saveState); m_UserMenuDialog.m_pbSaveAs->setEnabled(saveAsState); } ////////////////////////////// MenuentryType slots (right widget) ////////////////////////////// void UserMenuDialog::slotMenuentryTypeClicked() { UserMenuItem *current = dynamic_cast(m_menutree->currentItem()); if (!current) { return; } KILE_DEBUG_MAIN << "change menu item type of current item: " << current->text(0); QStringList typelist; for (int i = 0; i < CHOOSABLE_MENUTYPES; ++i) { typelist << m_listMenutypes[i]; } int oldtype = current->menutype(); bool ok = false; QString item = QInputDialog::getItem(this, i18n("Menutype"), i18n("Please choose a menutype"), typelist, oldtype, false, &ok); if (!ok) { return; } int newtype = m_listMenutypes.indexOf(item); if (newtype == -1 || newtype == oldtype) { return; } // set new values current->setMenutype( UserMenuData::MenuType(newtype) ); m_UserMenuDialog.m_lbMenuentryType->setText(item); if (newtype == UserMenuData::Text) { setMenuentryFileChooser(current,false); setMenuentryFileParameter(current,false); setMenuentryTextEdit(current,true); setMenuentryCheckboxes(current,false); } else if (newtype == UserMenuData::FileContent) { setMenuentryFileChooser(current,true); setMenuentryFileParameter(current,false); setMenuentryTextEdit(current,false); setMenuentryCheckboxes(current,false); } else { /* if (newtype == UserMenuData::Program) */ setMenuentryFileChooser(current,true); setMenuentryFileParameter(current,true); setMenuentryTextEdit(current,false); setMenuentryCheckboxes(current,true); } setModified(); } ////////////////////////////// Menuentry slot (right widget) ////////////////////////////// void UserMenuDialog::slotMenuentryTextChanged(const QString &text) { UserMenuItem *current = dynamic_cast( m_menutree->currentItem() ); if (current) { current->setText(0,text); } setModified(); } ////////////////////////////// KUrlRequester slots (right widget) ////////////////////////////// void UserMenuDialog::slotUrlTextChanged(const QString &) { UserMenuItem *current = dynamic_cast(m_menutree->currentItem()); if (!current) { return; } QString file = m_UserMenuDialog.m_urlRequester->text().trimmed(); QString color = "black"; int type = current->menutype(); if (type == UserMenuData::FileContent) { if (file.isEmpty() || !QFile::exists(file)) { color = "red"; } } else if (type == UserMenuData::Program) { if (file.isEmpty() || !m_menutree->isItemExecutable(file)) { color= "red"; } } m_UserMenuDialog.m_urlRequester->setStyleSheet( "QLineEdit { color: " + color + "; }" ); setModified(); } ////////////////////////////// Icon slots (right widget) ////////////////////////////// void UserMenuDialog::slotIconClicked() { QString iconname = KIconDialog::getIcon(KIconLoader::Small, KIconLoader::Any,true); if (iconname!=m_currentIcon && !iconname.isEmpty()) { QString iconpath = KIconLoader::global()->iconPath(iconname,KIconLoader::Small); KILE_DEBUG_MAIN << "icon changed: " << iconname << " path=" << iconpath; m_currentIcon = iconpath; setMenuentryIcon(m_currentIcon); setModified(); } } void UserMenuDialog::slotIconDeleteClicked() { m_currentIcon.clear(); setMenuentryIcon(m_currentIcon); setModified(); } void UserMenuDialog::setMenuentryIcon(const QString &icon) { UserMenuItem *current = dynamic_cast(m_menutree->currentItem()); if (current) { if (icon.isEmpty()) { current->setIcon(0, QIcon::fromTheme(QString())); } else { current->setIcon(0, QIcon::fromTheme(icon)); } current->setMenuicon(icon); // update icon widgets setMenuentryIcon(current,true,icon); setModified(); } } ////////////////////////////// Shortcut slots (right widget) ////////////////////////////// void UserMenuDialog::slotKeySequenceChanged(const QKeySequence &seq) { QString shortcut = seq.toString(QKeySequence::NativeText); KILE_DEBUG_MAIN << "key sequence changed: " << shortcut; UserMenuItem *current = dynamic_cast( m_menutree->currentItem() ); if (current) { current->setText(1, shortcut); current->setShortcut(shortcut); m_UserMenuDialog.m_keyChooser->applyStealShortcut(); setModified(); } } ////////////////////////////// Selection checkbox slots (right widget) ////////////////////////////// void UserMenuDialog::slotSelectionStateChanged(int state) { m_UserMenuDialog.m_cbContextMenu->setEnabled(state); if(!state) { m_UserMenuDialog.m_cbContextMenu->setChecked(state); } setModified(); } void UserMenuDialog::slotCheckboxStateChanged(int) { setModified(); } ////////////////////////////// read menu item data ////////////////////////////// void UserMenuDialog::readMenuentryData(UserMenuItem *item) { KILE_DEBUG_MAIN << "read current menu item ..."; if (!item) { return; } UserMenuData::MenuType type = UserMenuData::MenuType( m_listMenutypes.indexOf(m_UserMenuDialog.m_lbMenuentryType->text()) ); item->setMenutype(type); if (type == UserMenuData::Separator) { return; } item->setMenutitle(m_UserMenuDialog.m_leMenuEntry->text().trimmed()); item->setFilename(m_UserMenuDialog.m_urlRequester->text().trimmed()); item->setParameter(m_UserMenuDialog.m_leParameter->text().trimmed()); item->setPlaintext(m_UserMenuDialog.m_teText->toPlainText()); item->setMenuicon(m_currentIcon); item->setShortcut(m_UserMenuDialog.m_keyChooser->keySequence().toString(QKeySequence::NativeText)); item->setNeedsSelection(m_UserMenuDialog.m_cbNeedsSelection->checkState()); item->setUseContextMenu(m_UserMenuDialog.m_cbContextMenu->checkState()); item->setReplaceSelection(m_UserMenuDialog.m_cbReplaceSelection->checkState()); item->setSelectInsertion(m_UserMenuDialog.m_cbSelectInsertion->checkState()); item->setInsertOutput(m_UserMenuDialog.m_cbInsertOutput->checkState()); bool executable = (type==UserMenuData::Program && m_menutree->isItemExecutable(item->filename())); item->setModelData(executable); item->setText(0, item->updateMenutitle()); } ////////////////////////////// show menu item data ////////////////////////////// void UserMenuDialog::showMenuentryData(UserMenuItem *item) { KILE_DEBUG_MAIN << "show new menu item ..."; if (!item) { disableMenuEntryData(); return; } UserMenuData::MenuType type = item->menutype(); blockSignals(true); switch (type) { case UserMenuData::Text: setTextEntry(item); break; case UserMenuData::FileContent: setFileContentEntry(item); break; case UserMenuData::Program: setProgramEntry(item); break; case UserMenuData::Separator: setSeparatorEntry(item); break; case UserMenuData::Submenu: setSubmenuEntry(item); break; default: disableMenuEntryData(); // should not happen } blockSignals(false); } void UserMenuDialog::setTextEntry(UserMenuItem *item) { setMenuentryText(item, true); setMenuentryType(item, true, true); setMenuentryFileChooser(item, false); setMenuentryFileParameter(item, false); setMenuentryTextEdit(item, true); setMenuentryIcon(item, true); setMenuentryShortcut(item, true); setParameterGroupbox(true); setMenuentryCheckboxes(item, false); } void UserMenuDialog::setFileContentEntry(UserMenuItem *item) { setMenuentryText(item, true); setMenuentryType(item, true, true); setMenuentryFileChooser(item, true); setMenuentryFileParameter(item, false); setMenuentryTextEdit(item, false); setMenuentryIcon(item, true); setMenuentryShortcut(item, true); setParameterGroupbox(true); setMenuentryCheckboxes(item, false); } void UserMenuDialog::setProgramEntry(UserMenuItem *item) { setMenuentryText(item, true); setMenuentryType(item, true, true); setMenuentryFileChooser(item, true); setMenuentryFileParameter(item, true); setMenuentryTextEdit(item, false); setMenuentryIcon(item, true); setMenuentryShortcut(item, true); setParameterGroupbox(true); setMenuentryCheckboxes(item, true); } void UserMenuDialog::setSeparatorEntry(UserMenuItem *item) { disableMenuEntryData(); setMenuentryType(item, true, false); } void UserMenuDialog::setSubmenuEntry(UserMenuItem *item) { setMenuentryText(item, true); setMenuentryType(item, true, false); setMenuentryFileChooser(Q_NULLPTR, false); setMenuentryFileParameter(Q_NULLPTR, false); setMenuentryTextEdit(Q_NULLPTR, false); setMenuentryIcon(Q_NULLPTR, false); setMenuentryShortcut(Q_NULLPTR, false); setParameterGroupbox(false); setMenuentryCheckboxes(Q_NULLPTR, false); } ////////////////////////////// update data widgets////////////////////////////// void UserMenuDialog::setMenuentryType(UserMenuItem *item, bool state1, bool state2) { const QString s = (item && state1) ? m_listMenutypes[item->menutype()] : QString(); m_UserMenuDialog.m_lbMenuentryType->setText(s); m_UserMenuDialog.m_lbMenuentryType->setEnabled(state1); m_UserMenuDialog.m_pbMenuentryType->setEnabled(state2); } void UserMenuDialog::setMenuentryText(UserMenuItem *item, bool state) { const QString s = (item && state) ? item->menutitle() : QString(); m_UserMenuDialog.m_leMenuEntry->setText(s); m_UserMenuDialog.m_lbMenuEntry->setEnabled(state); m_UserMenuDialog.m_leMenuEntry->setEnabled(state); } void UserMenuDialog::setMenuentryFileChooser(UserMenuItem *item, bool state) { const QString s = (item && state) ? item->filename() : QString(); m_UserMenuDialog.m_urlRequester->setText(s); m_UserMenuDialog.m_lbFile->setEnabled(state); m_UserMenuDialog.m_urlRequester->setEnabled(state); } void UserMenuDialog::setMenuentryFileParameter(UserMenuItem *item, bool state) { const QString s = (item && state) ? item->parameter() : QString(); m_UserMenuDialog.m_leParameter->setText(s); m_UserMenuDialog.m_lbParameter->setEnabled(state); m_UserMenuDialog.m_leParameter->setEnabled(state); } void UserMenuDialog::setMenuentryTextEdit(UserMenuItem *item, bool state) { const QString s = (item && state) ? item->plaintext() : QString(); m_UserMenuDialog.m_teText->setPlainText(s); m_UserMenuDialog.m_lbText->setEnabled(state); m_UserMenuDialog.m_teText->setEnabled(state); } void UserMenuDialog::setMenuentryIcon(UserMenuItem *item, bool state, const QString &icon) { if (item && state) { m_currentIcon = (icon.isEmpty()) ? item->menuicon() : icon; } else { m_currentIcon.clear(); } // update widgets if (m_currentIcon.isEmpty()) { m_UserMenuDialog.m_lbIconChosen->setText(m_currentIcon); m_UserMenuDialog.m_lbIconChosen->hide(); m_UserMenuDialog.m_pbIcon->show(); } else { QString iconpath = KIconLoader::global()->iconPath(m_currentIcon,KIconLoader::Small); m_UserMenuDialog.m_lbIconChosen->setText(""); m_UserMenuDialog.m_lbIconChosen->show(); m_UserMenuDialog.m_pbIcon->hide(); } m_UserMenuDialog.m_lbIcon->setEnabled(state); m_UserMenuDialog.m_pbIcon->setEnabled(state); m_UserMenuDialog.m_lbIconChosen->setEnabled(state); bool deleteIconState = ( state && !m_currentIcon.isEmpty() ); m_UserMenuDialog.m_pbIconDelete->setEnabled(deleteIconState); } void UserMenuDialog::setMenuentryShortcut(UserMenuItem *item, bool state) { if (item && state) { QString shortcut = item->shortcut(); if (shortcut.isEmpty()) { m_UserMenuDialog.m_keyChooser->clearKeySequence(); } else { m_UserMenuDialog.m_keyChooser->setKeySequence(QKeySequence(shortcut)); } item->setText(1, shortcut); } else { m_UserMenuDialog.m_keyChooser->clearKeySequence(); } m_UserMenuDialog.m_lbShortcut->setEnabled(state); m_UserMenuDialog.m_keyChooser->setEnabled(state); } void UserMenuDialog::setParameterGroupbox(bool state) { m_UserMenuDialog.m_gbParameter->setEnabled(state); } void UserMenuDialog::setMenuentryCheckboxes(UserMenuItem *item, bool useInsertOutput) { bool selectionState, insertionState, outputState, replaceState, contextState; if (item) { selectionState = item->needsSelection(); replaceState = item->replaceSelection(); insertionState = item->selectInsertion(); outputState = (useInsertOutput) ? item->insertOutput() : false; contextState = (selectionState) ? item->useContextMenu() : false; } else { selectionState = false; replaceState = false; insertionState = false; outputState = false; contextState = false; } // m_cbNeedsSelection and m_cbSelectInsertion are always enabled m_UserMenuDialog.m_cbNeedsSelection->setChecked(selectionState); // m_cbContextMenu needs a selection to be enabled m_UserMenuDialog.m_cbContextMenu->setEnabled(selectionState); m_UserMenuDialog.m_cbContextMenu->setChecked(contextState); m_UserMenuDialog.m_cbReplaceSelection->setChecked(replaceState); m_UserMenuDialog.m_cbSelectInsertion->setChecked(insertionState); m_UserMenuDialog.m_cbInsertOutput->setChecked(outputState); m_UserMenuDialog.m_cbInsertOutput->setEnabled(useInsertOutput); } void UserMenuDialog::clearMenuEntryData() { m_UserMenuDialog.m_leMenuEntry->clear(); m_UserMenuDialog.m_lbMenuentryType->clear(); m_UserMenuDialog.m_urlRequester->clear(); m_UserMenuDialog.m_teText->clear(); m_UserMenuDialog.m_pbIcon->setIcon(QIcon::fromTheme(i18n("Choose"))); m_UserMenuDialog.m_keyChooser->clearKeySequence(); m_UserMenuDialog.m_cbNeedsSelection->setChecked(false); m_UserMenuDialog.m_cbReplaceSelection->setChecked(false); m_UserMenuDialog.m_cbContextMenu->setChecked(false); m_UserMenuDialog.m_cbSelectInsertion->setChecked(false); m_UserMenuDialog.m_cbInsertOutput->setChecked(false); } void UserMenuDialog::disableMenuEntryData() { setMenuentryText(Q_NULLPTR, false); setMenuentryType(Q_NULLPTR, false, false); setMenuentryFileChooser(Q_NULLPTR, false); setMenuentryFileParameter(Q_NULLPTR, false); setMenuentryTextEdit(Q_NULLPTR, false); setMenuentryIcon(Q_NULLPTR, false); setMenuentryShortcut(Q_NULLPTR, false); setParameterGroupbox(false); setMenuentryCheckboxes(Q_NULLPTR, false); } } diff --git a/src/docpart.cpp b/src/docpart.cpp index c1e0639c..bbfaea44 100644 --- a/src/docpart.cpp +++ b/src/docpart.cpp @@ -1,129 +1,129 @@ /************************************************************************************************* begin : Sun Jul 29 2001 copyright : (C) 2001 - 2003 by Brachet Pascal 2004 by Jeroen Wijnhout (Jeroen.Wijnhout@kdemail.net) - 2008 by Michel Ludwig (michel.ludwig@kdemail.net) + 2008 - 2019 by Michel Ludwig (michel.ludwig@kdemail.net) *************************************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "docpart.h" #include #include #include #include #include #include #include #include -#include #include "kiledebug.h" +#include "utilities.h" DocumentationViewer::DocumentationViewer(QWidget *parent) : KHTMLPart(parent, parent, BrowserViewGUI) { m_hpos = 0; - QString rc = QStandardPaths::locate(QStandardPaths::DataLocation, "docpartui.rc"); + QString rc = KileUtilities::locate(QStandardPaths::AppDataLocation, "docpartui.rc"); setXMLFile(rc); KStandardAction::back(this, SLOT(back()), (QObject*)actionCollection()); KStandardAction::forward(this, SLOT(forward()), (QObject*)actionCollection()); KStandardAction::home(this, SLOT(home()), (QObject*)actionCollection()); } DocumentationViewer::~DocumentationViewer() { } bool DocumentationViewer::urlSelected(const QString &url, int button, int state, const QString &_target, const KParts::OpenUrlArguments &args, const KParts::BrowserArguments & /* browserArgs */) { QUrl cURL = completeURL(url); QMimeDatabase db; QString mime = db.mimeTypeForUrl(cURL).name(); //load this URL in the embedded viewer if KHTML can handle it, or when mimetype detection failed KService::Ptr service = KService::serviceByDesktopName("khtml"); if (db.mimeTypeForUrl(cURL).isDefault() || (service && service->hasServiceType(mime))) { KHTMLPart::urlSelected(url, button, state, _target, args); openUrl(cURL); addToHistory(cURL.url()); } //KHTML can't handle it, look for an appropriate application else { KService::List offers = KMimeTypeTrader::self()->query(mime, "Type == 'Application'"); if(offers.isEmpty()) { KMessageBox::error(view(), i18n("No KDE service found for the MIME type \"%1\".", mime)); return false; } QList lst; lst.append(cURL); KRun::runService(*(offers.first()), lst, view()); } return true; } void DocumentationViewer::home() { if(!m_history.isEmpty()) { openUrl(QUrl::fromLocalFile(m_history.first())); } } void DocumentationViewer::forward() { if(forwardEnable()) { ++m_hpos; openUrl(QUrl::fromLocalFile(m_history[m_hpos])); emit updateStatus(backEnable(), forwardEnable()); } } void DocumentationViewer::back() { if(backEnable()) { --m_hpos; openUrl(QUrl::fromLocalFile(m_history[m_hpos])); emit updateStatus(backEnable(), forwardEnable()); } } void DocumentationViewer::addToHistory(const QString& url) { if(m_history.count() > 0) { while(m_hpos < m_history.count() - 1) { m_history.pop_back(); } } if(!m_history.isEmpty()) { ++m_hpos; } m_history.append(url); m_hpos = m_history.count() - 1; emit updateStatus(backEnable(), forwardEnable()); } bool DocumentationViewer::backEnable() { return (m_hpos > 0); } bool DocumentationViewer::forwardEnable() { return (m_hpos < m_history.count() - 1); } diff --git a/src/kile.cpp b/src/kile.cpp index 8e9b91b5..da33d0de 100644 --- a/src/kile.cpp +++ b/src/kile.cpp @@ -1,3046 +1,3046 @@ /**************************************************************************************** Copyright (C) 2003 by Jeroen Wijnhout (Jeroen.Wijnhout@kdemail.net) (C) 2007-2018 by Michel Ludwig (michel.ludwig@kdemail.net) (C) 2007 Holger Danielsson (holger.danielsson@versanet.de) (C) 2009 Thomas Braun (thomas.braun@virtuell-zuhause.de) ****************************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ // 2007-03-12 dani // - use KileDocument::Extensions #include "kile.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "abbreviationmanager.h" #include "configurationmanager.h" #include "documentinfo.h" #include "errorhandler.h" #include "kileactions.h" #include "kiledebug.h" #include "kilestdactions.h" #include "widgets/statusbar.h" #include "dialogs/configurationdialog.h" #include "kileproject.h" #include "widgets/projectview.h" #include "dialogs/projectdialogs.h" #include "kilelyxserver.h" #include "dialogs/findfilesdialog.h" #include "kiletool_enums.h" #include "kiletool.h" #include "kiletoolmanager.h" #include "kilestdtools.h" #include "widgets/outputview.h" #include "widgets/konsolewidget.h" #include "dialogs/quickdocumentdialog.h" #include "dialogs/tabbingdialog.h" #include "widgets/structurewidget.h" #include "convert.h" #include "dialogs/includegraphicsdialog.h" #include "kiledocmanager.h" #include "kileversion.h" #include "kileviewmanager.h" #include "kileconfig.h" #include "dialogs/configcheckerdialog.h" #include "widgets/sidebar.h" #include "dialogs/floatdialog.h" #include "dialogs/mathenvironmentdialog.h" #include "dialogs/tabular/newtabulardialog.h" #include "dialogs/postscriptdialog.h" #include "dialogs/pdf-wizard/pdfdialog.h" #include "latexcmd.h" #include "mainadaptor.h" #include "dialogs/statisticsdialog.h" #include "widgets/scriptsmanagementwidget.h" #include "scriptmanager.h" #include "widgets/previewwidget.h" #include "symbolviewclasses.h" #include "livepreview.h" #include "parser/parsermanager.h" #include "dialogs/usermenu/usermenudialog.h" #include "usermenu/usermenudata.h" #include "usermenu/usermenu.h" #include "utilities.h" #define LOG_TAB 0 #define OUTPUT_TAB 1 #define KONSOLE_TAB 2 #define PREVIEW_TAB 3 /* * Class Kile. */ Kile::Kile(bool allowRestore, QWidget *parent) : KParts::MainWindow(), KileInfo(this), m_toolsToolBar(Q_NULLPTR), // we have to set all of these to null as the constructor m_userHelpActionMenu(Q_NULLPTR), // might return early m_bibTagSettings(Q_NULLPTR), m_compilerActions(Q_NULLPTR), m_viewActions(Q_NULLPTR), m_convertActions(Q_NULLPTR), m_quickActions(Q_NULLPTR), m_bibTagActionMenu(Q_NULLPTR), ModeAction(Q_NULLPTR), WatchFileAction(Q_NULLPTR), m_actionMessageView(Q_NULLPTR), m_actRecentFiles(Q_NULLPTR), m_pFullScreen(Q_NULLPTR), m_sideBar(Q_NULLPTR), m_kileAbbrevView(Q_NULLPTR), m_topWidgetStack(Q_NULLPTR), m_horizontalSplitter(Q_NULLPTR), m_verticalSplitter(Q_NULLPTR), m_toolBox(Q_NULLPTR), m_commandViewToolBox(Q_NULLPTR), m_symbolViewMFUS(Q_NULLPTR), m_symbolViewRelation(Q_NULLPTR), m_symbolViewArrows(Q_NULLPTR), m_symbolViewMiscMath(Q_NULLPTR), m_symbolViewMiscText(Q_NULLPTR), m_symbolViewOperators(Q_NULLPTR), m_symbolViewUser(Q_NULLPTR), m_symbolViewDelimiters(Q_NULLPTR), m_symbolViewGreek(Q_NULLPTR), m_symbolViewSpecial(Q_NULLPTR), m_symbolViewCyrillic(Q_NULLPTR), m_commandView(Q_NULLPTR), m_latexOutputErrorToolBar(Q_NULLPTR), m_buildMenuTopLevel(Q_NULLPTR), m_buildMenuCompile(Q_NULLPTR), m_buildMenuConvert(Q_NULLPTR), m_buildMenuViewer(Q_NULLPTR), m_buildMenuOther(Q_NULLPTR), m_buildMenuQuickPreview(Q_NULLPTR), m_actRecentProjects(Q_NULLPTR), m_lyxserver(Q_NULLPTR) { setObjectName("Kile"); m_config = KSharedConfig::openConfig(); setStandardToolBarMenuEnabled(true); m_singlemode = true; m_viewManager= new KileView::Manager(this, actionCollection(), parent, "KileView::Manager"); viewManager()->setClient(this); // fail gracefully if we cannot instantiate Okular part correctly if(!m_viewManager->viewerPart()) { return; } - QSplashScreen splashScreen(QPixmap(QStandardPaths::locate(QStandardPaths::DataLocation, "pics/kile_splash.png")), Qt::WindowStaysOnTopHint); + QSplashScreen splashScreen(QPixmap(KileUtilities::locate(QStandardPaths::AppDataLocation, "pics/kile_splash.png")), Qt::WindowStaysOnTopHint); if(KileConfig::showSplashScreen()) { splashScreen.show(); qApp->processEvents(); } m_codeCompletionManager = new KileCodeCompletion::Manager(this, parent); // process events for correctly displaying the splash screen qApp->processEvents(); m_latexCommands = new KileDocument::LatexCommands(m_config.data(), this); // at first (dani) m_edit = new KileDocument::EditorExtension(this); m_help = new KileHelp::Help(m_edit, this); m_errorHandler = new KileErrorHandler(this, this, actionCollection()); m_quickPreview = new KileTool::QuickPreview(this); m_extensions = new KileDocument::Extensions(); m_jScriptManager = new KileScript::Manager(this, m_config.data(), actionCollection(), parent, "KileScript::Manager"); // do initializations first m_bWatchFile = false; setStatusBar(new KileWidget::StatusBar(m_errorHandler, parent)); // process events for correctly displaying the splash screen qApp->processEvents(); connect(viewManager(), &KileView::Manager::currentViewChanged, this, &Kile::newCaption); connect(viewManager(), &KileView::Manager::currentViewChanged, this, [this](QWidget* view) { activateView(view); }); connect(viewManager(), &KileView::Manager::currentViewChanged, this, &Kile::updateModeStatus); connect(viewManager(), &KileView::Manager::updateCaption, this, &Kile::newCaption); connect(viewManager(), &KileView::Manager::updateModeStatus, this, &Kile::updateModeStatus); connect(viewManager(), &KileView::Manager::cursorPositionChanged, this, &Kile::updateStatusBarCursorPosition); connect(viewManager(), &KileView::Manager::viewModeChanged, this, &Kile::updateStatusBarViewMode); connect(viewManager(), &KileView::Manager::informationMessage, this, &Kile::updateStatusBarInformationMessage); connect(viewManager(), &KileView::Manager::selectionChanged, this, &Kile::updateStatusBarSelection); connect(docManager(), &KileDocument::Manager::documentNameChanged, this, &Kile::newCaption); connect(docManager(), &KileDocument::Manager::documentUrlChanged, this, &Kile::newCaption); connect(docManager(), &KileDocument::Manager::documentReadWriteStateChanged, this, &Kile::newCaption); m_topWidgetStack = new QStackedWidget(); m_topWidgetStack->setFocusPolicy(Qt::NoFocus); m_horizontalSplitter = new QSplitter(Qt::Horizontal); setupSideBar(); m_horizontalSplitter->addWidget(m_sideBar); m_verticalSplitter = new QSplitter(Qt::Vertical); m_horizontalSplitter->addWidget(m_verticalSplitter); viewManager()->createTabs(m_verticalSplitter); connect(viewManager(), &KileView::Manager::activateView, this, &Kile::activateView); connect(viewManager(), &KileView::Manager::startQuickPreview, this, &Kile::slotQuickPreview); connect(parserManager(), &KileParser::Manager::documentParsingStarted, this, &Kile::handleDocumentParsingStarted); connect(parserManager(), &KileParser::Manager::documentParsingComplete, this, &Kile::handleDocumentParsingComplete); // process events for correctly displaying the splash screen qApp->processEvents(); setupBottomBar(); m_verticalSplitter->addWidget(m_bottomBar); m_topWidgetStack->addWidget(m_horizontalSplitter); setCentralWidget(m_topWidgetStack); // Parser manager and view manager must be created before the tool manager! m_manager = new KileTool::Manager(this, m_config.data(), m_outputWidget, m_topWidgetStack, 10000, actionCollection()); //FIXME make timeout configurable connect(m_manager, &KileTool::Manager::jumpToFirstError, m_errorHandler, &KileErrorHandler::jumpToFirstError); connect(m_manager, &KileTool::Manager::previewDone, this, &Kile::focusPreview); m_latexOutputErrorToolBar->addAction(actionCollection()->action(QLatin1String("Stop"))); errorHandler()->setErrorHandlerToolBar(m_latexOutputErrorToolBar); // add the remaining actions to m_latexOutputErrorToolBar m_bottomBar->addExtraWidget(viewManager()->getViewerControlToolBar()); m_livePreviewManager = new KileTool::LivePreviewManager(this, actionCollection()); connect(this, &Kile::masterDocumentChanged, m_livePreviewManager, &KileTool::LivePreviewManager::handleMasterDocumentChanged); m_toolFactory = new KileTool::Factory(m_manager, m_config.data(), actionCollection()); m_manager->setFactory(m_toolFactory); setupGraphicTools(); setupPreviewTools(); setupActions(); initSelectActions(); newCaption(); m_help->setUserhelp(m_manager, m_userHelpActionMenu); // kile user help (dani) // process events for correctly displaying the splash screen qApp->processEvents(); connect(docManager(), &KileDocument::Manager::updateModeStatus, this, &Kile::updateModeStatus); connect(docManager(), &KileDocument::Manager::updateStructure, viewManager(), &KileView::Manager::updateStructure); connect(docManager(), &KileDocument::Manager::closingDocument, m_kwStructure, &KileWidget::StructureWidget::closeDocumentInfo); connect(docManager(), &KileDocument::Manager::documentInfoCreated, m_kwStructure, &KileWidget::StructureWidget::addDocumentInfo); connect(docManager(), &KileDocument::Manager::updateReferences, m_kwStructure, &KileWidget::StructureWidget::updateReferences); connect(docManager(), &KileDocument::Manager::documentModificationStatusChanged, viewManager(), &KileView::Manager::reflectDocumentModificationStatus); if(KileConfig::rCVersion() < 8) { transformOldUserSettings(); transformOldUserTags(); // before Kile 2.1 shortcuts were stored in a "Shortcuts" group inside // Kile's configuration file, but this led to problems with the way of how shortcuts // are generally stored in kdelibs; we now delete the "Shortcuts" group if it // still present in Kile's configuration file. if(m_config->hasGroup("Shortcuts")) { KConfigGroup shortcutGroup = m_config->group("Shortcuts"); actionCollection()->readSettings(&shortcutGroup); m_config->deleteGroup("Shortcuts"); } if(m_config->hasGroup("Complete")) { KConfigGroup completionGroup = m_config->group("Complete"); completionGroup.deleteEntry("maxCwlFiles"); // in Kile 3.0 the UI has been changed so that this setting is no longer // needed } } readGUISettings(); readRecentFileSettings(); readConfig(); createToolActions(); // this creates the actions for the tools and user tags, which is required before 'activePartGUI' is called setupGUI(KXmlGuiWindow::StatusBar | KXmlGuiWindow::Save, "kileui.rc"); createShellGUI(true); // do not call guiFactory()->refreshActionProperties() after this! (bug 314580) m_userMenu = new KileMenu::UserMenu(this, this); connect(m_userMenu, &KileMenu::UserMenu::sendText, this, static_cast(&Kile::insertText)); connect(m_userMenu, &KileMenu::UserMenu::updateStatus, this, &Kile::slotUpdateUserMenuStatus); updateUserDefinedMenus(); // we can only do this here after the main GUI has been set up { guiFactory()->addClient(viewManager()->viewerPart()); QMenu *documentViewerMenu = static_cast(guiFactory()->container("menu_document_viewer", this)); QMenu *popup = static_cast(guiFactory()->container("menu_okular_part_viewer", viewManager()->viewerPart())); if(documentViewerMenu && popup) { // we populate our menu with the actions from the part's menu documentViewerMenu->addActions(popup->actions()); documentViewerMenu->setEnabled(false); connect(viewManager()->viewerPart(), SIGNAL(viewerMenuStateChange(bool)), documentViewerMenu, SLOT(setEnabled(bool))); } else { if(documentViewerMenu) { documentViewerMenu->setVisible(false); } delete popup; } } resize(KileConfig::mainwindowWidth(), KileConfig::mainwindowHeight()); applyMainWindowSettings(m_config->group("KileMainWindow")); restoreLastSelectedAction(); // don't call this inside 'setupTools' as it is not compatible with KParts switching! QList sizes; int verSplitTop = KileConfig::verticalSplitterTop(); int verSplitBottom = KileConfig::verticalSplitterBottom(); sizes << verSplitTop << verSplitBottom; m_verticalSplitter->setSizes(sizes); sizes.clear(); int horSplitLeft = KileConfig::horizontalSplitterLeft(); int horSplitRight = KileConfig::horizontalSplitterRight(); if(horSplitLeft <= 0 && horSplitRight <= 0) { // compute default values horSplitLeft = m_sideBar->width(); horSplitRight = width() / 2; // leave some room for the viewer part } // the size of the third widget is computed from the sizes of the two other widgets sizes << horSplitLeft << horSplitRight << width() - (horSplitLeft + horSplitRight); m_horizontalSplitter->setSizes(sizes); show(); if(KileConfig::showSplashScreen()) { splashScreen.finish(this); } // Due to 'processEvents' being called earlier we only create the DBUS adaptor and // the LyX server when all of Kile's structures have been set up. // publish the D-Bus interfaces new MainAdaptor(this); QDBusConnection dbus = QDBusConnection::sessionBus(); dbus.registerObject("/main", this); dbus.registerService("net.sourceforge.kile"); // register under a constant name m_lyxserver = new KileLyxServer(KileConfig::runLyxServer()); connect(m_lyxserver, &KileLyxServer::insert, this, [this](const KileAction::TagData &data) { insertTag(data); }); if(m_listUserTools.count() > 0) { KMessageBox::information(0, i18n("You have defined some tools in the User menu. From now on these tools will be available from the Build->Other menu and can be configured in the configuration dialog (go to the Settings menu and choose Configure Kile). This has some advantages; your own tools can now be used in a QuickBuild command if you wish."), i18n("User Tools Detected")); m_listUserTools.clear(); } if(KileConfig::rCVersion() < 8) { // if KileConfig::rCVersion() <= 0, then 'kilerc' is (most likely) fresh or empty, // otherwise, we have to ask the user if she wants to reset the tools if ((KileConfig::rCVersion() <= 0) || (KMessageBox::questionYesNo(mainWindow(), i18n("

The tool settings need to be reset for this version of Kile to function properly.
" "This will overwrite any changes you have made.

" "

Do you want to reset the tools now?

"), i18n("Tools need to be reset")) == KMessageBox::Yes)) { m_toolFactory->resetToolConfigurations(); } } restoreFilesAndProjects(allowRestore); initMenu(); updateModeStatus(); // finally init all actions for the ScriptManager m_jScriptManager->initScriptActions(); setUpdatesEnabled(false); setAutoSaveSettings(QLatin1String("KileMainWindow"),true); m_userMenu->refreshActionProperties(); setUpdatesEnabled(true); // finally, we check whether the system check assistant should be run, which is important for // version 3.0 regarding the newly introduced live preview feature const QString& lastVersionRunFor = KileConfig::systemCheckLastVersionRunForAtStartUp(); if(lastVersionRunFor.isEmpty() || compareVersionStrings(lastVersionRunFor, "2.9.91") < 0) { slotPerformCheck(); KileConfig::setSystemCheckLastVersionRunForAtStartUp(kileFullVersion); } if(m_livePreviewManager) { m_livePreviewManager->buildLivePreviewMenu(m_config.data()); m_livePreviewManager->disableBootUpMode(); } } Kile::~Kile() { KILE_DEBUG_MAIN << "cleaning up..." << endl; guiFactory()->removeClient(viewManager()->viewerPart()); delete m_userMenu; delete m_livePreviewManager; delete m_toolFactory; delete m_manager; delete m_quickPreview; delete m_edit; delete m_help; delete m_lyxserver; //QObject without parent, have to delete it ourselves delete m_latexCommands; delete m_extensions; delete m_viewManager; } // currently not usable due to https://bugs.kde.org/show_bug.cgi?id=194732 // void Kile::plugActionList(const QString& name, const QList& actionList) // { // plugActionList(name, actionList); // } // // void Kile::unplugActionList(const QString& name) // { // unplugActionList(name); // } void Kile::setupSideBar() { m_sideBar = new KileWidget::SideBar(m_horizontalSplitter); m_fileBrowserWidget = new KileWidget::FileBrowserWidget(m_extensions, m_sideBar); m_sideBar->addPage(m_fileBrowserWidget, QIcon::fromTheme("document-open"), i18n("Open File")); connect(m_fileBrowserWidget, &KileWidget::FileBrowserWidget::fileSelected, docManager(), [this](const KFileItem& item) { docManager()->fileSelected(item); }); setupProjectView(); setupStructureView(); setupSymbolViews(); setupScriptsManagementView(); setupCommandViewToolbox(); setupAbbreviationView(); m_sideBar->switchToTab(KileConfig::selectedLeftView()); m_sideBar->setVisible(KileConfig::sideBar()); m_sideBar->setDirectionalSize(KileConfig::sideBarSize()); } void Kile::setupProjectView() { KileWidget::ProjectView *projectView = new KileWidget::ProjectView(m_sideBar, this); // viewManager()->setProjectView(projectView); m_sideBar->addPage(projectView, QIcon::fromTheme("relation"), i18n("Files and Projects")); connect(projectView, QOverload::of(&KileWidget::ProjectView::fileSelected), docManager(), QOverload::of(&KileDocument::Manager::fileSelected)); connect(projectView, QOverload::of(&KileWidget::ProjectView::fileSelected), docManager(), QOverload::of(&KileDocument::Manager::fileSelected)); connect(projectView, &KileWidget::ProjectView::closeURL, docManager(), [this](const QUrl& url) { docManager()->fileClose(url); }); connect(projectView, &KileWidget::ProjectView::closeProject, docManager(), [this](const QUrl& url) { docManager()->projectClose(url); }); connect(projectView, &KileWidget::ProjectView::projectOptions, docManager(), [this](const QUrl& url) { docManager()->projectOptions(url); }); connect(projectView, &KileWidget::ProjectView::projectArchive, this, [this](const QUrl& url) { runArchiveTool(url); }); connect(projectView, &KileWidget::ProjectView::removeFromProject, docManager(), &KileDocument::Manager::removeFromProject); connect(projectView, &KileWidget::ProjectView::addFiles, docManager(), [this](const QUrl &url) { docManager()->projectAddFiles(url); }); connect(projectView, &KileWidget::ProjectView::openAllFiles, docManager(), [this](const QUrl &url) { docManager()->projectOpenAllFiles(url); }); connect(projectView, &KileWidget::ProjectView::toggleArchive, docManager(), &KileDocument::Manager::toggleArchive); connect(projectView, &KileWidget::ProjectView::addToProject, docManager(), [this](const QUrl &url) { docManager()->addToProject(url); }); connect(projectView, &KileWidget::ProjectView::saveURL, docManager(), &KileDocument::Manager::saveURL); connect(projectView, &KileWidget::ProjectView::buildProjectTree, docManager(), [this](const QUrl &url) { docManager()->buildProjectTree(url); }); connect(docManager(), &KileDocument::Manager::projectTreeChanged, projectView, &KileWidget::ProjectView::refreshProjectTree); connect(docManager(), QOverload::of(&KileDocument::Manager::removeFromProjectView), projectView, QOverload::of(&KileWidget::ProjectView::remove)); connect(docManager(), QOverload::of(&KileDocument::Manager::removeFromProjectView), projectView, QOverload::of(&KileWidget::ProjectView::remove)); connect(docManager(), QOverload::of(&KileDocument::Manager::addToProjectView), projectView, QOverload::of(&KileWidget::ProjectView::add)); connect(docManager(), QOverload::of(&KileDocument::Manager::addToProjectView), projectView, QOverload::of(&KileWidget::ProjectView::add)); connect(docManager(), &KileDocument::Manager::removeItemFromProjectView, projectView, &KileWidget::ProjectView::removeItem); connect(docManager(), QOverload::of(&KileDocument::Manager::addToProjectView), projectView, [projectView](KileProjectItem *item) { projectView->add(item); }); } void Kile::setupStructureView() { m_kwStructure = new KileWidget::StructureWidget(this, m_sideBar); m_sideBar->addPage(m_kwStructure, QIcon::fromTheme("view-list-tree"), i18n("Structure")); m_kwStructure->setFocusPolicy(Qt::ClickFocus); connect(configurationManager(), &KileConfiguration::Manager::configChanged, m_kwStructure, &KileWidget::StructureWidget::configChanged); connect(m_kwStructure, &KileWidget::StructureWidget::setCursor, this, &Kile::setCursor); connect(m_kwStructure, &KileWidget::StructureWidget::fileOpen, docManager(), [this](const QUrl &url, const QString &encoding) { docManager()->fileOpen(url, encoding); }); connect(m_kwStructure, &KileWidget::StructureWidget::fileNew, docManager(), [this](const QUrl &url) { docManager()->fileNew(url); }); connect(m_kwStructure, &KileWidget::StructureWidget::sendText, this, [this](const QString &text) { insertText(text); }); connect(m_kwStructure, &KileWidget::StructureWidget::sectioningPopup, m_edit, &KileDocument::EditorExtension::sectioningCommand); } void Kile::setupScriptsManagementView() { m_scriptsManagementWidget = new KileWidget::ScriptsManagement(this, m_sideBar); m_sideBar->addPage(m_scriptsManagementWidget, QIcon::fromTheme("preferences-plugin-script"), i18n("Scripts")); } void Kile::enableSymbolViewMFUS() { m_toolBox->setItemEnabled(m_toolBox->indexOf(m_symbolViewMFUS),true); connect(m_symbolViewRelation, &KileWidget::SymbolView::addToList, m_symbolViewMFUS, &KileWidget::SymbolView::slotAddToList); connect(m_symbolViewOperators, &KileWidget::SymbolView::addToList, m_symbolViewMFUS, &KileWidget::SymbolView::slotAddToList); connect(m_symbolViewArrows, &KileWidget::SymbolView::addToList, m_symbolViewMFUS, &KileWidget::SymbolView::slotAddToList); connect(m_symbolViewMiscMath, &KileWidget::SymbolView::addToList, m_symbolViewMFUS, &KileWidget::SymbolView::slotAddToList); connect(m_symbolViewMiscText, &KileWidget::SymbolView::addToList, m_symbolViewMFUS, &KileWidget::SymbolView::slotAddToList); connect(m_symbolViewDelimiters, &KileWidget::SymbolView::addToList, m_symbolViewMFUS, &KileWidget::SymbolView::slotAddToList); connect(m_symbolViewGreek, &KileWidget::SymbolView::addToList, m_symbolViewMFUS, &KileWidget::SymbolView::slotAddToList); connect(m_symbolViewSpecial, &KileWidget::SymbolView::addToList, m_symbolViewMFUS, &KileWidget::SymbolView::slotAddToList); connect(m_symbolViewCyrillic, &KileWidget::SymbolView::addToList, m_symbolViewMFUS, &KileWidget::SymbolView::slotAddToList); connect(m_symbolViewUser, &KileWidget::SymbolView::addToList, m_symbolViewMFUS, &KileWidget::SymbolView::slotAddToList); } void Kile::disableSymbolViewMFUS() { m_toolBox->setItemEnabled(m_toolBox->indexOf(m_symbolViewMFUS),false); m_toolBox->setItemToolTip(m_toolBox->indexOf(m_symbolViewMFUS),QString()); disconnect(m_symbolViewRelation, &KileWidget::SymbolView::addToList, m_symbolViewMFUS, &KileWidget::SymbolView::slotAddToList); disconnect(m_symbolViewOperators, &KileWidget::SymbolView::addToList, m_symbolViewMFUS, &KileWidget::SymbolView::slotAddToList); disconnect(m_symbolViewArrows, &KileWidget::SymbolView::addToList, m_symbolViewMFUS, &KileWidget::SymbolView::slotAddToList); disconnect(m_symbolViewMiscMath, &KileWidget::SymbolView::addToList, m_symbolViewMFUS, &KileWidget::SymbolView::slotAddToList); disconnect(m_symbolViewMiscText, &KileWidget::SymbolView::addToList, m_symbolViewMFUS, &KileWidget::SymbolView::slotAddToList); disconnect(m_symbolViewDelimiters, &KileWidget::SymbolView::addToList, m_symbolViewMFUS, &KileWidget::SymbolView::slotAddToList); disconnect(m_symbolViewGreek, &KileWidget::SymbolView::addToList, m_symbolViewMFUS, &KileWidget::SymbolView::slotAddToList); disconnect(m_symbolViewSpecial, &KileWidget::SymbolView::addToList, m_symbolViewMFUS, &KileWidget::SymbolView::slotAddToList); disconnect(m_symbolViewCyrillic, &KileWidget::SymbolView::addToList, m_symbolViewMFUS, &KileWidget::SymbolView::slotAddToList); disconnect(m_symbolViewUser, &KileWidget::SymbolView::addToList, m_symbolViewMFUS, &KileWidget::SymbolView::slotAddToList); } void Kile::setupSymbolViews() { m_toolBox = new QToolBox(m_sideBar); m_sideBar->addPage(m_toolBox,QIcon::fromTheme("math0"),i18n("Symbols")); m_symbolViewMFUS = new KileWidget::SymbolView(this, m_toolBox, KileWidget::SymbolView::MFUS); m_toolBox->addItem(m_symbolViewMFUS,i18n("Most Frequently Used")); m_toolBox->setItemEnabled(m_toolBox->indexOf(m_symbolViewMFUS),false); connect(m_symbolViewMFUS, &KileWidget::SymbolView::insertText, this, static_cast&)>(&Kile::insertText)); m_symbolViewRelation = new KileWidget::SymbolView(this, m_toolBox, KileWidget::SymbolView::Relation); m_toolBox->addItem(m_symbolViewRelation,QIcon::fromTheme("math1"),i18n("Relation")); connect(m_symbolViewRelation, &KileWidget::SymbolView::insertText, this, static_cast&)>(&Kile::insertText)); m_symbolViewOperators = new KileWidget::SymbolView(this, m_toolBox, KileWidget::SymbolView::Operator); m_toolBox->addItem(m_symbolViewOperators,QIcon::fromTheme("math2"),i18n("Operators")); connect(m_symbolViewOperators, &KileWidget::SymbolView::insertText, this, static_cast&)>(&Kile::insertText)); m_symbolViewArrows = new KileWidget::SymbolView(this, m_toolBox, KileWidget::SymbolView::Arrow); m_toolBox->addItem(m_symbolViewArrows,QIcon::fromTheme("math3"),i18n("Arrows")); connect(m_symbolViewArrows, &KileWidget::SymbolView::insertText, this, static_cast&)>(&Kile::insertText)); m_symbolViewMiscMath = new KileWidget::SymbolView(this, m_toolBox, KileWidget::SymbolView::MiscMath); m_toolBox->addItem(m_symbolViewMiscMath,QIcon::fromTheme("math4"),i18n("Miscellaneous Math")); connect(m_symbolViewMiscMath, &KileWidget::SymbolView::insertText, this, static_cast&)>(&Kile::insertText)); m_symbolViewMiscText = new KileWidget::SymbolView(this, m_toolBox, KileWidget::SymbolView::MiscText); m_toolBox->addItem(m_symbolViewMiscText,QIcon::fromTheme("math5"),i18n("Miscellaneous Text")); connect(m_symbolViewMiscText, &KileWidget::SymbolView::insertText, this, static_cast&)>(&Kile::insertText)); m_symbolViewDelimiters= new KileWidget::SymbolView(this, m_toolBox, KileWidget::SymbolView::Delimiters); m_toolBox->addItem(m_symbolViewDelimiters,QIcon::fromTheme("math6"),i18n("Delimiters")); connect(m_symbolViewDelimiters, &KileWidget::SymbolView::insertText, this, static_cast&)>(&Kile::insertText)); m_symbolViewGreek = new KileWidget::SymbolView(this, m_toolBox, KileWidget::SymbolView::Greek); m_toolBox->addItem(m_symbolViewGreek,QIcon::fromTheme("math7"),i18n("Greek")); connect(m_symbolViewGreek, &KileWidget::SymbolView::insertText, this, static_cast&)>(&Kile::insertText)); m_symbolViewSpecial = new KileWidget::SymbolView(this, m_toolBox, KileWidget::SymbolView::Special); m_toolBox->addItem(m_symbolViewSpecial,QIcon::fromTheme("math8"),i18n("Special Characters")); connect(m_symbolViewSpecial, &KileWidget::SymbolView::insertText, this, static_cast&)>(&Kile::insertText)); m_symbolViewCyrillic = new KileWidget::SymbolView(this, m_toolBox, KileWidget::SymbolView::Cyrillic); m_toolBox->addItem(m_symbolViewCyrillic,QIcon::fromTheme("math10"),i18n("Cyrillic Characters")); connect(m_symbolViewCyrillic, &KileWidget::SymbolView::insertText, this, static_cast&)>(&Kile::insertText)); m_symbolViewUser = new KileWidget::SymbolView(this, m_toolBox, KileWidget::SymbolView::User); m_toolBox->addItem(m_symbolViewUser,QIcon::fromTheme("math9"),i18n("User Defined")); connect(m_symbolViewUser, &KileWidget::SymbolView::insertText, this, static_cast&)>(&Kile::insertText)); for(int i = 0; i < m_toolBox->count(); ++i) { m_toolBox->setItemToolTip(i, i18n("

Move the mouse over the icons to see the corresponding LaTeX commands.
" "Click on an image to insert the corresponding command, additionally pressing \"Shift\" inserts " "it in math mode, pressing \"Ctrl\" in curly brackets.

")); } } void Kile::setupCommandViewToolbox() { m_commandViewToolBox = new KileWidget::CommandViewToolBox(this, m_sideBar); m_sideBar->addPage(m_commandViewToolBox, QIcon::fromTheme("texlion"), i18n("LaTeX")); connect(m_commandViewToolBox, &KileWidget::CommandViewToolBox::sendText, this, QOverload::of(&Kile::insertText)); } void Kile::setupAbbreviationView() { m_kileAbbrevView = new KileWidget::AbbreviationView(abbreviationManager(), m_sideBar); connect(abbreviationManager(), &KileAbbreviation::Manager::abbreviationsChanged, m_kileAbbrevView, &KileWidget::AbbreviationView::updateAbbreviations); m_sideBar->addPage(m_kileAbbrevView, QIcon::fromTheme("complete3"), i18n("Abbreviation")); connect(m_kileAbbrevView, &KileWidget::AbbreviationView::sendText, this, QOverload::of(&Kile::insertText)); } void Kile::setupBottomBar() { m_bottomBar = new KileWidget::BottomBar(this); m_bottomBar->setFocusPolicy(Qt::ClickFocus); connect(errorHandler(), &KileErrorHandler::showingErrorMessage, this, &Kile::focusLog); QWidget *widget = new QWidget(this); QHBoxLayout *layout = new QHBoxLayout(widget); layout->setMargin(0); widget->setLayout(layout); m_latexOutputErrorToolBar = new KToolBar(widget); m_latexOutputErrorToolBar->setToolButtonStyle(Qt::ToolButtonIconOnly); m_latexOutputErrorToolBar->setIconDimensions(KIconLoader::SizeSmall); m_latexOutputErrorToolBar->setOrientation(Qt::Vertical); layout->addWidget(errorHandler()->outputWidget()); layout->addWidget(m_latexOutputErrorToolBar); m_bottomBar->addPage(widget, QIcon::fromTheme("utilities-log-viewer"), i18n("Log and Messages")); m_outputWidget = new KileWidget::OutputView(this); m_outputWidget->setFocusPolicy(Qt::ClickFocus); m_outputWidget->setMinimumHeight(40); m_outputWidget->setReadOnly(true); m_bottomBar->addPage(m_outputWidget, QIcon::fromTheme("output_win"), i18n("Output")); m_texKonsole = new KileWidget::Konsole(this, this); m_bottomBar->addPage(m_texKonsole, QIcon::fromTheme("utilities-terminal"),i18n("Konsole")); connect(viewManager(), static_cast(&KileView::Manager::currentViewChanged), m_texKonsole, static_cast(&KileWidget::Konsole::sync)); m_previewWidget = new KileWidget::PreviewWidget(this, m_bottomBar); m_bottomBar->addPage(m_previewWidget, QIcon::fromTheme ("document-preview"), i18n ("Preview")); m_bottomBar->setVisible(true); m_bottomBar->switchToTab(KileConfig::bottomBarIndex()); m_bottomBar->setDirectionalSize(KileConfig::bottomBarSize()); } void Kile::setupGraphicTools() { KileConfig::setImagemagick(!(QStandardPaths::findExecutable("identify").isNull())); } void Kile::setupPreviewTools() { // search for tools bool dvipng = !(QStandardPaths::findExecutable("dvipng").isNull()); bool convert = !(QStandardPaths::findExecutable("convert").isNull()); KileConfig::setDvipng(dvipng); KileConfig::setConvert(convert); // disable some previews, if tools are missing if ( ! dvipng ) { KileConfig::setMathgroupPreviewInWidget(false); // no mathgroup preview in bottom bar if ( ! convert ) { KileConfig::setEnvPreviewInWidget(false); // no preview in bottom bar at all KileConfig::setSelPreviewInWidget(false); } } } template QAction* Kile::createAction(const QString &text, const QString &actionName, const QString& iconName, const QKeySequence& shortcut, const ContextType* context, Func function) { QAction *action = new QAction(this); action->setText(text); connect(action, &QAction::triggered, context, function); actionCollection()->addAction(actionName, action); if(!shortcut.isEmpty()) { actionCollection()->setDefaultShortcut(action, shortcut); } if(!iconName.isEmpty()) { action->setIcon(QIcon::fromTheme(iconName)); } return action; } template QAction* Kile::createAction(KStandardAction::StandardAction actionType, const QString &actionName, const ContextType* context, Func function) { QAction *action = KStandardAction::create(actionType, context, function, this); if(!actionName.isEmpty()) { action->setObjectName(actionName); } actionCollection()->addAction(actionName, action); return action; } void Kile::setupActions() { QAction *act; createAction(KStandardAction::New, "file_new", docManager(), [this]() { docManager()->fileNew(); }); createAction(KStandardAction::Open, "file_open", docManager(), [this]() { docManager()->fileOpen(); }); m_actRecentFiles = KStandardAction::openRecent(docManager(), [this](const QUrl& url) { docManager()->fileOpen(url); }, this); m_actRecentFiles->setObjectName("file_open_recent"); actionCollection()->addAction("file_open_recent", m_actRecentFiles); connect(docManager(), &KileDocument::Manager::addToRecentFiles, this, &Kile::addRecentFile); m_actRecentFiles->loadEntries(m_config->group("Recent Files")); createAction(i18n("Save All"), "file_save_all", "document-save-all", docManager(), &KileDocument::Manager::fileSaveAll); createAction(i18n("Create Template From Document..."), "template_create", docManager(), &KileDocument::Manager::createTemplate); createAction(i18n("&Remove Template..."), "template_remove", docManager(), &KileDocument::Manager::removeTemplate); createAction(KStandardAction::Close, "file_close", docManager(), [this]() { docManager()->fileClose();} ); createAction(i18n("Close All"), "file_close_all", docManager(), &KileDocument::Manager::fileCloseAll); createAction(i18n("Close All Ot&hers"), "file_close_all_others", docManager(), [this]() { docManager()->fileCloseAllOthers(); }); createAction(i18n("S&tatistics"), "Statistics", this, [this]() { showDocInfo(); }); createAction(i18n("&ASCII"), "file_export_ascii", this, [this]() { convertToASCII(); }); createAction(i18n("Latin-&1 (iso 8859-1)"), "file_export_latin1", this, [this]() { convertToEnc(); }); createAction(i18n("Latin-&2 (iso 8859-2)"), "file_export_latin2", this, [this]() { convertToEnc(); }); createAction(i18n("Latin-&3 (iso 8859-3)"), "file_export_latin3", this, [this]() { convertToEnc(); }); createAction(i18n("Latin-&4 (iso 8859-4)"), "file_export_latin4", this, [this]() { convertToEnc(); }); createAction(i18n("Latin-&5 (iso 8859-5)"), "file_export_latin5", this, [this]() { convertToEnc(); }); createAction(i18n("Latin-&9 (iso 8859-9)"), "file_export_latin9", this, [this]() { convertToEnc(); }); createAction(i18n("&Central European (cp-1250)"), "file_export_cp1250", this, [this]() { convertToEnc(); }); createAction(i18n("&Western European (cp-1252)"), "file_export_cp1252", this, [this]() { convertToEnc(); }); createAction(KStandardAction::Quit, "file_quit", this, &Kile::close); createAction(i18n("Move Tab Left"), "move_view_tab_left", "arrow-left", viewManager(), [this]() { viewManager()->moveTabLeft(); }); createAction(i18n("Move Tab Right"), "move_view_tab_right", "arrow-right", viewManager(), [this]() { viewManager()->moveTabRight(); }); createAction(i18n("Next section"), "edit_next_section", "nextsection", QKeySequence(Qt::ALT + Qt::Key_Down), m_edit, &KileDocument::EditorExtension::gotoNextSectioning); createAction(i18n("Prev section"), "edit_prev_section", "prevsection", QKeySequence(Qt::ALT + Qt::Key_Up), m_edit, &KileDocument::EditorExtension::gotoPrevSectioning); createAction(i18n("Next paragraph"), "edit_next_paragraph", "nextparagraph", QKeySequence(Qt::ALT + Qt::SHIFT + Qt::Key_Down), m_edit, [this]() { m_edit->gotoNextParagraph(); }); createAction(i18n("Prev paragraph"), "edit_prev_paragraph", "prevparagraph", QKeySequence(Qt::ALT + Qt::SHIFT + Qt::Key_Up), m_edit, [this]() { m_edit->gotoPrevParagraph(); }); createAction(i18n("Find &in Files..."), "FindInFiles", "filegrep", this, &Kile::findInFiles); createAction(i18n("Refresh Str&ucture"), "RefreshStructure", "refreshstructure", QKeySequence(Qt::Key_F12), this, &Kile::refreshStructure); //project actions createAction(i18n("&New Project..."), "project_new", "window-new", docManager(), &KileDocument::Manager::projectNew); createAction(i18n("&Open Project..."), "project_open", "project-open", docManager(), [this]() { docManager()->projectOpen(); }); m_actRecentProjects = new KRecentFilesAction(i18n("Open &Recent Project"), actionCollection()); actionCollection()->addAction("project_openrecent", m_actRecentProjects); connect(m_actRecentProjects, &KRecentFilesAction::urlSelected, docManager(), [this](const QUrl& url) { docManager()->projectOpen(url); }); connect(docManager(), &KileDocument::Manager::removeFromRecentProjects, this, &Kile::removeRecentProject); connect(docManager(), &KileDocument::Manager::addToRecentProjects, this, &Kile::addRecentProject); m_actRecentProjects->loadEntries(m_config->group("Projects")); createAction(i18n("A&dd Files to Project..."), "project_add", "project_add", docManager(), [this]() { m_docManager->projectAddFiles(); }); createAction(i18n("Refresh Project &Tree"), "project_buildtree", "project_rebuild", docManager(), [this]() { m_docManager->buildProjectTree(); }); createAction(i18n("&Archive"), "project_archive", "project_archive", this, [this]() { runArchiveTool(); }); createAction(i18n("Project &Options"), "project_options", "configure_project", docManager(), [this]() { m_docManager->projectOptions(); }); createAction(i18n("&Close Project"), "project_close", "project-development-close", docManager(), [this]() { m_docManager->projectClose(); }); // new project actions (dani) createAction(i18n("&Show Projects..."), "project_show", docManager(), &KileDocument::Manager::projectShow); createAction(i18n("Re&move Files From Project..."), "project_remove", "project_remove", docManager(), &KileDocument::Manager::projectRemoveFiles); createAction(i18n("Show Project &Files..."), "project_showfiles", "project_show", docManager(), &KileDocument::Manager::projectShowFiles); // tbraun createAction(i18n("Open All &Project Files"), "project_openallfiles", docManager(), [this]() { docManager()->projectOpenAllFiles(); }); createAction(i18n("Find in &Project..."), "project_findfiles", "projectgrep", this, &Kile::findInProjects); //build actions act = createAction(i18n("Clean"), "CleanAll", "user-trash", this, [this]() { cleanAll(); }); createAction(i18n("Next Document"), "gotoNextDocument", "go-next-view-page", QKeySequence(Qt::ALT + Qt::Key_Right), viewManager(), &KileView::Manager::gotoNextView); createAction(i18n("Previous Document"), "gotoPrevDocument", "go-previous-view-page", QKeySequence(Qt::ALT + Qt::Key_Left), viewManager(), &KileView::Manager::gotoPrevView); createAction(i18n("Focus Log/Messages View"), "focus_log", QKeySequence("CTRL+Alt+M"), this, &Kile::focusLog); createAction(i18n("Focus Output View"), "focus_output", QKeySequence("CTRL+Alt+O"), this, &Kile::focusOutput); createAction(i18n("Focus Konsole View"), "focus_konsole", QKeySequence("CTRL+Alt+K"), this, &Kile::focusKonsole); createAction(i18n("Focus Editor View"), "focus_editor", QKeySequence("CTRL+Alt+F"), this, &Kile::focusEditor); createAction(i18nc("@action: Starts the completion of the current LaTeX command", "Complete (La)TeX Command"), "edit_complete_word", "complete1", QKeySequence(Qt::SHIFT + Qt::CTRL + Qt::Key_Space), codeCompletionManager(), [this]() { codeCompletionManager()->startLaTeXCompletion(); }); createAction(i18nc("@action: Starts the input (and completion) of a LaTeX environment", "Complete LaTeX Environment"), "edit_complete_env", "complete2", QKeySequence(Qt::SHIFT + Qt::ALT + Qt::Key_Space), codeCompletionManager(), [this]() { codeCompletionManager()->startLaTeXEnvironment(); }); createAction(i18nc("@action: Starts the completion of the current abbreviation", "Complete Abbreviation"), "edit_complete_abbrev", "complete3", QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_Space), codeCompletionManager(), [this]() { codeCompletionManager()->startAbbreviationCompletion(); }); createAction(i18n("Next Bullet"), "edit_next_bullet", "nextbullet", QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_Right), m_edit, [this]() { m_edit->nextBullet(); }); createAction(i18n("Prev Bullet"), "edit_prev_bullet", "prevbullet", QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_Left), m_edit, [this]() { m_edit->prevBullet(); }); // advanced editor (dani) createAction(i18n("Environment (inside)"), "edit_select_inside_env", "selenv_i", QKeySequence("CTRL+Alt+S, E"), m_edit, &KileDocument::EditorExtension::selectEnvInside); createAction(i18n("Environment (outside)"), "edit_select_outside_env", "selenv_o", QKeySequence("CTRL+Alt+S, F"), m_edit, &KileDocument::EditorExtension::selectEnvOutside); createAction(i18n("TeX Group (inside)"), "edit_select_inside_group", "selgroup_i", QKeySequence("CTRL+Alt+S, T"), m_edit, &KileDocument::EditorExtension::selectTexgroupInside); createAction(i18n("TeX Group (outside)"), "edit_select_outside_group", "selgroup_o", QKeySequence("CTRL+Alt+S, U"), m_edit, &KileDocument::EditorExtension::selectTexgroupOutside); createAction(i18n("Math Group"), "edit_select_mathgroup", "selmath", QKeySequence("CTRL+Alt+S, M"), m_edit, [this]() { m_edit->selectMathgroup(); }); createAction(i18n("Paragraph"), "edit_select_paragraph", "selpar", QKeySequence("CTRL+Alt+S, P"), m_edit, [this]() { m_edit->selectParagraph(); }); createAction(i18n("Line"), "edit_select_line", "selline", QKeySequence("CTRL+Alt+S, L"), m_edit, [this]() { m_edit->selectLine(); }); createAction(i18n("TeX Word"), "edit_select_word", "selword", QKeySequence("CTRL+Alt+S, W"), m_edit, [this]() { m_edit->selectWord(); }); createAction(i18n("Environment (inside)"), "edit_delete_inside_env", "delenv_i", QKeySequence("CTRL+Alt+T, E"), m_edit, &KileDocument::EditorExtension::deleteEnvInside); createAction(i18n("Environment (outside)"), "edit_delete_outside_env", "delenv_o", QKeySequence("CTRL+Alt+T, F"), m_edit, &KileDocument::EditorExtension::deleteEnvOutside); createAction(i18n("TeX Group (inside)"), "edit_delete_inside_group", "delgroup_i", QKeySequence("CTRL+Alt+T, T"), m_edit, &KileDocument::EditorExtension::deleteTexgroupInside); createAction(i18n("TeX Group (outside)"), "edit_delete_outside_group", "delgroup_o",QKeySequence("CTRL+Alt+T, U"), m_edit, &KileDocument::EditorExtension::deleteTexgroupInside); createAction(i18n("Math Group"), "edit_delete_mathgroup", "delmath", QKeySequence("CTRL+Alt+T, M"), m_edit, [this]() { m_edit->deleteMathgroup(); }); createAction(i18n("Paragraph"), "edit_delete_paragraph", "delpar", QKeySequence("CTRL+Alt+T, P"), m_edit, [this]() { m_edit->deleteParagraph(); }); createAction(i18n("To End of Line"), "edit_delete_eol", "deleol", QKeySequence("CTRL+Alt+T, L"), m_edit, [this]() { m_edit->deleteEndOfLine(); }); createAction(i18n("TeX Word"), "edit_delete_word", "delword", QKeySequence("CTRL+Alt+T, W"), m_edit, [this]() { m_edit->deleteWord(); }); createAction(i18n("Go to Begin"), "edit_begin_env", "gotobeginenv", QKeySequence("CTRL+Alt+E, B"), m_edit, &KileDocument::EditorExtension::gotoBeginEnv); createAction(i18n("Go to End"), "edit_end_env", "gotoendenv", QKeySequence("CTRL+Alt+E, E"), m_edit, &KileDocument::EditorExtension::gotoEndEnv); createAction(i18n("Match"), "edit_match_env", "matchenv", QKeySequence("CTRL+Alt+E, M"), m_edit, &KileDocument::EditorExtension::matchEnv); createAction(i18n("Close"), "edit_close_env", "closeenv", QKeySequence("CTRL+Alt+E, C"), m_edit, &KileDocument::EditorExtension::closeEnv); createAction(i18n("Close All"), "edit_closeall_env", "closeallenv", QKeySequence("CTRL+Alt+E, A"), m_edit, &KileDocument::EditorExtension::closeAllEnv); createAction(i18n("Go to Begin"), "edit_begin_group", "gotobegingroup", QKeySequence("CTRL+Alt+G, B"), m_edit, &KileDocument::EditorExtension::gotoBeginTexgroup); createAction(i18n("Go to End"), "edit_end_group", "gotoendgroup", QKeySequence("CTRL+Alt+G, E"), m_edit, &KileDocument::EditorExtension::gotoEndTexgroup); createAction(i18n("Match"), "edit_match_group", "matchgroup", QKeySequence("CTRL+Alt+G, M"), m_edit, [this]() { m_edit->matchTexgroup(); }); createAction(i18n("Close"), "edit_close_group", "closegroup", QKeySequence("CTRL+Alt+G, C"), m_edit, [this]() { m_edit->closeTexgroup(); }); createAction(i18n("Selection"), "quickpreview_selection", "preview_sel", QKeySequence("CTRL+Alt+P, S"), this, &Kile::quickPreviewSelection); createAction(i18n("Environment"), "quickpreview_environment", "preview_env",QKeySequence("CTRL+Alt+P, E"), this, &Kile::quickPreviewEnvironment); createAction(i18n("Subdocument"), "quickpreview_subdocument", "preview_subdoc",QKeySequence("CTRL+Alt+P, D"), this, &Kile::quickPreviewSubdocument); createAction(i18n("Mathgroup"), "quickpreview_math", "preview_math", QKeySequence("CTRL+Alt+P, M"), this, &Kile::quickPreviewMathgroup); KileStdActions::setupStdTags(this, this, actionCollection(), this); KileStdActions::setupMathTags(this, actionCollection()); m_bibTagActionMenu = new KActionMenu(i18n("&Bibliography"), actionCollection()); m_bibTagActionMenu->setDelayed(false); actionCollection()->addAction("menu_bibliography", m_bibTagActionMenu); createAction(i18n("Clean"), "CleanBib", this, &Kile::cleanBib); m_bibTagSettings = new KSelectAction(i18n("&Settings"),actionCollection()); actionCollection()->addAction("settings_menu_bibliography", m_bibTagSettings); act = createAction(i18n("Settings for BibTeX"), "setting_bibtex", this, &Kile::rebuildBibliographyMenu); act->setCheckable(true); m_bibTagSettings->addAction(act); act = createAction(i18n("Settings for Biblatex"), "setting_biblatex", this, &Kile::rebuildBibliographyMenu); act->setCheckable(true); m_bibTagSettings->addAction(act); m_bibTagSettings->setCurrentAction(action((QString("setting_") + KileConfig::bibliographyType()).toLatin1())); rebuildBibliographyMenu(); createAction(i18n("Quick Start"), "wizard_document", "quickwizard", this, &Kile::quickDocument); connect(docManager(), &KileDocument::Manager::startWizard, this, &Kile::quickDocument); createAction(i18n("Tabular"), "wizard_tabular", "wizard_tabular", this, &Kile::quickTabular); createAction(i18n("Array"), "wizard_array", "wizard_array", this, &Kile::quickArray); createAction(i18n("Tabbing"), "wizard_tabbing", "wizard_tabbing", this, &Kile::quickTabbing); createAction(i18n("Floats"), "wizard_float", "wizard_float", this, &Kile::quickFloat); createAction(i18n("Math"), "wizard_mathenv", "wizard_math", this, &Kile::quickMathenv); createAction(i18n("Postscript Tools"), "wizard_postscript", "wizard_pstools", this, &Kile::quickPostscript); createAction(i18n("PDF Tools"), "wizard_pdf", "wizard_pdftools", this, &Kile::quickPdf); ModeAction = new KToggleAction(i18n("Define Current Document as '&Master Document'"), actionCollection()); actionCollection()->addAction("Mode", ModeAction); ModeAction->setIcon(QIcon::fromTheme("master")); connect(ModeAction, &KToggleAction::triggered, this, &Kile::toggleMasterDocumentMode); KToggleAction *showDocumentViewer = new KToggleAction(i18n("Show Document Viewer"), actionCollection()); actionCollection()->addAction("ShowDocumentViewer", showDocumentViewer); showDocumentViewer->setChecked(KileConfig::showDocumentViewer()); connect(showDocumentViewer, &KToggleAction::toggled, viewManager(), &KileView::Manager::setDocumentViewerVisible); connect(viewManager(), &KileView::Manager::documentViewerWindowVisibilityChanged, showDocumentViewer, &KToggleAction::setChecked); KToggleAction *tact = new KToggleAction(i18n("Show S&ide Bar"), actionCollection()); actionCollection()->addAction("StructureView", tact); tact->setChecked(KileConfig::sideBar()); connect(tact, &KToggleAction::toggled, m_sideBar, &Kile::setVisible); connect(m_sideBar, &KileWidget::SideBar::visibilityChanged, this, &Kile::sideOrBottomBarChanged); m_actionMessageView = new KToggleAction(i18n("Show Mess&ages Bar"), actionCollection()); actionCollection()->addAction("MessageView", m_actionMessageView); m_actionMessageView->setChecked(true); connect(m_actionMessageView, &KToggleAction::toggled, m_bottomBar, &Kile::setVisible); connect(m_bottomBar, &KileWidget::SideBar::visibilityChanged, this, &Kile::sideOrBottomBarChanged); if(m_singlemode) { ModeAction->setChecked(false); } else { ModeAction->setChecked(true); } WatchFileAction = new KToggleAction(i18n("Watch File Mode"), actionCollection()); actionCollection()->addAction("WatchFile", WatchFileAction); WatchFileAction->setIcon(QIcon::fromTheme("watchfile")); connect(WatchFileAction, &KToggleAction::toggled, this, &Kile::toggleWatchFile); if(m_bWatchFile) { WatchFileAction->setChecked(true); } else { WatchFileAction->setChecked(false); } createAction(i18n("TeX Guide"), "help_tex_guide", QKeySequence("CTRL+Alt+H, G"), m_help, &KileHelp::Help::helpTexGuide); createAction(i18n("LaTeX"), "help_latex_index", QKeySequence("CTRL+Alt+H, L"), m_help, &KileHelp::Help::helpLatexIndex); createAction(i18n("LaTeX Command"), "help_latex_command", QKeySequence("CTRL+Alt+H, C"), m_help, &KileHelp::Help::helpLatexCommand); createAction(i18n("LaTeX Subject"), "help_latex_subject", QKeySequence("CTRL+Alt+H, S"), m_help, &KileHelp::Help::helpLatexSubject); createAction(i18n("LaTeX Env"), "help_latex_env", QKeySequence("CTRL+Alt+H, E"), m_help, &KileHelp::Help::helpLatexEnvironment); createAction(i18n("Context Help"), "help_context", QKeySequence("CTRL+Alt+H, K"), m_help, [this]() { m_help->helpKeyword(); }); createAction(i18n("Documentation Browser"), "help_docbrowser", QKeySequence("CTRL+Alt+H, B"), m_help, &KileHelp::Help::helpDocBrowser); createAction(i18n("LaTeX Reference"), "help_latex_reference", "help-latex", this, &Kile::helpLaTex); createAction(i18n("&About Editor Component"), "help_about_editor", this, &Kile::aboutEditorComponent); QAction *kileconfig = KStandardAction::preferences(this, &Kile::generalOptions, actionCollection()); kileconfig->setIcon(QIcon::fromTheme("configure-kile")); createAction(KStandardAction::KeyBindings, this, &Kile::configureKeys); createAction(KStandardAction::ConfigureToolbars, this, &Kile::configureToolbars); createAction(i18n("&System Check..."), "settings_perform_check", this, &Kile::slotPerformCheck); m_userHelpActionMenu = new KActionMenu(i18n("User Help"), actionCollection()); actionCollection()->addAction("help_userhelp", m_userHelpActionMenu); m_pFullScreen = KStandardAction::fullScreen(this, &Kile::slotToggleFullScreen, this, actionCollection()); } void Kile::rebuildBibliographyMenu() { KILE_DEBUG_MAIN << " current is " << m_bibTagSettings->currentText(); QString currentItem = m_bibTagSettings->currentText(); QString name; if( currentItem == i18n("BibTeX") ) { // avoid writing i18n'ed strings to config file name = QString("bibtex"); } else if ( currentItem == i18n("Biblatex") ) { name = QString("biblatex"); } else { KILE_DEBUG_MAIN << "wrong currentItem in bibliography settings menu"; name = QString("bibtex"); } KileConfig::setBibliographyType(name); m_bibTagActionMenu->menu()->clear(); KileStdActions::setupBibTags(this, actionCollection(),m_bibTagActionMenu); m_bibTagActionMenu->addSeparator(); m_bibTagActionMenu->addAction(action("CleanBib")); m_bibTagActionMenu->addSeparator(); m_bibTagActionMenu->addAction(action("settings_menu_bibliography")); } QAction* Kile::createToolAction(const QString& toolName) { return createAction(toolName, "tool_" + toolName, KileTool::iconFor(toolName, m_config.data()), this, [this, toolName]() { runTool(toolName); }); } void Kile::createToolActions() { QStringList tools = KileTool::toolList(m_config.data()); for (QStringList::iterator i = tools.begin(); i != tools.end(); ++i) { QString toolName = *i; if(!actionCollection()->action("tool_" + toolName)) { KILE_DEBUG_MAIN << "Creating action for tool" << toolName; createToolAction(toolName); } } } void Kile::setupTools() { KILE_DEBUG_MAIN << "==Kile::setupTools()===================" << endl; if(!m_buildMenuCompile || !m_buildMenuConvert || !m_buildMenuTopLevel || !m_buildMenuQuickPreview || !m_buildMenuViewer || !m_buildMenuOther) { KILE_DEBUG_MAIN << "BUG, menu pointers are Q_NULLPTR" << (m_buildMenuCompile == Q_NULLPTR) << (m_buildMenuConvert == Q_NULLPTR) << (m_buildMenuTopLevel == Q_NULLPTR) << (m_buildMenuQuickPreview == Q_NULLPTR) << (m_buildMenuViewer == Q_NULLPTR) << (m_buildMenuOther == Q_NULLPTR); return; } QStringList tools = KileTool::toolList(m_config.data()); QString toolMenu, grp; QList *pl; QAction *act; ToolbarSelectAction *pSelectAction = Q_NULLPTR; m_compilerActions->saveCurrentAction(); m_viewActions->saveCurrentAction(); m_convertActions->saveCurrentAction(); m_quickActions->saveCurrentAction(); // do plugActionList by hand ... foreach(act, m_listQuickActions) { m_buildMenuTopLevel->removeAction(act); } m_buildMenuCompile->clear(); m_buildMenuConvert->clear(); m_buildMenuViewer->clear(); m_buildMenuOther->clear(); m_compilerActions->removeAllActions(); m_viewActions->removeAllActions(); m_convertActions->removeAllActions(); m_quickActions->removeAllActions(); for (int i = 0; i < tools.count(); ++i) { grp = KileTool::groupFor(tools[i], m_config.data()); toolMenu = KileTool::menuFor(tools[i], m_config.data()); KILE_DEBUG_MAIN << tools[i] << " is using group: " << grp << " and menu: "<< toolMenu; if(toolMenu == "none") { continue; } if ( toolMenu == "Compile" ) { pl = &m_listCompilerActions; pSelectAction = m_compilerActions; } else if ( toolMenu == "View" ) { pl = &m_listViewerActions; pSelectAction = m_viewActions; } else if ( toolMenu == "Convert" ) { pl = &m_listConverterActions; pSelectAction = m_convertActions; } else if ( toolMenu == "Quick" ) { pl = &m_listQuickActions; pSelectAction = m_quickActions; } else { pl = &m_listOtherActions; pSelectAction = Q_NULLPTR; } KILE_DEBUG_MAIN << "\tadding " << tools[i] << " " << toolMenu << " #" << pl->count() << endl; act = actionCollection()->action("tool_" + tools[i]); if(!act) { KILE_DEBUG_MAIN << "no tool for " << tools[i]; createToolAction(tools[i]); } pl->append(act); if(pSelectAction) { pSelectAction->addAction(actionCollection()->action("tool_" + tools[i])); } } m_quickActions->addSeparator(); m_quickActions->addAction(action("quickpreview_selection")); m_quickActions->addAction(action("quickpreview_environment")); m_quickActions->addAction(action("quickpreview_subdocument")); m_quickActions->addSeparator(); m_quickActions->addAction(action("quickpreview_math")); cleanUpActionList(m_listCompilerActions, tools); cleanUpActionList(m_listViewerActions, tools); cleanUpActionList(m_listConverterActions, tools); cleanUpActionList(m_listQuickActions, tools); cleanUpActionList(m_listOtherActions, tools); m_buildMenuTopLevel->insertActions(m_buildMenuQuickPreview->menuAction(),m_listQuickActions); m_buildMenuCompile->addActions(m_listCompilerActions); m_buildMenuConvert->addActions(m_listConverterActions); m_buildMenuViewer->addActions(m_listViewerActions); m_buildMenuOther->addActions(m_listOtherActions); m_compilerActions->restoreCurrentAction(); m_viewActions->restoreCurrentAction(); m_convertActions->restoreCurrentAction(); m_quickActions->restoreCurrentAction(); } void Kile::initSelectActions() { m_compilerActions = new ToolbarSelectAction(i18n("Compile"), this); m_viewActions = new ToolbarSelectAction(i18n("View"), this); m_convertActions = new ToolbarSelectAction(i18n("Convert"), this); m_quickActions = new ToolbarSelectAction(i18n("Quick"), this); actionCollection()->setShortcutsConfigurable(m_compilerActions, false); actionCollection()->setShortcutsConfigurable(m_viewActions, false); actionCollection()->setShortcutsConfigurable(m_convertActions, false); actionCollection()->setShortcutsConfigurable(m_quickActions, false); actionCollection()->addAction("list_compiler_select", m_compilerActions); actionCollection()->addAction("list_convert_select", m_convertActions); actionCollection()->addAction("list_view_select", m_viewActions); actionCollection()->addAction("list_quick_select", m_quickActions); } void Kile::saveLastSelectedAction() { KILE_DEBUG_MAIN << "Kile::saveLastSelectedAction()" << endl; QStringList list; list << "Compile" << "Convert" << "View" << "Quick"; ToolbarSelectAction *pSelectAction = Q_NULLPTR ; KConfigGroup grp = m_config->group("ToolSelectAction"); for(QStringList::Iterator it = list.begin(); it != list.end() ; ++it) { if ( *it == "Compile" ) { pSelectAction = m_compilerActions; } else if ( *it == "View" ) { pSelectAction = m_viewActions; } else if ( *it == "Convert" ) { pSelectAction = m_convertActions; } else if ( *it == "Quick" ) { pSelectAction = m_quickActions; } KILE_DEBUG_MAIN << "current item is " << pSelectAction->currentItem(); grp.writeEntry(*it, pSelectAction->currentItem()); } } void Kile::restoreLastSelectedAction() { QStringList list; list << "Compile" << "Convert" << "View" << "Quick"; ToolbarSelectAction *pSelectAction = Q_NULLPTR; int defaultAction = 0; KConfigGroup grp = m_config->group("ToolSelectAction"); for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) { if ( *it == "Compile" ) { pSelectAction = m_compilerActions; defaultAction = 9; // PDFLatex } else if ( *it == "View" ) { pSelectAction = m_viewActions; defaultAction = 4; // ViewPDF } else if ( *it == "Convert" ) { pSelectAction = m_convertActions; defaultAction = 0; } else if ( *it == "Quick" ) { pSelectAction = m_quickActions; defaultAction = 0; } int actIndex = grp.readEntry(*it, defaultAction); KILE_DEBUG_MAIN << "selecting" << actIndex << "for" << *it; pSelectAction->setCurrentItem(actIndex); } } void Kile::cleanUpActionList(QList &list, const QStringList &tools) { // KILE_DEBUG_MAIN << "cleanUpActionList tools are" << tools.join("; "); QList::iterator it, testIt; for ( it= list.begin(); it != list.end(); ++it) { QAction *act = *it; if ( act != Q_NULLPTR && !act->objectName().isEmpty() && !tools.contains(act->objectName().mid(5)) ) { if (act->associatedWidgets().contains(toolBar("toolsToolBar"))) { toolBar("toolsToolBar")->removeAction(act); } // KILE_DEBUG_MAIN << "about to delete action: " << act->objectName(); testIt = list.erase(it); if( testIt == list.end()) { break; } } } } void Kile::restoreFilesAndProjects(bool allowRestore) { if (!(allowRestore && KileConfig::restore())) { return; } QUrl url; for (int i=0; i < m_listProjectsOpenOnStart.count(); ++i) { // don't open project files as they will be opened later in this method docManager()->projectOpen(QUrl::fromUserInput(m_listProjectsOpenOnStart[i]), i, m_listProjectsOpenOnStart.count(), false); } for (int i = 0; i < m_listDocsOpenOnStart.count(); ++i) { docManager()->fileOpen(QUrl::fromUserInput(m_listDocsOpenOnStart[i]), m_listEncodingsOfDocsOpenOnStart[i]); } if (ModeAction) { ModeAction->setChecked(!m_singlemode); } updateModeStatus(); m_listProjectsOpenOnStart.clear(); m_listDocsOpenOnStart.clear(); m_listEncodingsOfDocsOpenOnStart.clear(); KILE_DEBUG_MAIN << "lastDocument=" << KileConfig::lastDocument() << endl; KTextEditor::Document *doc = docManager()->docFor(QUrl::fromUserInput(KileConfig::lastDocument())); if (doc) { viewManager()->switchToTextView(doc->url(), true); // request the focus on the view } setMasterDocumentFileName(KileConfig::singleFileMasterDocument()); } void Kile::setActive() { KILE_DEBUG_MAIN << "Activating" << endl; raise(); activateWindow(); show(); } void Kile::setLine(const QString &line) { bool ok; uint l = line.toUInt(&ok, 10); KTextEditor::View *view = viewManager()->currentTextView(); if (view && ok) { show(); raise(); activateWindow(); // be very aggressive when it comes to raising the main window to the top KWindowSystem::forceActiveWindow(winId()); focusTextView(view); editorExtension()->goToLine(l - 1, view); } } void Kile::setCursor(const QUrl &url, int parag, int index) { KTextEditor::Document *doc = docManager()->docFor(url); if(doc) { KTextEditor::View *view = (KTextEditor::View*)doc->views().first(); if(view) { view->setCursorPosition(KTextEditor::Cursor(parag, index)); focusTextView(view); } } } void Kile::runArchiveTool() { runArchiveTool(QUrl()); } void Kile::runArchiveTool(const QUrl &url) { KileTool::Archive *tool = dynamic_cast(m_manager->createTool("Archive", QString(), false)); if(!tool) { KMessageBox::error(mainWindow(), i18n("It was impossible to create the \"Archive\" tool.\n\n" "Please check and repair your installation of Kile."), i18n("Unable to Create Archive Tool")); return; } if(url.isValid()) { tool->setSource(url.toLocalFile()); } tool->prepareToRun(); m_manager->run(tool); } //TODO: move to KileView::Manager void Kile::activateView(QWidget* w, bool updateStruct /* = true */ ) //Needs to be QWidget because of QTabWidget::currentChanged { //KILE_DEBUG_MAIN << "==Kile::activateView==========================" << endl; if (!w || !w->inherits("KTextEditor::View")) { return; } //disable gui updates to avoid flickering of toolbars setUpdatesEnabled(false); QList toolBarsList = toolBars(); QHash toolBarVisibilityHash; for(QList::iterator i = toolBarsList.begin(); i != toolBarsList.end(); ++i) { KToolBar *toolBar = *i; toolBarVisibilityHash[toolBar] = toolBar->isVisible(); } KTextEditor::View* view = dynamic_cast(w); Q_ASSERT(view); for(int i = 0; i < viewManager()->textViewCount(); ++i) { KTextEditor::View *view2 = viewManager()->textView(i); if(view == view2) { continue; } guiFactory()->removeClient(view2); view2->clearFocus(); } guiFactory()->addClient(view); for(QList::iterator i = toolBarsList.begin(); i != toolBarsList.end(); ++i) { KToolBar *toolBar = *i; toolBar->setVisible(toolBarVisibilityHash[*i]); } setUpdatesEnabled(true); if(updateStruct) { viewManager()->updateStructure(); } focusTextView(view); } void Kile::updateModeStatus() { KILE_DEBUG_MAIN << "==Kile::updateModeStatus()=========="; KileProject *project = docManager()->activeProject(); QString shortName = m_masterDocumentFileName; int pos = shortName.lastIndexOf('/'); shortName.remove(0, pos + 1); if(project) { if (m_singlemode) { statusBar()->setHintText(i18n("Project: %1", project->name())); } else { statusBar()->setHintText(i18n("Project: %1 (Master document: %2)", project->name(), shortName)); } } else { if (m_singlemode) { statusBar()->setHintText(i18n("Normal mode")); } else { statusBar()->setHintText(i18n("Master document: %1", shortName)); } } if(m_singlemode) { ModeAction->setText(i18n("Define Current Document as 'Master Document'")); ModeAction->setChecked(false); } else { ModeAction->setText(i18n("Normal mode (current master document: %1)", shortName)); ModeAction->setChecked(true); } // enable or disable entries in Kile'S menu updateMenu(); KTextEditor::View *view = viewManager()->currentTextView(); // Passing Q_NULLPTR is ok updateStatusBarCursorPosition(view, (view ? view->cursorPosition() : KTextEditor::Cursor())); updateStatusBarViewMode(view); updateStatusBarSelection(view); } void Kile::openDocument(const QUrl &url) { docManager()->fileSelected(url); } void Kile::openDocument(const QString& s) { openDocument(QUrl::fromUserInput(s)); } void Kile::closeDocument() { docManager()->fileClose(); } void Kile::openProject(const QUrl &url) { docManager()->projectOpen(url); } void Kile::openProject(const QString& proj) { openProject(QUrl::fromUserInput(proj)); } void Kile::focusPreview() { m_bottomBar->switchToTab(PREVIEW_TAB); } void Kile::focusLog() { m_bottomBar->switchToTab(LOG_TAB); } void Kile::focusOutput() { m_bottomBar->switchToTab(OUTPUT_TAB); } void Kile::focusKonsole() { m_bottomBar->switchToTab(KONSOLE_TAB); } void Kile::focusEditor() { KTextEditor::View *view = viewManager()->currentTextView(); if(view) { focusTextView(view); } } void Kile::sideOrBottomBarChanged(bool visible) { if ( ! visible ) { focusEditor(); } } //FIXME: documents probably shouldn't be closed in this method yet (also see API doc of 'queryClose') bool Kile::queryClose() { KTextEditor::View *view = viewManager()->currentTextView(); if(view) { KileConfig::setLastDocument(view->document()->url().toLocalFile()); } else { KileConfig::setLastDocument(""); } //don't close Kile if embedded viewers are present KILE_DEBUG_MAIN << "==bool Kile::queryClose==========" << endl; m_listProjectsOpenOnStart.clear(); m_listDocsOpenOnStart.clear(); m_listEncodingsOfDocsOpenOnStart.clear(); for(int i = 0; i < viewManager()->textViewCount(); ++i) { KTextEditor::Document *doc = viewManager()->textView(i)->document(); const QUrl url = doc->url(); if(url.isEmpty()) { continue; } m_listDocsOpenOnStart.append(url.toLocalFile()); m_listEncodingsOfDocsOpenOnStart.append(doc->encoding()); } KILE_DEBUG_MAIN << "#projects = " << docManager()->projects().count() << endl; QList projectList = docManager()->projects(); for(QList::iterator i = projectList.begin(); i != projectList.end(); ++i) { const QUrl url = (*i)->url(); if(url.isEmpty()) { // shouldn't happen, but just in case... continue; } m_listProjectsOpenOnStart.append(url.toLocalFile()); } bool stage1 = docManager()->projectCloseAll(); bool stage2 = true; if(stage1) { stage2 = docManager()->fileCloseAll(); } bool close = stage1 && stage2; if(close) { saveSettings(); } return close; } void Kile::showDocInfo(KTextEditor::View *view) { if(!view) { view = viewManager()->currentTextView(); } if(!view) { return; } KileDocument::TextInfo *docinfo = docManager()->textInfoFor(view->document()); KileProject *project = KileInfo::docManager()->activeProject(); if(docinfo) { // we have to ensure that we always get a _valid_ docinfo object KileDialog::StatisticsDialog *dlg = new KileDialog::StatisticsDialog(project, docinfo, this, view); dlg->exec(); delete dlg; } else { qWarning() << "There is no KileDocument::Info object belonging to this document!"; } } void Kile::convertToASCII(KTextEditor::Document *doc) { if(!doc) { KTextEditor::View *view = viewManager()->currentTextView(); if(view) { doc = view->document(); } else { return; } } ConvertIO io(doc); ConvertEncToASCII conv = ConvertEncToASCII(doc->encoding(), &io); doc->setEncoding("ISO 8859-1"); conv.convert(); } void Kile::convertToEnc(KTextEditor::Document *doc) { if(!doc) { KTextEditor::View *view = viewManager()->currentTextView(); if (view) doc = view->document(); else return; } if(sender()) { ConvertIO io(doc); QString name = QString(sender()->objectName()).section('_', -1); ConvertASCIIToEnc conv = ConvertASCIIToEnc(name, &io); conv.convert(); doc->setEncoding(ConvertMap::encodingNameFor(name)); } } KileWidget::StatusBar * Kile::statusBar() { return static_cast(KXmlGuiWindow::statusBar()); } ////////////////// GENERAL SLOTS ////////////// int Kile::lineNumber() { KTextEditor::View *view = viewManager()->currentTextView(); int para = 0; if (view) { para = view->cursorPosition().line(); } return para; } void Kile::newCaption() { KTextEditor::View *view = viewManager()->currentTextView(); if(view) { const bool showFullPath = KileConfig::showFullPathInWindowTitle(); KTextEditor::Document *doc = view->document(); const QString caption = (doc->isReadWrite() ? getName(doc, !showFullPath) : i18nc("Window caption in read-only mode: [Read-Only]", "%1 [Read-Only]", getName(doc, !showFullPath))); setWindowTitle(caption); if (m_bottomBar->currentPage() && m_bottomBar->currentPage()->inherits("KileWidget::Konsole")) { m_texKonsole->sync(); } } else { setWindowTitle(""); } } void Kile::grepItemSelected(const QString &abs_filename, int line) { KILE_DEBUG_MAIN << "Open file: " << abs_filename << " (" << line << ")" << endl; docManager()->fileOpen(QUrl::fromUserInput(abs_filename)); setLine(QString::number(line)); } void Kile::findInFiles() { static QPointer dlg = 0; if (!dlg) { KILE_DEBUG_MAIN << "grep guard: create findInFiles dlg" << endl; dlg = new KileDialog::FindFilesDialog(mainWindow(), this, KileGrep::Directory); dlg->show(); connect(dlg, &KileDialog::FindFilesDialog::itemSelected, this, &Kile::grepItemSelected); } else { KILE_DEBUG_MAIN << "grep guard: show findInFiles dlg" << endl; dlg->activateWindow(); dlg->raise(); } } void Kile::findInProjects() { static QPointer project_dlg = Q_NULLPTR; if(!project_dlg) { KILE_DEBUG_MAIN << "grep guard: create findInProjects dlg" << endl; project_dlg = new KileDialog::FindFilesDialog(mainWindow(), this, KileGrep::Project); project_dlg->show(); connect(project_dlg, &KileDialog::FindFilesDialog::itemSelected, this, &Kile::grepItemSelected); } else { KILE_DEBUG_MAIN << "grep guard: show findInProjects dlg" << endl; project_dlg->activateWindow(); project_dlg->raise(); } } /////////////////// PART & EDITOR WIDGET ////////// bool Kile::resetPart() { KILE_DEBUG_MAIN << "==Kile::resetPart()=============================" << endl; statusBar()->reset(); updateModeStatus(); newCaption(); KTextEditor::View *view = viewManager()->currentTextView(); if (view) { activateView(view); } return true; } void Kile::updateUserDefinedMenus() { m_buildMenuTopLevel = dynamic_cast(m_mainWindow->guiFactory()->container("menu_build", m_mainWindow)); m_buildMenuCompile = dynamic_cast(m_mainWindow->guiFactory()->container("menu_compile", m_mainWindow)); m_buildMenuConvert = dynamic_cast(m_mainWindow->guiFactory()->container("menu_convert", m_mainWindow)); m_buildMenuViewer = dynamic_cast(m_mainWindow->guiFactory()->container("menu_viewer", m_mainWindow)); m_buildMenuOther = dynamic_cast(m_mainWindow->guiFactory()->container("menu_other", m_mainWindow)); m_buildMenuQuickPreview = dynamic_cast(m_mainWindow->guiFactory()->container("quickpreview", m_mainWindow)); m_userMenu->updateGUI(); setupTools(); } void Kile::enableGUI(bool enable) { // update action lists QList actions = actionCollection()->actions(); for(QList::iterator itact = actions.begin(); itact != actions.end(); ++itact) { if (m_dictMenuAction.contains((*itact)->objectName()) || m_dictMenuFile.contains((*itact)->objectName())) { (*itact)->setEnabled(enable); } } // update latex usermenu actions if ( m_userMenu ) { QList useractions = m_userMenu->menuActions(); foreach ( QAction *action, useractions ) { action->setEnabled(enable); } } // enable or disable userhelp entries m_help->enableUserhelpEntries(enable); QList actionList; actionList << m_listQuickActions << m_listCompilerActions << m_listConverterActions << m_listViewerActions << m_listOtherActions; // enable or disable list actions for(QList::iterator i = actionList.begin(); i != actionList.end(); ++i) { (*i)->setEnabled(enable); } // enable or disable bibliography menu entries actionList = m_bibTagActionMenu->menu()->actions(); for(QList::iterator it = actionList.begin(); it != actionList.end(); ++it) { (*it)->setEnabled(enable); } QStringList menuList; menuList << "file" << "edit" << "view" << "menu_build" << "menu_project" << "menu_latex" << "wizard" << "tools"; for(QStringList::iterator it = menuList.begin(); it != menuList.end(); ++it) { QMenu *menu = dynamic_cast(guiFactory()->container(*it, this)); if(menu) { updateMenuActivationStatus(menu); } } updateUserMenuStatus(enable); } // adds action names to their lists void Kile::initMenu() { QStringList projectlist,filelist,actionlist; projectlist << "project_add" << "project_remove" << "project_showfiles" << "project_buildtree" << "project_options" << "project_findfiles" << "project_archive" << "project_close" << "project_openallfiles" ; filelist // file << "convert" // edit << "goto_menu" << "complete" << "bullet" << "select" << "delete" << "environment" << "texgroup" // build << "quickpreview" << "menu_compile" << "menu_convert" << "menu_viewers" << "menu_other" // latex << "menu_preamble" << "menu_lists" << "menu_sectioning" << "references" << "menu_environment" << "menu_listenv" << "menu_tabularenv" << "menu_floatenv" << "menu_code" << "menu_math" << "menu_mathenv" << "menu_mathamsenv" << "menu_bibliography" << "menu_fontstyles" << "menu_spacing" ; actionlist // file << "file_save_copy_as" << "file_save_all" << "template_create" << "Statistics" << "file_close" << "file_close_all" << "file_close_all_others" // edit << "RefreshStructure" // view << "gotoPrevDocument" << "gotoNextDocument" // build << "quickpreview_selection" << "quickpreview_environment" << "quickpreview_subdocument" << "quickpreview_math" << "WatchFile" << "CleanAll" // latex << "tag_documentclass" << "tag_usepackage" << "tag_amspackages" << "tag_env_document" << "tag_author" << "tag_title" << "tag_maketitle" << "tag_titlepage" << "tag_env_abstract" << "tag_tableofcontents" << "tag_listoffigures" << "tag_listoftables" << "tag_makeindex" << "tag_printindex" << "tag_makeglossary" << "tag_env_thebibliography" << "tag_part" << "tag_chapter" << "tag_section" << "tag_subsection" << "tag_subsubsection" << "tag_paragraph" << "tag_subparagraph" << "tag_label" << "tag_ref" << "tag_pageref" << "tag_index" << "tag_footnote" << "tag_cite" // << "citeViewBib" << "tag_center" << "tag_flushleft" << "tag_flushright" << "tag_env_minipage" << "tag_quote" << "tag_quotation" << "tag_verse" << "tag_env_itemize" << "tag_env_enumerate" << "tag_env_description" << "tag_item" << "tag_env_tabular" << "tag_env_tabular*" << "tag_env_tabbing" << "tag_multicolumn" << "tag_hline" << "tag_vline" << "tag_cline" << "tag_figure" << "tag_table" << "tag_verbatim" << "tag_env_verbatim*" << "tag_verb" << "tag_verb*" << "tag_mathmode" << "tag_equation" << "tag_subscript" << "tag_superscript" << "tag_sqrt" << "tag_nroot" << "tag_left" << "tag_right" << "tag_leftright" << "tag_bigl" << "tag_bigr" << "tag_Bigl" << "tag_Bigr" << "tag_biggl" << "tag_biggr" << "tag_Biggl" << "tag_Biggr" << "tag_text" << "tag_intertext" << "tag_boxed" << "tag_frac" << "tag_dfrac" << "tag_tfrac" << "tag_binom" << "tag_dbinom" << "tag_tbinom" << "tag_xleftarrow" << "tag_xrightarrow" << "tag_mathrm" << "tag_mathit" << "tag_mathbf" << "tag_mathsf" << "tag_mathtt" << "tag_mathcal" << "tag_mathbb" << "tag_mathfrak" << "tag_acute" << "tag_grave" << "tag_tilde" << "tag_bar" << "tag_vec" << "tag_hat" << "tag_check" << "tag_breve" << "tag_dot" << "tag_ddot" << "tag_space_small" << "tag_space_medium" << "tag_space_large" << "tag_quad" << "tag_qquad" << "tag_enskip" << "tag_env_displaymath" << "tag_env_equation" << "tag_env_equation*" << "tag_env_array" << "tag_env_multline" << "tag_env_multline*" << "tag_env_split" << "tag_env_gather" << "tag_env_gather*" << "tag_env_align" << "tag_env_align*" << "tag_env_flalign" << "tag_env_flalign*" << "tag_env_alignat" << "tag_env_alignat*" << "tag_env_aligned" << "tag_env_gathered" << "tag_env_alignedat" << "tag_env_cases" << "tag_env_matrix" << "tag_env_pmatrix" << "tag_env_vmatrix" << "tag_env_VVmatrix" << "tag_env_bmatrix" << "tag_env_BBmatrix" // bibliography stuff << "menu_bibliography" << "setting_bibtex" << "setting_biblatex" << "tag_textit" << "tag_textsl" << "tag_textbf" << "tag_underline" << "tag_texttt" << "tag_textsc" << "tag_emph" << "tag_strong" << "tag_rmfamily" << "tag_sffamily" << "tag_ttfamily" << "tag_mdseries" << "tag_bfseries" << "tag_upshape" << "tag_itshape" << "tag_slshape" << "tag_scshape" << "tag_newline" << "tag_newpage" << "tag_linebreak" << "tag_pagebreak" << "tag_bigskip" << "tag_medskip" << "tag_smallskip" << "tag_hspace" << "tag_hspace*" << "tag_vspace" << "tag_vspace*" << "tag_hfill" << "tag_hrulefill" << "tag_dotfill" << "tag_vfill" << "tag_includegraphics" << "tag_include" << "tag_input" // wizard << "wizard_tabular" << "wizard_array" << "wizard_tabbing" << "wizard_float" << "wizard_mathenv" << "wizard_usermenu" << "wizard_usermenu2" // settings << "Mode" // help << "help_context" // action lists << "structure_list" << "size_list" << "other_list" << "left_list" << "right_list" // tool lists << "list_compiler_select" << "list_convert_select" << "list_view_select" << "list_quick_select" // user help << "help_userhelp" << "edit_next_bullet" << "edit_prev_bullet" << "edit_next_section" << "edit_prev_section" << "edit_next_paragraph" << "edit_prev_paragraph" << "edit_select_inside_env" << "edit_select_outside_env" << "edit_select_inside_group" << "edit_select_outside_group" << "edit_select_mathgroup" << "edit_select_paragraph" << "edit_select_line" << "edit_select_word" << "edit_delete_inside_env" << "edit_delete_outside_env" << "edit_delete_inside_group" << "edit_delete_outside_group" << "edit_delete_mathgroup" << "edit_delete_paragraph" << "edit_delete_eol" << "edit_delete_word" << "edit_complete_word" << "edit_complete_env" << "edit_complete_abbrev" << "edit_begin_env" << "edit_end_env" << "edit_match_env" << "edit_close_env" << "edit_closeall_env" << "edit_begin_group" << "edit_end_group" << "edit_match_group" << "edit_close_group" << "file_export_ascii" << "file_export_latin1" << "file_export_latin2" << "file_export_latin3" << "file_export_latin4" << "file_export_latin5" << "file_export_latin9" << "file_export_cp1250" << "file_export_cp1252" ; setMenuItems(projectlist,m_dictMenuProject); setMenuItems(filelist,m_dictMenuFile); setMenuItems(actionlist,m_dictMenuAction); } void Kile::setMenuItems(QStringList &list, QMap &dict) { for ( QStringList::Iterator it=list.begin(); it!=list.end(); ++it ) { dict[(*it)] = true; } } void Kile::updateMenu() { KILE_DEBUG_MAIN << "==Kile::updateMenu()====================" << endl; QAction *a; QMap::Iterator it; // update project menus m_actRecentProjects->setEnabled( m_actRecentProjects->items().count() > 0 ); bool project_open = ( docManager()->isProjectOpen() ) ; for ( it=m_dictMenuProject.begin(); it!=m_dictMenuProject.end(); ++it ) { a = actionCollection()->action(it.key()); if(a) { a->setEnabled(project_open); } } // project_show is only enabled, when more than 1 project is opened a = actionCollection()->action("project_show"); if(a) { a->setEnabled(project_open && docManager()->projects().count() > 1); } // update file menus m_actRecentFiles->setEnabled( m_actRecentFiles->items().count() > 0 ); bool file_open = ( viewManager()->currentTextView() ); KILE_DEBUG_MAIN << "\tprojectopen=" << project_open << " fileopen=" << file_open << endl; enableGUI(file_open); } bool Kile::updateMenuActivationStatus(QMenu *menu) { return updateMenuActivationStatus(menu, QSet()); } bool Kile::updateMenuActivationStatus(QMenu *menu, const QSet& visited) { if(visited.contains(menu)) { qWarning() << "Recursive menu structure detected - aborting!"; return true; } if(menu->objectName() == "usermenu-submenu") { menu->setEnabled(true); return true; } bool enabled = false; QList actionList = menu->actions(); for(QList::iterator it = actionList.begin(); it != actionList.end(); ++it) { QAction *action = *it; QMenu *subMenu = action->menu(); if(subMenu) { QSet newVisited(visited); newVisited.insert(menu); if(updateMenuActivationStatus(subMenu, newVisited)) { enabled = true; } } else if(!action->isSeparator() && action->isEnabled()) { enabled = true; } } menu->setEnabled(enabled); return enabled; } void Kile::updateLatexenuActivationStatus(QMenu *menu, bool state) { if ( menu->isEmpty() || !viewManager()->currentTextView() ) { state = false; } menu->menuAction()->setVisible(state); } void Kile::runTool(const QString& tool) { runToolWithConfig(tool, QString()); } void Kile::runToolWithConfig(const QString &toolName, const QString &config) { KILE_DEBUG_MAIN << toolName << config; focusLog(); KileTool::Base *tool = m_manager->createTool(toolName, config); if(!tool || (tool->requestSaveAll() && !m_docManager->fileSaveAll())) { delete tool; return; } return m_manager->run(tool); } void Kile::cleanAll(KileDocument::TextInfo *docinfo) { const QString noactivedoc = i18n("There is no active document or it is not saved."); if(!docinfo) { KTextEditor::Document *doc = activeTextDocument(); if (doc) { docinfo = docManager()->textInfoFor(doc); } else { errorHandler()->printMessage(KileTool::Error, noactivedoc, i18n("Clean")); return; } } if (docinfo) { docManager()->cleanUpTempFiles(docinfo->url(), false); } } void Kile::refreshStructure() { viewManager()->updateStructure(true); } void Kile::insertTag(const KileAction::TagData& data) { errorHandler()->clearMessages(); if(data.description.length() > 0) { focusLog(); errorHandler()->printMessage(data.description); } KTextEditor::View *view = viewManager()->currentTextView(); if(!view) { return; } focusTextView(view); editorExtension()->insertTag(data, view); } void Kile::insertTag(const QString& tagB, const QString& tagE, int dx, int dy) { insertTag(KileAction::TagData(QString(), tagB, tagE, dx, dy)); } void Kile::insertAmsTag(const KileAction::TagData& data) { insertTag(data, QStringList("amsmath")); } void Kile::insertTag(const KileAction::TagData& data,const QList &pkgs) { QStringList packages; QString pkgName; QList::const_iterator it; for(it = pkgs.begin(); it != pkgs.end() ; it++) { pkgName = (*it).name; if(!pkgName.isEmpty()) { packages.append(pkgName); } } insertTag(data,packages); } void Kile::insertTag(const KileAction::TagData& data,const QStringList &pkgs) { KILE_DEBUG_MAIN << "void Kile::insertTag(const KileAction::TagData& data,const QStringList " << pkgs.join(",") << ")" << endl; insertTag(data); KileDocument::TextInfo *docinfo = docManager()->textInfoFor(getCompileName()); if(docinfo) { QStringList packagelist = allPackages(docinfo); QStringList::const_iterator it; QStringList warnPkgs; for ( it = pkgs.begin(); it != pkgs.end(); ++it) { if(!packagelist.contains(*it)) { warnPkgs.append(*it); } } if(warnPkgs.count() > 0) { if(warnPkgs.count() == 1) { errorHandler()->printMessage(KileTool::Error, i18n("You have to include the package %1.", warnPkgs.join(",")), i18n("Insert text")); } else { errorHandler()->printMessage(KileTool::Error, i18n("You have to include the packages %1.", warnPkgs.join(",")), i18n("Insert text")); } } } } void Kile::insertText(const QString &text) { if(text.indexOf("%C")>=0) insertTag(KileAction::TagData(QString(), text, QString(), 0, 0)); else insertTag(KileAction::TagData(QString(), text, "%C", 0, 0)); } void Kile::insertText(const QString &text, const QStringList &pkgs) { insertTag(KileAction::TagData(QString(), text, "%C", 0, 0), pkgs); } void Kile::insertText(const QString &text, const QList &pkgs) { insertTag(KileAction::TagData(QString(), text, "%C", 0, 0), pkgs); } void Kile::quickDocument() { KileDialog::QuickDocument *dlg = new KileDialog::QuickDocument(m_config.data(), this, "Quick Start", i18n("Quick Start")); if(dlg->exec()) { if(!viewManager()->currentTextView()) { docManager()->createNewLaTeXDocument(); } insertTag( dlg->tagData() ); viewManager()->updateStructure(true); } delete dlg; } void Kile::quickArray() { quickTabulardialog(false); } void Kile::quickTabular() { quickTabulardialog(true); } void Kile::quickTabulardialog(bool tabularenv) { if(!viewManager()->currentTextView()) { return; } QString env; if(tabularenv) { KConfigGroup group = m_config->group("Wizard"); env = group.readEntry("TabularEnvironment", "tabular"); } else { env = "array"; } KileDialog::NewTabularDialog dlg(env, m_latexCommands, m_config.data(), this); if(dlg.exec()) { insertTag(dlg.tagData(), dlg.requiredPackages()); if(tabularenv) { KConfigGroup group = m_config->group("Wizard"); group.writeEntry("TabularEnvironment", dlg.environment()); m_config->sync(); } } } void Kile::quickTabbing() { if(!viewManager()->currentTextView()) { return; } KileDialog::QuickTabbing *dlg = new KileDialog::QuickTabbing(m_config.data(), this, this, "Tabbing", i18n("Tabbing")); if(dlg->exec()) { insertTag(dlg->tagData()); } delete dlg; } void Kile::quickFloat() { if(!viewManager()->currentTextView()) { return; } KileDialog::FloatEnvironmentDialog *dlg = new KileDialog::FloatEnvironmentDialog(m_config.data(), this, this); if(dlg->exec()) { insertTag(dlg->tagData()); } delete dlg; } void Kile::quickMathenv() { if(!viewManager()->currentTextView()) { return; } KileDialog::MathEnvironmentDialog *dlg = new KileDialog::MathEnvironmentDialog(this, m_config.data(), this, m_latexCommands); if(dlg->exec()) { insertTag(dlg->tagData()); } delete dlg; } void Kile::quickPostscript() { QString startdir = QDir::homePath(); QString texfilename; KTextEditor::View *view = viewManager()->currentTextView(); if(view) { startdir = QFileInfo(view->document()->url().toLocalFile()).path(); texfilename = getCompileName(); } KileDialog::PostscriptDialog *dlg = new KileDialog::PostscriptDialog(this, texfilename, startdir, m_extensions->latexDocuments(), errorHandler(), m_outputWidget); dlg->exec(); delete dlg; } void Kile::quickPdf() { QString startDir = QDir::homePath(); QString texFileName; KTextEditor::View *view = viewManager()->currentTextView(); if(view) { startDir = QFileInfo(view->document()->url().toLocalFile()).path(); texFileName = getCompileName(); } KileDialog::PdfDialog *dlg = new KileDialog::PdfDialog(m_mainWindow, texFileName, startDir, m_extensions->latexDocuments(), m_manager, errorHandler(), m_outputWidget); dlg->exec(); delete dlg; } void Kile::quickUserMenuDialog() { m_userMenu->removeShortcuts(); QPointer dlg = new KileMenu::UserMenuDialog(m_config.data(), this, m_userMenu, m_userMenu->xmlFile(), m_mainWindow); dlg->exec(); connect(dlg, &QDialog::finished, this, [this] (int result) { Q_UNUSED(result); // tell all the documents and views to update their action shortcuts (bug 247646) docManager()->reloadXMLOnAllDocumentsAndViews(); // a new usermenu could have been installed, even if the return value is QDialog::Rejected m_userMenu->refreshActionProperties(); }); delete dlg; } void Kile::slotUpdateUserMenuStatus() { KILE_DEBUG_MAIN << "slot update usermenu status"; updateUserMenuStatus(true); } void Kile::updateUserMenuStatus(bool state) { KILE_DEBUG_MAIN << "update usermenu status"; if(m_userMenu) { QMenu *menu = m_userMenu->getMenuItem(); if(menu) { updateLatexenuActivationStatus(menu,state); } } } void Kile::helpLaTex() { - QString loc = QStandardPaths::locate(QStandardPaths::DataLocation, "help/latexhelp.html"); + QString loc = KileUtilities::locate(QStandardPaths::AppDataLocation, "help/latexhelp.html"); KileTool::Base *tool = toolManager()->createTool("ViewHTML", QString(), false); if(!tool) { errorHandler()->printMessage(KileTool::Error, i18n("Could not create the \"ViewHTML\" tool. Please reset the tools.")); return; } tool->setFlags(KileTool::NeedSourceExists | KileTool::NeedSourceRead); tool->setSource(loc); tool->setTargetPath(loc); tool->prepareToRun(); m_manager->run(tool); } void Kile::readGUISettings() { } // transform old user tags to xml file void Kile::transformOldUserTags() { KILE_DEBUG_MAIN << "Convert old user tags"; - QString xmldir = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/usermenu/"; + QString xmldir = KileUtilities::writableLocation(QStandardPaths::AppDataLocation) + "/usermenu/"; // create dir if not existing QDir testDir(xmldir); if (!testDir.exists()) { testDir.mkpath(xmldir); } KConfigGroup userGroup = m_config->group("User"); int len = userGroup.readEntry("nUserTags", 0); if ( len > 0) { QString usertagfile = "usertags.xml"; QString filename = xmldir + usertagfile; KILE_DEBUG_MAIN << "-convert user tags " << filename; QFile file(filename); if ( !file.open(QFile::WriteOnly | QFile::Text) ) { KILE_DEBUG_MAIN << "-Error - could not open file to write: " << filename; return; } KILE_DEBUG_MAIN << "Write xml: " << filename; QXmlStreamWriter xml(&file); xml.setAutoFormatting(true); xml.setAutoFormattingIndent(2) ; xml.writeStartDocument(); xml.writeStartElement("UserMenu"); for (int i = 0; i < len; ++i) { const QString tagNameConfigKey = "userTagName" + QString::number(i); const QString tagname = userGroup.readEntry(tagNameConfigKey, i18n("No Name")); const QString tagConfigKey = "userTag" + QString::number(i); QString tag = userGroup.readEntry(tagConfigKey, ""); tag = tag.replace('\n',"\\n"); xml.writeStartElement("menu"); xml.writeAttribute("type", "text"); xml.writeTextElement(KileMenu::UserMenuData::xmlMenuTagName(KileMenu::UserMenuData::XML_TITLE), tagname); xml.writeTextElement(KileMenu::UserMenuData::xmlMenuTagName(KileMenu::UserMenuData::XML_PLAINTEXT), tag); xml.writeTextElement(KileMenu::UserMenuData::xmlMenuTagName(KileMenu::UserMenuData::XML_SHORTCUT), QString("Ctrl+Shift+%1").arg(i+1)); xml.writeEndElement(); userGroup.deleteEntry(tagNameConfigKey); userGroup.deleteEntry(tagConfigKey); } xml.writeEndDocument(); file.close(); // save current xml file KileConfig::setUserMenuFile(usertagfile); } userGroup.deleteEntry("nUserTags"); } void Kile::transformOldUserSettings() { //delete old editor key if(m_config->hasGroup("Editor")) { m_config->deleteGroup("Editor"); } //convert user tools to new KileTool classes KConfigGroup userGroup = m_config->group("User"); userItem tempItem; int len = userGroup.readEntry("nUserTools", 0); for (int i=0; i< len; ++i) { tempItem.name = userGroup.readEntry("userToolName" + QString::number(i), i18n("no name")); tempItem.tag = userGroup.readEntry("userTool" + QString::number(i), ""); m_listUserTools.append(tempItem); } if(len > 0) { //move the tools userGroup.writeEntry("nUserTools", 0); for(int i = 0; i < len; ++i) { tempItem = m_listUserTools[i]; KConfigGroup toolsGroup = m_config->group("Tools"); toolsGroup.writeEntry(tempItem.name, "Default"); KileTool::setGUIOptions(tempItem.name, "Other", "preferences-other", m_config.data()); KConfigGroup group = m_config->group(KileTool::groupFor(tempItem.name, "Default")); QString bin = KRun::binaryName(tempItem.tag, false); group.writeEntry("command", bin); group.writeEntry("options", tempItem.tag.mid(bin.length())); group.writeEntry("class", "Base"); group.writeEntry("type", "Process"); group.writeEntry("from", ""); group.writeEntry("to", ""); if(i < 10) { QAction *toolAction = static_cast(actionCollection()->action("tool_" + tempItem.name)); actionCollection()->setDefaultShortcut(toolAction, "Alt+Shift+" + QString::number(i + 1)); //should be alt+shift+ } } } } void Kile::readRecentFileSettings() { KConfigGroup group = m_config->group("FilesOpenOnStart"); int n = group.readEntry("NoDOOS", 0); for (int i = 0; i < n; ++i) { const QString urlString = group.readPathEntry("DocsOpenOnStart" + QString::number(i), ""); if(urlString.isEmpty()) { continue; } m_listDocsOpenOnStart.append(urlString); m_listEncodingsOfDocsOpenOnStart.append(group.readPathEntry("EncodingsOfDocsOpenOnStart" + QString::number(i), "")); } n = group.readEntry("NoPOOS", 0); for(int i = 0; i < n; ++i) { const QString urlString = group.readPathEntry("ProjectsOpenOnStart" + QString::number(i), ""); if(urlString.isEmpty()) { continue; } m_listProjectsOpenOnStart.append(urlString); } } void Kile::readConfig() { m_codeCompletionManager->readConfig(m_config.data()); if(m_livePreviewManager) { m_livePreviewManager->readConfig(m_config.data()); } //m_edit->initDoubleQuotes(); m_edit->readConfig(); docManager()->updateInfos(); m_jScriptManager->readConfig(); docManager()->readConfig(); viewManager()->readConfig(m_horizontalSplitter); // set visible views in sidebar m_sideBar->setPageVisible(m_scriptsManagementWidget, KileConfig::scriptingEnabled()); m_sideBar->setPageVisible(m_commandViewToolBox, KileConfig::showCwlCommands()); m_sideBar->setPageVisible(m_kileAbbrevView, KileConfig::completeShowAbbrev()); m_scriptsManagementWidget->setScriptNameColumnWidth(KileConfig::scriptNameColumnWidth()); if(KileConfig::displayMFUS()) { enableSymbolViewMFUS(); } else { disableSymbolViewMFUS(); } m_commandViewToolBox->readCommandViewFiles(); abbreviationManager()->readAbbreviationFiles(); } void Kile::saveSettings() { m_fileBrowserWidget->writeConfig(); if(m_livePreviewManager) { m_livePreviewManager->writeConfig(); } m_symbolViewMFUS->writeConfig(); saveLastSelectedAction(); // Store recent files m_actRecentFiles->saveEntries(m_config->group("Recent Files")); m_actRecentProjects->saveEntries(m_config->group("Projects")); m_config->deleteGroup("FilesOpenOnStart"); if (KileConfig::restore()) { KConfigGroup configGroup = m_config->group("FilesOpenOnStart"); KileConfig::setSingleFileMasterDocument(getMasterDocumentFileName()); configGroup.writeEntry("NoDOOS", m_listDocsOpenOnStart.count()); for (int i = 0; i < m_listDocsOpenOnStart.count(); ++i) { configGroup.writePathEntry("DocsOpenOnStart" + QString::number(i), m_listDocsOpenOnStart[i]); configGroup.writePathEntry("EncodingsOfDocsOpenOnStart" + QString::number(i), m_listEncodingsOfDocsOpenOnStart[i]); } configGroup.writeEntry("NoPOOS", m_listProjectsOpenOnStart.count()); for (int i = 0; i < m_listProjectsOpenOnStart.count(); ++i) { configGroup.writePathEntry("ProjectsOpenOnStart"+QString::number(i), m_listProjectsOpenOnStart[i]); } } KConfigGroup configGroup = KSharedConfig::openConfig()->group("KileMainWindow"); saveMainWindowSettings(configGroup); docManager()->writeConfig(); viewManager()->writeConfig(); scriptManager()->writeConfig(); KileConfig::setScriptNameColumnWidth(m_scriptsManagementWidget->scriptNameColumnWidth()); KileConfig::setRCVersion(KILERC_VERSION); KileConfig::setMainwindowWidth(width()); KileConfig::setMainwindowHeight(height()); QList sizes; QList::Iterator it; sizes = m_horizontalSplitter->sizes(); it = sizes.begin(); KileConfig::setHorizontalSplitterLeft(*it); ++it; KileConfig::setHorizontalSplitterRight(*it); sizes.clear(); sizes = m_verticalSplitter->sizes(); it = sizes.begin(); KileConfig::setVerticalSplitterTop(*it); ++it; KileConfig::setVerticalSplitterBottom(*it); #ifdef __GNUC__ #warning Restoring the side bar sizes from minimized after start up does not work perfectly yet! #endif // // sync vertical splitter and size of bottom bar // int sizeBottomBar = m_bottomBar->directionalSize(); // if(m_bottomBar->isVisible()) { // sizeBottomBar = m_verSplitBottom; // } // else { // m_verSplitBottom = sizeBottomBar; // } KileConfig::setSideBar(!m_sideBar->isHidden()); // do not use 'isVisible()'! KileConfig::setSideBarSize(m_sideBar->directionalSize()); KileConfig::setBottomBar(!m_bottomBar->isHidden()); // do not use 'isVisible()'! KileConfig::setBottomBarSize(m_bottomBar->directionalSize()); KileConfig::setBottomBarIndex(m_bottomBar->currentTab()); KileConfig::setSelectedLeftView(m_sideBar->currentTab()); abbreviationManager()->saveLocalAbbreviations(); KileConfig::self()->save(); m_config->sync(); } ///////////////// OPTIONS //////////////////// void Kile::setMasterDocumentFileName(const QString& fileName) { if(fileName.isEmpty() || !viewManager()->viewForLocalFilePresent(fileName)) { return; } m_masterDocumentFileName = fileName; QString shortName = QFileInfo(m_masterDocumentFileName).fileName(); ModeAction->setText(i18n("Normal mode (current master document: %1)", shortName)); ModeAction->setChecked(true); m_singlemode = false; updateModeStatus(); emit masterDocumentChanged(); KILE_DEBUG_MAIN << "SETTING master to " << m_masterDocumentFileName << " singlemode = " << m_singlemode << endl; } void Kile::clearMasterDocument() { ModeAction->setText(i18n("Define Current Document as 'Master Document'")); ModeAction->setChecked(false); m_singlemode = true; m_masterDocumentFileName.clear(); updateModeStatus(); emit masterDocumentChanged(); KILE_DEBUG_MAIN << "CLEARING master document"; } void Kile::toggleMasterDocumentMode() { if (!m_singlemode) { clearMasterDocument(); } else if (m_singlemode && viewManager()->currentTextView()) { QString name = getName(); if(name.isEmpty()) { ModeAction->setChecked(false); KMessageBox::error(this, i18n("In order to define the current document as a master document, it has to be saved first.")); return; } setMasterDocumentFileName(name); } else { ModeAction->setChecked(false); updateModeStatus(); } } void Kile::toggleWatchFile() { m_bWatchFile=!m_bWatchFile; if (m_bWatchFile) { WatchFileAction->setChecked(true); } else { WatchFileAction->setChecked(false); } } // execute configuration dialog void Kile::generalOptions() { KileDialog::Config *dlg = new KileDialog::Config(m_config.data(), this, this); KileUtilities::scheduleCenteringOfWidget(dlg); if (dlg->exec()) { // update new settings readConfig(); saveLastSelectedAction(); // save the old current tools before calling setupTools() which calls restoreLastSelectedActions() setupTools(); m_help->update(); newCaption(); // for the 'showFullPathInWindowTitle' setting configurationManager()->emitConfigChanged(); //stop/restart LyX server if necessary if(KileConfig::runLyxServer() && !m_lyxserver->isRunning()) { m_lyxserver->start(); } if(!KileConfig::runLyxServer() && m_lyxserver->isRunning()) { m_lyxserver->stop(); } } delete dlg; } void Kile::slotPerformCheck() { // first we have to disable the live preview that may be running, and clear the master document const bool livePreviewEnabledForFreshlyOpenedDocuments = KileConfig::previewEnabledForFreshlyOpenedDocuments(); const bool livePreviewEnabledForCurrentDocument = livePreviewManager() && livePreviewManager()->isLivePreviewEnabledForCurrentDocument(); if (livePreviewManager()) { KileConfig::setPreviewEnabledForFreshlyOpenedDocuments(false); livePreviewManager()->setLivePreviewEnabledForCurrentDocument(false); } // we show the message output widget in the bottom bar and shrink the side bar int sideBarTab = m_sideBar->currentTab(); int bottomBarTab = m_bottomBar->currentTab(); m_sideBar->shrink(); m_bottomBar->switchToTab(0); // show the log widget int outputTab = m_errorHandler->currentOutputTabIndex(); m_errorHandler->showMessagesOutput(); QString currentMasterDocument = m_masterDocumentFileName; if(!m_singlemode) { clearMasterDocument(); } // we hide the editor pane and tabs m_viewManager->setTabsAndEditorVisible(false); // now, we can run the tests KileDialog::ConfigChecker *dlg = new KileDialog::ConfigChecker(this); dlg->exec(); delete dlg; m_errorHandler->clearMessages(); m_errorHandler->clearErrorOutput(); // finally, we restore the rest to what it was before launching the tests m_viewManager->setTabsAndEditorVisible(true); if(!currentMasterDocument.isEmpty()) { setMasterDocumentFileName(currentMasterDocument); } m_errorHandler->setCurrentOutputTab(outputTab); if(sideBarTab >= 0) { m_sideBar->switchToTab(sideBarTab); } if(bottomBarTab < 0) { m_bottomBar->shrink(); } else { m_bottomBar->switchToTab(bottomBarTab); } if (livePreviewManager()) { KileConfig::setPreviewEnabledForFreshlyOpenedDocuments(livePreviewEnabledForFreshlyOpenedDocuments); if(livePreviewEnabledForCurrentDocument) { livePreviewManager()->setLivePreviewEnabledForCurrentDocument(true); } } } void Kile::aboutEditorComponent() { KTextEditor::Editor *editor = m_docManager->getEditor(); if(!editor) { return; } KAboutApplicationDialog dialog(editor->aboutData(), this); dialog.exec(); } /////////////// KEYS - TOOLBARS CONFIGURATION //////////////// void Kile::configureKeys() { KShortcutsDialog dlg(KShortcutsEditor::AllActions, KShortcutsEditor::LetterShortcutsAllowed, this); // due to bug 280988, we can't add all the clients... // QList clients = guiFactory()->clients(); // for(QList::iterator it = clients.begin(); it != clients.end(); ++it) { // dlg.addCollection((*it)->actionCollection()); // } dlg.addCollection(mainWindow()->actionCollection()); KTextEditor::View *view = m_viewManager->currentTextView(); if(view) { dlg.addCollection(view->actionCollection()); } KParts::ReadOnlyPart *part = viewManager()->viewerPart(); if(part) { dlg.addCollection(part->actionCollection()); } dlg.configure(); // tell all the documents and views to update their action shortcuts (bug 247646) docManager()->reloadXMLOnAllDocumentsAndViews(); // tell m_userMenu that key bindings may have been changed m_userMenu->updateKeyBindings(); } void Kile::configureToolbars() { { KConfigGroup configGroup = KSharedConfig::openConfig()->group("KileMainWindow"); saveMainWindowSettings(configGroup); } KEditToolBar dlg(factory()); connect(&dlg, &KEditToolBar::newToolBarConfig, this, [this] () { setUpdatesEnabled(false); applyMainWindowSettings(m_config->group("KileMainWindow")); updateUserDefinedMenus(); setUpdatesEnabled(true); }); dlg.exec(); } //////////////////// CLEAN BIB ///////////////////// void Kile::cleanBib() { KTextEditor::View *view = viewManager()->currentTextView(); if ( ! view ) return; QRegExp reOptional( "(ALT|OPT)(\\w+)\\s*=\\s*(\\S.*)" ); QRegExp reNonEmptyEntry( ".*\\w.*" ); QString s; int i = 0; while(i < view->document()->lines()) { s = view->document()->line(i); // do we have a line that starts with ALT or OPT? if(reOptional.indexIn(s) >= 0) { // yes! capture type and entry QString type = reOptional.cap( 2 ); QString entry = reOptional.cap( 3 ); view->document()->removeLine( i ); view->document()->setModified(true); if(reNonEmptyEntry.indexIn(entry) >= 0) { type.append(" = "); type.append(entry); view->document()->insertLine(i, type); ++i; } } else { ++i; } } int j = 0; for (i = 0; i < view->document()->lines(); ++i) { j = i+1; if(j < view->document()->lines() && view->document()->line(j).contains(QRegExp("^\\s*\\}\\s*$"))) { s = view->document()->line(i); view->document()->removeLine(i); s.remove(QRegExp(",\\s*$")); view->document()->setModified(true); view->document()->insertLine(i, s); } } } void Kile::includeGraphics() { KTextEditor::View *view = viewManager()->currentTextView(); if ( !view ) return; QFileInfo fi( view->document()->url().toLocalFile() ); KileDialog::IncludeGraphics *dialog = new KileDialog::IncludeGraphics(this, fi.path(), this); if ( dialog->exec() == QDialog::Accepted ) { insertTag(dialog->getTemplate(), "%C", 0,0); docManager()->projectAddFile( dialog->getFilename(),true ); } delete dialog; } void Kile::slotToggleFullScreen() { if (!m_pFullScreen->isChecked()) { setWindowState( windowState() & ~Qt::WindowFullScreen ); } else { setWindowState( windowState() | Qt::WindowFullScreen ); } } /////////////// QuickPreview (dani) //////////////// // all calls of QuickPreview will get here, so we can decide what to do // rewritten Sep 05 2006 to work together with preview in the bottom bar void Kile::slotQuickPreview(int type) { KILE_DEBUG_MAIN << "==Kile::slotQuickPreview()==========================" << endl; KTextEditor::View *view = viewManager()->currentTextView(); if ( ! view) return; KTextEditor::Document *doc = view->document(); if ( ! doc ) return; switch ( type ) { case KileTool::qpSelection: m_quickPreview->previewSelection(view); break; case KileTool::qpEnvironment: m_quickPreview->previewEnvironment(doc); break; case KileTool::qpSubdocument: m_quickPreview->previewSubdocument(doc); break; case KileTool::qpMathgroup: m_quickPreview->previewMathgroup(doc); break; } } /* FIXME Port the citeViewBib function as soon as we got a kbib version for KDE4. void Kile::citeViewBib() { KILE_DEBUG_MAIN << "===void Kile::citeViewBib()===" << endl; DCOPClient *client = kapp->dcopClient(); QByteArray params, replyData; Q3CString replyType; QDataStream stream(params, QIODevice::WriteOnly); QCStringList functions,remoteApps,remoteObjs; const Q3CString viewBibApp = "kbib"; // currently these things are hardcoded because only kbib supports it const Q3CString viewBibObj = "kbibapp"; const Q3CString viewBibFncDef = "QString cite()"; const Q3CString viewBibFnc = "cite()"; remoteApps = client->registeredApplications(); if( !remoteApps.contains(viewBibApp) ) { errorHandler()->printMessage(KileTool::Warning, i18n("No ViewBib tool running, trying to start it now"), i18n("ViewBib Citation")); uint ret = runWith("ViewBib","KBib"); if( ret == 0 ) errorHandler()->printMessage(KileTool::Info, i18n("Please select the desired bibliographies and re-execute this command"), i18n("ViewBib Citation")); return; } remoteObjs = client->remoteObjects(viewBibApp); if( !remoteObjs.contains(viewBibObj) ) { errorHandler()->printMessage(KileTool::Warning, i18n("The ViewBib tool does not have the correct interface"), i18n("ViewBib Citation")); return; } functions = client->remoteFunctions(viewBibApp,viewBibObj); if( !functions.contains(viewBibFncDef) ) { errorHandler()->printMessage(KileTool::Warning, i18n("The ViewBib tool does not have the correct definition of the cite function"), i18n("ViewBib Citation")); return; } if ( !client->call(viewBibApp, viewBibObj, viewBibFnc, params, replyType, replyData) ) { // we should never get here qWarning() << "internal error in viewbib citation" << endl; return; } else{ QDataStream reply(replyData, QIODevice::ReadOnly); if (replyType == "QString") { QString result; reply >> result; if (result.isEmpty()) { errorHandler()->printMessage(KileTool::Warning, i18n("No reference selected.\nPlease select a reference first!"), i18n("ViewBib Citation")); } else { insertTag(KileAction::TagData(i18n("ViewBib Citation"), result, QString(), result.length())); } } } } */ void Kile::addRecentFile(const QUrl &url) { m_actRecentFiles->addUrl(url); } void Kile::removeRecentFile(const QUrl &url) { m_actRecentFiles->removeUrl(url); } void Kile::addRecentProject(const QUrl &url) { m_actRecentProjects->addUrl(url); } void Kile::removeRecentProject(const QUrl &url) { m_actRecentProjects->removeUrl(url); } void Kile::updateStatusBarCursorPosition(KTextEditor::View *view, const KTextEditor::Cursor &newPosition) { if(!view) { statusBar()->clearLineColumn(); } else { statusBar()->setLineColumn(newPosition.line() + 1, newPosition.column() + 1); } } void Kile::updateStatusBarViewMode(KTextEditor::View *view) { if(!view) { statusBar()->clearViewMode(); } else { statusBar()->setViewMode(view->viewModeHuman()); } } void Kile::updateStatusBarInformationMessage(KTextEditor::View * /* view */, const QString &message) { statusBar()->showMessage(message, 5000); } void Kile::updateStatusBarSelection(KTextEditor::View *view) { if(!view) { statusBar()->clearSelectionMode(); } else { const QString text = view->blockSelection() ? i18nc("@info:status status bar label for block selection mode", "BLOCK") + ' ' : i18nc("@info:status status bar label for line selection mode", "LINE") + ' '; statusBar()->setSelectionMode(text); } } void Kile::handleDocumentParsingStarted() { statusBar()->setParserStatus(i18n("Refreshing structure...")); } void Kile::handleDocumentParsingComplete() { statusBar()->clearParserStatus(); } diff --git a/src/kilehelp.cpp b/src/kilehelp.cpp index 6698cfaf..3585675d 100644 --- a/src/kilehelp.cpp +++ b/src/kilehelp.cpp @@ -1,402 +1,402 @@ /********************************************************************************************** Copyright (C) 2004-2012 by Holger Danielsson (holger.danielsson@versanet.de) **********************************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "kilehelp.h" #include #include #include -#include #include "editorextension.h" #include "errorhandler.h" #include "kiledebug.h" #include "kiletool_enums.h" #include "kiletoolmanager.h" #include "kileviewmanager.h" #include "kileinfo.h" #include "dialogs/texdocumentationdialog.h" #include "kileconfig.h" +#include "utilities.h" // tbraun 27.06.2007 // it _looks_ like texlive 2007 has the same layout than texlive 2005 so don't get confused about the variable names :) namespace KileHelp { Help::Help(KileDocument::EditorExtension *edit, QWidget *mainWindow) : m_mainWindow(mainWindow), m_edit(edit), m_userhelp(Q_NULLPTR) { - m_helpDir = QStandardPaths::locate(QStandardPaths::DataLocation, "help/", QStandardPaths::LocateDirectory); // this must end in '/' + m_helpDir = KileUtilities::locate(QStandardPaths::AppDataLocation, "help/", QStandardPaths::LocateDirectory); // this must end in '/' KILE_DEBUG_MAIN << "help dir: " << m_helpDir; m_kileReference = m_helpDir + "latexhelp.html"; m_latex2eReference = m_helpDir + "latex2e-texlive.html"; m_contextHelpType = contextHelpType(); initTexDocumentation(); initContextHelp(); } Help::~Help() { delete m_userhelp; } void Help::initTexDocumentation() { // use documentation for teTeX v3.x, TexLive 2005-2007, TexLive 2009, TexLive2 010-2011 (TUG) m_texdocPath = KileConfig::location(); // first check for TexLive 2010-2011 (TUG) m_texlivePath = locateTexLive201x(); if ( !m_texlivePath.isEmpty() ) { KILE_DEBUG_MAIN << "found TexLive 2010-2011 (TUG): " << m_texlivePath; m_texVersion = TEXLIVE_201x_TUG; m_texVersionText = "TexLive " + m_texlivePath.right(4) + " (TUG)"; m_texrefsReference = "/generic/tex-refs/"; return; } // then check for TexLive 2009 (as found with Debian, Ubuntu, ...) QDir dir(m_texdocPath + "/generic/tex-refs/"); if ( dir.exists() ) { KILE_DEBUG_MAIN << "found TexLive 2009: " << m_texdocPath; m_texVersion = TEXLIVE2009; m_texVersionText = "TexLive 2009"; m_texrefsReference = "/generic/tex-refs/"; return; } // then check for older versions of TexLive 2005-2007 dir.setPath(m_texdocPath + "/english/tex-refs"); if ( dir.exists() ) { KILE_DEBUG_MAIN << "found TexLive 2005-2007: " << m_texdocPath; m_texVersion = TEXLIVE2005; m_texVersionText = "TexLive 2005-2007"; m_texrefsReference = "/english/tex-refs/"; return; } // finally we check for tetex3 dir.setPath(m_texdocPath + "/latex/tex-refs"); if ( dir.exists() ) { m_texVersion = TETEX3; m_texVersionText = "teTeX v3.x"; // check if this is buggy tetex3.0 or an updated version with subdirectory 'html' dir.setPath(m_texdocPath + "/latex/tex-refs/html"); m_texrefsReference = ( dir.exists() ) ? "/latex/tex-refs/html/" : "/latex/tex-refs/"; return; } // found no tex documents for LaTeX help m_texVersion = TEX_UNKNOWN; } void Help::initContextHelp() { // read a list with keywords for context help if ( m_contextHelpType == HelpKileRefs ) { readHelpList("latex-kile.lst"); } else if ( m_contextHelpType == HelpLatex2eRefs ) { readHelpList("latex2e-texlive.lst"); } else if ( m_contextHelpType == HelpTexRefs ) { QString keyfile = ( m_texVersion != TETEX3 ) ? "latex-texlive-3.9.lst" : "latex-tetex3.lst"; readHelpList(keyfile); } } QString Help::locateTexLivePath(const QStringList &paths) { QString sep = QDir::separator(); QRegExp re( sep + "texlive" + sep + "(201\\d)" + sep ); for (QStringList::ConstIterator it = paths.begin(); it != paths.end(); ++it) { // Remove any leading or trailing ", this is commonly used in the environment variables QString path = (*it); if (path.startsWith('\"')) path = path.right(path.length() - 1); if (path.endsWith('\"')) path = path.left(path.length() - 1); if ( re.indexIn(path) > 0 ) { return path.left(re.pos(1)+4); } } return QString(); } QString Help::locateTexLive201x() { #if defined(Q_OS_WIN32) QRegExp splitReg("[;,]"); #else QRegExp splitReg("[:]"); #endif QStringList paths = QString::fromLocal8Bit(getenv("PATH")).split(splitReg, QString::SkipEmptyParts); return locateTexLivePath(paths); } ////////////////////// update paths and context help of TeX documentation ////////////////////// void Help::update() { if ( m_texdocPath != KileConfig::location() ) { initTexDocumentation(); } HelpType contextHelp = contextHelpType(); if ( m_contextHelpType != contextHelp ) { m_contextHelpType = contextHelp; initContextHelp(); } } ////////////////////// set parameter/initialize user help ////////////////////// void Help::setUserhelp(KileTool::Manager *manager, KActionMenu *userHelpActionMenu) { m_manager = manager; m_userhelp = new UserHelp(manager, userHelpActionMenu, m_mainWindow); } void Help::enableUserhelpEntries(bool state) { if(m_userhelp) { m_userhelp->enableUserHelpEntries(state); } } ////////////////////// show help ////////////////////// void Help::showHelpFile(const QString ¶meter) { KILE_DEBUG_MAIN << "--------------------------------------------> help file: " << parameter; KileTool::Base *tool = m_manager->createTool("ViewHTML", QString(), false); if(!tool) { return; } tool->setFlags(KileTool::NeedSourceExists | KileTool::NeedSourceRead); //FIXME strip the #label part of the source (not the target), //somehow this is already done somewhere (by accident), //bad to rely on it tool->setMsg(KileTool::NeedSourceExists, ki18n("Could not find the LaTeX documentation at %1; please set the correct path in Settings->Configure Kile->Help.")); tool->setSource(parameter); tool->setTargetPath(parameter); tool->prepareToRun(); m_manager->run(tool); } void Help::helpKeyword() { //FIXME: we should have a better way to access the current view helpKeyword(m_manager->info()->viewManager()->currentTextView()); } ////////////////////// Help: TexDoc ////////////////////// void Help::helpDocBrowser() { KileDialog::TexDocDialog *dlg = new KileDialog::TexDocDialog(); dlg->exec(); delete dlg; } ////////////////////// Help: TeTeX ////////////////////// void Help::helpTexGuide() { QString filename = m_texdocPath; switch(m_texVersion) { case TEXLIVE_201x_TUG: filename = filename.replace("texmf-dist","texmf"); filename += "/texlive/texlive-en/texlive-en.html"; break; case TEXLIVE2009: filename += "/texlive/texlive-en/texlive-en.html"; break; case TEXLIVE2005: filename += "/english/texlive-en/live.html"; break; case TETEX3: filename += "/index.html"; break; default: return; } KILE_DEBUG_MAIN << "show TeX Guide: " << m_texVersionText << " file=" << filename; showHelpFile( filename ); } ////////////////////// Help: LaTeX ////////////////////// void Help::helpLatex(HelpType type) { QString filename; // use older 'tex-refs' documentation, if this document is present and explicitly wanted // in all other cases use current TexLive documentation (latex2e-texlive.html) if ( m_contextHelpType==HelpTexRefs && m_texVersion!=TETEX3 ) { QString link; switch(type) { case HelpLatexIndex: link = "tex-refs.html#latex"; break; case HelpLatexCommand: link = "tex-refs.html#tex-refs-idx"; break; case HelpLatexSubject: link = "tex-refs.html#commands"; break; case HelpLatexEnvironment: link = "tex-refs.html#env-latex"; break; default: return; } filename = m_texdocPath + m_texrefsReference + link; } else { QString link; switch(type) { case HelpLatexIndex: link = "LaTeX2e"; break; case HelpLatexCommand: link = "Command-Index"; break; case HelpLatexSubject: link = "SEC_Overview"; break; case HelpLatexEnvironment: link = "Environments"; break; default: return; } filename = m_latex2eReference + '#' + link; } // show help file KILE_DEBUG_MAIN << "show LaTeX help: " << m_texVersionText << " file=" << filename; showHelpFile( filename ); } ////////////////////// Help: Keyword ////////////////////// // Context help: user either current TexLive's Latex2e help, TexLive's older tex-refs help or Kile LaTeX help void Help::helpKeyword(KTextEditor::View *view) { QString word = getKeyword(view); KILE_DEBUG_MAIN << "keyword: " << word; if ( !m_helpDir.isEmpty() && !word.isEmpty() && m_dictHelpTex.contains(word) ) { KILE_DEBUG_MAIN << "about to show help for '" << word << "' (section " << m_dictHelpTex[word] << " )"; if ( m_contextHelpType == HelpLatex2eRefs ) { showHelpFile( m_latex2eReference + '#' + m_dictHelpTex[word] ); } else if ( m_contextHelpType == HelpTexRefs ) { showHelpFile( m_texdocPath + m_texrefsReference + m_dictHelpTex[word] ); } else if ( m_contextHelpType == HelpKileRefs ) { showHelpFile(m_kileReference + '#' + m_dictHelpTex[word]); } } else { noHelpAvailableFor(word); } } void Help::noHelpAvailableFor(const QString &word) { m_manager->info()->errorHandler()->printMessage(KileTool::Error, i18n("No help available for %1.", word), i18n("Help")); } QString Help::getKeyword(KTextEditor::View *view) { if(!view) { return QString(); } // get current position int row, col, col1, col2; QString word; KTextEditor::Document *doc = view->document(); KTextEditor::Cursor cursor = view->cursorPosition(); row = cursor.line(); col = cursor.column(); if (m_edit->getCurrentWord(doc, row, col, KileDocument::EditorExtension::smTex, word, col1, col2)) { // There is no starred keyword in the references. So if // dani 04.08.2004 // we find one, we better try the unstarred keyword. if(word.right(1) == "*") { return word.left(word.length() - 1); } else { return word; } } else { return QString(); } } HelpType Help::contextHelpType() { if ( KileConfig::latex2erefs() ) { return HelpLatex2eRefs; } else if ( KileConfig::texrefs() ) { return HelpTexRefs; } else { return HelpKileRefs; } } //////////////////// read help lists //////////////////// void Help::readHelpList(const QString &filename) { // clear old map m_dictHelpTex.clear(); QString file = m_helpDir + filename; if(file.isEmpty()) { KILE_DEBUG_MAIN << " file not found: " << filename << endl; return; } // KILE_DEBUG_MAIN << " read file: " << filename << endl; KILE_DEBUG_MAIN << "read keyword file: " << file; QRegExp reg("\\s*(\\S+)\\s*=>\\s*(\\S+)"); QFile f(file); if(f.open(QIODevice::ReadOnly)) { // file opened successfully QTextStream t(&f); // use a text stream while(!t.atEnd()) { // until end of file... QString s = t.readLine().trimmed(); // line of text excluding '\n' if(!(s.isEmpty() || s.at(0)=='#')) { int pos = reg.indexIn(s); if ( pos != -1 ) { m_dictHelpTex[reg.cap(1)] = reg.cap(2); } } } f.close(); } } } diff --git a/src/kilestdactions.cpp b/src/kilestdactions.cpp index 7c911728..dce12562 100644 --- a/src/kilestdactions.cpp +++ b/src/kilestdactions.cpp @@ -1,496 +1,495 @@ /************************************************************************** * Copyright (C) 2003 by Jeroen Wijnhout (Jeroen.Wijnhout@kdemail.net) * ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "kilestdactions.h" #include #include #include #include -#include - #include "kileactions.h" #include "editorextension.h" +#include "utilities.h" namespace KileStdActions { void setupStdTags(KileInfo *ki, const QObject* receiver, KActionCollection *actionCollection, QWidget *parentWidget) { (void) new KileAction::Tag(i18n("Document Class Selection - \\documentclass{}"), i18n("Document Class"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection, "tag_documentclass", "\\documentclass[10pt]{","}", 21, 0, i18n("\\documentclass[options]{class}\nclass : article,report,book,letter\nsize options : 10pt, 11pt, 12pt\npaper size options: a4paper, a5paper, b5paper, letterpaper, legalpaper, executivepaper\n" "other options: \nlandscape -- selects landscape format; default is portrait. \ntitlepage, notitlepage -- selects if there should be a separate title page.\nleqno -- display equation number on left side of equations; default is right side.\n" "fleqn -- display formulae flush left; default is centered.\nonecolumn, twocolumn -- one or two columns; defaults to one column\noneside, twoside -- selects one- or two-sided layout.\n" )); (void) new KileAction::Tag(i18n("Package Import - \\usepackage{}"), i18n("Package Import"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_usepackage", "\\usepackage{","}", 12, 0, i18n("Any options given in the \\documentclass command that are unknown by the selected document class\n" "are passed on to the packages loaded with \\usepackage.")); (void) new KileAction::Tag(i18n("AMS Packages"), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_amspackages","\\usepackage{amsmath}\n\\usepackage{amsfonts}\n\\usepackage{amssymb}\n",QString(),0,3,i18n("The principal American Mathematical Society packages")); (void) new KileAction::Tag(i18n("Start Document Body - \\begin{document}"), i18n("Start Document Body"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_env_document","\\begin{document}\n", "\n\\end{document}", 0,1,i18n("Text is allowed only between \\begin{document} and \\end{document}.\nThe 'preamble' (before \\begin{document} ) may contain declarations only.")); (void) new KileAction::Tag(i18n("Generate Title - \\maketitle"), i18n("Generate Title"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_maketitle","\\maketitle",QString(),10,0,i18n("This command generates a title on a separate title page\n- except in the article class, where the title normally goes at the top of the first page.")); (void) new KileAction::Tag(i18n("Table of Contents - \\tableofcontents"), i18n("Table of Contents"), "view-table-of-contents-ltr", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_tableofcontents","\\tableofcontents",QString(),16,0,i18n("Put this command where you want the table of contents to go")); (void) new KileAction::Tag(i18n("Title Definition - \\title{}"), i18n("Title Definition"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_title","\\title{","}",7,0,i18n( "\\title{text}\nThe \\title command declares text to be the title.\nUse \\\\ to tell LaTeX where to start a new line in a long title.")); (void) new KileAction::Tag(i18n("Author Definition - \\author{}"), i18n("Author Definition"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_author","\\author{","}",8,0,i18n( "\\author{names}\nThe \\author command declares the author(s), where names is a list of authors separated by \\and commands.")); (void) new KileAction::Tag(i18n("Center - \\begin{center}"), i18n("Center"), "format-justify-center", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_center", "\\begin{center}\n","%E\n\\end{center}", 0,1, i18n("Each line must be terminated with the string \\\\.")); (void) new KileAction::Tag(i18n("Align Left - \\begin{flushleft}"), i18n("Align Left"), "format-justify-left", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_flushleft", "\\begin{flushleft}\n","%E\n\\end{flushleft}", 0,1, i18n("Each line must be terminated with the string \\\\.") ); (void) new KileAction::Tag(i18n("Align Right - \\begin{flushright}"), i18n("Align Right"), "format-justify-right", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_flushright", "\\begin{flushright}\n","%E\n\\end{flushright}", 0,1, i18n("Each line must be terminated with the string \\\\.") ); (void) new KileAction::Tag(i18n("Quote - \\begin{quote}"), i18n("Quote"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_quote","\\begin{quote}\n","%E\n\\end{quote} ",0,1,i18n("The text is justified at both margins.\nLeaving a blank line between text produces a new paragraph.") ); (void) new KileAction::Tag(i18n("Quotation - \\begin{quotation}"), i18n("Quotation"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_quotation","\\begin{quotation}\n","%E\n\\end{quotation} ",0,1, i18n("The text is justified at both margins and there is paragraph indentation.\nLeaving a blank line between text produces a new paragraph.") ); (void) new KileAction::Tag(i18n("Verse - \\begin{verse}"), i18n("Verse"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_verse", "\\begin{verse}\n","%E\n\\end{verse} ",0,1,i18n("The verse environment is designed for poetry.\nSeparate the lines of each stanza with \\\\, and use one or more blank lines to separate the stanzas.") ); (void) new KileAction::Tag(i18n("Verbatim - \\begin{verbatim}"), i18n("Verbatim"), "verbatim", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_verbatim","\\begin{verbatim}\n","%E\n\\end{verbatim} ",0,1,i18n("Environment that gets LaTeX to print exactly what you type in.")); (void) new KileAction::Tag(i18n("Bulleted List - \\begin{itemize}"), i18n("Bulleted List"), "itemize", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_env_itemize","\\begin{itemize}\n%E\\item \n", "\\end{itemize}\n", 6,1,i18n("The itemize environment produces a 'bulleted' list.\nEach item of an itemized list begins with an \\item command.")); (void) new KileAction::Tag(i18n("Enumeration - \\begin{enumerate}"), i18n("Enumeration"), "enumerate", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_env_enumerate","\\begin{enumerate}\n%E\\item \n","\\end{enumerate}\n", 6,1,i18n("The enumerate environment produces a numbered list.\nEach item of an enumerated list begins with an \\item command.")); (void) new KileAction::Tag(i18n("Description - \\begin{description}"), i18n("Description"), "description", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_env_description","\\begin{description}\n%E\\item[] \n", "\\end{description}",6,1,i18n("The description environment is used to make labeled lists.\nEach item of the list begins with an \\item[label] command.\nThe 'label' is bold face and flushed right.")); (void) new KileAction::Tag(i18n("Table - \\begin{table}"), i18n("Table"), "table-env", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_table","\\begin{table}\n","%E\n\\caption{}\n\\end{table} ",0,1, i18n("\\begin{table}[placement]\nbody of the table\n\\caption{table title}\n\\end{table}\nTables are objects that are not part of the normal text, and are usually floated to a convenient place.\n" "The optional argument [placement] determines where LaTeX will try to place your table\nh : Here - at the position in the text where the table environment appears\nt : Top - at the top of a text page\nb : Bottom - at the bottom of a text page\n" "p : Page of floats - on a separate float page, which is a page containing no text, only floats.\nThe body of the table is made up of whatever text or LaTeX commands, etc., you wish.\nThe \\caption command allows you to title your table.")); (void) new KileAction::Tag(i18n("Figure - \\begin{figure}"), i18n("Figure"), "figure-env", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_figure","\\begin{figure}\n","%E\n\\caption{}\n\\end{figure} ",0,1, i18n("\\begin{figure}[placement]\nbody of the figure\n\\caption{figure title}\n\\end{figure}\nFigures are objects that are not part of the normal text, and are usually floated to a convenient place.\n" "The optional argument [placement] determines where LaTeX will try to place your figure\nh : Here - at the position in the text where the figure environment appears\nt : Top - at the top of a text page\n" "b : Bottom - at the bottom of a text page\np : Page of floats - on a separate float page, which is a page containing no text, only floats.\nThe body of the figure is made up of whatever text or LaTeX commands, etc., you wish.\nThe \\caption command allows you to title your figure.")); (void) new KileAction::Tag(i18n("Title Page - \\begin{titlepage}"), i18n("Title Page"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_titlepage","\\begin{titlepage}\n","%E\n\\end{titlepage} ",0,1, i18n("\\begin{titlepage}\ntext\n\\end{titlepage}\nThe titlepage environment creates a title page, i.e. a page with no printed page number or heading.")); new KileAction::Tag(i18n("Italics - \\textit{}"), i18n("Italics"), "format-text-italic", QKeySequence(Qt::ALT+Qt::SHIFT+Qt::Key_I), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_textit","\\textit{","}",8,0,i18n("\\textit{italic text}")); new KileAction::Tag(i18n("Slanted - \\textsl{}"), i18n("Slanted"), "slanted", QKeySequence(Qt::ALT+Qt::SHIFT+Qt::Key_A), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_textsl","\\textsl{","}",8,0,i18n("\\textsl{slanted text}")); new KileAction::Tag(i18n("Boldface - \\textbf{}"), i18n("Boldface"), "format-text-bold", QKeySequence(Qt::ALT+Qt::SHIFT+Qt::Key_B), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_textbf","\\textbf{","}",8,0,i18n("\\textbf{boldface text}")); new KileAction::Tag(i18n("Typewriter - \\texttt{}"), i18n("Typewriter"), "typewriter", QKeySequence(Qt::ALT+Qt::SHIFT+Qt::Key_T), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_texttt","\\texttt{","}",8,0,i18n("\\texttt{typewriter text}")); new KileAction::Tag(i18n("Small Caps - \\textsc{}"), i18n("Small Caps"), QKeySequence(Qt::ALT+Qt::SHIFT+Qt::Key_C), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_textsc","\\textsc{","}",8,0,i18n("\\textsc{small caps text}")); new KileAction::Tag("\\item", QString(), "item", QKeySequence(Qt::ALT+Qt::SHIFT+Qt::Key_H), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_item","\\item ",QString(),6,0, i18n("\\item[label] Hello!")); (void) new KileAction::Tag(i18n("Tabbing - \\begin{tabbing}"), i18n("Tabbing"), "tabbing", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_env_tabbing","\\begin{tabbing}\n","%E\n\\end{tabbing} ",0,1,i18n("The tabbing environment provides a way to align text in columns.\n\\begin{tabbing}\ntext \\= more text \\= still more text \\= last text \\\\\nsecond row \\> \\> more \\\\\n\\end{tabbing}\nCommands :\n\\= Sets a tab stop at the current position.\n\\> Advances to the next tab stop.\n\\< Allows you to put something to the left of the local margin without changing the margin. Can only be used at the start of the line.\n\\+ Moves the left margin of the next and all the following commands one tab stop to the right\n\\- Moves the left margin of the next and all the following commands one tab stop to the left\n\\' Moves everything that you have typed so far in the current column to the right of the previous column, flush against the current column's tab stop. \n\\` Allows you to put text flush right against any tab stop, including tab stop 0\n\\kill Sets tab stops without producing text.\n\\a In a tabbing environment, the commands \\=, \\' and \\` do not produce accents as normal. Instead, the commands \\a=, \\a' and \\a` are used.")); (void) new KileAction::Tag(i18n("Tabular - \\begin{tabular}"), i18n("Tabular"), "tabular", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_env_tabular","\\begin{tabular}{","}\n%E\n\\end{tabular} ",16,0,i18n("\\begin{tabular}[pos]{cols}\ncolumn 1 entry & column 2 entry ... & column n entry \\\\\n...\n\\end{tabular}\npos : Specifies the vertical position; default is alignment on the center of the environment.\n t - align on top row\n b - align on bottom row\ncols : Specifies the column formatting.\n l - A column of left-aligned items.\n r - A column of right-aligned items.\n c - A column of centered items.\n | - A vertical line the full height and depth of the environment.\n @{text} - this inserts text in every row.\nThe \\hline command draws a horizontal line the width of the table.\nThe \\cline{i-j} command draws horizontal lines across the columns specified, beginning in column i and ending in column j.\nThe \\vline command draws a vertical line extending the full height and depth of its row.")); (void) new KileAction::Tag(i18n("Multicolumn Cells - \\multicolumn"), i18n("Multicolumn Cells"), "multicolumn", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)),actionCollection,"tag_multicolumn","\\multicolumn{","}{}{} ",13,0,i18n("\\multicolumn{cols}{pos}{text}\ncol, specifies the number of columns to span.\npos specifies the formatting of the entry: c for centered, l for flushleft, r for flushright.\ntext specifies what text is to make up the entry.")); (void) new KileAction::Tag(i18n("Horizontal Line - \\hline"), i18n("Horizontal Line"), "hline", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_hline","\\hline ",QString(),7,0,i18n("The \\hline command draws a horizontal line the width of the table.")); (void) new KileAction::Tag(i18n("Vertical Line - \\vline"), i18n("Vertical Line"), "vline", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_vline","\\vline ",QString(),7,0,i18n("The \\vline command draws a vertical line extending the full height and depth of its row.")); (void) new KileAction::Tag(i18n("Horizontal Line Across Columns - \\cline{m-n}"), i18n("Horizontal Line Across Columns"), "cline", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_cline","\\cline{-} ",QString(),7,0,i18n("The \\cline{i-j} command draws horizontal lines across the columns specified, beginning in column i and ending in column j,")); (void) new KileAction::Tag(i18n("New Page - \\newpage"), i18n("New Page"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_newpage","\\newpage ",QString(),9,0,i18n("The \\newpage command ends the current page")); (void) new KileAction::Tag(i18n("Line Break - \\linebreak"), i18n("Line Break"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_linebreak","\\linebreak ",QString(),11,0,i18n("The \\linebreak command tells LaTeX to break the current line at the point of the command.")); (void) new KileAction::Tag(i18n("Page Break - \\pagebreak"), i18n("Page Break"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_pagebreak","\\pagebreak ",QString(),11,0,i18n("The \\pagebreak command tells LaTeX to break the current page at the point of the command.")); (void) new KileAction::Tag(i18n("\"Big\" Vertical Space - \\bigskip"), i18n("\"Big\" Vertical Space"), "bigskip", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_bigskip","\\bigskip ",QString(),9,0,i18n("The \\bigskip command adds a 'big' vertical space.")); (void) new KileAction::Tag(i18n("\"Medium\" Vertical Space - \\medskip"), i18n("\"Medium\" Vertical Space"), "medskip", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_medskip","\\medskip ",QString(),9,0,i18n("The \\medskip command adds a 'medium' vertical space.")); // includegraphics (dani) (void) new KileAction::Tag(i18n("Image Insertion - \\includegraphics{file}"), i18n("Image Insertion"), "insert-image", QKeySequence("Alt+I, G"),receiver,SLOT(includeGraphics()), actionCollection,"tag_includegraphics",0L); // two new shortcuts (dani) (void) new KileAction::InputTag(ki, i18n("Customizable File Inclusion - \\include{file}"), i18n("Customizable File Inclusion"), "include-file", QKeySequence("Alt+I, F"), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_include", parentWidget, KileAction::KeepHistory | KileAction::ShowBrowseButton | KileAction::AddProjectFile, "\\include{%R","}",9,0, i18n("\\include{file}\nThe \\include command is used in conjunction with the \\includeonly command for selective inclusion of files."),i18n("Type or select a filename: ")); (void) new KileAction::InputTag(ki, i18n("File Inclusion - \\input{file}"), i18n("File Inclusion"), "input-file", QKeySequence("Alt+I, P"), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_input", parentWidget, KileAction::KeepHistory | KileAction::ShowBrowseButton | KileAction::AddProjectFile, "\\input{%R","}",7,0,i18n("\\input{file}\nThe \\input command causes the indicated file to be read and processed, exactly as if its contents had been inserted in the current file at that point."),i18n("Type or select a filename: ")); ToolbarSelectAction *actionstructure_list = new ToolbarSelectAction(i18n("Sectioning"), actionCollection,false); actionCollection->addAction("structure_list", actionstructure_list); actionstructure_list->addAction(new KileAction::InputTag(ki,"&part", QString(), "part", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_part", parentWidget, KileAction::ShowAlternative|KileAction::ShowLabel, "\\part%A{%R}","\n", 0,1,i18n("\\part{title}\n\\part*{title} : do not include a number and do not make an entry in the table of contents\n"), i18n("&Part"),i18n("No &numbering"))); actionstructure_list->addSeparator(); actionstructure_list->addAction(new KileAction::InputTag(ki,"&chapter", QString(), "chapter", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_chapter", parentWidget, KileAction::ShowAlternative|KileAction::ShowLabel, "\\chapter%A{%R}","\n", 0,1,i18n("\\chapter{title}\n\\chapter*{title} : do not include a number and do not make an entry in the table of contents\nOnly for 'report' and 'book' class document."), i18n("C&hapter"),i18n("No &numbering"))); actionstructure_list->addAction(new KileAction::InputTag(ki,"§ion", QString(), "section", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_section", parentWidget, KileAction::ShowAlternative|KileAction::ShowLabel, "\\section%A{%R}","\n", 0,1,i18n("\\section{title}\n\\section*{title} : do not include a number and do not make an entry in the table of contents"), i18n("&Section"),i18n("No &numbering"))); actionstructure_list->addAction(new KileAction::InputTag(ki,"s&ubsection", QString(), "subsection", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_subsection", parentWidget, KileAction::ShowAlternative|KileAction::ShowLabel, "\\subsection%A{%R}","\n", 0,1,i18n("\\subsection{title}\n\\subsection*{title} : do not include a number and do not make an entry in the table of contents"), i18n("&Subsection"),i18n("No &numbering"))); actionstructure_list->addAction(new KileAction::InputTag(ki,"su&bsubsection", QString(), "subsubsection", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_subsubsection", parentWidget, KileAction::ShowAlternative|KileAction::ShowLabel, "\\subsubsection%A{%R}","\n", 0,1,i18n("\\subsubsection{title}\n\\subsubsection*{title} : do not include a number and do not make an entry in the table of contents"), i18n("&Subsubsection"),i18n("No &numbering"))); actionstructure_list->addSeparator(); actionstructure_list->addAction(new KileAction::InputTag(ki,"p&aragraph", QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_paragraph", parentWidget, KileAction::ShowAlternative|KileAction::ShowLabel, "\\paragraph%A{%R}","\n", 0,1,i18n("\\paragraph{title}\n\\paragraph*{title} : do not include a number and do not make an entry in the table of contents"), i18n("&Paragraph"),i18n("No &numbering"))); actionstructure_list->addAction(new KileAction::InputTag(ki,"subpa&ragraph", QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_subparagraph", parentWidget, KileAction::ShowAlternative|KileAction::ShowLabel, "\\subparagraph%A{%R}","\n", 0,1,i18n("\\subparagraph{title}\n\\subparagraph*{title} : do not include a number and do not make an entry in the table of contents"), i18n("&Subparagraph"),i18n("No &numbering"))); ToolbarSelectAction *actionsize_list = new ToolbarSelectAction(i18n("Size"), actionCollection,false); actionCollection->addAction("size_list", actionsize_list); actionsize_list->addAction(new KileAction::Tag(i18n("tiny"), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection, "tag_tiny", "\\begin{tiny}", "\\end{tiny}", 12, 0)); actionsize_list->addAction(new KileAction::Tag(i18n("scriptsize"), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection, "tag_scriptsize", "\\begin{scriptsize}", "\\end{scriptsize}", 18, 0)); actionsize_list->addAction(new KileAction::Tag(i18n("footnotesize"), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection, "tag_footnotesize", "\\begin{footnotesize}", "\\end{footnotesize}", 20, 0)); actionsize_list->addAction(new KileAction::Tag(i18n("small"), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection, "tag_small", "\\begin{small}", "\\end{small}", 13, 0)); actionsize_list->addSeparator(); actionsize_list->addAction(new KileAction::Tag(i18n("normalsize"), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection, "tag_normalsize", "\\begin{normalsize}", "\\end{normalsize}", 18, 0)); actionsize_list->addSeparator(); actionsize_list->addAction(new KileAction::Tag(i18n("large"), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_large", "\\begin{large}", "\\end{large}", 13, 0)); actionsize_list->addAction(new KileAction::Tag(i18n("Large"), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_Large", "\\begin{Large}", "\\end{Large}", 13, 0)); actionsize_list->addAction(new KileAction::Tag(i18n("LARGE"), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_LARGE", "\\begin{LARGE}", "\\end{LARGE}", 13, 0)); actionsize_list->addAction(new KileAction::Tag(i18n("huge"), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection, "tag_huge", "\\begin{huge}", "\\end{huge}", 12, 0)); actionsize_list->addAction(new KileAction::Tag(i18n("Huge"), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection, "tag_Huge", "\\begin{Huge}", "\\end{Huge}", 12, 0)); ToolbarSelectAction *actionother_list = new ToolbarSelectAction(i18n("Other"), actionCollection,false); actionCollection->addAction("other_list", actionother_list); actionother_list->addAction(new KileAction::Tag("label", QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_label", "\\label{","} ",7,0,i18n("\\label{key}"))); actionother_list->addAction(new KileAction::InputTag(ki,"ref", QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_ref", parentWidget, KileAction::FromLabelList, "\\ref{%R", "}", 5,0, QString(), i18n("Label") )); actionother_list->addAction(new KileAction::InputTag(ki,"pageref", QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_pageref", parentWidget, KileAction::FromLabelList, "\\pageref{%R", "}", 9,0, QString(), i18n("Label") )); actionother_list->addSeparator(); actionother_list->addAction(new KileAction::Tag("index", QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_index","\\index{","}",7,0,i18n( "\\index{word}"))); actionother_list->addAction(new KileAction::Tag("footnote", QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_footnote", "\\footnote{","}",10,0,i18n( "\\footnote{text}"))); actionother_list->addSeparator(); actionother_list->addAction(new KileAction::InputTag(ki,"cite", QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_cite", parentWidget, KileAction::FromBibItemList, "\\cite{%R", "}", 6,0, i18n("This command generates an in-text citation to the reference associated with the ref entry in the bib file\nYou can open the bib file with Kile to see all the available references"), i18n("Reference"))); // QAction *action = actionCollection->addAction("citeViewBib", receiver, SLOT(citeViewBib())); // action->setText(i18n("cite from ViewBib")); // actionother_list->addAction(action); (void) new KileAction::Tag(i18n("Underline - \\underline{}"), i18n("Underline"), "format-text-underline", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_underline", "\\underline{","}",11); QAction *action = actionCollection->addAction("tag_newline", ki->editorExtension(), SLOT(insertIntelligentNewline())); action->setText(i18n("Smart New Line")); actionCollection->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::Key_Return)); action->setIcon(QIcon::fromTheme("smartnewline")); action = actionCollection->addAction("tag_tabulator", ki->editorExtension(), SLOT(insertIntelligentTabulator())); action->setText(i18n("Smart Tabulator")); actionCollection->setDefaultShortcut(action, QKeySequence(Qt::ALT + Qt::Key_Ampersand)); // new tags (dani 29.01.2005) KActionCollection* ac = actionCollection; // environments (void) new KileAction::Tag(i18n("Abstract - \\begin{abstract}"), i18n("Abstract"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), ac,"tag_env_abstract","\\begin{abstract}\n","%E\n\\end{abstract} ",0,1, i18n("\\begin{abstract}\ntext\n\\end{abstract}\nThe abstract environment creates a title page, i.e. a page with no printed page number or heading.")); (void) new KileAction::Tag(i18n("Tabular* - \\begin{tabular*}"), i18n("Tabular*"), "tabular-star", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), ac,"tag_env_tabular*","\\begin{tabular*}{}{","}\n%E\n\\end{tabular*}\n",17,0, i18n("\\begin{tabular*}{width}[pos]{cols}\ncolumn 1 entry & column 2 entry ... & column n entry \\\\\n...\n\\end{tabular*}\nThis is an extended version of the tabular environment with an extra parameter for the width. There must be rubber space between columns that can stretch to fill out the specified width.")); (void) new KileAction::Tag(i18n("Minipage - \\begin{minipage}"), i18n("Minipage"), "minipage", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)),ac,"tag_env_minipage","\\begin{minipage}[","]{}\n%E\n\\end{minipage} ",17,0, i18n("The minipage environment is similar to a \\parbox command. It takes the same optional position argument and mandatory width argument. You may use other paragraph-making environments inside a minipage.")); // lists (void) new KileAction::Tag(i18n("Table of Figures - \\listoffigures"), i18n("Table of Figures"), QKeySequence(), receiver,SLOT(insertTag(KileAction::TagData)), ac,"tag_listoffigures","\\listoffigures",QString(),14,0, i18n("Put this command where you want the list of figures to go.")); (void) new KileAction::Tag(i18n("Table of Tables - \\listoftables"), i18n("Table of Tables"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), ac,"tag_listoftables","\\listoftables",QString(),14,0, i18n("Put this command where you want the list of tables to go.")); (void) new KileAction::Tag(i18n("Generate Index - \\makeindex"), i18n("Generate Index"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), ac,"tag_makeindex","\\makeindex",QString(),10,0, i18n("Put this command when you want to generate the raw index.")); (void) new KileAction::Tag(i18n("Print Index - \\printindex"), i18n("Print Index"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), ac,"tag_printindex","\\printindex",QString(),11,0, i18n("Put this command when you want to print the formatted index.")); (void) new KileAction::Tag(i18n("Glossary - \\makeglossary"), i18n("Glossary"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), ac,"tag_makeglossary","\\makeglossary",QString(),13,0, i18n("Put this command when you want to print a glossary.")); (void) new KileAction::Tag(i18n("Bibliography - \\begin{thebibliography}"), i18n("Bibliography"), QKeySequence(), receiver,SLOT(insertTag(KileAction::TagData)), ac,"tag_env_thebibliography","\\begin{thebibliography}{","}\n\n\\end{thebibliography} ",24,0, i18n("\\begin{thebibliography}{widest-label}\n\\bibitem[label]{cite_key}\n...\n\\end{thebibliography}\n\nwidest-label : Text that, when printed, is approximately as wide as the widest item label produces by the \\bibitem commands\n\\bibitem : Specify a bibliography item")); // verbatim code (void) new KileAction::Tag(i18n("Verbatim (show spaces) - \\begin{verbatim*}"), i18n("Verbatim (show spaces)"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)),ac,"tag_env_verbatim*","\\begin{verbatim*}\n","%E\n\\end{verbatim*}\n",0,1, i18n("Environment that gets LaTeX to print exactly what you type in. In this variant, spaces are printed in a special manner.")); (void) new KileAction::Tag(i18n("Embedded Code - \\verb||"), i18n("Embedded Code"), "verb", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)),ac,"tag_verb","\\verb|","|",6,0, i18n("Macro form of the verbatim environment.")); (void) new KileAction::Tag(i18n("Embedded Code (show spaces) - \\verb*||"), i18n("Embedded Code (show spaces)"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)),ac,"tag_verb*","\\verb*|","|",7,0, i18n("Macro form of the verbatim* environment.")); // horizontal/vertical space (void) new KileAction::Tag(i18n("\"Small\" Vertical Space - \\smallskip"), i18n("\"Small\" Vertical Space"), "smallskip", QKeySequence(), receiver,SLOT(insertTag(KileAction::TagData)), ac,"tag_smallskip","\\smallskip ",QString(),10,0, i18n("The \\smallskip command adds a 'small' vertical space.")); (void) new KileAction::Tag(i18n("\\enskip"), QString(), "enskip", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), ac,"tag_enskip", "\\enskip ", QString(), 8); (void) new KileAction::Tag(i18n("Horizontal Variable Space - \\hfill"), i18n("Horizontal Variable Space"), QKeySequence(), receiver,SLOT(insertTag(KileAction::TagData)),ac,"tag_hfill","\\hfill",QString(),6,0, i18n("The \\hfill fill command produces a \"rubber length\" which can stretch or shrink horizontally. It will be filled with spaces.")); (void) new KileAction::Tag(i18n("Horizontal Dots - \\dotfill"), i18n("Horizontal Dots"), QKeySequence(), receiver,SLOT(insertTag(KileAction::TagData)),ac,"tag_dotfill","\\dotfill",QString(),8,0, i18n("The \\dotfill command produces a \"rubber length\" that produces dots instead of just spaces.")); (void) new KileAction::Tag(i18n("Horizontal Rule - \\hrulefill"), i18n("Horizontal Rule"), QKeySequence(), receiver,SLOT(insertTag(KileAction::TagData)),ac,"tag_hrulefill","\\hrulefill",QString(),10,0, i18n("The \\hrulefill fill command produces a \"rubber length\" which can stretch or shrink horizontally. It will be filled with a horizontal rule.")); (void) new KileAction::Tag(i18n("Vertical Variable Space - \\vfill"), i18n("Vertical Variable Space"), QKeySequence(), receiver,SLOT(insertTag(KileAction::TagData)),ac,"tag_vfill","\\vfill",QString(),6,0, i18n("The \\vfill fill command produces a \"rubber length\" which can stretch or shrink vertically.")); (void) new KileAction::Tag(i18n("Horizontal Space - \\hspace{}"), i18n("Horizontal Space"), "hspace", QKeySequence(), receiver,SLOT(insertTag(KileAction::TagData)),ac,"tag_hspace","\\hspace{","}",8,0, i18n("The \\hspace command adds horizontal space. The length of the space can be expressed in any terms that LaTeX understands, i.e., points, inches, etc. You can add negative as well as positive space with an \\hspace command. Adding negative space is like backspacing.")); (void) new KileAction::Tag(i18n("Horizontal Space (forced) - \\hspace*{}"), i18n("Horizontal Space (forced)"), "hspace-star", QKeySequence(), receiver,SLOT(insertTag(KileAction::TagData)),ac,"tag_hspace*","\\hspace*{","}",9,0, i18n("The \\hspace* command adds horizontal space like the \\hspace command. LaTeX removes horizontal space that comes at the end of a line. If you do not want LaTeX to remove this space, include the optional * argument. Then the space is never removed.")); (void) new KileAction::Tag(i18n("Vertical Space - \\vspace{}"), i18n("Vertical Space"), "vspace", QKeySequence(), receiver,SLOT(insertTag(KileAction::TagData)),ac,"tag_vspace","\\vspace{","}",8,0, i18n("The \\vspace command adds vertical space. The length of the space can be expressed in any terms that LaTeX understands, i.e., points, inches, etc. You can add negative as well as positive space with an \\vspace command.")); (void) new KileAction::Tag(i18n("Vertical Space (forced) - \\vspace*{}"), i18n("Vertical Space (forced)"), "vspace-star", QKeySequence(), receiver,SLOT(insertTag(KileAction::TagData)),ac,"tag_vspace*","\\vspace*{","}",9,0, i18n("The \\vspace* command adds vertical space like the \\vspace command. LaTeX removes vertical space that comes at the end of a page. If you do not want LaTeX to remove this space, include the optional * argument. Then the space is never removed.")); // fonts new KileAction::Tag(i18n("Emphasized - \\emph{}"), i18n("Emphasized"), "emph", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), ac,"tag_emph","\\emph{","}",6,0,i18n("\\emph{emphasized text}")); new KileAction::Tag(i18n("Strong - \\strong{}"), i18n("Strong"), "strong", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), ac,"tag_strong","\\strong{","}",8,0,i18n("\\strong{text}")); (void) new KileAction::Tag(i18n("Roman - \\rmfamily"), i18n("Roman"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), ac,"tag_rmfamily", "\\rmfamily", QString(), 9); (void) new KileAction::Tag(i18n("Sans Serif - \\sffamily"), i18n("Sans Serif"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), ac,"tag_sffamily", "\\sffamily", QString(), 9); (void) new KileAction::Tag(i18n("Monospace - \\ttfamily"), i18n("Monospace"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), ac,"tag_ttfamily", "\\ttfamily", QString(), 9); (void) new KileAction::Tag(i18n("Medium - \\mdseries"), i18n("Medium"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), ac,"tag_mdseries", "\\mdseries", QString(), 9); (void) new KileAction::Tag(i18n("Bold - \\bfseries"), i18n("Bold"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), ac,"tag_bfseries", "\\bfseries", QString(), 9); (void) new KileAction::Tag(i18n("Upright - \\upshape"), i18n("Upright"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), ac,"tag_upshape", "\\upshape", QString(), 8); (void) new KileAction::Tag(i18n("Italic - \\itshape"), i18n("Italic"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), ac,"tag_itshape", "\\itshape", QString(), 8); (void) new KileAction::Tag(i18n("Slanted - \\slshape"), i18n("Slanted"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), ac,"tag_slshape", "\\slshape", QString(), 8); (void) new KileAction::Tag(i18n("Smallcaps - \\scshape"), i18n("Smallcaps"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), ac,"tag_scshape", "\\scshape", QString(), 8); } void setupBibTags(const QObject *receiver, KActionCollection *actionCollection, KActionMenu * menu) { KILE_DEBUG_MAIN << "void setupBibTags(const QObject *receiver, KActionCollection *actionCollection)"; QString filename; if(KileConfig::bibliographyType().isEmpty() || KileConfig::bibliographyType() == QString("bibtex") ) { menu->addAction(new KileAction::Tag(i18n("Bibliography Style Selection - \\bibliographystyle{}"), i18n("Bibliography Style Selection"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_bibliographystyle", "\\bibliographystyle{","} ",19,0,i18n("The argument to \\bibliographystyle refers to a file style.bst, which defines how your citations will look\nThe standard styles distributed with BibTeX are:\nalpha : sorted alphabetically. Labels are formed from name of author and year of publication.\nplain : sorted alphabetically. Labels are numeric.\nunsrt : like plain, but entries are in order of citation.\nabbrv : like plain, but more compact labels."))); menu->addAction(new KileAction::Tag(i18n("Bibliography Generation - \\bibliography{}"), i18n("Bibliography Generation"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_bibliography","\\bibliography{%S", "}\n",14, 0,i18n("The argument to \\bibliography refers to the bib file (without extension)\nwhich should contain your database in BibTeX format.\nKile inserts automatically the base name of the TeX file"))); menu->addSeparator(); - filename = QStandardPaths::locate(QStandardPaths::DataLocation, "bibtexentries.rc"); + filename = KileUtilities::locate(QStandardPaths::AppDataLocation, "bibtexentries.rc"); } else if(KileConfig::bibliographyType() == QString("biblatex")) { menu->addAction(new KileAction::Tag(i18n("Load Biblatex Package - \\usepackage{biblatex}"), i18n("Load Biblatex Package"), QKeySequence(), receiver,SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_bibliographyPackage", "\\usepackage{biblatex}\n",QString(),21,0,i18n("This includes the package biblatex"))); menu->addAction(new KileAction::Tag(i18n("Bibliography Generation - \\bibliography{}"), i18n("Bibliography Generation"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_bibliography","\\bibliography{%S", "}\n",14, 0,i18n("The argument to \\bibliography refers to the bib file (without extension)\nwhich should contain your database in BibTeX format.\nKile inserts automatically the base name of the TeX file"))); menu->addAction(new KileAction::Tag(i18n("Print Bibliography"), QString(), QKeySequence(), receiver,SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_printbibliography", "\\printbibliography",QString(),18,0,i18n("Prints the complete bibliography"))); menu->addAction(new KileAction::Tag(i18n("Print Bibliography by Section"), QString(), QKeySequence(), receiver,SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_bibliographyBySection", "\\bibbysection[","]",14,0,i18n("Print the bibliography for each section"))); menu->addAction(new KileAction::Tag(i18n("Print List of Shorthands"), QString(), QKeySequence(), receiver,SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_bibliographyShortHands", "\\printshorthands",QString(),16,0,QString())); menu->addSeparator(); /* use this to insert more menu->addAction(new KileAction::Tag(i18n(""), QKeySequence(), receiver,SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_", "\\",QString(),,0,i18n(""))); Load Biblatex-Package - \usepackage{biblatex} Bibliography File - \bibliography{} Print Bibliography - \printbibliography Print Bibliography by Section - \bibbysection[] Print List of Shorthands - \printshorthands */ - filename = QStandardPaths::locate(QStandardPaths::DataLocation, "biblatexentries.rc"); + filename = KileUtilities::locate(QStandardPaths::AppDataLocation, "biblatexentries.rc"); } else { filename.clear(); } if(filename.isEmpty()) { KILE_DEBUG_MAIN << "found no filename" << endl; return; } KConfig *bibCfg = new KConfig(filename, KConfig::SimpleConfig); if(bibCfg == Q_NULLPTR ) return; const QStringList groupList = bibCfg->groupList(); // check if a non-deleted group exists // groupList.count() == 0 is not enough due to bug 384039 { bool allDeleted = false; for(auto group : groupList) { if(bibCfg->hasGroup(group)) { allDeleted = false; break; } } if(allDeleted) { return; } } QString name, tag, internalName, keys, key; QStringList keyList, optKeyList, altKeyList; QString altText, optText, compText; for(auto group : groupList) { if(!bibCfg->hasGroup(group)) { // 'group' might have been deleted continue; // work around bug 384039 } altKeyList.clear(); keyList.clear(); optKeyList.clear(); KConfigGroup grp = bibCfg->group(group); // KILE_DEBUG_MAIN << "group " << grp.name(); tag = grp.name(); name = grp.readEntry(QString("name")); internalName = grp.readEntry(QString("internalName")); keyList = grp.readEntry(QString("key")).split(',', QString::SkipEmptyParts); altKeyList = grp.readEntry(QString("altkey")).split(',', QString::SkipEmptyParts); optKeyList = grp.readEntry(QString("optkey")).split(',', QString::SkipEmptyParts); // KILE_DEBUG_MAIN << "length(keys)=" << keyList.count() << ", length(altkeys)=" << altKeyList.count() << ", length(optkeys)=" << optKeyList.count(); // KILE_DEBUG_MAIN << "tag=" << tag << ", name=" << name << ", internalName=" << internalName; keys = QString("@%1{,\n").arg(tag); int length = keys.length() - 2; // do some trimming name = name.trimmed(); internalName = "tag_bib_" + internalName.trimmed(); tag = tag.trimmed(); for(QList::iterator it = keyList.begin(); it != keyList.end(); ++it) { key = (*it).trimmed(); key = QString(" %1 = {},\n").arg(key); keys.append(key); // KILE_DEBUG_MAIN << "key" << key ; } for(QList::iterator it = altKeyList.begin(); it != altKeyList.end(); ++it) { key = (*it).trimmed(); key = QString(" ALT%1 = {},\n").arg(key); keys.append(key); // KILE_DEBUG_MAIN << "altkey" << key ; } for(QList::iterator it = optKeyList.begin(); it != optKeyList.end(); ++it) { key = (*it).trimmed(); key = QString(" OPT%1 = {},\n").arg(key); keys.append(key); // KILE_DEBUG_MAIN << "optKey" << key; } keys.append("}\n"); altText = i18n("ALT.... : you have the choice between these two fields\n"); optText = i18n("OPT.... : optional fields (use the 'Clean' command to remove them)"); compText = i18n("Bib fields - %1\n",name); if( altKeyList.count() > 1 ) { compText.append(altText); } if( optKeyList.count() > 1 ) { compText.append(optText); } menu->addAction(new KileAction::Tag(name, QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,internalName,keys,QString(),length,0,compText)); } } void setupMathTags(const QObject *receiver, KActionCollection *actionCollection) { (void) new KileAction::Tag(i18n("\\mathrm{}"), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_mathrm","\\mathrm{","}",8); (void) new KileAction::Tag(i18n("\\mathit{}"), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_mathit","\\mathit{","}",8); (void) new KileAction::Tag(i18n("\\mathbf{}"), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_mathbf","\\mathbf{","}",8); (void) new KileAction::Tag(i18n("\\mathsf{}"), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_mathsf","\\mathsf{","}",8); (void) new KileAction::Tag(i18n("\\mathtt{}"), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_mathtt","\\mathtt{","}",8); (void) new KileAction::Tag(i18n("\\mathcal{}"), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_mathcal","\\mathcal{","}",9); (void) new KileAction::Tag(i18n("\\mathbb{}"), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_mathbb","\\mathbb{","}",8); (void) new KileAction::Tag(i18n("\\mathfrak{}"), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_mathfrak","\\mathfrak{","}",10); (void) new KileAction::Tag(i18n("\\acute{}"), QString(), "acute", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_acute", "\\acute{","}",7); (void) new KileAction::Tag(i18n("\\grave{}"), QString(), "grave", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_grave", "\\grave{","}", 7); (void) new KileAction::Tag(i18n("\\tilde{}"), QString(), "tilde", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_tilde", "\\tilde{","}", 7); (void) new KileAction::Tag(i18n("\\bar{}"), QString(), "bar", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_bar", "\\bar{","}", 5); (void) new KileAction::Tag(i18n("\\vec{}"), QString(), "vec", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_vec", "\\vec{","}", 5); (void) new KileAction::Tag(i18n("\\hat{}"), QString(), "hat", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_hat", "\\hat{","}", 5); (void) new KileAction::Tag(i18n("\\check{}"), QString(), "check", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_check", "\\check{","}", 7); (void) new KileAction::Tag(i18n("\\breve{}"), QString(), "breve", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_breve", "\\breve{","}", 7); (void) new KileAction::Tag(i18n("\\dot{}"), QString(), "dot", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_dot", "\\dot{","}", 5); (void) new KileAction::Tag(i18n("\\ddot{}"), QString(), "ddot", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_ddot", "\\ddot{","}", 6); (void) new KileAction::Tag(i18n("Small Space"), QString(), "thinspace", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_space_small", "\\,", QString(), 2); (void) new KileAction::Tag(i18n("Medium Space"), QString(), "medspace", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_space_medium", "\\:", QString(),2); (void) new KileAction::Tag(i18n("Large Space"), QString(), "bigspace", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_space_large", "\\;", QString(),2); (void) new KileAction::Tag(i18n("\\quad"), QString(), "quad", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_quad", "\\quad ", QString(), 6); (void) new KileAction::Tag(i18n("\\qquad"), QString(), "qquad", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_qquad", "\\qquad ", QString(), 7); (void) new KileAction::Tag(i18n("Math Mode - $...$"), i18n("Math Mode"), "mathmode", QKeySequence(Qt::ALT+Qt::SHIFT+Qt::Key_M), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_mathmode","$","$",1); (void) new KileAction::Tag(i18n("Displaymath Mode - \\[...\\]"), i18n("Displaymath Mode"), "displaymathmode", QKeySequence(Qt::ALT+Qt::SHIFT+Qt::Key_E), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_equation", "\\[","\\]", 2); (void) new KileAction::Tag(i18n("Equation - \\begin{equation}"), i18n("Equation"), "equation", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_env_equation","\\begin{equation}\n","%E\n\\end{equation} ",0,1); (void) new KileAction::Tag(i18n("Subscript - _{}"), i18n("Subscript"), "format-text-subscript", QKeySequence(Qt::ALT+Qt::SHIFT+Qt::Key_D), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_subscript","_{","}",2); (void) new KileAction::Tag(i18n("Superscript - ^{}"), i18n("Superscript"), "format-text-superscript", QKeySequence(Qt::ALT+Qt::SHIFT+Qt::Key_U), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_superscript","^{","}",2); (void) new KileAction::Tag(i18n("Normal Fraction - \\frac{}{}"), i18n("Normal Fraction"), "smallfrac", QKeySequence(Qt::ALT+Qt::SHIFT+Qt::Key_F), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_frac", "\\frac{","}{}",6); (void) new KileAction::Tag(i18n("Displaystyle Fraction - \\dfrac{}{}"), i18n("Displaystyle Fraction"), "dfrac", QKeySequence(Qt::ALT+Qt::SHIFT+Qt::Key_Q), receiver, SLOT(insertAmsTag(KileAction::TagData)), actionCollection,"tag_dfrac", "\\dfrac{","}{}", 7); (void) new KileAction::Tag(i18n("Textstyle Fraction - \\tfrac{}{}"), i18n("Textstyle Fraction"), QKeySequence(), receiver, SLOT(insertAmsTag(KileAction::TagData)), actionCollection, "tag_tfrac", "\\tfrac{", "}{}", 7); (void) new KileAction::Tag(i18n("Square Root - \\sqrt{}"), i18n("Square Root"), "sqrt", QKeySequence(Qt::ALT+Qt::SHIFT+Qt::Key_S), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_sqrt", "\\sqrt{","}", 6); (void) new KileAction::Tag(i18n("\\left"), QString(), QKeySequence(Qt::ALT+Qt::SHIFT+Qt::Key_L), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_left", "\\left", QString(), 5); (void) new KileAction::Tag(i18n("\\right"), QString(), QKeySequence(Qt::ALT+Qt::SHIFT+Qt::Key_R), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_right", "\\right", QString(), 6); (void) new KileAction::Tag(i18n("Array - \\begin{array}"), i18n("Array"), "array", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection,"tag_env_array", "\\begin{array}{}\n", "%E\n\\end{array}", 14, 0, i18n("\\begin{array}{col1col2...coln}\ncolumn 1 entry & column 2 entry ... & column n entry \\\\ \n...\n\\end{array}\nEach column, coln, is specified by a single letter that tells how items in that column should be formatted.\n" " c -- for centered \n l -- for flush left \n r -- for flush right\n")); ToolbarSelectAction *actionleft_list = new ToolbarSelectAction(i18n("Left Delimiter"), actionCollection,false); actionCollection->addAction("left_list", actionleft_list); actionleft_list->addAction(new KileAction::Tag(i18n("left ("), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection, "tag_left_(", "\\left( ", QString(), 7, 0)); actionleft_list->addAction(new KileAction::Tag(i18n("left ["), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection, "tag_left_[", "\\left[ ", QString(), 7, 0)); actionleft_list->addAction(new KileAction::Tag(i18n("left {"), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection, "tag_left_{", "\\left\\lbrace ", QString(), 14, 0)); actionleft_list->addAction(new KileAction::Tag(i18n("left <"), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection, "tag_left_<", "\\left\\langle ", QString(), 14, 0)); actionleft_list->addSeparator(); actionleft_list->addAction(new KileAction::Tag(i18n("left )"), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection, "tag_left_)", "\\left) ", QString(), 7, 0)); actionleft_list->addAction(new KileAction::Tag(i18n("left ]"), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection, "tag_left_]", "\\left] ", QString(), 7, 0)); actionleft_list->addAction(new KileAction::Tag(i18n("left }"), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection, "tag_left_}", "\\left\\rbrace ", QString(), 14, 0)); actionleft_list->addAction(new KileAction::Tag(i18n("left >"), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection, "tag_left_>", "\\left\\rangle ", QString(), 14, 0)); actionleft_list->addSeparator(); actionleft_list->addAction(new KileAction::Tag(i18n("left ."), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection, "tag_left_.", "\\left. ", QString(), 7, 0)); ToolbarSelectAction *actionright_list = new ToolbarSelectAction(i18n("Right Delimiter"), actionCollection,false); actionCollection->addAction("right_list", actionright_list); actionright_list->addAction(new KileAction::Tag(i18n("right )"), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection, "tag_right_)", "\\right) ", QString(), 8, 0)); actionright_list->addAction(new KileAction::Tag(i18n("right ]"), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection, "tag_right_]", "\\right] ", QString(), 8, 0)); actionright_list->addAction(new KileAction::Tag(i18n("right }"), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection, "tag_right_}", "\\right\\rbrace ", QString(), 14, 0)); actionright_list->addAction(new KileAction::Tag(i18n("right >"), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection, "tag_right_>", "\\right\\rangle ", QString(), 14, 0)); actionright_list->addSeparator(); actionright_list->addAction(new KileAction::Tag(i18n("right ("), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection, "tag_right_(", "\\right( ", QString(), 8, 0)); actionright_list->addAction(new KileAction::Tag(i18n("right ["), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection, "tag_right_[", "\\right[ ", QString(), 8, 0)); actionright_list->addAction(new KileAction::Tag(i18n("right {"), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection, "tag_right_{", "\\right\\lbrace ", QString(), 14, 0)); actionright_list->addAction(new KileAction::Tag(i18n("right <"), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection, "tag_right_<", "\\right\\langle ", QString(), 14, 0)); actionright_list->addSeparator(); actionright_list->addAction(new KileAction::Tag(i18n("right ."), QString(), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), actionCollection, "tag_right_.", "\\right. ", QString(), 8, 0)); // new math tags (dani 29.01.2005) KActionCollection* ac = actionCollection; (void) new KileAction::Tag(i18n("Normal Binomial - \\binom{}{}"), i18n("Normal Binomial"), "binom", QKeySequence(), receiver, SLOT(insertAmsTag(KileAction::TagData)), ac,"tag_binom", "\\binom{","}{}", 7); (void) new KileAction::Tag(i18n("Displaystyle Binomial - \\dbinom{}{}"), i18n("Displaystyle Binomial"), QKeySequence(), receiver,SLOT(insertAmsTag(KileAction::TagData)), ac,"tag_dbinom", "\\dbinom{","}{}", 8); (void) new KileAction::Tag(i18n("Textstyle Binomial - \\tbinom{}{}"), i18n("Textstyle Binomial"), QKeySequence(), receiver, SLOT(insertAmsTag(KileAction::TagData)), ac,"tag_tbinom", "\\tbinom{","}{}", 8); (void) new KileAction::Tag(i18n("N-th Root - \\sqrt[]{}"), i18n("N-th Root"), "nroot", QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), ac,"tag_nroot", "\\sqrt[]{","}", 6); (void) new KileAction::Tag(i18n("Left-Right () - \\left(..\\right)"), i18n("Left-Right ()"), "lr", QKeySequence(Qt::ALT+Qt::Key_ParenLeft), receiver, SLOT(insertTag(KileAction::TagData)), ac,"tag_leftright", "\\left( \\right)", QString(), 7); (void) new KileAction::Tag(i18n("Extendable Left Arrow - \\xleftarrow{}"), i18n("Extendable Left Arrow"), QKeySequence(), receiver, SLOT(insertAmsTag(KileAction::TagData)), ac,"tag_xleftarrow", "\\xleftarrow{","}", 12); (void) new KileAction::Tag(i18n("Extendable Right Arrow - \\xrightarrow{}"), i18n("Extendable Right Arrow"), QKeySequence(), receiver, SLOT(insertAmsTag(KileAction::TagData)), ac,"tag_xrightarrow", "\\xrightarrow{","}", 13); (void) new KileAction::Tag(i18n("Boxed Formula - \\boxed{}"), i18n("Boxed Formula"), QKeySequence(), receiver, SLOT(insertAmsTag(KileAction::TagData)), ac,"tag_boxed", "\\boxed{","}", 7); (void) new KileAction::Tag(i18n("bigl - \\bigl"), i18n("bigl"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), ac,"tag_bigl", "\\bigl",QString(), 5); (void) new KileAction::Tag(i18n("Bigl - \\Bigl"), i18n("Bigl"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), ac,"tag_Bigl", "\\Bigl",QString(), 5); (void) new KileAction::Tag(i18n("biggl - \\biggl"), i18n("biggl"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), ac,"tag_biggl", "\\biggl",QString(), 6); (void) new KileAction::Tag(i18n("Biggl - \\Biggl"), i18n("Biggl"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), ac,"tag_Biggl", "\\Biggl",QString(), 6); (void) new KileAction::Tag(i18n("bigr - \\bigr"), i18n("bigr"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), ac,"tag_bigr", "\\bigr",QString(), 5); (void) new KileAction::Tag(i18n("Bigr - \\Bigr"), i18n("Bigr"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), ac,"tag_Bigr", "\\Bigr",QString(), 5); (void) new KileAction::Tag(i18n("biggr - \\biggr"), i18n("biggr"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), ac,"tag_biggr", "\\biggr",QString(), 6); (void) new KileAction::Tag(i18n("Biggr - \\Biggr"), i18n("Biggr"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), ac,"tag_Biggr", "\\Biggr",QString(), 6); // text in mathmode (void) new KileAction::Tag(i18n("Text in Mathmode - \\text{}"), i18n("Text in Mathmode"), QKeySequence(), receiver, SLOT(insertAmsTag(KileAction::TagData)), ac,"tag_text", "\\text{","}", 6); (void) new KileAction::Tag(i18n("Intertext - \\intertext{}"), i18n("Intertext"), QKeySequence(), receiver, SLOT(insertAmsTag(KileAction::TagData)), ac,"tag_intertext", "\\intertext{","}\n", 11); // math environments (void) new KileAction::Tag(i18n("Displaymath - \\begin{displaymath}"), i18n("Displaymath"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), ac,"tag_env_displaymath","\\begin{displaymath}\n","%E\n\\end{displaymath}\n",0,1); (void) new KileAction::Tag(i18n("Equation (not numbered) - \\begin{equation*}"), i18n("Equation (not numbered)"), QKeySequence(), receiver, SLOT(insertTag(KileAction::TagData)), ac,"tag_env_equation*","\\begin{equation*}\n","%E\n\\end{equation*}\n",0,1); // AMS environments (void) new KileAction::Tag(i18n("Multline - \\begin{multline}"), i18n("Multline"), "multline", QKeySequence(), receiver, SLOT(insertAmsTag(KileAction::TagData)),ac,"tag_env_multline","\\begin{multline}\n","%E\n\\end{multline}\n", 0,1); (void) new KileAction::Tag(i18n("Multline* - \\begin{multline*}"), i18n("Multline*"), QKeySequence(), receiver, SLOT(insertAmsTag(KileAction::TagData)),ac,"tag_env_multline*","\\begin{multline*}\n","%E\n\\end{multline*}\n", 0,1); (void) new KileAction::Tag(i18n("Split - \\begin{split}"), i18n("Split"), QKeySequence(), receiver, SLOT(insertAmsTag(KileAction::TagData)),ac,"tag_env_split","\\begin{split}\n","%E\n\\end{split}\n", 0,1); (void) new KileAction::Tag(i18n("Gather - \\begin{gather}"), i18n("Gather"), "gather", QKeySequence(), receiver, SLOT(insertAmsTag(KileAction::TagData)),ac,"tag_env_gather","\\begin{gather}\n","%E\n\\end{gather}\n", 0,1); (void) new KileAction::Tag(i18n("Gather* - \\begin{gather*}"), i18n("Gather*"), QKeySequence(), receiver, SLOT(insertAmsTag(KileAction::TagData)),ac,"tag_env_gather*","\\begin{gather*}\n","%E\n\\end{gather*}\n", 0,1); (void) new KileAction::Tag(i18n("Align - \\begin{align}"), i18n("Align"), "align", QKeySequence(), receiver, SLOT(insertAmsTag(KileAction::TagData)),ac,"tag_env_align","\\begin{align}\n","%E\n\\end{align}\n", 0,1); (void) new KileAction::Tag(i18n("Align* - \\begin{align*}"), i18n("Align*"), QKeySequence(), receiver, SLOT(insertAmsTag(KileAction::TagData)),ac,"tag_env_align*","\\begin{align*}\n","%E\n\\end{align*}\n", 0,1); (void) new KileAction::Tag(i18n("Flalign - \\begin{flalign}"), i18n("Flalign"), "flalign", QKeySequence(), receiver, SLOT(insertAmsTag(KileAction::TagData)),ac,"tag_env_flalign","\\begin{flalign}\n","%E\n\\end{flalign}\n", 0,1); (void) new KileAction::Tag(i18n("Flalign* - \\begin{flalign*}"), i18n("Flalign*"), QKeySequence(), receiver, SLOT(insertAmsTag(KileAction::TagData)),ac,"tag_env_flalign*","\\begin{flalign*}\n","%E\n\\end{flalign*}\n", 0,1); (void) new KileAction::Tag(i18n("Alignat - \\begin{alignat}"), i18n("Alignat"), QKeySequence(), receiver, SLOT(insertAmsTag(KileAction::TagData)),ac,"tag_env_alignat","\\begin{alignat}{","}\n%E\n\\end{alignat}\n", 16,0); (void) new KileAction::Tag(i18n("Alignat* - \\begin{alignat*}"), i18n("Alignat*"), QKeySequence(), receiver, SLOT(insertAmsTag(KileAction::TagData)),ac,"tag_env_alignat*","\\begin{alignat*}{","}\n%E\n\\end{alignat*}\n", 17,0); (void) new KileAction::Tag(i18n("Aligned - \\begin{aligned}"), i18n("Aligned"), QKeySequence(), receiver, SLOT(insertAmsTag(KileAction::TagData)),ac,"tag_env_aligned","\\begin{aligned}\n","%E\n\\end{aligned}\n", 0,1); (void) new KileAction::Tag(i18n("Gathered - \\begin{gathered}"), i18n("Gathered"), QKeySequence(), receiver, SLOT(insertAmsTag(KileAction::TagData)),ac,"tag_env_gathered","\\begin{gathered}\n","%E\n\\end{gathered}\n", 0,1); (void) new KileAction::Tag(i18n("Alignedat - \\begin{alignedat}"), i18n("Alignedat"), QKeySequence(), receiver, SLOT(insertAmsTag(KileAction::TagData)),ac,"tag_env_alignedat","\\begin{alignedat}\n","%E\n\\end{alignedat}\n", 0,1); (void) new KileAction::Tag(i18n("Cases - \\begin{cases}"), i18n("Cases"), "cases", QKeySequence(), receiver, SLOT(insertAmsTag(KileAction::TagData)),ac,"tag_env_cases","\\begin{cases}\n","%E\n\\end{cases}\n", 0,1); (void) new KileAction::Tag(i18n("matrix - \\begin{matrix}"), i18n("matrix"), "matrix", QKeySequence(), receiver, SLOT(insertAmsTag(KileAction::TagData)),ac,"tag_env_matrix","\\begin{matrix}\n","%E\n\\end{matrix}\n", 0,1); (void) new KileAction::Tag(i18n("pmatrix - \\begin{pmatrix}"), i18n("pmatrix"), "pmatrix", QKeySequence(), receiver, SLOT(insertAmsTag(KileAction::TagData)),ac,"tag_env_pmatrix","\\begin{pmatrix}\n","%E\n\\end{pmatrix}\n", 0,1); (void) new KileAction::Tag(i18n("vmatrix - \\begin{vmatrix}"), i18n("vmatrix"), "vmatrix", QKeySequence(), receiver, SLOT(insertAmsTag(KileAction::TagData)),ac,"tag_env_vmatrix","\\begin{vmatrix}\n","%E\n\\end{vmatrix}\n", 0,1); (void) new KileAction::Tag(i18n("Vmatrix - \\begin{Vmatrix}"), i18n("Vmatrix"), "VVmatrix", QKeySequence(), receiver, SLOT(insertAmsTag(KileAction::TagData)),ac,"tag_env_VVmatrix","\\begin{Vmatrix}\n","%E\n\\end{Vmatrix}\n", 0,1); (void) new KileAction::Tag(i18n("bmatrix - \\begin{bmatrix}"), i18n("bmatrix"), "bmatrix", QKeySequence(), receiver, SLOT(insertAmsTag(KileAction::TagData)),ac,"tag_env_bmatrix","\\begin{bmatrix}\n","%E\n\\end{bmatrix}\n", 0,1); (void) new KileAction::Tag(i18n("Bmatrix - \\begin{Bmatrix}"), i18n("Bmatrix"), "BBmatrix", QKeySequence(), receiver, SLOT(insertAmsTag(KileAction::TagData)),ac,"tag_env_BBmatrix","\\begin{Bmatrix}\n","%E\n\\end{Bmatrix}\n", 0,1); } } diff --git a/src/kilestdtools.cpp b/src/kilestdtools.cpp index 7a60f324..b0f9dc81 100644 --- a/src/kilestdtools.cpp +++ b/src/kilestdtools.cpp @@ -1,823 +1,822 @@ /************************************************************************************** begin : Thu Nov 27 2003 copyright : (C) 2003 by Jeroen Wijnhout (Jeroen.Wijnhout@kdemail.net) (C) 2011-2017 by Michel Ludwig (michel.ludwig@kdemail.net) **************************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "kilestdtools.h" #include #include #include #include #include #include #include -#include #include "dialogs/listselector.h" #include "kileconfig.h" #include "kiletool.h" #include "kiletoolmanager.h" #include "kiletool_enums.h" #include "kileinfo.h" #include "kiledocmanager.h" #include "documentinfo.h" #include "outputinfo.h" #include "parser/parsermanager.h" #include "utilities.h" #define SHORTCUTS_GROUP_NAME "Shortcuts" namespace KileTool { Factory::Factory(Manager *mngr, KConfig *config, KActionCollection *actionCollection) : m_manager(mngr), m_config(config), m_actionCollection(actionCollection) { - m_standardToolConfigurationFileName = QStandardPaths::locate(QStandardPaths::DataLocation, "kilestdtools.rc"); + m_standardToolConfigurationFileName = KileUtilities::locate(QStandardPaths::AppDataLocation, "kilestdtools.rc"); } Factory::~Factory() { } Base* Factory::create(const QString& toolName, const QString& config, bool prepare /* = true */) { KILE_DEBUG_MAIN << toolName << config << prepare; KileTool::Base *tool = Q_NULLPTR; //perhaps we can find the tool in the config file if (m_config->hasGroup(groupFor(toolName, m_config))) { KConfigGroup configGroup = m_config->group(groupFor(toolName, m_config)); QString toolClass = configGroup.readEntry("class", QString()); if(toolClass == "LaTeX") { tool = new LaTeX(toolName, m_manager, prepare); } else if(toolClass == "LaTeXpreview") { tool = new PreviewLaTeX(toolName, m_manager, prepare); } else if(toolClass == "LaTeXLivePreview") { tool = new LivePreviewLaTeX(toolName, m_manager, prepare); } else if(toolClass == "ForwardDVI") { tool = new ForwardDVI(toolName, m_manager, prepare); } else if(toolClass == "ViewHTML") { tool = new ViewHTML(toolName, m_manager, prepare); } else if(toolClass == "ViewBib") { tool = new ViewBib(toolName, m_manager, prepare); } else if(toolClass == "Base") { tool = new Base(toolName, m_manager, prepare); } else if(toolClass == "Compile") { tool = new Compile(toolName, m_manager, prepare); } else if (BibliographyCompile::ToolClass == toolClass) { tool = new BibliographyCompile(toolName, m_manager, prepare); } else if(toolClass == "Convert") { tool = new Convert(toolName, m_manager, prepare); } else if(toolClass == "Archive") { tool = new Archive(toolName, m_manager, prepare); } else if(toolClass == "View") { tool = new View(toolName, m_manager, prepare); } else if(toolClass == "Sequence") { tool = new Sequence(toolName, m_manager, prepare); } } if(!tool) { return Q_NULLPTR; } if(!m_manager->configure(tool, config)) { delete tool; return Q_NULLPTR; } tool->setToolConfig(config); // this has to be done after the configuration step only! if(dynamic_cast(tool)) { dynamic_cast(tool)->setupSequenceTools(); } return tool; } void Factory::resetToolConfigurations() { KConfig stdToolConfig(m_standardToolConfigurationFileName, KConfig::NoGlobals); m_config->deleteGroup(QLatin1String("Tools")); m_config->deleteGroup(QLatin1String("ToolsGUI")); // we delete all the groups whose names start with "Tool/"; for(QString groupName : m_config->groupList()) { if(groupName.startsWith(QLatin1String("Tool/"))) { m_config->deleteGroup(groupName); } } // now we copy all the "Tool/" groups, the "Tools", and "ToolsGUI" groups over for(QString groupName : stdToolConfig.groupList()) { if(groupName != SHORTCUTS_GROUP_NAME) { KConfigGroup configGroup = stdToolConfig.group(groupName); m_config->deleteGroup(groupName); KConfigGroup newGroup = m_config->group(groupName); configGroup.copyTo(&newGroup, KConfigGroup::Persistent); } } } static void transferKeyStringPairsStartingWith(KConfigGroup& src, KConfigGroup& target, const QString& startsWith) { const QStringList keyList = src.keyList(); for(QString key : keyList) { if(key.startsWith(startsWith)) { QString value = src.readEntry(key, QString()); target.writeEntry(key, value); } } } void Factory::installStandardLivePreviewTools() { KConfig stdToolConfig(m_standardToolConfigurationFileName, KConfig::NoGlobals); const QStringList groupList = stdToolConfig.groupList(); for(QString groupName : groupList) { if(groupName.startsWith(QStringLiteral("Tool/LivePreview"))) { KConfigGroup configGroup = stdToolConfig.group(groupName); m_config->deleteGroup(groupName); KConfigGroup newGroup = m_config->group(groupName); configGroup.copyTo(&newGroup, KConfigGroup::Persistent); } } { // transfer the standard settings inside the "Tools" group const QString groupName(QStringLiteral("Tools")); KConfigGroup stdConfigGroup = stdToolConfig.group(groupName); KConfigGroup newGroup = m_config->group(groupName); transferKeyStringPairsStartingWith(stdConfigGroup, newGroup, QStringLiteral("LivePreview")); } { // transfer the standard settings inside the "ToolsGUI" group const QString groupName(QStringLiteral("ToolsGUI")); KConfigGroup stdConfigGroup = stdToolConfig.group(groupName); KConfigGroup newGroup = m_config->group(groupName); transferKeyStringPairsStartingWith(stdConfigGroup, newGroup, QStringLiteral("LivePreview")); } } /////////////// LaTeX //////////////// LaTeX::LaTeX(const QString& tool, Manager *mngr, bool prepare) : Compile(tool, mngr, prepare), m_latexOutputHandler(Q_NULLPTR) { } LaTeX::~LaTeX() { } void LaTeX::setupAsChildTool(KileTool::Base *child) { KileTool::LaTeX *latexChild = dynamic_cast(child); if(latexChild) { latexChild->setLaTeXOutputHandler(latexOutputHandler()); } } LaTeXOutputHandler* LaTeX::latexOutputHandler() { return m_latexOutputHandler; } void LaTeX::setLaTeXOutputHandler(LaTeXOutputHandler *h) { m_latexOutputHandler = h; } bool LaTeX::determineSource() { QString src = source(); // check whether the source has been set already if(!src.isEmpty()) { return true; } //the basedir is determined from the current compile target //determined by getCompileName() LaTeXOutputHandler *h = Q_NULLPTR; src = m_ki->getCompileName(false, &h); setSource(src); setLaTeXOutputHandler(h); return true; } int LaTeX::m_reRun = 0; // FIXME don't hardcode bbl and ind suffix here. bool LaTeX::updateBibs(bool checkOnlyBibDependencies) { KileDocument::TextInfo *docinfo = manager()->info()->docManager()->textInfoFor(source()); if(docinfo) { QFileInfo fileinfo(docinfo->url().toLocalFile()); QStringList dependencies; if (checkOnlyBibDependencies) { dependencies = manager()->info()->allBibliographies(docinfo); } else { dependencies = manager()->info()->allDependencies(docinfo); dependencies.append(fileinfo.fileName()); } if (!dependencies.empty()) { return needsUpdate(targetDir() + '/' + S() + ".bbl", KileUtilities::lastModifiedFile(dependencies, fileinfo.absolutePath())); } } return false; } bool LaTeX::updateIndex() { KileDocument::TextInfo *docinfo = manager()->info()->docManager()->textInfoFor(source()); if(docinfo) { QStringList pckgs = manager()->info()->allPackages(docinfo); if(pckgs.contains("makeidx") || pckgs.contains("imakeidx") || pckgs.contains("splitidx")) { return needsUpdate(targetDir() + '/' + S() + ".ind", manager()->info()->lastModifiedFile(docinfo)); } } return false; } bool LaTeX::updateAsy() { KileDocument::TextInfo *docinfo = manager()->info()->docManager()->textInfoFor(source()); if(docinfo) { QStringList pckgs = manager()->info()->allPackages(docinfo); // As asymptote doesn't properly notify the user when it needs to be rerun, we run // it every time LaTeX is run (but only for m_reRun == 0 if LaTeX has to be rerun). if(pckgs.contains("asymptote")) { return true; } } return false; } bool LaTeX::finish(int r) { KILE_DEBUG_MAIN << "==bool LaTeX::finish(" << r << ")====="; m_toolResult = r; if(m_toolResult == AbnormalExit || m_toolResult == Aborted) { return false; } // in case the compilation failed, we try to parse the log file in order to detect // errors reported by LaTeX QString log = targetDir() + '/' + S() + ".log"; manager()->parserManager()->parseOutput(this, log, source()); return true; } void LaTeX::latexOutputParserResultInstalled() { KILE_DEBUG_MAIN; if(m_latexOutputHandler) { m_latexOutputHandler->storeLaTeXOutputParserResult(m_nErrors, m_nWarnings, m_nBadBoxes, m_latexOutputInfoList, m_logFile); } checqCriticals(); if(readEntry("autoRun") == "yes") { checkAutoRun(); } Compile::finish(m_toolResult); } void LaTeX::checqCriticals() { // work around the 0 cases as the i18np call can cause some confusion when 0 is passed to it (#275700) QString es = (m_nErrors == 0 ? i18n("0 errors") : i18np("1 error", "%1 errors", m_nErrors)); QString ws = (m_nWarnings == 0 ? i18n("0 warnings") : i18np("1 warning", "%1 warnings", m_nWarnings)); QString bs = (m_nBadBoxes == 0 ? i18n("0 badboxes") : i18np("1 badbox", "%1 badboxes", m_nBadBoxes)); sendMessage(Info, i18nc("String displayed in the log panel showing the number of errors/warnings/badboxes", "%1, %2, %3", es, ws, bs)); // jump to first error if(!isPartOfLivePreview() && m_nErrors > 0 && (readEntry("jumpToFirstError") == "yes")) { connect(this, SIGNAL(jumpToFirstError()), manager(), SIGNAL(jumpToFirstError())); emit(jumpToFirstError()); } } void LaTeX::configureLaTeX(KileTool::Base *tool, const QString& source) { tool->setSource(source, workingDir()); } void LaTeX::configureBibTeX(KileTool::Base *tool, const QString& source) { tool->setSource(source, workingDir()); } void LaTeX::configureMakeIndex(KileTool::Base *tool, const QString& source) { tool->setSource(source, workingDir()); } void LaTeX::configureAsymptote(KileTool::Base *tool, const QString& source) { tool->setSource(source, workingDir()); } // if 'Biblatex' is not used in the document, 'hint' will be empty ToolConfigPair LaTeX::determineBibliographyBackend(const QString& hint) { if(m_latexOutputHandler) { ToolConfigPair userBibTool = m_latexOutputHandler->bibliographyBackendToolUserOverride(); if(userBibTool.isValid()) { // now we still check whether such a tool really exists if (manager()->containsBibliographyTool(userBibTool)) { return userBibTool; } else { KILE_DEBUG_MAIN << "Cannot find the following bibtool set by the user:" << userBibTool; KILE_DEBUG_MAIN << "trying to auto-detect it now!"; sendMessage(Warning, i18n("Manually selected bibliography tool does not exist: trying to " "auto-detect it now.")); } } } // we will now try to detect the bib tool by using the given command hint ToolConfigPair bibTool = manager()->findFirstBibliographyToolForCommand(hint); if(m_latexOutputHandler) { // if we managed to detect a backend, store (or update) it for future runs if(bibTool.isValid()) { m_latexOutputHandler->setBibliographyBackendToolAutoDetected(bibTool); } else { // perhaps we have it stored from a previous run? bibTool = m_latexOutputHandler->bibliographyBackendToolAutoDetected(); // perhaps the bib tools have changed from the previous run? if (!manager()->containsBibliographyTool(bibTool)) { bibTool = ToolConfigPair(); } } } // this tool must always be available const ToolConfigPair defaultBibTool = ToolConfigPair(QString("BibTeX"), DEFAULT_TOOL_CONFIGURATION); // if no tool has been detected, the default is BibTeX return bibTool.isValid() ? bibTool : defaultBibTool; } void LaTeX::checkAutoRun() { KILE_DEBUG_MAIN << "check for autorun, m_reRun is " << m_reRun; if(m_reRun >= 2) { KILE_DEBUG_MAIN << "Already rerun twice, doing nothing."; m_reRun = 0; return; } if(m_nErrors > 0) { KILE_DEBUG_MAIN << "Errors found, not running again."; m_reRun = 0; return; } bool reRunWarningFound = false; QString bibToolInLaTexOutput; bool haveUndefinedCitations = false; // check for "rerun" LaTeX and other tools warnings if(m_nWarnings > 0) { int sz = m_latexOutputInfoList.size(); // the messages we are looking for are the last ones (most likely the very last one), so go from end to beginning for(int i = sz-1; i >= 0; --i) { if (m_latexOutputInfoList[i].type() == LatexOutputInfo::itmWarning && m_latexOutputInfoList[i].message().contains("Rerun", Qt::CaseInsensitive)) { // the message could be a message from Biblatex like this: // Package biblatex Warning: The following entry could not be found // (biblatex) in the database: // (biblatex) // (biblatex) Please verify the spelling and rerun // (biblatex) LaTeX afterwards. // // our strategy: if the warning message contains "(biblatex)", Biblatex only // suggests to check the source files first, but not to recompile yet if (!m_latexOutputInfoList[i].message().contains("(biblatex)", Qt::CaseInsensitive)) { reRunWarningFound = true; break; } } } // Now look for messages from Biblatex like the following: // Please (re)run Biber on the file: // or // Please (re)run Bibtex on the file: QRegExp biblatexBackendMessage = QRegExp(".*Please \\(re\\)run ([A-Za-z]+) on the file", Qt::CaseInsensitive); for(int i = sz-1; i >= 0; --i) { // same here, start from the end if (m_latexOutputInfoList[i].type() == LatexOutputInfo::itmWarning && biblatexBackendMessage.indexIn(m_latexOutputInfoList[i].message()) != -1) { bibToolInLaTexOutput = biblatexBackendMessage.cap(1); KILE_DEBUG_MAIN << "Captured Bib tool: " << bibToolInLaTexOutput; break; } } // If we did not get a message from Biblatex about bibtool (re)run, then // we look for messages like "LaTeX Warning: Citation `A' on page 234 undefined on input line 12345." // In that case we probably need to (re)run the bibtool. if (bibToolInLaTexOutput.isEmpty()) { QRegExp citationUndefinedMessage = QRegExp("Citation `(.+)' on page (\\d+) undefined on input line (\\d+)", Qt::CaseInsensitive); for(int i = 0; i < sz; ++i) { if (m_latexOutputInfoList[i].type() == LatexOutputInfo::itmWarning && citationUndefinedMessage.indexIn(m_latexOutputInfoList[i].message()) != -1) { haveUndefinedCitations = true; KILE_DEBUG_MAIN << "Detected undefined citations"; break; } } } } bool asy = (m_reRun == 0) && updateAsy(); // We run bibtool in the following cases: // 1. Biblatex said that we have to (in this case bibToolInLaTexOutput is not empty), OR // 2. There are no undefined citations and at least one of the .bib files has a younger modification // date than the .bbl file, OR // 3. We have undefined citations and at least one of the source files (including .bib and .tex) is // younger than .bbl. // (If the .bbl file is younger than all of them, the next rerun will not change anything) bool bibs = !bibToolInLaTexOutput.isEmpty() || updateBibs(!haveUndefinedCitations); bool index = updateIndex(); KILE_DEBUG_MAIN << "asy:" << asy << "bibs:" << bibs << "index:" << index << "reRunWarningFound:" << reRunWarningFound; // Currently, we don't properly detect yet whether asymptote has to be run. // So, if asymtote figures are present, we run it each time after the first LaTeX run. bool reRun = (asy || bibs || index || reRunWarningFound); KILE_DEBUG_MAIN << "reRun:" << reRun; if(reRun) { KILE_DEBUG_MAIN << "rerunning LaTeX, m_reRun is now " << m_reRun; Base *tool = manager()->createTool(name(), toolConfig()); if(tool) { configureLaTeX(tool, source()); // e.g. for LivePreview, it is necessary that the paths are copied to child processes tool->copyPaths(this); runChildNext(tool); m_reRun++; } } else { m_reRun = 0; } if(bibs) { KILE_DEBUG_MAIN << "need to run the bibliography tool " << bibToolInLaTexOutput; ToolConfigPair bibTool = determineBibliographyBackend(bibToolInLaTexOutput); Base *tool = manager()->createTool(bibTool.first, bibTool.second); if(tool) { configureBibTeX(tool, targetDir() + '/' + S() + '.' + tool->from()); // e.g. for LivePreview, it is necessary that the paths are copied to child processes tool->copyPaths(this); runChildNext(tool); } } if(index) { KILE_DEBUG_MAIN << "need to run MakeIndex"; Base *tool = manager()->createTool("MakeIndex", QString()); KILE_DEBUG_MAIN << targetDir() << S() << tool->from(); if(tool) { configureMakeIndex(tool, targetDir() + '/' + S() + '.' + tool->from()); // e.g. for LivePreview, it is necessary that the paths are copied to child processes tool->copyPaths(this); runChildNext(tool); } } if(asy) { KILE_DEBUG_MAIN << "need to run asymptote"; int sz = manager()->info()->allAsyFigures().size(); for(int i = sz -1; i >= 0; --i) { Base *tool = manager()->createTool("Asymptote", QString()); if(tool) { configureAsymptote(tool, targetDir() + '/' + S() + '-' + QString::number(i + 1) + '.' + tool->from()); // e.g. for LivePreview, it is necessary that the paths are copied to child processes tool->copyPaths(this); runChildNext(tool); } } } } /////////////// PreviewLaTeX (dani) //////////////// PreviewLaTeX::PreviewLaTeX(const QString& tool, Manager *mngr, bool prepare) : LaTeX(tool, mngr, prepare) { } // PreviewLatex makes three steps: // - filterLogfile() : parse logfile and read info into InfoLists // - updateInfoLists(): change entries of temporary file into normal tex file // - checqCriticals() : count errors and warnings and emit signals bool PreviewLaTeX::finish(int r) { KILE_DEBUG_MAIN << r; m_toolResult = r; if(r != Success) { return Compile::finish(r); } QString log = targetDir() + '/' + S() + ".log"; manager()->parserManager()->parseOutput(this, log, source(), m_filename, m_selrow, m_docrow); return true; } void PreviewLaTeX::setPreviewInfo(const QString &filename, int selrow,int docrow) { m_filename = filename; m_selrow = selrow; m_docrow = docrow; } /////////////// LivePreviewLaTeX //////////////// LivePreviewLaTeX::LivePreviewLaTeX(const QString& tool, Manager *mngr, bool prepare) : LaTeX(tool, mngr, prepare) { } void LivePreviewLaTeX::configureLaTeX(KileTool::Base *tool, const QString& source) { LaTeX::configureLaTeX(tool, source); tool->setTargetDir(targetDir()); } void LivePreviewLaTeX::configureBibTeX(KileTool::Base *tool, const QString& source) { tool->setSource(source, targetDir()); } void LivePreviewLaTeX::configureMakeIndex(KileTool::Base *tool, const QString& source) { tool->setSource(source, targetDir()); } void LivePreviewLaTeX::configureAsymptote(KileTool::Base *tool, const QString& source) { tool->setSource(source, targetDir()); } // PreviewLatex makes three steps: // - filterLogfile() : parse logfile and read info into InfoLists // - updateInfoLists(): change entries of temporary file into normal tex file // - checqCriticals() : count errors and warnings and emit signals // bool LivePreviewLaTeX::finish(int r) // { // KILE_DEBUG_MAIN << "==bool PreviewLaTeX::finish(" << r << ")====="; // // int nErrors = 0, nWarnings = 0; // if(filterLogfile()) { // manager()->info()->outputFilter()->updateInfoLists(m_filename,m_selrow,m_docrow); // checqCriticals(nErrors,nWarnings); // } // // return Compile::finish(r); // } // // void LivePreviewLaTeX::setPreviewInfo(const QString &filename, int selrow,int docrow) // { // m_filename = filename; // m_selrow = selrow; // m_docrow = docrow; // } ForwardDVI::ForwardDVI(const QString& tool, Manager *mngr, bool prepare) : View(tool, mngr, prepare) { } bool ForwardDVI::checkPrereqs () { KProcess okularVersionTester; okularVersionTester.setOutputChannelMode(KProcess::MergedChannels); okularVersionTester.setProgram("okular", QStringList("--version")); okularVersionTester.start(); if (okularVersionTester.waitForFinished()) { QString output = okularVersionTester.readAll(); QRegExp regExp = QRegExp("Okular: (\\d+).(\\d+).(\\d+)"); if(output.contains(regExp)) { int majorVersion = regExp.cap(1).toInt(); int minorVersion = regExp.cap(2).toInt(); int veryMinorVersion = regExp.cap(3).toInt(); // see http://mail.kde.org/pipermail/okular-devel/2009-May/003741.html // the required okular version is > 0.8.5 if( majorVersion > 0 || ( majorVersion == 0 && minorVersion > 8 ) || ( majorVersion == 0 && minorVersion == 8 && veryMinorVersion > 5 ) ) { ; // everything okay } else { sendMessage(Error,i18n("The version %1.%2.%3 of okular is too old for ForwardDVI. Please update okular to version 0.8.6 or higher",majorVersion,minorVersion,veryMinorVersion)); } } } // don't return false here because we don't know for sure if okular is used return true; } bool ForwardDVI::determineTarget() { if (!View::determineTarget()) { return false; } int para = manager()->info()->lineNumber(); KTextEditor::Document *doc = manager()->info()->activeTextDocument(); if (!doc) { return false; } QString filepath = doc->url().toLocalFile(); QString texfile = QDir(baseDir()).relativeFilePath(filepath); QString relativeTarget = "file:" + targetDir() + '/' + target() + "#src:" + QString::number(para + 1) + ' ' + texfile; // space added, for files starting with numbers QString absoluteTarget = "file:" + targetDir() + '/' + target() + "#src:" + QString::number(para + 1) + filepath; if(readEntry("type") == "DocumentViewer") { addDict("%dir_target", targetDir()); addDict("%target", target()); addDict("%sourceFileName", filepath); addDict("%sourceLine", QString::number(para + 1)); } else { addDict("%dir_target", QString()); addDict("%target", relativeTarget); } addDict("%absolute_target", absoluteTarget); KILE_DEBUG_MAIN << "==KileTool::ForwardDVI::determineTarget()=============\n"; KILE_DEBUG_MAIN << "\tusing (absolute)" << absoluteTarget; KILE_DEBUG_MAIN << "\tusing (relative)" << relativeTarget; return true; } ViewBib::ViewBib(const QString& tool, Manager *mngr, bool prepare) : View(tool, mngr, prepare) { } bool ViewBib::determineSource() { KILE_DEBUG_MAIN << "==ViewBib::determineSource()======="; if (!View::determineSource()) { return false; } QString path = source(true); QFileInfo info(path); //get the bibliographies for this source QStringList bibs = manager()->info()->allBibliographies(manager()->info()->docManager()->textInfoFor(path)); KILE_DEBUG_MAIN << "\tfound " << bibs.count() << " bibs"; if(bibs.count() > 0) { QString bib = bibs.front(); if (bibs.count() > 1) { //show dialog bool bib_selected = false; KileListSelector *dlg = new KileListSelector(bibs, i18n("Select Bibliography"),i18n("Select a bibliography")); if (dlg->exec() && dlg->hasSelection()) { bib = dlg->selectedItems().first(); bib_selected = true; KILE_DEBUG_MAIN << "Bibliography selected : " << bib; } delete dlg; if(!bib_selected) { sendMessage(Warning, i18n("No bibliography selected.")); return false; } } KILE_DEBUG_MAIN << "filename before: " << info.path(); setSource(manager()->info()->checkOtherPaths(info.path(),bib + ".bib",KileInfo::bibinputs)); } else if(info.exists()) { //active doc is a bib file KILE_DEBUG_MAIN << "filename before: " << info.path(); setSource(manager()->info()->checkOtherPaths(info.path(),info.fileName(),KileInfo::bibinputs)); } else { sendMessage(Error, i18n("No bibliographies found.")); return false; } return true; } ViewHTML::ViewHTML(const QString& tool, Manager *mngr, bool prepare) : View(tool, mngr, prepare) { } bool ViewHTML::determineTarget() { if (target().isNull()) { //setRelativeBaseDir(S()); QString dir = readEntry("relDir"); QString trg = readEntry("target"); if(!dir.isEmpty()) { translate(dir); setRelativeBaseDir(dir); } if(!trg.isEmpty()) { translate(trg); setTarget(trg); } //auto-detect the file to view if(dir.isEmpty() && trg.isEmpty()) { QFileInfo file1 = QFileInfo(baseDir() + '/' + S() + "/index.html"); QFileInfo file2 = QFileInfo(baseDir() + '/' + S() + ".html"); bool read1 = file1.isReadable(); bool read2 = file2.isReadable(); if(!read1 && !read2) { sendMessage(Error, i18n("Unable to find %1 or %2; if you are trying to view some other HTML file, go to Settings->Configure Kile->Tools->ViewHTML->Advanced.", file1.absoluteFilePath(), file2.absoluteFilePath())); return false; } //both exist, take most recent if(read1 && read2) { read1 = file1.lastModified() > file2.lastModified(); read2 = !read1; } if(read1) { dir = S(); trg = "index.html"; translate(dir); setRelativeBaseDir(dir); translate(trg); setTarget(trg); } } } return View::determineTarget(); } } /* * BibliographyCompile */ const QString KileTool::BibliographyCompile::ToolClass = "Bibliography"; KileTool::BibliographyCompile::BibliographyCompile(const QString& name, KileTool::Manager* manager, bool prepare) : Compile(name, manager, prepare) { } diff --git a/src/scriptmanager.cpp b/src/scriptmanager.cpp index c98e96cd..fb6fca5f 100644 --- a/src/scriptmanager.cpp +++ b/src/scriptmanager.cpp @@ -1,467 +1,467 @@ /************************************************************************** -* Copyright (C) 2006-2016 by Michel Ludwig (michel.ludwig@kdemail.net) * +* Copyright (C) 2006-2019 by Michel Ludwig (michel.ludwig@kdemail.net) * ***************************************************************************/ /************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "scriptmanager.h" #include #include #include #include #include #include #include #include #include -#include #include "kiledebug.h" #include "kileconfig.h" #include "kileinfo.h" #include "kileversion.h" #include "kileviewmanager.h" #include "editorkeysequencemanager.h" +#include "utilities.h" #include "scripting/script.h" namespace KileScript { ////////////////////////////// Manager ////////////////////////////// Manager::Manager(KileInfo *kileInfo, KConfig *config, KActionCollection *actionCollection, QObject *parent, const char *name) : QObject(parent), m_jScriptDirWatch(Q_NULLPTR), m_kileInfo(kileInfo), m_config(config), m_actionCollection(actionCollection) { setObjectName(name); // create a local scripts directory if it doesn't exist yet - m_localScriptDir = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/scripts/"; + m_localScriptDir = KileUtilities::writableLocation(QStandardPaths::AppDataLocation) + "/scripts/"; QDir testDir(m_localScriptDir); if (!testDir.exists()) { testDir.mkpath(m_localScriptDir); } m_jScriptDirWatch = new KDirWatch(this); m_jScriptDirWatch->setObjectName("KileScript::Manager::ScriptDirWatch"); connect(m_jScriptDirWatch, SIGNAL(dirty(QString)), this, SLOT(scanScriptDirectories())); connect(m_jScriptDirWatch, SIGNAL(created(QString)), this, SLOT(scanScriptDirectories())); connect(m_jScriptDirWatch, SIGNAL(deleted(QString)), this, SLOT(scanScriptDirectories())); m_jScriptDirWatch->startScan(); // read plugin code for QScriptEngine readEnginePlugin(); m_scriptActionMap = new QMap; // init script objects m_kileScriptView = new KileScriptView(this, m_kileInfo->editorExtension()); m_kileScriptDocument = new KileScriptDocument(this, m_kileInfo, m_kileInfo->editorExtension(), m_scriptActionMap); m_kileScriptObject = new KileScriptObject(this, m_kileInfo, m_scriptActionMap); } Manager::~Manager() { delete m_jScriptDirWatch; delete m_scriptActionMap; delete m_kileScriptView; delete m_kileScriptDocument; delete m_kileScriptObject; //still need to delete the scripts for(QList::iterator it = m_jScriptList.begin(); it != m_jScriptList.end(); ++it) { delete *it; } } void Manager::executeScript(const Script *script) { KILE_DEBUG_MAIN << "execute script: " << script->getName(); // compatibility check QString code = script->getCode(); QRegExp endOfLineExp("(\r\n)|\n|\r"); int i = code.indexOf(endOfLineExp); QString firstLine = (i >= 0 ? code.left(i) : code); QRegExp requiredVersionTagExp("(kile-version:\\s*)(\\d+\\.\\d+(.\\d+)?)"); if(requiredVersionTagExp.indexIn(firstLine) != -1) { QString requiredKileVersion = requiredVersionTagExp.cap(2); if(compareVersionStrings(requiredKileVersion, kileFullVersion) > 0) { KMessageBox::sorry(m_kileInfo->mainWindow(), i18n("Version %1 of Kile is at least required to execute the script \"%2\". The execution has been aborted.", requiredKileVersion, script->getName()), i18n("Version Error")); return; } } // TODO only scripts with a current view can be started at this moment KTextEditor::View *view = m_kileInfo->viewManager()->currentTextView(); if(!view) { KMessageBox::sorry(m_kileInfo->mainWindow(), i18n("Cannot start the script: no view available"), i18n("Script Error")); return; } // TODO setup script objects (with existing views at this moment) m_kileScriptView->setView(view); m_kileScriptDocument->setView(view); m_kileScriptObject->setScriptname(script->getName()); // create environment for QtScript engine ScriptEnvironment env(m_kileInfo, m_kileScriptView, m_kileScriptDocument, m_kileScriptObject,m_enginePlugin); env.execute(script); } void Manager::executeScript(unsigned int id) { QMap::iterator i = m_idScriptMap.find(id); if(i != m_idScriptMap.end()) { executeScript(*i); } } const Script* Manager::getScript(unsigned int id) { QMap::iterator i = m_idScriptMap.find(id); return ((i != m_idScriptMap.end()) ? (*i) : Q_NULLPTR); } void Manager::scanScriptDirectories() { if(!KileConfig::scriptingEnabled()) { return; } deleteScripts(); populateDirWatch(); KConfigGroup configGroup = m_config->group("Scripts"); QList idList = configGroup.readEntry("IDs", QList()); unsigned int maxID = 0; QMap pathIDMap; QMap takenIDMap; for(QList::iterator i = idList.begin(); i != idList.end(); ++i) { QString fileName = configGroup.readPathEntry("Script" + QString::number(*i), QString()); if(!fileName.isEmpty()) { unsigned int id = *i; pathIDMap[fileName] = id; takenIDMap[id] = true; maxID = qMax(maxID, id); } } // scan *.js files QSet scriptFileNamesSet; - const QStringList dirs = QStandardPaths::locateAll(QStandardPaths::DataLocation, "scripts/", QStandardPaths::LocateDirectory); + const QStringList dirs = KileUtilities::locateAll(QStandardPaths::AppDataLocation, "scripts/", QStandardPaths::LocateDirectory); Q_FOREACH (const QString &dir, dirs) { QDirIterator it(dir, QStringList() << QStringLiteral("*.js"), QDir::Files | QDir::Readable, QDirIterator::Subdirectories); while (it.hasNext()) { scriptFileNamesSet.insert(it.next()); } } Q_FOREACH(const QString &scriptFileName, scriptFileNamesSet) { registerScript(scriptFileName, pathIDMap, takenIDMap, maxID); } //rewrite the IDs that are currently in use writeIDs(); m_actionCollection->readSettings(); emit scriptsChanged(); } void Manager::deleteScripts() { QList scriptList = m_jScriptList; m_jScriptList.clear(); // pretend that there are no scripts left QStringList keySequenceList; for(QList::iterator it = scriptList.begin(); it != scriptList.end(); ++it) { keySequenceList.push_back((*it)->getKeySequence()); } m_idScriptMap.clear(); m_kileInfo->editorKeySequenceManager()->removeKeySequence(keySequenceList); for(QList::iterator it = scriptList.begin(); it != scriptList.end(); ++it) { QAction *action = (*it)->getActionObject(); if(action) { foreach(QWidget *w, action->associatedWidgets()) { w->removeAction(action); } m_actionCollection->takeAction(action); delete action; } delete *it; } emit scriptsChanged(); } QList Manager::getScripts() { return m_jScriptList; } void Manager::registerScript(const QString& fileName, QMap& pathIDMap, QMap& takenIDMap, unsigned int &maxID) { unsigned int id; QMap::iterator it = pathIDMap.find(fileName); if(it != pathIDMap.end()) { id = *it; } else { id = findFreeID(takenIDMap, maxID); pathIDMap[fileName] = id; takenIDMap[id] = true; maxID = qMax(maxID, id); } Script* script = new Script(id, fileName); m_jScriptList.push_back(script); m_idScriptMap[id] = script; // start with setting up the key sequence KConfigGroup configGroup = m_config->group("Scripts"); int sequenceType = 0; QString editorKeySequence = QString(); QString seq = configGroup.readEntry("Script" + QString::number(id) + "KeySequence"); if ( !seq.isEmpty() ) { QRegExp re("(\\d+)-(.*)"); if ( re.exactMatch(seq) ) { sequenceType = re.cap(1).toInt(); if ( sequenceTypeScript::KEY_SHORTCUT ) { sequenceType = Script::KEY_SEQUENCE; } editorKeySequence = re.cap(2); } else { sequenceType = Script::KEY_SEQUENCE; editorKeySequence = re.cap(1); } } KILE_DEBUG_MAIN << "script type=" << sequenceType << " seq=" << editorKeySequence; // now set up a regular action object ScriptExecutionAction *action = new ScriptExecutionAction(id, this, m_actionCollection); // action with shortcut? if(!editorKeySequence.isEmpty()) { script->setSequenceType(sequenceType); script->setKeySequence(editorKeySequence); if ( sequenceType == Script::KEY_SEQUENCE ) { m_kileInfo->editorKeySequenceManager()->addAction(editorKeySequence, new KileEditorKeySequence::ExecuteScriptAction(script, this)); } else { action->setShortcut(editorKeySequence); } } // add to action collection m_actionCollection->addAction("script" + QString::number(id) + "_execution", action); script->setActionObject(action); } void Manager::writeConfig() { // don't delete the key sequence settings if scripting has been disabled if(!KileConfig::scriptingEnabled()) { return; } m_config->deleteGroup("Scripts"); writeIDs(); // write the key sequences KConfigGroup configGroup = m_config->group("Scripts"); for(QList::iterator i = m_jScriptList.begin(); i != m_jScriptList.end(); ++i) { QString seq = (*i)->getKeySequence(); QString sequenceEntry = ( seq.isEmpty() ) ? seq : QString("%1-%2").arg(QString::number((*i)->getSequenceType())).arg(seq); configGroup.writeEntry("Script" + QString::number((*i)->getID()) + "KeySequence", sequenceEntry); } } void Manager::setEditorKeySequence(Script* script, int type, const QString& keySequence) { if(keySequence.isEmpty()) { return; } if(script) { int oldType = script->getSequenceType(); QString oldSequence = script->getKeySequence(); if( oldType==type && oldSequence==keySequence) { return; } if ( oldType == KileScript::Script::KEY_SEQUENCE ) { m_kileInfo->editorKeySequenceManager()->removeKeySequence(oldSequence); } else { script->getActionObject()->setShortcut(QString()); } script->setSequenceType(type); script->setKeySequence(keySequence); if ( type == KileScript::Script::KEY_SEQUENCE ) { m_kileInfo->editorKeySequenceManager()->addAction(keySequence, new KileEditorKeySequence::ExecuteScriptAction(script, this)); } else { script->getActionObject()->setShortcut(keySequence); } writeConfig(); } } void Manager::removeEditorKeySequence(Script* script) { if(script) { QString keySequence = script->getKeySequence(); if(keySequence.isEmpty()) { return; } script->setKeySequence(QString()); int sequenceType = script->getSequenceType(); if ( sequenceType == Script::KEY_SEQUENCE ) { m_kileInfo->editorKeySequenceManager()->removeKeySequence(keySequence); } else { script->getActionObject()->setShortcut(QString()); } writeConfig(); } } void Manager::populateDirWatch() { - QStringList jScriptDirectories = QStandardPaths::locateAll(QStandardPaths::DataLocation, "scripts/", QStandardPaths::LocateDirectory); + QStringList jScriptDirectories = KileUtilities::locateAll(QStandardPaths::AppDataLocation, "scripts/", QStandardPaths::LocateDirectory); for(QStringList::iterator i = jScriptDirectories.begin(); i != jScriptDirectories.end(); ++i) { // FIXME: future KDE versions could support the recursive // watching of directories out of the box. addDirectoryToDirWatch(*i); } //we do not remove the directories that were once added as this apparently causes some strange //bugs (on KDE 3.5.x) } QString Manager::getLocalScriptDirectory() const { return m_localScriptDir; } void Manager::readConfig() { deleteScripts(); scanScriptDirectories(); } unsigned int Manager::findFreeID(const QMap& takenIDMap, unsigned int maxID) { if(takenIDMap.size() == 0) { return 0; } // maxID should have a real meaning now for(unsigned int i = 0; i < maxID; ++i) { if(takenIDMap.find(i) == takenIDMap.end()) { return i; } } return (maxID + 1); } void Manager::writeIDs() { KConfigGroup configGroup = m_config->group("Scripts"); //delete old entries QList idList = configGroup.readEntry("IDs", QList()); for(QList::iterator i = idList.begin(); i != idList.end(); ++i) { configGroup.deleteEntry("Script" + QString::number(*i)); } //write new ones idList.clear(); for(QMap::iterator i = m_idScriptMap.begin(); i != m_idScriptMap.end(); ++i) { unsigned int id = i.key(); idList.push_back(id); configGroup.writePathEntry("Script" + QString::number(id), (*i)->getFileName()); } configGroup.writeEntry("IDs", idList); } void Manager::addDirectoryToDirWatch(const QString& dir) { //FIXME: no recursive watching and no watching of files as it isn't implemented // yet //FIXME: check for KDE4 if(!m_jScriptDirWatch->contains(dir)) { m_jScriptDirWatch->addDir(dir, KDirWatch::WatchDirOnly); } QDir qDir(dir); QStringList list = qDir.entryList(QDir::Dirs); for(QStringList::iterator i = list.begin(); i != list.end(); ++i) { QString subdir = *i; if(subdir != "." && subdir != "..") { addDirectoryToDirWatch(qDir.filePath(subdir)); } } } void Manager::readEnginePlugin() { // TODO error message and disable scripting if not found - QString pluginUrl = QStandardPaths::locate(QStandardPaths::DataLocation, "script-plugins/cursor-range.js"); + QString pluginUrl = KileUtilities::locate(QStandardPaths::AppDataLocation, "script-plugins/cursor-range.js"); m_enginePlugin = Script::readFile(pluginUrl); } void Manager::initScriptActions() { QStringList m_scriptActionList = QStringList() << "tag_chapter" << "tag_section" << "tag_subsection" << "tag_subsubsection" << "tag_paragraph" << "tag_subparagraph" << "tag_label" << "tag_ref" << "tag_pageref" << "tag_index" << "tag_footnote" << "tag_cite" << "tools_comment" << "tools_uncomment" << "tools_uppercase" << "tools_lowercase" << "tools_capitalize" << "tools_join_lines" << "wizard_tabular" << "wizard_array" << "wizard_tabbing" << "wizard_float" << "wizard_mathenv" << "wizard_postscript" << "wizard_pdf" ; foreach ( KXMLGUIClient *client, m_kileInfo->mainWindow()->guiFactory()->clients() ) { KILE_DEBUG_MAIN << "collection count: " << client->actionCollection()->count() ; foreach ( QAction *action, client->actionCollection()->actions() ) { QString objectname = action->objectName(); if ( m_scriptActionList.indexOf(objectname) >= 0 ) { m_scriptActionMap->insert(objectname,action); } } } } ////////////////////////////// ScriptExecutionAction ////////////////////////////// ScriptExecutionAction::ScriptExecutionAction(unsigned int id, KileScript::Manager *manager, QObject* parent) : QAction(parent), m_manager(manager), m_id(id) { const KileScript::Script *script = m_manager->getScript(m_id); Q_ASSERT(script); setText(i18n("Execution of %1", script->getName())); connect(this, SIGNAL(triggered()), this, SLOT(executeScript())); } ScriptExecutionAction::~ScriptExecutionAction() { } void ScriptExecutionAction::executeScript() { m_manager->executeScript(m_id); } } diff --git a/src/templates.cpp b/src/templates.cpp index 734b0f29..1d6204f5 100644 --- a/src/templates.cpp +++ b/src/templates.cpp @@ -1,441 +1,441 @@ /******************************************************************************************* begin : Sat Apr 26 2003 copyright : (C) 2003 by Jeroen Wijnhout (wijnhout@science.uva.nl) 2005 by Holger Danielsson (holger.danielsson@t-online.de) - 2007-2014 by Michel Ludwig (michel.ludwig@kdemail.net) + 2007-2019 by Michel Ludwig (michel.ludwig@kdemail.net) *******************************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "templates.h" #include #include #include #include #include #include #include #include #include -#include #include #include "kileinfo.h" #include "kiledebug.h" +#include "utilities.h" // 2005-08-04: dani // - added script support to search existing class files // (classes: Koma, Beamer, Prosper, HA-prosper) // - sort items ('Empty Document' will always be the first entry) // 2006-30-04: tbraun // - drag and drop makes no sense here // - use the Select mode namespace KileTemplate { ////////////////////// Info ////////////////////// Info::Info() : type(KileDocument::Undefined) { } bool Info::operator==(const Info ti) const { return name==ti.name; } ////////////////////// Manager ////////////////////// Manager::Manager(KileInfo* kileInfo, QObject* parent, const char* name) : QObject(parent), m_kileInfo(kileInfo) { setObjectName(name); } Manager::~Manager() { } bool Manager::copyAppData(const QUrl &src, const QString& subdir, const QString& fileName) { //let saveLocation find and create the appropriate place to //store the templates (usually $HOME/.kde/share/apps/kile/templates) - QString dir = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + '/' + subdir; + QString dir = KileUtilities::writableLocation(QStandardPaths::AppDataLocation) + '/' + subdir; QUrl targetURL = QUrl::fromUserInput(dir); targetURL = targetURL.adjusted(QUrl::StripTrailingSlash); targetURL.setPath(targetURL.path() + '/' + fileName); //if a directory is found if (!dir.isNull()) { // create dir if not existing, needed for copyjob QDir testDir(dir); if (!testDir.exists()) { testDir.mkpath(dir); } // copy file KIO::FileCopyJob* copyJob = KIO::file_copy(src, targetURL); KJobWidgets::setWindow(copyJob, m_kileInfo->mainWindow()); return copyJob->exec(); } else { KMessageBox::error(Q_NULLPTR, i18n("Could not find a folder to save %1 to.\nCheck whether you have a .kde folder with write permissions in your home folder.", fileName)); return false; } } bool Manager::removeAppData(const QString &file) { QFileInfo fileInfo(file); if(fileInfo.exists()) { KIO::SimpleJob* deleteJob = KIO::file_delete(QUrl::fromUserInput(file)); KJobWidgets::setWindow(deleteJob, m_kileInfo->mainWindow()); return deleteJob->exec(); } return true; } bool Manager::searchForTemplate(const QString& name, KileDocument::Type& type) const { for (KileTemplate::TemplateListConstIterator i = m_TemplateList.constBegin(); i != m_TemplateList.constEnd(); ++i) { KileTemplate::Info info = *i; if(info.name == name && info.type == type) { return true; } } return false; } bool Manager::add(const QUrl &templateSourceURL, const QString &name, const QUrl &icon) { KileDocument::Extensions *extensions = m_kileInfo->extensions(); KileDocument::Type type = extensions->determineDocumentType(templateSourceURL); return add(templateSourceURL, type, name, icon); } bool Manager::add(const QUrl &templateSourceURL, KileDocument::Type type, const QString &name, const QUrl &icon) { KileDocument::Extensions *extensions = m_kileInfo->extensions(); QString extension = extensions->defaultExtensionForDocumentType(type); return copyAppData(templateSourceURL, "templates", "template_" + name + extension) && copyAppData(icon, "pics", "type_" + name + extension + ".kileicon"); } bool Manager::remove(Info ti) { return removeAppData(ti.path) && removeAppData(ti.icon); } bool Manager::replace(const KileTemplate::Info& toBeReplaced, const QUrl &newTemplateSourceURL, const QString& newName, const QUrl& newIcon) { KileDocument::Type type = m_kileInfo->extensions()->determineDocumentType(newTemplateSourceURL); //start by copying the files that belong to the new template to a safe place QString templateTempFile, iconTempFile; if( newTemplateSourceURL.isLocalFile() ) { // file protocol. We do not need the network templateTempFile = newTemplateSourceURL.toLocalFile(); } else { QTemporaryFile tmpFile; tmpFile.setAutoRemove( false ); tmpFile.open(); templateTempFile = tmpFile.fileName(); m_TempFilePath = tmpFile.fileName(); KIO::FileCopyJob* fileCopyJob = KIO::file_copy( newTemplateSourceURL, QUrl::fromLocalFile(templateTempFile), -1, KIO::Overwrite ); KJobWidgets::setWindow( fileCopyJob, m_kileInfo->mainWindow() ); if( ! fileCopyJob->exec() ) { return false; } } if( newIcon.isLocalFile() ) { // file protocol. We do not need the network iconTempFile = newIcon.toLocalFile(); } else { QTemporaryFile tmpFile; tmpFile.setAutoRemove( false ); tmpFile.open(); iconTempFile = tmpFile.fileName(); m_TempFilePath = tmpFile.fileName(); KIO::FileCopyJob* fileCopyJob = KIO::file_copy( newIcon, QUrl::fromLocalFile(iconTempFile), -1, KIO::Overwrite ); KJobWidgets::setWindow( fileCopyJob, m_kileInfo->mainWindow() ); if( ! fileCopyJob->exec() ) { if( ! templateTempFile.isEmpty() ) QFile::remove( templateTempFile ); return false; } } //now delete the template that should be replaced if(!remove(toBeReplaced)) { if( ! templateTempFile.isEmpty() ) QFile::remove( templateTempFile ); if( ! iconTempFile.isEmpty() ) QFile::remove( iconTempFile ); } //finally, create the new template if(!add(QUrl::fromUserInput(templateTempFile), type, newName, QUrl::fromUserInput(iconTempFile))) { if( ! templateTempFile.isEmpty() ) QFile::remove( templateTempFile ); if( ! iconTempFile.isEmpty() ) QFile::remove( iconTempFile ); return false; } if( ! templateTempFile.isEmpty() ) QFile::remove( templateTempFile ); if( ! iconTempFile.isEmpty() ) QFile::remove( iconTempFile ); return true; } void Manager::scanForTemplates() { KILE_DEBUG_MAIN << "===scanForTemplates()==================="; - QStringList dirs = QStandardPaths::locateAll(QStandardPaths::DataLocation, "templates", QStandardPaths::LocateDirectory); + QStringList dirs = KileUtilities::locateAll(QStandardPaths::AppDataLocation, "templates", QStandardPaths::LocateDirectory); QDir templates; KileTemplate::Info ti; KileDocument::Extensions *extensions = m_kileInfo->extensions(); m_TemplateList.clear(); for(QStringList::iterator i = dirs.begin(); i != dirs.end(); ++i) { templates = QDir(*i, "template_*"); for (uint j = 0; j < templates.count(); ++j) { ti.path = templates.path() + '/' + templates[j]; QFileInfo fileInfo(ti.path); ti.name = fileInfo.completeBaseName().mid(9); //remove "template_", do it this way to avoid problems with user input! ti.type = extensions->determineDocumentType(QUrl::fromUserInput(ti.path)); - ti.icon = QStandardPaths::locate(QStandardPaths::DataLocation, "pics/type_" + ti.name + extensions->defaultExtensionForDocumentType(ti.type) + ".kileicon"); + ti.icon = KileUtilities::locate(QStandardPaths::AppDataLocation, "pics/type_" + ti.name + extensions->defaultExtensionForDocumentType(ti.type) + ".kileicon"); if (m_TemplateList.contains(ti)) { KILE_DEBUG_MAIN << "\tignoring: " << ti.path; } else { m_TemplateList.append(ti); KILE_DEBUG_MAIN << "\tadding: " << ti.name << " " << ti.path; } } } } QString Manager::defaultEmptyTemplateCaption() { return i18n("Empty File"); } QString Manager::defaultEmptyLaTeXTemplateCaption() { return i18n("Empty LaTeX File"); } QString Manager::defaultEmptyBibTeXTemplateCaption() { return i18n("Empty BibTeX File"); } TemplateList Manager::getAllTemplates() const { return m_TemplateList; } TemplateList Manager::getTemplates(KileDocument::Type type) const { if(type == KileDocument::Undefined) { return getAllTemplates(); } TemplateList toReturn; for (KileTemplate::TemplateListConstIterator i = m_TemplateList.constBegin(); i != m_TemplateList.constEnd(); ++i) { KileTemplate::Info info = *i; if(info.type == type) { toReturn.push_back(info); } } return toReturn; } } ////////////////////// TemplateItem ////////////////////// // new compare function to make the "Empty (...) Document" items appear at the beginning TemplateItem::TemplateItem(QListWidget * parent, const KileTemplate::Info& info) : QListWidgetItem(QPixmap(info.icon), info.name, parent) { m_info = info; } bool TemplateItem::operator<(const QListWidgetItem &other) const { if(text() == KileTemplate::Manager::defaultEmptyTemplateCaption()) { return true; } else if(other.text() == KileTemplate::Manager::defaultEmptyTemplateCaption()) { return false; } else { return QListWidgetItem::operator<(other); } } ////////////////////// TemplateIconView ////////////////////// TemplateIconView::TemplateIconView(QWidget *parent) : QListWidget(parent), m_templateManager(Q_NULLPTR), m_proc(Q_NULLPTR) { setViewMode(QListView::IconMode); setMovement(QListView::Static); setResizeMode(QListView::Adjust); setSelectionMode(QAbstractItemView::SingleSelection); setFlow(QListView::TopToBottom); setMinimumHeight(100); setIconSize(QSize(48, 48)); } TemplateIconView::~TemplateIconView() { } void TemplateIconView::setTemplateManager(KileTemplate::Manager *templateManager) { m_templateManager = templateManager; } void TemplateIconView::fillWithTemplates(KileDocument::Type type) { if(!m_templateManager) { return; } clear(); if(type == KileDocument::LaTeX) { searchLaTeXClassFiles(); } else { addTemplateIcons(type); } } void TemplateIconView::searchLaTeXClassFiles() { if(!m_templateManager) { return; } m_output.clear(); QString command = "kpsewhich -format=tex scrartcl.cls beamer.cls prosper.cls HA-prosper.sty"; delete m_proc; m_proc = new KProcess(this); (*m_proc) << KShell::splitArgs(command); m_proc->setOutputChannelMode(KProcess::MergedChannels); m_proc->setReadChannel(QProcess::StandardOutput); connect(m_proc, SIGNAL(readyReadStandardOutput()), this, SLOT(slotProcessOutput())); connect(m_proc, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(slotProcessExited(int,QProcess::ExitStatus))); connect(m_proc, SIGNAL(error(QProcess::ProcessError)), this, SLOT(slotProcessError())); KILE_DEBUG_MAIN << "=== NewFileWidget::searchClassFiles() ===================="; KILE_DEBUG_MAIN << "\texecute: " << command; m_proc->start(); } void TemplateIconView::slotProcessOutput() { QByteArray buf = m_proc->readAllStandardOutput(); m_output += QString::fromLocal8Bit(buf.data(), buf.size()); } void TemplateIconView::slotProcessError() { addTemplateIcons(KileDocument::LaTeX); emit classFileSearchFinished(); } void TemplateIconView::slotProcessExited(int /*exitCode*/, QProcess::ExitStatus exitStatus) { if(exitStatus != QProcess::NormalExit) { m_output.clear(); } addTemplateIcons(KileDocument::LaTeX); emit classFileSearchFinished(); } void TemplateIconView::addTemplateIcons(KileDocument::Type type) { if(!m_templateManager) { return; } - QString emptyIcon = QStandardPaths::locate(QStandardPaths::DataLocation, "pics/" + QString(DEFAULT_EMPTY_ICON) + ".png" ); + QString emptyIcon = KileUtilities::locate(QStandardPaths::AppDataLocation, "pics/" + QString(DEFAULT_EMPTY_ICON) + ".png" ); KileTemplate::Info emptyDocumentInfo; emptyDocumentInfo.name = KileTemplate::Manager::defaultEmptyTemplateCaption(); emptyDocumentInfo.icon = emptyIcon; emptyDocumentInfo.type = type; TemplateItem *emp = new TemplateItem(this, emptyDocumentInfo); setCurrentItem(emp); if(type == KileDocument::LaTeX) { // disable non standard templates QMap map; map["Scrartcl"] = false; map["Scrbook"] = false; map["Scrreprt"] = false; map["Scrlttr2"] = false; map["Beamer"] = false; map["Prosper"] = false; map["HA-prosper"] = false; // split search results and look, which class files are present QStringList list = m_output.split('\n'); for(QStringList::Iterator it=list.begin(); it!=list.end(); ++it) { QString filename = QFileInfo(*it).fileName(); if(filename=="scrartcl.cls") { map["Scrartcl"] = true; map["Scrbook"] = true; map["Scrreprt"] = true; map["Scrlttr2"] = true; } else if(filename=="beamer.cls") { map["Beamer"] = true; } else if(filename=="prosper.cls") { map["Prosper"] = true; } else if(filename=="HA-prosper.sty") { map["HA-prosper"] = true; } } KileTemplate::TemplateList templateList = m_templateManager->getTemplates(KileDocument::LaTeX); // insert all standard templates, all user-defined templates // and those templates, which have a present class for (KileTemplate::TemplateListIterator i=templateList.begin(); i != templateList.end(); ++i) { KileTemplate::Info info = *i; QString classname = info.name; if(!map.contains(classname) || map[classname]==true) { new TemplateItem(this, info); } } } else { KileTemplate::TemplateList templateList = m_templateManager->getTemplates(type); for (KileTemplate::TemplateListIterator i=templateList.begin(); i != templateList.end(); ++i) { new TemplateItem(this, *i); } } // sort all items (item for 'Empty Document' will always be the first one) sortItems(); } diff --git a/src/usermenu/usermenu.cpp b/src/usermenu/usermenu.cpp index f9e3d3c0..c4053a44 100644 --- a/src/usermenu/usermenu.cpp +++ b/src/usermenu/usermenu.cpp @@ -1,975 +1,975 @@ /*********************************************************************************** Copyright (C) 2011-2012 by Holger Danielsson (holger.danielsson@versanet.de) - (C) 2017-2018 by Michel Ludwig (michel.ludwig@kdemail.net) + (C) 2017-2019 by Michel Ludwig (michel.ludwig@kdemail.net) ***********************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "usermenu/usermenu.h" #include #include #include #include #include #include #include #include -#include #include "kileactions.h" #include "editorextension.h" #include "kileviewmanager.h" #include "kileconfig.h" #include "kiledebug.h" +#include "utilities.h" namespace KileMenu { // The UserMenu uses six values/data structures: // // - getUserMenu(): the menu with its entries/actions itself (QMenu *) // (actions for menu items are named 'useraction-n', where n is a // number starting at 0. It is also used as index for the m_menudata list.) // // - m_menudata: a list, containing all info for menu item (QList) // // - m_actioncollection: KActionCollection of KileMainWindow (KActionCollection *) // // - m_actionlist: a list with all actions of the menu (QList) // // - m_actionlistContextMenu: a list with all actions of the context menu for selected text (QList) // -// - a menu is defined in an xml file, which is placed in QStandardPaths::locate(QStandardPaths::DataLocation, "usermenu", QStandardPaths::LocateDirectory) +// - a menu is defined in an xml file, which is placed in KileUtilities::locate(QStandardPaths::AppDataLocation, "usermenu", QStandardPaths::LocateDirectory) UserMenu::UserMenu(KileInfo *ki, QObject *receiver) : m_ki(ki), m_receiver(receiver), m_proc(Q_NULLPTR) { KXmlGuiWindow *mainwindow = m_ki->mainWindow(); m_actioncollection = mainwindow->actionCollection(); // add actions and menu entries m_wizardAction1 = new QAction(this); m_wizardAction1->setSeparator(true); m_wizardAction2 = createAction("wizard_usermenu"); m_latexAction1 = new QAction(this); m_latexAction1->setSeparator(true); m_latexAction2 = createAction("wizard_usermenu2"); m_latexMenuEntry = new QMenu(i18n("User Menu")); m_latexMenuEntry->setObjectName("usermenu-submenu"); addSpecialActionsToMenus(); // look for an existing menufile: // if filename matches 'basename.ext' then the file is placed in 'KILE-LOCAL-DIR/usermenu' directory m_currentXmlFile = KileConfig::userMenuFile(); if ( !m_currentXmlFile.isEmpty() ) { if ( !m_currentXmlFile.contains("/") ) { - m_currentXmlFile = QStandardPaths::locate(QStandardPaths::DataLocation, "usermenu", QStandardPaths::LocateDirectory) + m_currentXmlFile; + m_currentXmlFile = KileUtilities::locate(QStandardPaths::AppDataLocation, "usermenu", QStandardPaths::LocateDirectory) + m_currentXmlFile; } if ( QFile(m_currentXmlFile).exists() ) { KILE_DEBUG_MAIN << "install menufile: " << m_currentXmlFile; installXml(m_currentXmlFile); } else { m_currentXmlFile.clear(); } } updateUsermenuPosition(); } UserMenu::~UserMenu() { delete m_proc; } bool UserMenu::isEmpty() { return (getMenuItem()->actions().size() == 0); } /////////////////////// install usermenu////////////////////////////// QAction *UserMenu::createAction(const QString &name) { QAction *action = m_actioncollection->addAction(name, m_receiver, SLOT(quickUserMenuDialog())); action->setText(i18n("Edit User Menu")); action->setIcon(QIcon::fromTheme("wizard_usermenu")); return action; } void UserMenu::addSpecialActionsToMenus() { KXmlGuiWindow *mainwindow = m_ki->mainWindow(); // update wizard menu QMenu *wizard_menu = dynamic_cast(mainwindow->guiFactory()->container("wizard", mainwindow)); wizard_menu->addAction(m_wizardAction1); wizard_menu->addAction(m_wizardAction2); // update latex menu QMenu *latex_menu = dynamic_cast(mainwindow->guiFactory()->container("menu_latex", mainwindow)); latex_menu->addAction(m_latexAction1); latex_menu->addAction(m_latexAction2); latex_menu->addMenu(m_latexMenuEntry); } void UserMenu::updateUsermenuPosition() { // and set the new one const bool show = !isEmpty() && m_ki->viewManager()->currentTextView(); if(getUserMenuLocation() == StandAloneLocation) { setStandAloneMenuVisible(true, show); } else { setStandAloneMenuVisible(false, show); } } void UserMenu::setStandAloneMenuVisible(bool state, bool show) { m_wizardAction1->setVisible(state); m_wizardAction2->setVisible(state); m_latexAction1->setVisible(!state); m_latexAction2->setVisible(!state); m_latexMenuEntry->menuAction()->setVisible(!state && show); KXmlGuiWindow *mainwindow = m_ki->mainWindow(); QMenu *standAloneMenu = dynamic_cast(mainwindow->guiFactory()->container("menu_usermenu", mainwindow)); if(standAloneMenu) { standAloneMenu->menuAction()->setVisible(state && show); } } ///////////////////////////// clear all data ////////////////////////////// // clear all lists and data for an existing usermenu void UserMenu::clear() { // clear usermenu and menudata if(getMenuItem()) { getMenuItem()->clear(); } m_menudata.clear(); // remove all actions from actioncollection for(QAction *action : m_actionlist) { m_actioncollection->removeAction(action); } // clear actionlists m_actionlist.clear(); m_actionlistContextMenu.clear(); } ///////////////////////////// update GUI ////////////////////////////// // repopulate the user menu and show it at the desired location void UserMenu::updateGUI() { KILE_DEBUG_MAIN << "updating usermenu ..."; addSpecialActionsToMenus(); // adding actions twice has no effect // like installXmlFile(), but without updating KileConfig::userMenuFile // first clear old usermenu, menudata, actions and actionlists clear(); // then install if(!m_currentXmlFile.isEmpty() && installXml(m_currentXmlFile)) { // add changed context menu to all existing views KileView::Manager* viewManager = m_ki->viewManager(); int views = viewManager->textViewCount(); for ( int i=0; iinstallContextMenu( viewManager->textView(i) ); } } updateUsermenuPosition(); } ///////////////////////////// update key bindings ////////////////////////////// // shortcut dialog was called, so key bindings may have been changed void UserMenu::updateKeyBindings() { if ( m_currentXmlFile.isEmpty() && !QFile(m_currentXmlFile).exists() ) { return; } // new key bindings are found in kileui.rc (ActionProperties) // remove them, as they will be written into usermenu xml file removeActionProperties(); // update xml file of current usermenu updateXmlFile(m_currentXmlFile); } QMenu* UserMenu::getMenuItem() { if(getUserMenuLocation() == StandAloneLocation) { KParts::MainWindow *mainWindow = m_ki->mainWindow(); return dynamic_cast(mainWindow->guiFactory()->container("menu_usermenu", mainWindow)); } else { return m_latexMenuEntry; } } void UserMenu::removeActionProperties() { QString xmlfile = "kileui.rc"; QString xml(KXMLGUIFactory::readConfigFile(xmlfile)); if ( xml.isEmpty() ) { KILE_DEBUG_MAIN << "STOP: xmlfile not found: " << xmlfile; return; } QDomDocument doc; doc.setContent( xml ); // process XML data in section 'ActionProperties' QDomElement actionPropElement = KXMLGUIFactory::actionPropertiesElement( doc ); if ( actionPropElement.isNull() ) { KILE_DEBUG_MAIN << "QDomElement actionPropertiesElement not found "; return; } // search for all actions of the user-defined UserMenu KILE_DEBUG_MAIN << "QDomElement actionPropertiesElement found "; bool changed = false; QRegExp re("useraction-(\\d+)$"); QDomElement e = actionPropElement.firstChildElement(); while(!e.isNull()) { QString tag = e.tagName(); if(tag != "Action") { continue; } QString shortcut = e.attribute("shortcut"); QString name = e.attribute("name"); QDomElement removeElement; if ( re.indexIn(name) == 0) { int index = re.cap(1).toInt(); KILE_DEBUG_MAIN << "action property was changed: old=" << m_menudata[index].shortcut << " new=" << name << " actionIndex=" << index; removeElement = e; changed = true; } e = e.nextSiblingElement(); // finally delete element if ( !removeElement.isNull() ) { KILE_DEBUG_MAIN << "remove ActionProperty: shortcut=" << shortcut << " name=" << name; actionPropElement.removeChild(removeElement); } } // Write back to XML file if ( changed ) { KXMLGUIFactory::saveConfigFile(doc,xmlfile); } } ///////////////////////////// update action properties (shortcuts) ////////////////////////////// // Calling m_mainWindow->guiFactory()->refreshActionProperties() in kile.cpp removes all // user-defined action shortcuts and icons. Here they will be refreshed again. void UserMenu::refreshActionProperties() { KILE_DEBUG_MAIN << "refresh action properties"; QRegExp re("useraction-(\\d+)$"); foreach ( QAction *action, m_actionlist ) { if ( re.indexIn(action->objectName()) == 0 ) { int actionIndex = re.cap(1).toInt(); if ( !m_menudata[actionIndex].icon.isEmpty() ) { action->setIcon( QIcon::fromTheme(m_menudata[actionIndex].icon) ); } if ( !m_menudata[actionIndex].shortcut.isEmpty() ) { action->setShortcut( QKeySequence(m_menudata[actionIndex].shortcut,QKeySequence::NativeText) ); } } } } // Before calling usermenu dialog, all user-defined action shortcuts must be removed, // or the dialog will give a lot of warnings. All shortcuts (even if changed) in the usermenu // will be refreshed again, when the dialog is finished void UserMenu::removeShortcuts() { foreach ( QAction *action, m_actionlist ) { action->setShortcut( QKeySequence() ); } } ///////////////////////////// install/remove xml ////////////////////////////// // call from the menu: no xml file given void UserMenu::installXmlMenufile() { KILE_DEBUG_MAIN << "install xml file with QFileDialog::getOpenFileName"; QString directory = selectUserMenuDir(); QString filter = i18n("User Menu Files (*.xml)"); QString filename = QFileDialog::getOpenFileName(m_ki->mainWindow(), i18n("Select Menu File"), directory, filter); if(filename.isEmpty()) { return; } if( !QFile::exists(filename) ) { KMessageBox::error(m_ki->mainWindow(), i18n("File '%1' does not exist.", filename)); } else { installXmlFile(filename); } } // SIGNAL from usermenu dialog: install new usermenu (xml file given) // // use 'basename.ext' if the file is placed in 'KILE-LOCAL-DIR/usermenu' directory and full filepath else void UserMenu::installXmlFile(const QString &filename) { KILE_DEBUG_MAIN << "install xml file" << filename; // clear old usermenu, menudata, actions and actionlists clear(); if ( installXml(filename) ) { // update current xml filename (with path) m_currentXmlFile = filename; // save xml file in config (with or without path) QString xmlfile = filename; - QString dir = QStandardPaths::locate(QStandardPaths::DataLocation, "usermenu", QStandardPaths::LocateDirectory); + QString dir = KileUtilities::locate(QStandardPaths::AppDataLocation, "usermenu", QStandardPaths::LocateDirectory); if ( filename.startsWith(dir) ) { QString basename = filename.right( filename.length()-dir.length() ); if ( !basename.isEmpty() && !basename.contains("/") ) { xmlfile = basename; } } KileConfig::setUserMenuFile(xmlfile); emit (updateStatus()); // add changed context menu to all existing views KileView::Manager* viewManager = m_ki->viewManager(); int views = viewManager->textViewCount(); for ( int i=0; iinstallContextMenu( viewManager->textView(i) ); } } } void UserMenu::removeXmlFile() { KILE_DEBUG_MAIN << "remove xml file"; clear(); m_currentXmlFile.clear(); KileConfig::setUserMenuFile(m_currentXmlFile); emit (updateStatus()); } ///////////////////////////// install usermenu from XML ////////////////////////////// // pre: usermenu is already cleared bool UserMenu::installXml(const QString &filename) { KILE_DEBUG_MAIN << "install: start"; QMenu *userMenu = getMenuItem(); if(!userMenu) { KILE_DEBUG_MAIN << "Hmmmm: found no usermenu"; return false; } // read content of xml file QDomDocument doc("UserMenu"); QFile file(filename); if ( !file.open(QFile::ReadOnly | QFile::Text) ) { // TODO KMessageBox KILE_DEBUG_MAIN << "STOP: can't open xml file " << filename; return false; } if( !doc.setContent( &file ) ) { file.close(); return false; } file.close(); KILE_DEBUG_MAIN << "parse xml ..."; m_actionsContextMenu = 0; // parse toplevelitems int actionnumber = 0; QDomElement root = doc.documentElement(); QDomElement e = root.firstChildElement(); while ( !e.isNull()) { QString tag = e.tagName(); if ( tag=="submenu" || tag=="separator") { if ( tag == "submenu" ) { installXmlSubmenu(e, userMenu, actionnumber); } else { /* tag=="separator" */ userMenu->addSeparator(); } // try to get some structure into to the context menu if ( m_actionsContextMenu > 0 ) { m_actionlistContextMenu.append(Q_NULLPTR); m_actionsContextMenu = 0; } } else { /* if ( tag == "menu" ) */ installXmlMenuentry(e, userMenu, actionnumber); } e = e.nextSiblingElement(); } KILE_DEBUG_MAIN << "install: finished "; return true; } // install a submenu item void UserMenu::installXmlSubmenu(const QDomElement &element, QMenu *parentmenu, int &actionnumber) { QMenu *submenu = parentmenu->addMenu(QString()); QString title; if ( element.hasChildNodes() ) { QDomElement e = element.firstChildElement(); while ( !e.isNull()) { QString tag = e.tagName(); if ( tag == "title" ) { title = e.text(); submenu->setTitle(title); } else if ( tag == "submenu" ) { installXmlSubmenu(e,submenu,actionnumber); } else if ( tag == "separator" ) { submenu->addSeparator(); } else { /* if ( tag == "menu" ) */ installXmlMenuentry(e,submenu,actionnumber); } e = e.nextSiblingElement(); } } } // install a standard menu item void UserMenu::installXmlMenuentry(const QDomElement &element, QMenu *parentmenu, int &actionnumber) { UserMenuData menudata; menudata.menutype = UserMenuData::xmlMenuType( element.attribute("type") ); // read values if ( element.hasChildNodes() ) { QDomElement e = element.firstChildElement(); while ( !e.isNull()) { QString tag = e.tagName(); QString text = e.text(); int index = UserMenuData::xmlMenuTag(tag); switch (index) { case UserMenuData::XML_TITLE: menudata.menutitle = text; break; case UserMenuData::XML_PLAINTEXT: menudata.text = UserMenuData::decodeLineFeed(text); break; case UserMenuData::XML_FILENAME: menudata.filename = text; break; case UserMenuData::XML_PARAMETER: menudata.parameter = text; break; case UserMenuData::XML_ICON: menudata.icon = text; break; case UserMenuData::XML_SHORTCUT: menudata.shortcut = text; break; case UserMenuData::XML_NEEDSSELECTION: menudata.needsSelection = str2bool(text); break; case UserMenuData::XML_USECONTEXTMENU: menudata.useContextMenu = str2bool(text); break; case UserMenuData::XML_REPLACESELECTION: menudata.replaceSelection = str2bool(text); break; case UserMenuData::XML_SELECTINSERTION: menudata.selectInsertion = str2bool(text); break; case UserMenuData::XML_INSERTOUTPUT: menudata.insertOutput = str2bool(text); break; } e = e.nextSiblingElement(); } } // add menu item, if its title is not empty if ( !menudata.menutitle.isEmpty() ) { QAction *action = m_actioncollection->addAction(QString("useraction-%1").arg(actionnumber), this, SLOT(slotUserMenuAction()) ); if ( action ) { action->setText(menudata.menutitle); if ( !menudata.icon.isEmpty() ) { action->setIcon( QIcon::fromTheme(menudata.icon) ); } if ( !menudata.shortcut.isEmpty() ) { action->setShortcut( QKeySequence(menudata.shortcut,QKeySequence::PortableText) ); } parentmenu->addAction(action); m_menudata.append(menudata); m_actionlist.append(action); if ( menudata.useContextMenu ) { m_actionlistContextMenu.append(action); m_actionsContextMenu++; } actionnumber++; } } } ///////////////////////////// update XML file ////////////////////////////// // key bindings dialog was called, so the usermenu xml file must be updated, if one of these actions was changed // pre: xml file exists void UserMenu::updateXmlFile(const QString &filename) { KILE_DEBUG_MAIN << "update xml file: " << filename; // read content of xml file QDomDocument doc("UserMenu"); QFile file(filename); file.open(QFile::ReadOnly | QFile::Text); doc.setContent(&file); file.close(); KILE_DEBUG_MAIN << "parse xml ..."; // parse toplevelitems bool changed = false; int actionnumber = 0; QDomElement root = doc.documentElement(); QDomElement e = root.firstChildElement(); while ( !e.isNull()) { QString tag = e.tagName(); if ( tag == "submenu" ) { changed = changed || updateXmlSubmenu(doc,e,actionnumber); } else if ( tag == "menu" ) { changed = changed || updateXmlMenuentry(doc,e,actionnumber); } e = e.nextSiblingElement(); } KILE_DEBUG_MAIN << "update finished "; if ( changed ) { KILE_DEBUG_MAIN << "found changes, so write updated xml file "; QFile outfile(filename); outfile.open(QFile::WriteOnly | QFile::Text); QTextStream stream(&outfile); doc.save(stream,3); outfile.close(); } } // install a submenu item bool UserMenu::updateXmlSubmenu(QDomDocument &doc, QDomElement &element, int &actionnumber) { bool changed = false; if ( element.hasChildNodes() ) { QDomElement e = element.firstChildElement(); while ( !e.isNull()) { QString tag = e.tagName(); if ( tag == "submenu" ) { changed = changed || updateXmlSubmenu(doc,e,actionnumber); } else if ( tag == "menu" ) { changed = changed || updateXmlMenuentry(doc,e,actionnumber); } e = e.nextSiblingElement(); } } return changed; } // install a standard menu item bool UserMenu::updateXmlMenuentry(QDomDocument &doc, QDomElement &element, int &actionnumber) { bool changed = false; // read values if ( element.hasChildNodes() ) { QDomElement oldElement; QDomElement e = element.firstChildElement(); while ( !e.isNull()) { QString tag = e.tagName(); if ( UserMenuData::xmlMenuTag(tag) == UserMenuData::XML_SHORTCUT) { oldElement = e; //oldText = e.text(); value not needed, is also in m_menudata[] } e = e.nextSiblingElement(); } // keybindings dialog has already updated all actions QString currentShortcut = m_actionlist[actionnumber]->shortcut().toString(QKeySequence::PortableText); if ( currentShortcut != m_menudata[actionnumber].shortcut ) { // an existing shortcut always needs a new QDomElement if ( !currentShortcut.isEmpty() ) { // create element with new shortcut QDomElement newElement = doc.createElement( UserMenuData::xmlMenuTagName(UserMenuData::XML_SHORTCUT) ); QDomText newText = doc.createTextNode(currentShortcut); newElement.appendChild(newText); // replace existing node with new node if ( !oldElement.isNull() ) { element.replaceChild(newElement,oldElement); } // or insert a new node else { element.appendChild(newElement); } } // or delete an existing QDomElement else { element.removeChild(oldElement); } changed = true; } } actionnumber++; return changed; } ////////////////////////////// load dir for xml files (static) ////////////////////////////// // - start with search for xml files in the local directory // - if no files are present, but in global directory, start with global // - if not a single file was found: back to local directory QString UserMenu::selectUserMenuDir() { - QStringList dirs = QStandardPaths::locateAll(QStandardPaths::DataLocation, "usermenu", QStandardPaths::LocateDirectory); + QStringList dirs = KileUtilities::locateAll(QStandardPaths::AppDataLocation, "usermenu", QStandardPaths::LocateDirectory); if ( dirs.size() < 2 ) { return dirs.at(0); } QStringList namefilter = QStringList() << "*.xml"; QString localDirName = dirs.at(0); QDir localDir = QDir(localDirName); QStringList localList = localDir.entryList (namefilter,QDir::Files | QDir::Readable); if ( localList.size() > 0 ) { return localDirName; } QDir globalDir = QDir(dirs.at(1)); QStringList globalList = globalDir.entryList (namefilter,QDir::Files | QDir::Readable); return ( globalList.size() > 0 ) ? dirs.at(1) : localDirName; } ////////////////////////////// execUserMenuAction ////////////////////////////// // an action was called from the usermenu: // - identify action // - find textview // - execute action void UserMenu::slotUserMenuAction() { KILE_DEBUG_MAIN << "want to start an action from usermenu ..."; QAction *action = dynamic_cast(sender()); if ( !action ) { return; } QString actionName = action->objectName(); KILE_DEBUG_MAIN << "action name: " << actionName << "classname=" << action->metaObject()->className(); QRegExp re("useraction-(\\d+)$"); if ( re.indexIn(actionName) != 0) { KILE_DEBUG_MAIN << "STOP: found wrong action name: " << actionName; return; } bool ok; int actionIndex = re.cap(1).toInt(&ok); if ( actionIndex < 0 || actionIndex >= m_menudata.size() ) { KILE_DEBUG_MAIN << "STOP: invalid action (range error): " << actionIndex << " list size: " << m_menudata.size(); return; } // check view and action requirements KTextEditor::View *view = m_ki->viewManager()->currentTextView(); if ( !view ) { return; } if ( !view->selection() && m_menudata[actionIndex].needsSelection ) { return; } UserMenuData::MenuType type = m_menudata[actionIndex].menutype; if ( type == UserMenuData::Text ) { execActionText(view,m_menudata[actionIndex]); } else if ( type == UserMenuData::FileContent ) { execActionFileContent(view,m_menudata[actionIndex]); } else if ( type == UserMenuData::Program ) { execActionProgramOutput(view,m_menudata[actionIndex]); } else { KILE_DEBUG_MAIN << "STOP: unknown action type: " << type; } } ////////////////////////////// execActionText ////////////////////////////// // execute an action: insert text void UserMenu::execActionText(KTextEditor::View *view, const UserMenuData &menudata) { KILE_DEBUG_MAIN << "want to insert text ... "; insertText(view, menudata.text, menudata.replaceSelection, menudata.selectInsertion); } ////////////////////////////// execActionFileContent ////////////////////////////// // execute an action: insert file contents void UserMenu::execActionFileContent(KTextEditor::View *view, const UserMenuData &menudata) { KILE_DEBUG_MAIN << "want to insert contents of a file: " << menudata.filename; QFile file(menudata.filename); if ( !file.open(QFile::ReadOnly | QFile::Text) ) { KILE_DEBUG_MAIN << "STOP: could not open file " << menudata.filename; return; } QTextStream stream( &file ); QString text = stream.readAll(); file.close(); if ( !text.isEmpty() ) { insertText(view, text, menudata.replaceSelection, menudata.selectInsertion); } } ////////////////////////////// execActionFileContent ////////////////////////////// // execute an action: run a program void UserMenu::execActionProgramOutput(KTextEditor::View *view, const UserMenuData &menudata) { KILE_DEBUG_MAIN << "want to start a program ... "; // delete old process if (m_proc) { delete m_proc; m_proc = Q_NULLPTR; } // build commandline QString cmdline = menudata.filename + ' ' + menudata.parameter; bool useTemporaryFile = cmdline.contains("%M"); bool needsSelection = menudata.needsSelection; bool hasSelection = view->selection(); // check parameter if ( needsSelection && !hasSelection ) { KILE_DEBUG_MAIN << "STOP: this program needs selected text"; return; } // do we need a temporary file for the selected text? if ( hasSelection && useTemporaryFile ) { KILE_DEBUG_MAIN << "selection and 'placeholder' %M found --> create temporary file"; // create temporary file QTemporaryFile tempfile; //code was tempfile.setSuffix(".txt"); //Add to constructor and adapt if necessay: QDir::tempPath() + QLatin1String("/myapp_XXXXXX") + QLatin1String(".txt") tempfile.setAutoRemove(false); if ( !tempfile.open() ) { KILE_DEBUG_MAIN << "STOP: could not create tempfile for selected text" ; return; } // get filename QString selfile = tempfile.fileName(); // write selection QTextStream stream( &tempfile ); stream << view->selectionText() << "\n"; tempfile.close(); // update comamndline with temporary filename of selection cmdline.replace("%M",selfile); } // replace %F with the complete base name of the file without the path. // The complete base name consists of all characters in the file up to // (but not including) the last '.' character. if ( cmdline.contains("%S") ) { QFileInfo fi(view->document()->url().toLocalFile()); QString basename = fi.completeBaseName(); cmdline.replace("%S",basename); } m_proc = new KProcess(this); m_proc->setShellCommand(cmdline); m_proc->setOutputChannelMode(KProcess::MergedChannels); m_proc->setReadChannel(QProcess::StandardOutput); connect(m_proc, SIGNAL(readyReadStandardOutput()), this, SLOT(slotProcessOutput())); connect(m_proc, SIGNAL(readyReadStandardError()), this, SLOT(slotProcessOutput())); connect(m_proc, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(slotProcessExited(int,QProcess::ExitStatus))); KILE_DEBUG_MAIN << "... start proc: " << cmdline; // init and/or save important data m_procOutput.clear(); m_procView = view; m_procMenudata = &menudata; m_proc->start(); } void UserMenu::slotProcessOutput() { m_procOutput += m_proc->readAll(); } void UserMenu::slotProcessExited(int /* exitCode */, QProcess::ExitStatus exitStatus) { KILE_DEBUG_MAIN << "... finish proc "; KILE_DEBUG_MAIN << "output: " << m_procOutput; if ( exitStatus == QProcess::NormalExit && m_procMenudata->insertOutput && !m_procOutput.isEmpty() ) { insertText(m_procView, m_procOutput, m_procMenudata->replaceSelection, m_procMenudata->selectInsertion); } } ////////////////////////////// auxiliary ////////////////////////////// // action is finished, now insert some text void UserMenu::insertText(KTextEditor::View *view, const QString &text, bool replaceSelection, bool selectInsertion) { KILE_DEBUG_MAIN << "insert text from action: " << text; // metachars: %R - references (like \ref{%R}, \pageref{%R} ...) // %T - citations (like \cite{%T} ...) QString metachar,label; int actiontype =0; if(text.contains("%R")) { metachar = "%R"; label = i18n("Label"); actiontype = KileAction::FromLabelList; } else if(text.contains("%T")) { metachar = "%T"; label = i18n("Reference"); actiontype = KileAction::FromBibItemList; } if(!metachar.isEmpty()) { QStringList list = text.split(metachar); KileAction::InputTag tag(m_ki, i18n("Input Dialog"), QString(), QKeySequence(), m_receiver, SLOT(insertTag(KileAction::TagData)), m_actioncollection,"tag_temporary_action", m_ki->mainWindow(), actiontype, list.at(0)+metachar, list.at(1), list.at(0).length(), 0, QString(), label); tag.activate(QAction::Trigger); return; } // metachars: %B - bullet // %M - selected text // %C - place cursor // %E - indent in environment QString ins = text; bool bullet = ins.contains("%B"); // deselect and/or remove current selection if(view->selection()) { if(ins.contains("%M")) { ins.replace("%M", view->selectionText()); } if(replaceSelection) { view->removeSelectionText(); } else { view->removeSelection(); } } else { ins.replace("%M", QString()); } KILE_DEBUG_MAIN << " ---> " << ins; // insert new text KTextEditor::Cursor cursor1 = view->cursorPosition(); emit( sendText(ins) ); // select inserted text if(selectInsertion) { KTextEditor::Cursor cursor2 = view->cursorPosition(); view->setSelection(KTextEditor::Range(cursor1, cursor2)); } // text with bullet metachar %B if(bullet) { view->setCursorPosition(cursor1); m_ki->editorExtension()->gotoBullet(false, view); } } ////////////////////////////// auxiliary ////////////////////////////// bool UserMenu::str2bool(const QString &value) { return ( value == "true" ); } } diff --git a/src/utilities.cpp b/src/utilities.cpp index 1a7cc773..0d7c2dda 100644 --- a/src/utilities.cpp +++ b/src/utilities.cpp @@ -1,142 +1,205 @@ /************************************************************************** * Copyright (C) 2008-2018 by Michel Ludwig (michel.ludwig@kdemail.net) * ***************************************************************************/ /************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "utilities.h" #include #include #include #include +#include #include #include #include #include "kiledebug.h" ServiceRunAction::ServiceRunAction(const KService& service, const QList& urls, QWidget* window, bool tempFiles, const QString& suggestedFileName, const QByteArray& asn, QObject *parent) : QAction(QIcon::fromTheme(service.icon()), service.genericName(), parent), m_service(service), m_urlList(urls), m_window(window), m_tempFiles(tempFiles), m_suggestedFileName(suggestedFileName), m_asn(asn) { connect(this, SIGNAL(triggered()), this, SLOT(runService())); } ServiceRunAction::~ServiceRunAction() { } void ServiceRunAction::runService() { KRun::runService(m_service, m_urlList, m_window, m_tempFiles, m_suggestedFileName, m_asn); } QString KileUtilities::lastModifiedFile(const QStringList& files, const QString& baseDir) { KILE_DEBUG_MAIN << "==KileUtilities::lastModifiedFile()=====" << files << "baseDir:" << baseDir; if(files.empty()) { return QString(); } QStringList absoluteFileNames; if(baseDir.isEmpty()) { absoluteFileNames = files; } else { QDir basePath(baseDir); Q_FOREACH(const QString& file, files) { absoluteFileNames.append(basePath.absoluteFilePath(file)); } } QDateTime lastModifiedTime; const QString* lastModifiedFile = Q_NULLPTR; Q_FOREACH(const QString& file, absoluteFileNames) { QFileInfo fileInfo(file); if(!fileInfo.exists()) { KILE_DEBUG_MAIN << "file does not exist:" << file << "files:" << files; continue; } QDateTime modificationTime = fileInfo.lastModified(); if(!lastModifiedTime.isValid() || modificationTime > lastModifiedTime) { lastModifiedFile = &file; lastModifiedTime = modificationTime; } } if(lastModifiedFile) { return *lastModifiedFile; } else { return QString(); } } void centerWidgetRelativeToParentRect(QWidget *widget, const QRect& parentRect) { QRect alignedRect = QStyle::alignedRect(Qt::LeftToRight, Qt::AlignCenter, widget->size(), parentRect); widget->move(alignedRect.x(), alignedRect.y()); } void KileUtilities::centerWidgetRelativeToParent(QWidget *widget) { QWidget *parentWidget = widget->parentWidget(); if(!parentWidget) { centerWidgetRelativeToParentRect(widget, QApplication::desktop()->availableGeometry(widget)); } else { QRect parentRect(parentWidget->mapToGlobal(QPoint(0, 0)), parentWidget->size()); centerWidgetRelativeToParentRect(widget, parentRect); } } void KileUtilities::scheduleCenteringOfWidget(QWidget *widget) { QTimer::singleShot(0, widget, [=] () { centerWidgetRelativeToParent(widget); }); } QUrl KileUtilities::canonicalUrl(const QUrl &url) { if(!url.isLocalFile()) { return url; } QFileInfo fileInfo(url.toLocalFile()); if(fileInfo.exists()) { const QString canonicalFileName = fileInfo.canonicalFilePath(); Q_ASSERT_X(!canonicalFileName.isEmpty(), "canonicalUrl", "empty although file exists!"); return QUrl::fromLocalFile(canonicalFileName); } else { return QUrl::fromLocalFile(QDir::cleanPath(url.toLocalFile())); } } + +static inline QString getRelativeSharePath() +{ + return QCoreApplication::applicationDirPath() + QLatin1String("/../share/kile/"); +} + +QString KileUtilities::findExecutable(const QString &executableName, const QStringList &paths) +{ + return findExecutable(executableName, paths); +} + +QString KileUtilities::locate(QStandardPaths::StandardLocation type, const QString &fileName, + QStandardPaths::LocateOptions options) +{ + if(type == QStandardPaths::AppDataLocation || type == QStandardPaths::DataLocation) { + const QString candidate = getRelativeSharePath() + fileName; + if((options == QStandardPaths::LocateFile) && QFileInfo::exists(candidate)) { + return candidate; + } + else if((options == QStandardPaths::LocateDirectory) && QDir(candidate).exists()) { + return candidate; + } + } + + return QStandardPaths::locate(type, fileName, options); +} + +QStringList KileUtilities::locateAll(QStandardPaths::StandardLocation type, const QString &fileName, + QStandardPaths::LocateOptions options) +{ + QStringList toReturn; + if(type == QStandardPaths::AppDataLocation || type == QStandardPaths::DataLocation) { + const QString candidate = getRelativeSharePath() + fileName; + if((options == QStandardPaths::LocateFile) && QFileInfo::exists(candidate)) { + toReturn << candidate; + } + else if((options == QStandardPaths::LocateDirectory) && QDir(candidate).exists()) { + toReturn << candidate; + } + } + toReturn << QStandardPaths::locateAll(type, fileName, options); + + return toReturn; +} + +QStringList KileUtilities::standardLocations(QStandardPaths::StandardLocation type) +{ + QStringList toReturn; + if(type == QStandardPaths::AppDataLocation || type == QStandardPaths::DataLocation) { + toReturn << getRelativeSharePath(); + } + toReturn << standardLocations(type); + + return toReturn; +} + +QString KileUtilities::writableLocation(QStandardPaths::StandardLocation type) +{ + return QStandardPaths::writableLocation(type); +} + +// kate: indent-width 4; replace-tabs: true; diff --git a/src/utilities.h b/src/utilities.h index e44aac7f..736f7b4a 100644 --- a/src/utilities.h +++ b/src/utilities.h @@ -1,78 +1,100 @@ /************************************************************************** -* Copyright (C) 2008-2018 by Michel Ludwig (michel.ludwig@kdemail.net) * +* Copyright (C) 2008-2019 by Michel Ludwig (michel.ludwig@kdemail.net) * ***************************************************************************/ /************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef UTILITIES_H #define UTILITIES_H #include +#include #include #include class ServiceRunAction : public QAction { Q_OBJECT public: ServiceRunAction(const KService& service, const QList& urls, QWidget* window, bool tempFiles = false, const QString& suggestedFileName = QString(), const QByteArray& asn = "", QObject *parent = Q_NULLPTR); ~ServiceRunAction(); protected Q_SLOTS: void runService(); protected: const KService& m_service; QList m_urlList; QWidget* m_window; bool m_tempFiles; QString m_suggestedFileName; QByteArray m_asn; }; namespace KileUtilities { /** * @brief Finds the file with the most recent modification time from a list * * Checks last modification time for files and returns absolute (see @ref baseDir description) file name of * file with the latest modification time * @param files List of filenames, relative to @ref baseDir * @param baseDir Path to base directory. If empty, @ref files are used as they are * @return Absolute path of the file with the latest modification time or empty string if @ref files is empty **/ QString lastModifiedFile(const QStringList& files, const QString& baseDir = QString()); /** * Centers the given widget w.r.t. its parent. If it doesn't have a parent, the containing screen is used. **/ void centerWidgetRelativeToParent(QWidget *widget); /** * Schedules the centering of the given widget w.r.t. its parent in the event loop. **/ void scheduleCenteringOfWidget(QWidget *widget); /** * If 'url' is a local file, the canonical file path is returned if the file exists. Otherwise, * the cleaned file path is returned (see QDir::cleanPath). * If 'url' is not a local file, 'url' is returned. **/ QUrl canonicalUrl(const QUrl &url); + + +/** + * Add our own versions of most QStandardPaths:: methods, which allow to locate 'DataLocation' or + * 'AppDataLocation' items under /../share/kile + * This is necessary for being able to create an AppImage + **/ + +QString findExecutable(const QString &executableName, const QStringList &paths = QStringList()); + +QString locate(QStandardPaths::StandardLocation type, + const QString &fileName, + QStandardPaths::LocateOptions options = QStandardPaths::LocateFile); + +QStringList locateAll(QStandardPaths::StandardLocation type, + const QString &fileName, + QStandardPaths::LocateOptions options = QStandardPaths::LocateFile); + +QStringList standardLocations(QStandardPaths::StandardLocation type); + +QString writableLocation(QStandardPaths::StandardLocation type); } #endif diff --git a/src/widgets/symbolview.cpp b/src/widgets/symbolview.cpp index ad7c07d8..b4c437aa 100644 --- a/src/widgets/symbolview.cpp +++ b/src/widgets/symbolview.cpp @@ -1,475 +1,477 @@ /**************************************************************************************** begin : Fri Aug 1 2003 copyright : (C) 2003 by Jeroen Wijnhout (Jeroen.Wijnhout@kdemail.net) 2006 - 2009 by Thomas Braun - 2012 by Michel Ludwig (michel.ludwig@kdemail.net) + 2012 - 2019 by Michel Ludwig (michel.ludwig@kdemail.net) ****************************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /* dani 2005-11-22 - add some new symbols - rearranged source tbraun 2006-07-01 - added tooltips which show the keys, copied from kfileiconview - reorganized the hole thing, more flexible png loading, removing the old big code_array, more groups tbraun 2007-06-04 - Send a warning in the logwidget if needed packages are not included for the command tbraun 2007-06-13 - Added Most frequently used symbolview, including remembering icons upon restart, removing of least popular item and configurable max item count */ #include "symbolview.h" #include #include #include #include #include -#include #include #include #include #include #include #include "kileconfig.h" #include "kiledebug.h" #include "kileinfo.h" #include "../symbolviewclasses.h" +#include "utilities.h" #define MFUS_GROUP "MostFrequentlyUsedSymbols" #define MFUS_PREFIX "MFUS" namespace KileWidget { SymbolView::SymbolView(KileInfo *kileInfo, QWidget *parent, int type, const char *name) : QListWidget(parent), m_ki(kileInfo) { setObjectName(name); setViewMode(IconMode); setGridSize(QSize(36, 36)); setSpacing(5); setWordWrap(false); setResizeMode(Adjust); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); setMovement(Static); setSortingEnabled(false); setFlow(LeftToRight); setDragDropMode(NoDragDrop); m_brush = KStatefulBrush(KColorScheme::View, KColorScheme::NormalText); initPage(type); } SymbolView::~SymbolView() { } /* key format from old symbols with package info 1%\textonequarter%%%{textcomp}%%/home/kdedev/.kde4/share/apps/kile/mathsymbols/misc-text/img072misc-text.png from old symbols without package info 1%\oldstylenums{9}%%%%%/home/kdedev/.kde4/share/apps/kile/mathsymbols/misc-text/img070misc-text.png new symbol 1%\neq%≠%[utf8x,,]{inputenc,ucs,}%[fleqn,]{amsmath,}%This command gives nice weather!%/home/kdedev/.kde4/share/apps/kile/mathsymbols/user/img002math.png */ void SymbolView::extract(const QString& key, int& refCnt) { if (!key.isEmpty()) { refCnt = key.section('%', 0, 0).toInt(); } } void SymbolView::extractPackageString(const QString&string, QList &packages) { QRegExp rePkgs("(?:\\[(.*)\\])?\\{(.*)\\}"); QStringList args,pkgs; Package pkg; if(string.isEmpty()) { return; } packages.clear(); if(rePkgs.exactMatch(string)) { args = rePkgs.cap(1).split(','); pkgs = rePkgs.cap(2).split(','); } else { return; } for(int i = 0 ; i < pkgs.count() && i < args.count() ; i++) { const QString packageName = pkgs.at(i); if(packageName.isEmpty()) { continue; } pkg.name = packageName; pkg.arguments = args.at(i); packages.append(pkg); } } void SymbolView::extract(const QString& key, Command &cmd) { if (key.isEmpty()) { return; } QStringList contents = key.split('%'); QString packages; cmd.referenceCount = contents.at(0).toInt(); cmd.latexCommand = contents.at(1); cmd.unicodeCommand = contents.at(2); extractPackageString(contents.at(3), cmd.unicodePackages); extractPackageString(contents.at(4), cmd.packages); cmd.comment = contents.at(5); cmd.path = contents.at(6); } void SymbolView::initPage(int page) { switch(page) { case MFUS: fillWidget(MFUS_PREFIX); break; case Relation: fillWidget("relation"); break; case Operator: fillWidget("operators"); break; case Arrow: fillWidget("arrows"); break; case MiscMath: fillWidget("misc-math"); break; case MiscText: fillWidget("misc-text"); break; case Delimiters: fillWidget("delimiters"); break; case Greek: fillWidget("greek"); break; case Special: fillWidget("special"); break; case Cyrillic: fillWidget("cyrillic"); break; case User: fillWidget("user"); break; default: qWarning() << "wrong argument in initPage()"; break; } } QString SymbolView::getToolTip(const QString &key) { Command cmd; extract(key, cmd); QString label = "

"; label += "" + i18n("Command: %1", cmd.latexCommand.toHtmlEscaped()) + ""; if(!cmd.unicodeCommand.isEmpty()) { label += i18n("
Unicode: %1", cmd.unicodeCommand.toHtmlEscaped()); } if(cmd.packages.count() > 0) { QString packageString; if(cmd.packages.count() == 1) { Package pkg = cmd.packages.at(0); if(!pkg.arguments.isEmpty()) { packageString += '[' + pkg.arguments + ']' + pkg.name; } else { packageString += pkg.name; } } else { packageString = "

    "; for (int i = 0; i < cmd.packages.count() ; ++i) { Package pkg = cmd.packages.at(i); if(!pkg.arguments.isEmpty()) { packageString += "
  • [" + pkg.arguments + ']' + pkg.name + "
  • "; } else { packageString += "
  • " + pkg.name + "
  • "; } } packageString += "
"; } label += "
" + i18np("Required Package: %2", "Required Packages: %2", cmd.packages.count(), packageString); } if(!cmd.comment.isEmpty()) { label += "
" + i18n("Comment: %1", cmd.comment.toHtmlEscaped()) + ""; } label += "

"; return label; } void SymbolView::mousePressEvent(QMouseEvent *event) { Command cmd; QString code_symbol; QList packages; QListWidgetItem *item = Q_NULLPTR; bool math = false, bracket = false; if(event->button() == Qt::LeftButton && (item = itemAt(event->pos()))) { bracket = event->modifiers() & Qt::ControlModifier; math = event->modifiers() & Qt::ShiftModifier; extract(item->data(Qt::UserRole).toString(), cmd); if(KileConfig::symbolViewUTF8()) { code_symbol = cmd.unicodeCommand; if(code_symbol.isEmpty()) { code_symbol = cmd.latexCommand; } packages = cmd.unicodePackages; } else { code_symbol = cmd.latexCommand; packages = cmd.packages; } if(math != bracket) { if(math) { code_symbol = '$' + code_symbol + '$'; } else if(bracket) { code_symbol = '{' + code_symbol + '}'; } } emit(insertText(code_symbol, packages)); emit(addToList(item)); m_ki->focusEditor(); } KILE_DEBUG_MAIN << "math is " << math << ", bracket is " << bracket << " and item->data(Qt::UserRole).toString() is " << (item ? item->data(Qt::UserRole).toString() : ""); } QString convertLatin1StringtoUTF8(const QString &string) { if(string.isEmpty()) { return QString(); } QVector stringAsIntVector; QStringList stringList = string.split(',', QString::SkipEmptyParts); QStringList::const_iterator it; QString str; bool ok; int stringAsInt; for(it = stringList.constBegin(); it != stringList.constEnd(); it++) { str = *it; str.remove("U+"); stringAsInt = str.toInt(&ok); if(!ok) { return QString(); } stringAsIntVector.append(stringAsInt); } return QString::fromUcs4(stringAsIntVector.data(),stringAsIntVector.count()); } void SymbolView::fillWidget(const QString& prefix) { KILE_DEBUG_MAIN << "===SymbolView::fillWidget(const QString& " << prefix << " )==="; QImage image; QListWidgetItem* item; QStringList refCnts, paths, unicodeValues; QString key; // find paths if (prefix == MFUS_PREFIX) { // case: most frequently used symbols KConfigGroup config = KSharedConfig::openConfig()->group(MFUS_GROUP); QString configPaths = config.readEntry("paths"); QString configrefCnts = config.readEntry("counts"); paths = configPaths.split(',', QString::SkipEmptyParts); refCnts = configrefCnts.split(',', QString::SkipEmptyParts); KILE_DEBUG_MAIN << "Read " << paths.count() << " paths and " << refCnts.count() << " refCnts"; if(paths.count() != refCnts.count()) { KILE_DEBUG_MAIN << "error in saved LRU list"; paths.clear(); refCnts.clear(); } } else { // case: any other group of math symbols - const QStringList dirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, "kile/mathsymbols/" + prefix, QStandardPaths::LocateDirectory); - Q_FOREACH (const QString &dir, dirs) { + const QStringList dirs = KileUtilities::locateAll(QStandardPaths::AppDataLocation, + QLatin1String("mathsymbols/") + prefix, + QStandardPaths::LocateDirectory); + for(const QString &dir : dirs) { const QStringList fileNames = QDir(dir).entryList(QStringList() << QStringLiteral("*.png")); - Q_FOREACH (const QString &file, fileNames) { + for(const QString &file : fileNames) { const QString path = dir + '/' + file; if (!paths.contains(path)) { paths.append(path); } } } paths.sort(); for (int i = 0; i < paths.count(); i++) { refCnts.append("1"); } } // render symbols for (int i = 0; i < paths.count(); i++) { if (image.load(paths[i])) { item = new QListWidgetItem(this); key = refCnts[i] + '%' + image.text("Command"); key += '%' + convertLatin1StringtoUTF8(image.text("CommandUnicode")); key += '%' + image.text("UnicodePackages"); key += '%' + image.text("Packages"); key += '%' + convertLatin1StringtoUTF8(image.text("Comment")); key += '%' + paths[i]; item->setData(Qt::UserRole, key); item->setToolTip(getToolTip(key)); if (prefix != QLatin1String("user")) { if (image.format() != QImage::Format_ARGB32_Premultiplied && image.format() != QImage::Format_ARGB32) { image = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); } QPainter p; p.begin(&image); p.setCompositionMode(QPainter::CompositionMode_SourceAtop); p.fillRect(image.rect(), m_brush.brush(QPalette::Active)); p.end(); } item->setIcon(QPixmap::fromImage(image)); } else { KILE_DEBUG_MAIN << "Loading file " << paths[i] << " failed"; } } } void SymbolView::writeConfig() { QListWidgetItem *item; QStringList paths; QList refCnts; Command cmd; KConfigGroup grp = KSharedConfig::openConfig()->group(MFUS_GROUP); if (KileConfig::clearMFUS()) { grp.deleteEntry("paths"); grp.deleteEntry("counts"); } else { for(int i = 0; i < count(); ++i) { item = this->item(i); extract(item->data(Qt::UserRole).toString(),cmd); refCnts.append(cmd.referenceCount); paths.append(cmd.path); KILE_DEBUG_MAIN << "path=" << paths.last() << ", count is " << refCnts.last(); } grp.writeEntry("paths", paths); grp.writeEntry("counts", refCnts); } } void SymbolView::slotAddToList(const QListWidgetItem *item) { if(!item || item->icon().isNull()) { return; } QListWidgetItem *tmpItem = Q_NULLPTR; bool found = false; const QRegExp reCnt("^\\d+"); KILE_DEBUG_MAIN << "===void SymbolView::slotAddToList(const QIconViewItem *" << item << " )==="; for(int i = 0; i < count(); ++i) { tmpItem = this->item(i); if (item->data(Qt::UserRole).toString().section('%', 1) == tmpItem->data(Qt::UserRole).toString().section('%', 1)) { found = true; break; } } if(!found && static_cast(this->count() + 1) > KileConfig::numSymbolsMFUS()) { // we check before adding the symbol int refCnt, minRefCnt = 10000; QListWidgetItem *unpopularItem = Q_NULLPTR; KILE_DEBUG_MAIN << "Removing most unpopular item"; for (int i = 0; i < count(); ++i) { tmpItem = this->item(i); extract(tmpItem->data(Qt::UserRole).toString(), refCnt); if (refCnt < minRefCnt) { refCnt = minRefCnt; unpopularItem = tmpItem; } } KILE_DEBUG_MAIN << " minRefCnt is " << minRefCnt; delete unpopularItem; } if(found) { KILE_DEBUG_MAIN << "item is already in the iconview"; int refCnt; extract(tmpItem->data(Qt::UserRole).toString(), refCnt); QString key = tmpItem->data(Qt::UserRole).toString(); key.replace(reCnt, QString::number(refCnt + 1)); tmpItem->setData(Qt::UserRole, key); tmpItem->setToolTip(getToolTip(key)); } else { tmpItem = new QListWidgetItem(this); tmpItem->setIcon(item->icon()); QString key = item->data(Qt::UserRole).toString(); tmpItem->setData(Qt::UserRole, key); tmpItem->setToolTip(getToolTip(key)); } } }