diff --git a/interfaces/idocumentcontroller.h b/interfaces/idocumentcontroller.h index d085a62bbd..d036afac93 100644 --- a/interfaces/idocumentcontroller.h +++ b/interfaces/idocumentcontroller.h @@ -1,178 +1,180 @@ /*************************************************************************** * Copyright 2007 Alexander Dymo * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef IDOCUMENTCONTROLLER_H #define IDOCUMENTCONTROLLER_H #include +#include #include #include #include #include "interfacesexport.h" #include "idocument.h" namespace KDevelop { class ICore; class KDEVPLATFORMINTERFACES_EXPORT IDocumentFactory { public: virtual ~IDocumentFactory() {} virtual IDocument* create(const KUrl&, ICore* ) = 0; }; /** * * Allows to access the open documents and also open new ones * * @class IDocumentController */ class KDEVPLATFORMINTERFACES_EXPORT IDocumentController: public QObject { Q_OBJECT public: enum DocumentActivation { DefaultMode = 0, /**Activate document and create a view if no other flags passed.*/ DoNotActivate = 1, /**Don't activate the Document.*/ DoNotCreateView = 2, /**Don't create and show the view for the Document.*/ DoNotForceCurrentView = 4 /**If the document is open in another existing view, switch to that one instead of opening it in the current one*/ }; Q_DECLARE_FLAGS(DocumentActivationParams, DocumentActivation) IDocumentController(QObject *parent); /**Call this before a call to @ref editDocument to set the encoding of the document to be opened. @param encoding The encoding to open as.*/ Q_SCRIPTABLE virtual void setEncoding( const QString &encoding ) = 0; Q_SCRIPTABLE virtual QString encoding() const = 0; /**Finds the first document object corresponding to a given url. @param url The Url of the document. @return The corresponding document, or null if not found.*/ Q_SCRIPTABLE virtual KDevelop::IDocument* documentForUrl( const KUrl & url ) const = 0; /**@return The list of open documents*/ Q_SCRIPTABLE virtual QList openDocuments() const = 0; /**Refers to the document currently active or focused. @return The active document.*/ Q_SCRIPTABLE virtual KDevelop::IDocument* activeDocument() const = 0; Q_SCRIPTABLE virtual void activateDocument( KDevelop::IDocument * document, const KTextEditor::Range& range = KTextEditor::Range::invalid() ) = 0; virtual void registerDocumentForMimetype( const QString&, KDevelop::IDocumentFactory* ) = 0; Q_SCRIPTABLE virtual bool saveAllDocuments(KDevelop::IDocument::DocumentSaveMode mode = KDevelop::IDocument::Default) = 0; + Q_SCRIPTABLE virtual bool saveSomeDocuments(const QList& list, KDevelop::IDocument::DocumentSaveMode mode = KDevelop::IDocument::Default) = 0; /** Opens a text document containing the @p data text. */ Q_SCRIPTABLE virtual KDevelop::IDocument* openDocumentFromText( const QString& data ) = 0; virtual void notifyDocumentClosed(IDocument* doc) = 0; virtual IDocumentFactory* factory(const QString& mime) const = 0; Q_SCRIPTABLE virtual KTextEditor::Document* globalTextEditorInstance()=0; public Q_SLOTS: /**Opens a new or existing document. @param url The full Url of the document to open. @param range The location information, if applicable. @param activate Indicates whether to fully activate the document.*/ KDevelop::IDocument* openDocument( const KUrl &url, const KTextEditor::Cursor& cursor, DocumentActivationParams activationParams = 0, const QString& encoding = ""); /**Opens a new or existing document. @param url The full Url of the document to open. @param range The range of text to select, if applicable. @param activate Indicates whether to fully activate the document.*/ virtual KDevelop::IDocument* openDocument( const KUrl &url, const KTextEditor::Range& range = KTextEditor::Range::invalid(), DocumentActivationParams activationParams = 0, const QString& encoding = "") = 0; /** Opens a document from the IDocument instance. @param doc The IDocument to add @param range The location information, if applicable. @param activationParams Indicates whether to fully activate the document.*/ virtual Q_SCRIPTABLE bool openDocument(IDocument* doc, const KTextEditor::Range& range = KTextEditor::Range::invalid(), DocumentActivationParams activationParams = 0) = 0; /**Opens a new or existing document. @param url The full Url of the document to open. @param prefName The name of the preferred KPart to open that document,*/ virtual KDevelop::IDocument* openDocument( const KUrl &url, const QString& prefname ) = 0; virtual void closeAllDocuments() = 0; Q_SIGNALS: /**Emitted when the document has been activated.*/ void documentActivated( KDevelop::IDocument* document ); ///Emitted whenever the active cursor jumps from one document+cursor to another, caused by a call to openDocument(..) ///This is also emitted when a document is only activated, then previousDocument is zero void documentJumpPerformed( KDevelop::IDocument* newDocument, KTextEditor::Cursor newCursor, KDevelop::IDocument* previousDocument, KTextEditor::Cursor previousCursor); /**Emitted when a document has been saved.*/ void documentSaved( KDevelop::IDocument* document ); /**Emitted when a document has been opened. The document may not be loaded from disk/network at this point. Note, no views exist for the document at the time this signal is emitted.*/ void documentOpened( KDevelop::IDocument* document ); /**Emitted when a document has been loaded. Note, no views exist for the document at the time this signal is emitted.*/ void documentLoaded( KDevelop::IDocument* document ); /**Emitted when a text document has been loaded, and the text document created. Note, no views exist for the document at the time this signal is emitted.*/ void textDocumentCreated( KDevelop::IDocument* document ); /**Emitted when a document has been closed.*/ void documentClosed( KDevelop::IDocument* document ); /**This is emitted when the document state(the relationship * between the file in the editor and the file stored on disk) changes.*/ void documentStateChanged( KDevelop::IDocument* document ); /**This is emitted when the document content changed.*/ void documentContentChanged( KDevelop::IDocument* document ); /**Emitted when a document has been loaded, but before documentLoaded(..) is emitted. * this allows parts of kdevplatform to prepare data-structures that can be used by other parts * during documentLoaded(..).*/ void documentLoadedPrepare( KDevelop::IDocument* document ); /**Emitted when a document url has changed.*/ void documentUrlChanged( KDevelop::IDocument* document ); friend class IDocument; }; Q_DECLARE_OPERATORS_FOR_FLAGS(IDocumentController::DocumentActivationParams) } #endif diff --git a/plugins/grepview/CMakeLists.txt b/plugins/grepview/CMakeLists.txt index 8704d97dfb..6c9602f14c 100644 --- a/plugins/grepview/CMakeLists.txt +++ b/plugins/grepview/CMakeLists.txt @@ -1,45 +1,44 @@ project(grepview) add_definitions( -DKDE_DEFAULT_DEBUG_AREA=9001 ) ########### next target ############### set(kdevgrepview_PART_SRCS grepviewplugin.cpp grepdialog.cpp grepoutputmodel.cpp grepoutputdelegate.cpp grepjob.cpp grepfindthread.cpp grepoutputview.cpp ) set(kdevgrepview_PART_UI grepwidget.ui grepoutputview.ui ) kde4_add_ui_files(kdevgrepview_PART_SRCS ${kdevgrepview_PART_UI}) kde4_add_plugin(kdevgrepview ${kdevgrepview_PART_SRCS}) target_link_libraries(kdevgrepview ${KDE4_KDECORE_LIBS} ${KDE4_KDEUI_LIBS} ${KDE4_KPARTS_LIBS} ${KDE4_KTEXTEDITOR_LIBS} ${KDEVPLATFORM_INTERFACES_LIBRARIES} ${KDEVPLATFORM_OUTPUTVIEW_LIBRARIES} ${KDEVPLATFORM_PROJECT_LIBRARIES} ${KDEVPLATFORM_UTIL_LIBRARIES} ${KDEVPLATFORM_LANGUAGE_LIBRARIES} - ${KDEVPLATFORM_SHELL_LIBRARIES} ) install(TARGETS kdevgrepview DESTINATION ${PLUGIN_INSTALL_DIR} ) ########### install files ############### install( FILES kdevgrepview.desktop DESTINATION ${SERVICES_INSTALL_DIR} ) install( FILES kdevgrepview.rc DESTINATION ${DATA_INSTALL_DIR}/kdevgrepview ) add_subdirectory(tests) diff --git a/plugins/grepview/grepdialog.cpp b/plugins/grepview/grepdialog.cpp index 1891b5b14d..e6902f0ee6 100644 --- a/plugins/grepview/grepdialog.cpp +++ b/plugins/grepview/grepdialog.cpp @@ -1,392 +1,383 @@ /*************************************************************************** * Copyright 1999-2001 Bernd Gehrmann and the KDevelop Team * * bernd@kdevelop.org * * Copyright 2007 Dukju Ahn * * * * 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 "grepdialog.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 "grepviewplugin.h" #include "grepjob.h" #include "grepoutputview.h" #include "grepfindthread.h" using namespace KDevelop; namespace { static int const MAX_LAST_SEARCH_ITEMS_COUNT = 15; const QStringList template_desc = QStringList() << "verbatim" << "word" << "assignment" << "->MEMBER(" << "class::MEMBER(" << "OBJECT->member("; const QStringList template_str = QStringList() << "%s" << "\\b%s\\b" << "\\b%s\\b\\s*=[^=]" << "\\->\\s*\\b%s\\b\\s*\\(" << "([a-z0-9_$]+)\\s*::\\s*\\b%s\\b\\s*\\(" << "\\b%s\\b\\s*\\->\\s*([a-z0-9_$]+)\\s*\\("; const QStringList repl_template = QStringList() << "%s" << "%s" << "%s = " << "->%s(" << "\\1::%s(" << "%s->\\1("; const QStringList filepatterns = QStringList() << "*.h,*.hxx,*.hpp,*.hh,*.h++,*.H,*.tlh,*.cpp,*.cc,*.C,*.c++,*.cxx,*.ocl,*.inl,*.idl,*.c,*.m,*.mm,*.M" << "*.cpp,*.cc,*.C,*.c++,*.cxx,*.ocl,*.inl,*.c,*.m,*.mm,*.M" << "*.h,*.hxx,*.hpp,*.hh,*.h++,*.H,*.tlh,*.idl" << "*.adb" << "*.cs" << "*.f" << "*.html,*.htm" << "*.hs" << "*.java" << "*.js" << "*.php,*.php3,*.php4" << "*.pl" << "*.pp,*.pas" << "*.py" << "*.js,*.css,*.yml,*.rb,*.rhtml,*.html.erb,*.rjs,*.js.rjs,*.rxml,*.xml.builder" << "CMakeLists.txt,*.cmake" << "*"; const QStringList excludepatterns = QStringList() << "/CVS/,/SCCS/,/.svn/,/_darcs/,/build/,/.git/" << ""; } const KDialog::ButtonCode GrepDialog::SearchButton = KDialog::User1; const KDialog::ButtonCode GrepDialog::ReplaceButton = KDialog::User2; GrepDialog::GrepDialog( GrepViewPlugin * plugin, QWidget *parent, bool setLastUsed ) : KDialog(parent), Ui::GrepWidget(), m_plugin( plugin ) { setAttribute(Qt::WA_DeleteOnClose); setButtons( SearchButton | ReplaceButton | KDialog::Cancel ); setButtonText( SearchButton, i18n("Search") ); setButtonText( ReplaceButton, i18n("Replace") ); setCaption( i18n("Find/Replace In Files") ); setDefaultButton( SearchButton ); setupUi(mainWidget()); KConfigGroup cg = KGlobal::config()->group( "GrepDialog" ); // add default values when the most recent ones should not be set if(!setLastUsed) { patternCombo->addItem( "" ); replacementCombo->addItem( "" ); } patternCombo->addItems( cg.readEntry("LastSearchItems", QStringList()) ); patternCombo->setInsertPolicy(QComboBox::InsertAtTop); templateTypeCombo->addItems(template_desc); templateTypeCombo->setCurrentIndex( cg.readEntry("LastUsedTemplateIndex", 0) ); templateEdit->setText( cg.readEntry("LastUsedTemplateString", template_str[0]) ); replacementTemplateEdit->setText( cg.readEntry("LastUsedReplacementTemplateString", repl_template[0]) ); replacementCombo->addItems( cg.readEntry("LastReplacementItems", QStringList()) ); replacementCombo->setInsertPolicy(QComboBox::InsertAtTop); regexCheck->setChecked(cg.readEntry("regexp", false )); caseSensitiveCheck->setChecked(cg.readEntry("case_sens", true)); setDirectory( QDir::homePath() ); directoryRequester->setMode( KFile::Directory | KFile::ExistingOnly | KFile::LocalOnly ); syncButton->setIcon(KIcon("dirsync")); recursiveCheck->setChecked(cg.readEntry("recursive", true)); limitToProjectCheck->setChecked(cg.readEntry("search_project_files", true)); filesCombo->addItems(cg.readEntry("file_patterns", filepatterns)); excludeCombo->addItems(cg.readEntry("exclude_patterns", excludepatterns) ); connect(this, SIGNAL(buttonClicked(KDialog::ButtonCode)), this, SLOT(performAction(KDialog::ButtonCode))); connect(syncButton, SIGNAL(clicked()), this, SLOT(syncButtonClicked())); connect(templateTypeCombo, SIGNAL(activated(int)), this, SLOT(templateTypeComboActivated(int))); connect(patternCombo, SIGNAL(editTextChanged(const QString&)), this, SLOT(patternComboEditTextChanged( const QString& ))); patternComboEditTextChanged( patternCombo->currentText() ); patternCombo->setFocus(); connect(directoryRequester, SIGNAL(textChanged(const QString&)), this, SLOT(directoryChanged(const QString&))); } void GrepDialog::directoryChanged(const QString& dir) { setEnableProjectBox(false); KUrl currentUrl = dir; if( !currentUrl.isValid() ) return; IProject *proj = ICore::self()->projectController()->findProjectForUrl( currentUrl ); if( proj && proj->folder().isLocalFile() ) { setEnableProjectBox(! proj->files().isEmpty() ); } } // Returns the contents of a QComboBox as a QStringList static QStringList qCombo2StringList( QComboBox* combo, bool allowEmpty = false ) { QStringList list; if (!combo) { return list; } int skippedItem = -1; if (!combo->currentText().isEmpty() || allowEmpty) { list << combo->currentText(); } if (combo->currentIndex() != -1 && !combo->itemText(combo->currentIndex()).isEmpty()) { skippedItem = combo->currentIndex(); } for (int i = 0; i < std::min(MAX_LAST_SEARCH_ITEMS_COUNT, combo->count()); ++i) { if (i != skippedItem && !combo->itemText(i).isEmpty()) { list << combo->itemText(i); } } return list; } GrepDialog::~GrepDialog() { KConfigGroup cg = KGlobal::config()->group( "GrepDialog" ); // memorize the last patterns and paths cg.writeEntry("LastSearchItems", qCombo2StringList(patternCombo)); cg.writeEntry("LastReplacementItems", qCombo2StringList(replacementCombo, true)); cg.writeEntry("regexp", regexCheck->isChecked()); cg.writeEntry("recursive", recursiveCheck->isChecked()); cg.writeEntry("search_project_files", limitToProjectCheck->isChecked()); cg.writeEntry("case_sens", caseSensitiveCheck->isChecked()); cg.writeEntry("exclude_patterns", qCombo2StringList(excludeCombo)); cg.writeEntry("file_patterns", qCombo2StringList(filesCombo)); cg.writeEntry("LastUsedTemplateIndex", templateTypeCombo->currentIndex()); cg.writeEntry("LastUsedTemplateString", templateEdit->text()); cg.writeEntry("LastUsedReplacementTemplateString", replacementTemplateEdit->text()); cg.sync(); } void GrepDialog::templateTypeComboActivated(int index) { templateEdit->setText(template_str[index]); replacementTemplateEdit->setText(repl_template[index]); } void GrepDialog::syncButtonClicked( ) { IDocument *doc = m_plugin->core()->documentController()->activeDocument(); - kDebug(9001) << doc; if ( doc ) { KUrl url = doc->url(); if ( url.isLocalFile() ) { setDirectory( url.upUrl().toLocalFile() ); } } } void GrepDialog::setEnableProjectBox(bool enable) { limitToProjectCheck->setEnabled(enable); if (!enable) limitToProjectCheck->setChecked(false); } void GrepDialog::setPattern(const QString &pattern) { patternCombo->setEditText(pattern); } void GrepDialog::setDirectory(const QString &dir) { directoryRequester->lineEdit()->setText(dir); directoryRequester->fileDialog()->setUrl( KUrl( dir ) ); directoryRequester->completionObject()->setDir( dir ); } QString GrepDialog::patternString() const { return patternCombo->currentText(); } QString GrepDialog::templateString() const { return templateEdit->text().isEmpty() ? "%s" : templateEdit->text(); } QString GrepDialog::replacementTemplateString() const { return replacementTemplateEdit->text(); } QString GrepDialog::replacementString() const { return replacementCombo->currentText(); } QString GrepDialog::filesString() const { return filesCombo->currentText(); } QString GrepDialog::excludeString() const { return excludeCombo->currentText(); } KUrl GrepDialog::directory() const { return directoryRequester->url(); } bool GrepDialog::useProjectFilesFlag() const { return limitToProjectCheck->isChecked(); } bool GrepDialog::regexpFlag() const { return regexCheck->isChecked(); } bool GrepDialog::recursiveFlag() const { return recursiveCheck->isChecked(); } bool GrepDialog::caseSensitiveFlag() const { return caseSensitiveCheck->isChecked(); } void GrepDialog::patternComboEditTextChanged( const QString& text) { enableButton( SearchButton, !text.isEmpty() ); enableButton( ReplaceButton, !text.isEmpty() ); } void GrepDialog::performAction(KDialog::ButtonCode button) { // a click on cancel trigger this signal too if( button != SearchButton && button != ReplaceButton ) return; // search for unsaved documents QList unsavedFiles; QStringList include = GrepFindFilesThread::parseInclude(filesString()); QStringList exclude = GrepFindFilesThread::parseExclude(excludeString()); foreach(IDocument* doc, ICore::self()->documentController()->openDocuments()) { KUrl docUrl = doc->url(); if(doc->state() != IDocument::Clean && directory().isParentOf(docUrl) && QDir::match(include, docUrl.fileName()) && !QDir::match(exclude, docUrl.toLocalFile())) { unsavedFiles << doc; } } - if(!unsavedFiles.empty()) + if(!ICore::self()->documentController()->saveSomeDocuments(unsavedFiles)) { - // show dialog - KSaveSelectDialog dlg(unsavedFiles, this); - if(dlg.exec() == QDialog::Rejected) - { - close(); - return; - } + close(); + return; } GrepJob* job = m_plugin->grepJob(); GrepOutputViewFactory *m_factory = new GrepOutputViewFactory(); GrepOutputView *toolView = (GrepOutputView*)ICore::self()->uiController()-> findToolView(i18n("Replace in files"), m_factory, IUiController::CreateAndRaise); toolView->renewModel(); toolView->enableReplace(button == ReplaceButton); toolView->setPlugin(m_plugin); connect(job, SIGNAL(showErrorMessage(QString, int)), toolView, SLOT(showErrorMessage(QString))); connect(job, SIGNAL(showMessage(KDevelop::IStatus*, QString, int)), toolView, SLOT(showMessage(KDevelop::IStatus*, QString))); connect(toolView, SIGNAL(outputViewIsClosed()), job, SLOT(kill())); job->setOutputModel(toolView->model()); job->setPatternString(patternString()); job->setReplacementTemplateString(replacementTemplateString()); job->setTemplateString(templateString()); job->setReplaceString(replacementString()); job->setFilesString(filesString()); job->setExcludeString(excludeString()); job->setDirectory(directory()); job->setProjectFilesFlag( useProjectFilesFlag() ); job->setRegexpFlag( regexpFlag() ); job->setRecursive( recursiveFlag() ); job->setCaseSensitive( caseSensitiveFlag() ); job->setReplaceFlag( button == ReplaceButton ); - kDebug() << "registering job"; ICore::self()->runController()->registerJob(job); m_plugin->rememberSearchDirectory(directory().toLocalFile(KUrl::AddTrailingSlash)); close(); } #include "grepdialog.moc" diff --git a/plugins/grepview/grepjob.cpp b/plugins/grepview/grepjob.cpp index faf83fe6c6..5088abdb4c 100644 --- a/plugins/grepview/grepjob.cpp +++ b/plugins/grepview/grepjob.cpp @@ -1,367 +1,365 @@ /*************************************************************************** * Copyright 1999-2001 by Bernd Gehrmann * * bernd@kdevelop.org * * Copyright 2007 Dukju Ahn * * Copyright 2008 by Hamish Rodda * * rodda@kde.org * * Copyright 2010 Silvère Lestang * * * * 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 "grepjob.h" #include "grepoutputmodel.h" -#include "grepoutputview.h" #include #include -#include #include #include #include #include #include #include #include #include #include using namespace KDevelop; GrepOutputItem::List grepFile(const QString &filename, const QRegExp &re, const QString &repl, bool replace) { GrepOutputItem::List res; QFile file(filename); if(!file.open(QIODevice::ReadOnly)) return res; int lineno = 0; // detect encoding (unicode files can be feed forever, stops when confidence reachs 99% KEncodingProber prober; while(!file.atEnd() && prober.state() == KEncodingProber::Probing && prober.confidence() < 0.99) { prober.feed(file.read(0xFF)); } kDebug() << prober.encoding() << prober.confidence() << prober.state() << file.pos() << file.size(); // reads file with detected encoding file.seek(0); QTextStream stream(&file); stream.setCodec(prober.encodingName()); while( !stream.atEnd() ) { QString data = stream.readLine(); // remove line terminators (in order to not match them) for(int pos = data.length()-1; pos >= 0 && (data[pos] == '\r' || data[pos] == '\n'); pos--) { data.chop(1); } int offset = 0; // allow empty string matching result in an infinite loop ! while( re.indexIn(data, offset)!=-1 && re.cap(0).length() > 0 ) { int start = re.pos(0); int end = start + re.cap(0).length(); DocumentChangePointer change = DocumentChangePointer(new DocumentChange( IndexedString(filename), SimpleRange(lineno, start, lineno, end), re.cap(0), re.cap(0).replace(re, repl))); res << GrepOutputItem(change, data, replace); offset = end; } lineno++; } file.close(); return res; } GrepJob::GrepJob( QObject* parent ) : KJob( parent ), m_workState(WorkIdle) { setCapabilities(Killable); KDevelop::ICore::self()->uiController()->registerStatus(this); connect(this, SIGNAL(result(KJob *)), this, SLOT(testFinishState(KJob *))); } QString GrepJob::statusName() const { return i18n("Find in Files"); } QString substitudePattern(const QString& pattern, const QString& searchString) { QString subst = searchString; QString result; bool expectEscape = false; foreach(const QChar &ch, pattern) { if(expectEscape) { expectEscape = false; if(ch == '%') result.append('%'); else if(ch == 's') result.append(subst); else result.append('%').append(ch); } else if(ch == '%') expectEscape = true; else result.append(ch); } // kDebug() << "Pattern substituded:" << pattern << "+" << searchString << "=" << result; return result; } void GrepJob::slotFindFinished() { if(m_findThread && !m_findThread->triesToAbort()) { m_fileList = m_findThread->files(); delete m_findThread; } else { m_fileList.clear(); emit hideProgress(this); emit clearMessage(this); emit showErrorMessage(i18n("Search aborted"), 5000); emitResult(); return; } if(m_fileList.isEmpty()) { m_workState = WorkIdle; emit hideProgress(this); emit clearMessage(this); emit showErrorMessage(i18n("No files found matching the wildcard patterns"), 5000); //model()->slotFailed(); emitResult(); return; } if(!m_regexpFlag) { m_patternString = QRegExp::escape(m_patternString); } if(m_replaceFlag && m_regexpFlag && QRegExp(m_patternString).captureCount() > 0) { emit showErrorMessage(i18n("Captures are not allowed in pattern string"), 5000); return; } QString pattern = substitudePattern(m_templateString, m_patternString); m_regExp.setPattern(pattern); m_regExp.setPatternSyntax(QRegExp::RegExp2); m_regExp.setCaseSensitivity( m_caseSensitiveFlag ? Qt::CaseSensitive : Qt::CaseInsensitive ); if(pattern == QRegExp::escape(pattern)) { // enable wildcard mode when possible // if pattern has already been escaped (raw text serch) a second escape will result in a different string anyway m_regExp.setPatternSyntax(QRegExp::Wildcard); } // backslashes can be sprecial chars QString replacement = (m_regExp.patternSyntax() == QRegExp::Wildcard) ? m_replaceString : m_replaceString.replace("\\", "\\\\"); m_finalReplacement = substitudePattern(m_replacementTemplateString, replacement); m_outputModel->setRegExp(m_regExp); if(m_replaceFlag) { emit showMessage(this, i18np("Replace %2 by %3 in one file", "Replace %2 by %3 in %1 files", m_fileList.length(), Qt::escape(m_regExp.pattern()), Qt::escape(m_finalReplacement))); } else { emit showMessage(this, i18np("Searching for %2 in one file", "Searching for %2 in %1 files", m_fileList.length(), Qt::escape(m_regExp.pattern()))); } m_workState = WorkGrep; QMetaObject::invokeMethod( this, "slotWork", Qt::QueuedConnection); } void GrepJob::slotWork() { switch(m_workState) { case WorkIdle: m_workState = WorkCollectFiles; m_fileIndex = 0; emit showProgress(this, 0,0,0); QMetaObject::invokeMethod(this, "slotWork", Qt::QueuedConnection); break; case WorkCollectFiles: m_findThread = new GrepFindFilesThread(this, m_directory, m_recursiveFlag, m_filesString, m_excludeString, m_useProjectFilesFlag); emit showMessage(this, i18n("Collecting files...")); connect(m_findThread, SIGNAL(finished()), this, SLOT(slotFindFinished())); m_findThread->start(); break; case WorkGrep: if(m_fileIndex < m_fileList.length()) { emit showProgress(this, 0, m_fileList.length(), m_fileIndex); if(m_fileIndex < m_fileList.length()) { QString file = m_fileList[m_fileIndex].toLocalFile(); GrepOutputItem::List items = grepFile(file, m_regExp, m_finalReplacement, m_replaceFlag); if(!items.isEmpty()) { m_findSomething = true; emit foundMatches(file, items); } m_fileIndex++; } QMetaObject::invokeMethod(this, "slotWork", Qt::QueuedConnection); } else { emit hideProgress(this); emit clearMessage(this); m_workState = WorkIdle; //model()->slotCompleted(); emitResult(); } break; case WorkCancelled: emit hideProgress(this); emit clearMessage(this); emit showErrorMessage(i18n("Search aborted"), 5000); emitResult(); break; } } void GrepJob::start() { if(m_workState!=WorkIdle) return; m_fileList.clear(); m_workState = WorkIdle; m_fileIndex = 0; m_findSomething = false; m_outputModel->clear(); qRegisterMetaType(); connect(this, SIGNAL(foundMatches(QString, GrepOutputItem::List)), m_outputModel, SLOT(appendOutputs(QString, GrepOutputItem::List)), Qt::QueuedConnection); QMetaObject::invokeMethod(this, "slotWork", Qt::QueuedConnection); } bool GrepJob::doKill() { if(m_workState!=WorkIdle && !m_findThread.isNull()) { m_workState = WorkIdle; m_findThread->tryAbort(); return false; } else { m_workState = WorkCancelled; } return true; } void GrepJob::testFinishState(KJob *job) { if(!job->error()) { if(!m_findSomething) emit showMessage(this, i18n("No results found")); } } void GrepJob::setOutputModel(GrepOutputModel* model) { m_outputModel = model; } void GrepJob::setTemplateString(const QString& templateString) { m_templateString = templateString; } void GrepJob::setReplacementTemplateString(const QString &replTmplString) { m_replacementTemplateString = replTmplString; } void GrepJob::setFilesString(const QString& filesString) { m_filesString = filesString; } void GrepJob::setExcludeString(const QString& excludeString) { m_excludeString = excludeString; } void GrepJob::setDirectory(const KUrl& directory) { m_directory = directory; } void GrepJob::setCaseSensitive(bool caseSensitive) { m_caseSensitiveFlag = caseSensitive; } void GrepJob::setRecursive(bool recursive) { m_recursiveFlag = recursive; } void GrepJob::setRegexpFlag(bool regexpFlag) { m_regexpFlag = regexpFlag; } void GrepJob::setProjectFilesFlag(bool projectFilesFlag) { m_useProjectFilesFlag = projectFilesFlag; } void GrepJob::setReplaceFlag(bool replaceFlag) { m_replaceFlag = replaceFlag; } void GrepJob::setReplaceString(const QString& replaceString) { m_replaceString = replaceString; } void GrepJob::setPatternString(const QString& patternString) { m_patternString = patternString; setObjectName(i18n("Grep: %1", m_patternString)); } #include "grepjob.moc" diff --git a/plugins/grepview/grepjob.h b/plugins/grepview/grepjob.h index 0dec80079e..032949bb7a 100644 --- a/plugins/grepview/grepjob.h +++ b/plugins/grepview/grepjob.h @@ -1,127 +1,127 @@ /*************************************************************************** * Copyright 1999-2001 by Bernd Gehrmann * * bernd@kdevelop.org * * Copyright 2008 by Hamish Rodda * * rodda@kde.org * * Copyright 2010 Silvère Lestang * * * * 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 GREPJOB_H #define GREPJOB_H -#include #include #include #include #include #include #include "grepfindthread.h" #include "grepoutputmodel.h" namespace KDevelop { class IProject; class ProcessLineMaker; } +class QRegExp; class GrepViewPlugin; class FindReplaceTest; //FIXME: this is useful only for tests class GrepJob : public KJob, public KDevelop::IStatus { Q_OBJECT Q_INTERFACES( KDevelop::IStatus ) friend class GrepViewPlugin; friend class FindReplaceTest; private: ///Job can only be instanciated by plugin GrepJob( QObject *parent = 0 ); public: void setOutputModel(GrepOutputModel * model); void setPatternString(const QString& patternString); void setTemplateString(const QString &templateString); void setReplacementTemplateString(const QString &replTmplString); void setReplaceString(const QString &replaceString); void setFilesString(const QString &filesString); void setExcludeString(const QString &excludeString); void setDirectory(const KUrl &directory); void setRecursive(bool recursive); void setRegexpFlag(bool regexpFlag); void setCaseSensitive(bool caseSensitive); void setProjectFilesFlag(bool projectFilesFlag); void setReplaceFlag(bool replaceFlag); virtual void start(); virtual QString statusName() const; protected: virtual bool doKill(); // GrepOutputModel* model() const; private Q_SLOTS: void slotFindFinished(); void testFinishState(KJob *job); Q_SIGNALS: void clearMessage( KDevelop::IStatus* ); void showMessage( KDevelop::IStatus*, const QString & message, int timeout = 0); void showErrorMessage(const QString & message, int timeout = 0); void hideProgress( KDevelop::IStatus* ); void showProgress( KDevelop::IStatus*, int minimum, int maximum, int value); void foundMatches( const QString& filename, const GrepOutputItem::List& matches); private: Q_INVOKABLE void slotWork(); QString m_patternString; QRegExp m_regExp; QString m_regExpSimple; GrepOutputModel *m_outputModel; enum { WorkCollectFiles, WorkGrep, WorkIdle, WorkCancelled } m_workState; KUrl::List m_fileList; int m_fileIndex; QPointer m_findThread; QString m_templateString; QString m_replacementTemplateString; QString m_replaceString; QString m_finalReplacement; // computed with m_replaceString and m_replacementTemplateString QString m_filesString; QString m_excludeString; KUrl m_directory; bool m_useProjectFilesFlag; bool m_regexpFlag; bool m_recursiveFlag; bool m_caseSensitiveFlag; bool m_replaceFlag; bool m_findSomething; }; //FIXME: this function is used externally only for tests, find a way to keep it // static for a regular compilation GrepOutputItem::List grepFile(const QString &filename, const QRegExp &re, const QString &repl, bool replace); #endif diff --git a/plugins/grepview/grepoutputdelegate.cpp b/plugins/grepview/grepoutputdelegate.cpp index 649aa183ad..27532a5ba6 100644 --- a/plugins/grepview/grepoutputdelegate.cpp +++ b/plugins/grepview/grepoutputdelegate.cpp @@ -1,115 +1,113 @@ /*************************************************************************** * This file is part of KDevelop * * Copyright (C) 2007 Andreas Pakulat * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "grepoutputdelegate.h" #include "grepoutputmodel.h" #include #include #include #include #include #include #include -#include - GrepOutputDelegate* GrepOutputDelegate::m_self = 0; GrepOutputDelegate* GrepOutputDelegate::self() { Q_ASSERT(m_self); return m_self; } GrepOutputDelegate::GrepOutputDelegate( QObject* parent ) : QStyledItemDelegate(parent) { Q_ASSERT(!m_self); m_self = this; } GrepOutputDelegate::~GrepOutputDelegate() { m_self = 0; } void GrepOutputDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const { // there is no function in QString to left-trim. A call to remove this this regexp does the job static const QRegExp leftspaces("^\\s*", Qt::CaseSensitive, QRegExp::RegExp); // rich text component const GrepOutputModel *model = dynamic_cast(index.model()); const GrepOutputItem *item = dynamic_cast(model->itemFromIndex(index)); if(item && item->isText()) { QStyleOptionViewItemV4 options = option; initStyleOption(&options, index); // building item representation const KDevelop::SimpleRange rng = item->change()->m_range; QTextDocument doc; QTextCursor cur(&doc); QPalette::ColorGroup cg = options.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled; QPalette::ColorRole cr = options.state & QStyle::State_Selected ? QPalette::HighlightedText : QPalette::Text; QTextCharFormat fmt = cur.charFormat(); fmt.setFont(options.font); // the line number appears grayed fmt.setForeground(options.palette.brush(QPalette::Disabled, cr)); cur.insertText(QString("%1: ").arg(item->lineNumber()), fmt); // switch to normal color fmt.setForeground(options.palette.brush(cg, cr)); cur.insertText(item->text().left(rng.start.column).remove(leftspaces), fmt); fmt.setFontWeight(QFont::Bold); cur.insertText(item->text().mid(rng.start.column, rng.end.column - rng.start.column), fmt); fmt.setFontWeight(QFont::Normal); cur.insertText(item->text().right(item->text().length() - rng.end.column), fmt); painter->save(); options.text = QString(); // text will be drawn separately options.widget->style()->drawControl(QStyle::CE_ItemViewItem, &options, painter, options.widget); // set correct draw area QRect clip = options.widget->style()->subElementRect(QStyle::SE_ItemViewItemText, &options); QFontMetrics metrics(options.font); painter->translate(clip.topLeft() - QPoint(0, metrics.descent())); clip.setTopLeft(QPoint(0,0)); painter->setClipRect(clip); QAbstractTextDocumentLayout::PaintContext ctx; ctx.clip = clip; doc.documentLayout()->draw(painter, ctx); painter->restore(); } else { QStyledItemDelegate::paint(painter, option, index); } } diff --git a/plugins/grepview/grepoutputmodel.cpp b/plugins/grepview/grepoutputmodel.cpp index 84cb8dfbff..a6953d7bd7 100644 --- a/plugins/grepview/grepoutputmodel.cpp +++ b/plugins/grepview/grepoutputmodel.cpp @@ -1,343 +1,345 @@ /*************************************************************************** * Copyright 1999-2001 Bernd Gehrmann and the KDevelop Team * * bernd@kdevelop.org * * Copyright 2007 Dukju Ahn * * Copyright 2010 Silvère Lestang * * * * 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 "grepoutputmodel.h" #include "grepviewplugin.h" -#include -#include + #include #include #include + +#include +#include #include #include using namespace KDevelop; GrepOutputItem::GrepOutputItem(DocumentChangePointer change, const QString &text, bool replace) : QStandardItem(), m_change(change) { setText(text); setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); if(replace) { setCheckable(true); setCheckState(Qt::Checked); QString replacement = Qt::escape(text.left(change->m_range.start.column)) + // start of line "" + Qt::escape(change->m_newText) + "" + // replaced part Qt::escape(text.right(text.length() - change->m_range.end.column)); // rest of line setToolTip(replacement.trimmed()); } } GrepOutputItem::GrepOutputItem(const QString& filename, const QString& text, bool replace) : QStandardItem(), m_change(new DocumentChange(IndexedString(filename), SimpleRange::invalid(), QString(), QString())) { setText(text); setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); if(replace) { setCheckable(true); setTristate(true); setCheckState(Qt::Checked); } } int GrepOutputItem::lineNumber() const { // line starts at 0 for cursor but we want to start at 1 return m_change->m_range.start.line + 1; } QString GrepOutputItem::filename() const { return m_change->m_document.str(); } DocumentChangePointer GrepOutputItem::change() const { return m_change; } bool GrepOutputItem::isText() const { return m_change->m_range.isValid(); } void GrepOutputItem::propagateState() { for(int i = 0; i < rowCount(); i++) { GrepOutputItem *item = static_cast(child(i)); if(item->isEnabled()) { item->setCheckState(checkState()); item->propagateState(); } } } void GrepOutputItem::refreshState() { if(rowCount() > 0) { int checked = 0; int unchecked = 0; int enabled = 0; //only enabled items are relevants for(int i = 0; i < rowCount(); i++) { QStandardItem *item = child(i); if(item->isEnabled()) { enabled += 1; switch(child(i)->checkState()) { case Qt::Checked: checked += 1; break; case Qt::Unchecked: unchecked += 1; break; default: break; } } } if(enabled == 0) { setCheckState(Qt::Unchecked); setEnabled(false); } else if(checked == enabled) { setCheckState(Qt::Checked); } else if (unchecked == enabled) { setCheckState(Qt::Unchecked); } else { setCheckState(Qt::PartiallyChecked); } } if(GrepOutputItem *p = static_cast(parent())) { p->refreshState(); } } GrepOutputItem::~GrepOutputItem() {} /////////////////////////////////////////////////////////////// GrepOutputModel::GrepOutputModel( QObject *parent ) : QStandardItemModel( parent ), m_regExp(""), m_rootItem(0), m_fileCount(0), m_matchCount(0) { connect(this, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(updateCheckState(QStandardItem*))); } GrepOutputModel::~GrepOutputModel() {} void GrepOutputModel::clear() { QStandardItemModel::clear(); m_fileCount = 0; m_matchCount = 0; } void GrepOutputModel::setRegExp(const QRegExp& re) { m_regExp = re; } void GrepOutputModel::activate( const QModelIndex &idx ) { QStandardItem *stditem = itemFromIndex(idx); GrepOutputItem *grepitem = dynamic_cast(stditem); if( !grepitem || !grepitem->isText() ) return; KUrl url(grepitem->filename()); int line = grepitem->lineNumber() - 1; KTextEditor::Range range( line, 0, line+1, 0); // Try to find the actual text range we found during the grep IDocument* doc = ICore::self()->documentController()->documentForUrl( url ); if(!doc) doc = ICore::self()->documentController()->openDocument( url, range ); if(!doc) return; if (KTextEditor::Document* tdoc = doc->textDocument()) { QString text = tdoc->line(line); int index = m_regExp.indexIn(text); if (index!=-1) { range.setBothLines(line); range.start().setColumn(index); range.end().setColumn(index+m_regExp.matchedLength()); doc->setTextSelection( range ); } } ICore::self()->documentController()->activateDocument( doc, range ); } QModelIndex GrepOutputModel::previousItemIndex(const QModelIndex ¤tIdx) const { int row = currentIdx.row(); GrepOutputItem* current_item = dynamic_cast(itemFromIndex(currentIdx)); if(current_item->parent() != 0) //we do nothing if it's the root item { if(!current_item->isText()) // the item is a file { int item_row = current_item->row(); if(item_row > 0) { int idx_last_item = current_item->parent()->child(item_row - 1)->rowCount() - 1; return current_item->parent()->child(item_row - 1)->child(idx_last_item)->index(); } } else // the item is a match { if(row > 0) return current_item->parent()->child(row - 1)->index(); else // we return the index of the last item of the previous file { int parrent_row = current_item->parent()->row(); if(parrent_row > 0) { int idx_last_item = current_item->parent()->parent()->child(parrent_row - 1)->rowCount() - 1; return current_item->parent()->parent()->child(parrent_row - 1)->child(idx_last_item)->index(); } } } } return currentIdx; } QModelIndex GrepOutputModel::nextItemIndex(const QModelIndex ¤tIdx) const { int row = currentIdx.row(); GrepOutputItem* current_item = dynamic_cast(itemFromIndex(currentIdx)); if(current_item->parent() != 0) //we do nothing if it's the root item { if(!current_item->isText()) // the item is a file { int item_row = current_item->row(); if(item_row < current_item->parent()->rowCount()) { return current_item->parent()->child(item_row)->child(0)->index(); } } else // the item is a match { if(row < current_item->parent()->rowCount() - 1) return current_item->parent()->child(row + 1)->index(); else // we return the index of the first item of the next file { int parrent_row = current_item->parent()->row(); if(parrent_row < current_item->parent()->parent()->rowCount() - 1) { return current_item->parent()->parent()->child(parrent_row + 1)->child(0)->index(); } } } } return currentIdx; } void GrepOutputModel::appendOutputs( const QString &filename, const GrepOutputItem::List &items ) { if(items.isEmpty()) return; bool replace = items[0].isCheckable(); //FIXME : find a cleaner way to get this ! if(rowCount() == 0) { m_rootItem = new GrepOutputItem("", "", replace); appendRow(m_rootItem); } m_fileCount += 1; m_matchCount += items.length(); m_rootItem->setText(i18n("%1 matches in %2 files", m_matchCount, m_fileCount)); QString fnString = i18np("%2 (one match)", "%2 (%1 matches)", items.length(), filename); GrepOutputItem *fileItem = new GrepOutputItem(filename, fnString, replace); m_rootItem->appendRow(fileItem); //m_tracker.addUrl(KUrl(filename)); foreach( const GrepOutputItem& item, items ) { fileItem->appendRow(new GrepOutputItem(item)); } } void GrepOutputModel::updateCheckState(QStandardItem* item) { // if we don't disconnect the SIGNAL, the setCheckState will call it in loop disconnect(SIGNAL(itemChanged(QStandardItem*))); // try to update checkstate on non checkable items would make a checkbox appear if(item->isCheckable()) { GrepOutputItem *it = static_cast(item); it->propagateState(); it->refreshState(); } connect(this, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(updateCheckState(QStandardItem*))); } void GrepOutputModel::doReplacements() { DocumentChangeSet changeSet; changeSet.setFormatPolicy(DocumentChangeSet::NoAutoFormat); for(int fileRow = 0; fileRow < m_rootItem->rowCount(); fileRow++) { GrepOutputItem *file = static_cast(m_rootItem->child(fileRow)); for(int matchRow = 0; matchRow < file->rowCount(); matchRow++) { GrepOutputItem *match = static_cast(file->child(matchRow)); if(match->checkState() == Qt::Checked) { changeSet.addChange(match->change()); // this item cannot be checked anymore match->setCheckState(Qt::Unchecked); match->setEnabled(false); } } } DocumentChangeSet::ChangeResult result = changeSet.applyAllChanges(); //TODO : really display this if(!result.m_success) { DocumentChangePointer ch = result.m_reasonChange; emit showErrorMessage(i18n("Failed to replace %1 by %2 in %3:%4:%5").arg(Qt::escape(ch->m_oldText)).arg(Qt::escape(ch->m_newText)) .arg(ch->m_document.toUrl().toLocalFile()).arg(ch->m_range.start.line + 1).arg(ch->m_range.start.column + 1)); } } #include "grepoutputmodel.moc" diff --git a/plugins/grepview/grepoutputmodel.h b/plugins/grepview/grepoutputmodel.h index e1e4bc5cc8..cb3d1f068f 100644 --- a/plugins/grepview/grepoutputmodel.h +++ b/plugins/grepview/grepoutputmodel.h @@ -1,87 +1,88 @@ /*************************************************************************** * Copyright 1999-2001 Bernd Gehrmann and the KDevelop Team * * bernd@kdevelop.org * * Copyright 2007 Dukju Ahn * * Copyright 2010 Silvère Lestang * * * * 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 GREPOUTPUTMODEL_H #define GREPOUTPUTMODEL_H #include -#include #include + #include class QModelIndex; +class QRegExp; namespace KDevelop { class IStatus; } class GrepOutputItem : public QStandardItem { public: typedef QList List; GrepOutputItem(KDevelop::DocumentChangePointer change, const QString &text, bool replace); GrepOutputItem(const QString &filename, const QString &text, bool replace); ~GrepOutputItem(); QString filename() const ; int lineNumber() const ; KDevelop::DocumentChangePointer change() const ; bool isText() const ; /// Recursively apply check state to children void propagateState() ; /// Check children to determine current state void refreshState() ; private: KDevelop::DocumentChangePointer m_change; void showCollapsed(); void showExpanded(); }; Q_DECLARE_METATYPE(GrepOutputItem::List); class GrepOutputModel : public QStandardItemModel { Q_OBJECT public: explicit GrepOutputModel( QObject *parent = 0 ); ~GrepOutputModel(); void setRegExp(const QRegExp& re); void clear(); // resets file & match counts QModelIndex previousItemIndex(const QModelIndex ¤tIdx) const; QModelIndex nextItemIndex(const QModelIndex ¤tIdx) const; public Q_SLOTS: void appendOutputs( const QString &filename, const GrepOutputItem::List &lines ); void activate( const QModelIndex &idx ); void doReplacements(); Q_SIGNALS: void showErrorMessage(const QString & message, int timeout = 0); private: QRegExp m_regExp; GrepOutputItem *m_rootItem; int m_fileCount; int m_matchCount; private slots: void updateCheckState(QStandardItem*); }; #endif diff --git a/plugins/grepview/grepoutputview.cpp b/plugins/grepview/grepoutputview.cpp index d1c703d2a1..8b0335916c 100644 --- a/plugins/grepview/grepoutputview.cpp +++ b/plugins/grepview/grepoutputview.cpp @@ -1,165 +1,162 @@ /************************************************************************** * Copyright 2010 Silvère Lestang * * * * 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 "grepjob.h" #include "grepoutputview.h" #include "grepoutputmodel.h" #include "grepoutputdelegate.h" #include "ui_grepoutputview.h" -#include "grepdialog.h" #include "grepviewplugin.h" #include -#include #include using namespace KDevelop; GrepOutputViewFactory::GrepOutputViewFactory() {} QWidget* GrepOutputViewFactory::create(QWidget* parent) { return new GrepOutputView(parent); } Qt::DockWidgetArea GrepOutputViewFactory::defaultPosition() { return Qt::BottomDockWidgetArea; } QString GrepOutputViewFactory::id() const { return "org.kdevelop.GrepOutputView"; } GrepOutputView::GrepOutputView(QWidget* parent) : QWidget(parent) { Ui::GrepOutputView::setupUi(this); setWindowTitle(i18n("Replace output view")); setWindowIcon(SmallIcon("edit-find")); m_apply = new QAction(KIcon("dialog-ok-apply"), i18n("&Replace"), this); QAction *previous = new QAction(KIcon("go-previous"), i18n("&Previous"), this); QAction *next = new QAction(KIcon("go-next"), i18n("&Next"), this); QAction *separator = new QAction(this); separator->setSeparator(true); QAction *change_criteria = new QAction(KIcon("configure"), i18n("&Change criteria"), this); addAction(m_apply); addAction(previous); addAction(next); addAction(separator); addAction(change_criteria); resultsTreeView->setModel(new GrepOutputModel); resultsTreeView->setItemDelegate(GrepOutputDelegate::self()); resultsTreeView->setHeaderHidden(true); connect(m_apply, SIGNAL(triggered(bool)), this, SLOT(onApply())); connect(previous, SIGNAL(triggered(bool)), this, SLOT(selectPreviousItem())); connect(next, SIGNAL(triggered(bool)), this, SLOT(selectNextItem())); connect(change_criteria, SIGNAL(triggered(bool)), this, SLOT(showDialog())); } GrepOutputView::~GrepOutputView() { emit outputViewIsClosed(); } GrepOutputModel* GrepOutputView::renewModel() { GrepOutputModel* oldModel = model(); GrepOutputModel* newModel = new GrepOutputModel(resultsTreeView); resultsTreeView->setModel(newModel); connect(resultsTreeView, SIGNAL(activated(QModelIndex)), newModel, SLOT(activate(QModelIndex))); connect(newModel, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(expandRootElement(QModelIndex))); connect(newModel, SIGNAL(showErrorMessage(QString,int)), this, SLOT(showErrorMessage(QString))); oldModel->deleteLater(); return newModel; } GrepOutputModel* GrepOutputView::model() { return static_cast(resultsTreeView->model()); } void GrepOutputView::setPlugin(GrepViewPlugin* plugin) { m_plugin = plugin; } void GrepOutputView::setMessage(const QString& msg) { messageLabel->setText(msg); } void GrepOutputView::enableReplace(bool enable) { m_apply->setEnabled(enable); } void GrepOutputView::showErrorMessage( const QString& errorMessage ) { setStyleSheet("QLabel { color : red; }"); setMessage(errorMessage); } void GrepOutputView::showMessage( KDevelop::IStatus* , const QString& message ) { setStyleSheet(""); setMessage(message); } void GrepOutputView::onApply() { setEnabled(false); model()->doReplacements(); setEnabled(true); } void GrepOutputView::showDialog() { m_plugin->showDialog(true); } void GrepOutputView::expandRootElement(const QModelIndex& parent) { if(!parent.isValid()) { resultsTreeView->setExpanded(model()->index(0,0), true); } } void GrepOutputView::selectPreviousItem() { QModelIndex idx = resultsTreeView->currentIndex(); if(idx.isValid()) { QModelIndex prev_idx = model()->previousItemIndex(idx); resultsTreeView->setCurrentIndex(prev_idx); model()->activate(prev_idx); } } void GrepOutputView::selectNextItem() { QModelIndex idx = resultsTreeView->currentIndex(); if(idx.isValid()) { QModelIndex next_idx = model()->nextItemIndex(idx); resultsTreeView->setCurrentIndex(next_idx); model()->activate(next_idx); } } \ No newline at end of file diff --git a/plugins/grepview/grepoutputview.h b/plugins/grepview/grepoutputview.h index edb2f9c7b2..7f09ce8d4d 100644 --- a/plugins/grepview/grepoutputview.h +++ b/plugins/grepview/grepoutputview.h @@ -1,80 +1,76 @@ /************************************************************************** * Copyright 2010 Silvère Lestang * * * * 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 GREPOUTPUTVIEW_H #define GREPOUTPUTVIEW_H -#include -#include -#include - #include #include "ui_grepoutputview.h" namespace KDevelop { class IStatus; } class GrepViewPlugin; class GrepOutputModel; class GrepOutputDelegate; class GrepOutputViewFactory: public KDevelop::IToolViewFactory { public: GrepOutputViewFactory(); virtual QWidget* create(QWidget *parent = 0); virtual Qt::DockWidgetArea defaultPosition(); virtual QString id() const; }; class GrepOutputView : public QWidget, Ui::GrepOutputView { Q_OBJECT public: GrepOutputView(QWidget* parent); ~GrepOutputView(); GrepOutputModel* model(); /** * This causes the creation of a new model, the old one is deleted. * This is necessary because the previous job, if any, is not killed instantly and * sometimes continues to feed the model. * @return pointer to the new model */ GrepOutputModel* renewModel(); void setMessage(const QString& msg); void enableReplace(bool enable); void setPlugin(GrepViewPlugin *plugin); public Q_SLOTS: void showErrorMessage( const QString& errorMessage ); void showMessage( KDevelop::IStatus*, const QString& message ); Q_SIGNALS: void outputViewIsClosed(); private: QAction* m_apply; GrepViewPlugin *m_plugin; private slots: void selectPreviousItem(); void selectNextItem(); void onApply(); void showDialog(); void expandRootElement( const QModelIndex & parent ); }; #endif // GREPOUTPUTVIEW_H diff --git a/plugins/grepview/grepviewplugin.cpp b/plugins/grepview/grepviewplugin.cpp index f1f329c84a..623bfc438a 100644 --- a/plugins/grepview/grepviewplugin.cpp +++ b/plugins/grepview/grepviewplugin.cpp @@ -1,208 +1,202 @@ /*************************************************************************** * Copyright 1999-2001 by Bernd Gehrmann * * bernd@kdevelop.org * * Copyright 2007 Dukju Ahn * * Copyright 2010 Benjamin Port * * * 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 "grepviewplugin.h" #include "grepdialog.h" #include "grepoutputmodel.h" #include "grepoutputdelegate.h" #include "grepjob.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 K_PLUGIN_FACTORY(GrepViewFactory, registerPlugin(); ) K_EXPORT_PLUGIN(GrepViewFactory(KAboutData("kdevgrepview","kdevgrepview", ki18n("Find/Replace In Files"), "0.1", ki18n("Support for running grep over a list of files"), KAboutData::License_GPL))) GrepViewPlugin::GrepViewPlugin( QObject *parent, const QVariantList & ) : KDevelop::IPlugin( GrepViewFactory::componentData(), parent ), m_currentJob(0) { setXMLFile("kdevgrepview.rc"); KAction *action = actionCollection()->addAction("edit_grep"); action->setText(i18n("Find/replace in Fi&les...")); action->setShortcut( i18n("Ctrl+Alt+f") ); connect(action, SIGNAL(triggered(bool)), this, SLOT(showDialogFromMenu())); action->setToolTip( i18n("Search for expressions over several files") ); action->setWhatsThis( i18n("Find/Replace in files

" "Opens the 'Find/Replace in files' dialog. There you " "can enter a regular expression which is then " "searched for within all files in the directories " "you specify. Matches will be displayed, you " "can switch to a match directly. You can also do replacement.

") ); action->setIcon(KIcon("edit-find")); // instantiate delegate, it's supposed to be deleted via QObject inheritance new GrepOutputDelegate(this); } GrepViewPlugin::~GrepViewPlugin() { } KDevelop::ContextMenuExtension GrepViewPlugin::contextMenuExtension(KDevelop::Context* context) { KDevelop::ContextMenuExtension extension = KDevelop::IPlugin::contextMenuExtension(context); if( context->type() == KDevelop::Context::ProjectItemContext ) { KDevelop::ProjectItemContext* ctx = dynamic_cast( context ); QList items = ctx->items(); // verify if there is only one folder selected if ((items.count() == 1) && (items.first()->folder())) { KAction* action = new KAction( i18n( "Find and replace in this folder" ), this ); action->setIcon(KIcon("edit-find")); m_contextMenuDirectory = items.at(0)->folder()->url().toLocalFile(); connect( action, SIGNAL(triggered()), this, SLOT(showDialogFromProject())); extension.addAction( KDevelop::ContextMenuExtension::ExtensionGroup, action ); } } if ( context->type() == KDevelop::Context::EditorContext ) { KDevelop::EditorContext *econtext = dynamic_cast(context); if ( econtext->view()->selection() ) { QAction* action = new QAction(KIcon("edit-find"), i18n("&Find/Replace in Files"), this); connect(action, SIGNAL(triggered(bool)), this, SLOT(showDialogFromMenu())); extension.addAction(KDevelop::ContextMenuExtension::ExtensionGroup, action); } } return extension; } void GrepViewPlugin::showDialog(bool setLastUsed) { GrepDialog* dlg = new GrepDialog( this, core()->uiController()->activeMainWindow(), setLastUsed ); KDevelop::IDocument* doc = core()->documentController()->activeDocument(); if(!setLastUsed) { QString pattern; if( doc ) { KTextEditor::Range range = doc->textSelection(); if( range.isValid() ) { - kDebug() << "got valid range:" << range; pattern = doc->textDocument()->text( range ); - kDebug() << "context now:" << pattern; } if( pattern.isEmpty() ) { - kDebug() << "fetching current word"; pattern = doc->textWord(); - kDebug() << "word is:" << pattern; } } // Before anything, this removes line feeds from the // beginning and the end. int len = pattern.length(); if (len > 0 && pattern[0] == '\n') { pattern.remove(0, 1); len--; } if (len > 0 && pattern[len-1] == '\n') pattern.truncate(len-1); if (!pattern.isEmpty()) { dlg->setPattern( pattern ); } dlg->enableButtonOk( !pattern.isEmpty() ); } if (!m_directory.isEmpty() && QFileInfo(m_directory).isDir()) { dlg->setDirectory(m_directory); } else { KUrl currentUrl; KDevelop::IDocument *document = core()->documentController()->activeDocument(); dlg->setEnableProjectBox(false); if( document ) { currentUrl = document->url(); } if( currentUrl.isValid() ) { KDevelop::IProject *proj = core()->projectController()->findProjectForUrl( currentUrl ); if( proj && proj->folder().isLocalFile() ) { dlg->setEnableProjectBox(! proj->files().isEmpty() ); if (!m_directory.startsWith(proj->folder().toLocalFile())) { dlg->setDirectory( proj->folder().toLocalFile() ); } } } } dlg->show(); } void GrepViewPlugin::showDialogFromMenu() { showDialog(); } void GrepViewPlugin::showDialogFromProject() { rememberSearchDirectory(m_contextMenuDirectory); showDialog(); } void GrepViewPlugin::rememberSearchDirectory(QString const & directory) { m_directory = directory; } GrepJob* GrepViewPlugin::grepJob() { if(m_currentJob != 0) { m_currentJob->kill(); } m_currentJob = new GrepJob(); connect(m_currentJob, SIGNAL(finished(KJob*)), this, SLOT(jobFinished(KJob*))); return m_currentJob; } void GrepViewPlugin::jobFinished(KJob* job) { if(job == m_currentJob) { m_currentJob = 0; } } #include "grepviewplugin.moc" diff --git a/shell/CMakeLists.txt b/shell/CMakeLists.txt index ec197b8efd..9d8cb599b2 100644 --- a/shell/CMakeLists.txt +++ b/shell/CMakeLists.txt @@ -1,155 +1,154 @@ add_definitions( -DKDE_DEFAULT_DEBUG_AREA=9501 ) add_subdirectory(settings) add_subdirectory(tests) set(kdevplatformshell_LIB_SRCS workingsetcontroller.cpp workingsets/workingset.cpp workingsets/workingsetfilelabel.cpp workingsets/workingsettoolbutton.cpp workingsets/workingsettooltipwidget.cpp workingsets/workingsetwidget.cpp workingsets/closedworkingsetswidget.cpp workingsets/workingsethelpers.cpp assistantpopup.cpp mainwindow.cpp mainwindow_p.cpp plugincontroller.cpp shellextension.cpp core.cpp uicontroller.cpp projectcontroller.cpp project.cpp partcontroller.cpp #document.cpp partdocument.cpp textdocument.cpp documentcontroller.cpp languagecontroller.cpp language.cpp statusbar.cpp runcontroller.cpp sessioncontroller.cpp session.cpp savedialog.cpp sessiondialog.cpp sourceformattercontroller.cpp completionsettings.cpp openprojectpage.cpp openprojectdialog.cpp projectinfopage.cpp selectioncontroller.cpp documentationcontroller.cpp debugcontroller.cpp launchconfiguration.cpp launchconfigurationdialog.cpp loadedpluginsdialog.cpp progressmanager.cpp progresswidget.cpp overlaywidget.cpp progressdialog.cpp projectsourcepage.cpp # TODO: Re-Enable after generating new kross bindings for project model # kross/krossplugin.cpp # kross/krossbuildsystemmanager.cpp # kross/krossdistributedversioncontrol.cpp # kross/krosstoolviewfactory.cpp # kross/krossvcsjob.cpp # kross/wrappers/krosscontext.cpp # kross/wrappers/krosscontextmenuextension.cpp # kross/wrappers/krossvcsrevision.cpp # kross/wrappers/krossvcslocation.cpp # kross/wrappers/krossprojectmodel.cpp # # kross/wrappers/krossiuicontroller.cpp # kross/wrappers/krossidocument.cpp # # kross/wrappers/krosstopducontext.cpp # # kross/wrappers/krossducontext.cpp # kross/wrappers/krossilanguage.cpp # # kross/wrappers/krossdeclaration.cpp # # kross/wrappers/krossuse.cpp # kross/wrappers/krossidentifier.cpp # kross/wrappers/krossduchainlock.cpp # kross/wrappers/krossiproblem.cpp # kross/wrappers/krossibuildsystemmanager.cpp # kross/wrappers/krossiprojectfilemanager.cpp # kross/wrappers/krossiprojectbuilder.cpp # kross/wrappers/krosseditorcontext.cpp # kross/wrappers/krossqtoolbar.cpp ) if(HAVE_KOMPARE) set(kdevplatformshell_LIB_SRCS ${kdevplatformshell_LIB_SRCS} patchdocument.cpp) endif(HAVE_KOMPARE) set(kdevplatformshell_UI sessiondialog.ui projectinfopage.ui launchconfigurationdialog.ui projectsourcepage.ui ) kde4_add_ui_files( kdevplatformshell_LIB_SRCS ${kdevplatformshell_UI} ) kde4_add_library(kdevplatformshell SHARED ${kdevplatformshell_LIB_SRCS}) target_link_libraries(kdevplatformshell ${KDE4_KIO_LIBS} ${KDE4_KFILE_LIBS} ${KDE4_KCMUTILS_LIBS} ${KDE4_KPARTS_LIBS} ${KDE4_KNOTIFYCONFIG_LIBS} ${KDE4_KTEXTEDITOR_LIBS} ${KDE4_THREADWEAVER_LIBRARIES} ${KDE4_KROSSCORE_LIBS} kdevplatforminterfaces kdevplatformproject kdevplatformvcs kdevplatformlanguage sublime kdevplatformutil kdevplatformoutputview kdevplatformdebugger kdevplatformdocumentation) # need to add kdevplatform* once those are exported targets target_link_libraries(kdevplatformshell LINK_INTERFACE_LIBRARIES ${KDE4_KDEUI_LIBS} ${KDE4_KDECORE_LIBS} kdevplatforminterfaces) set_target_properties(kdevplatformshell PROPERTIES VERSION ${KDEVPLATFORM_LIB_VERSION} SOVERSION ${KDEVPLATFORM_LIB_SOVERSION}) install(FILES mainwindow.h plugincontroller.h shellextension.h core.h uicontroller.h projectcontroller.h project.h partcontroller.h partdocument.h textdocument.h documentcontroller.h languagecontroller.h session.h sessioncontroller.h sourceformattercontroller.h language.h shellexport.h selectioncontroller.h runcontroller.h launchconfiguration.h - savedialog.h DESTINATION ${INCLUDE_INSTALL_DIR}/kdevplatform/shell COMPONENT Devel ) install(TARGETS kdevplatformshell EXPORT KDevPlatformTargets ${INSTALL_TARGETS_DEFAULT_ARGS} ) install( FILES debugger/kdevdebuggershellui.rc DESTINATION ${DATA_INSTALL_DIR}/kdevdebugger ) install( FILES kdevsessionui.rc DESTINATION ${DATA_INSTALL_DIR}/kdevsession ) install( FILES kdevsourceformatter.rc DESTINATION ${DATA_INSTALL_DIR}/kdevsourceformatter ) if(NOT WIN32) macro_optional_add_subdirectory(kross) endif(NOT WIN32) diff --git a/shell/savedialog.h b/shell/savedialog.h index 4c0051ddb7..f09242f93b 100644 --- a/shell/savedialog.h +++ b/shell/savedialog.h @@ -1,50 +1,49 @@ /* This file is part of the KDE project Copyright (C) 2002 Harald Fernengel Copyright (C) 2008 Hamish Rodda This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef SAVEDIALOG_H #define SAVEDIALOG_H #include -#include "shellexport.h" class QListWidget; namespace KDevelop { class IDocument; -class KDEVPLATFORMSHELL_EXPORT KSaveSelectDialog : public KDialog +class KSaveSelectDialog : public KDialog { Q_OBJECT public: KSaveSelectDialog( const QList& files, QWidget * parent ); virtual ~KSaveSelectDialog(); private Q_SLOTS: void save(); private: QListWidget* m_listWidget; }; } #endif