diff options
Diffstat (limited to 'parts/replace')
-rw-r--r-- | parts/replace/Makefile.am | 16 | ||||
-rw-r--r-- | parts/replace/README | 3 | ||||
-rw-r--r-- | parts/replace/README.dox | 24 | ||||
-rw-r--r-- | parts/replace/kdevpart_replace.rc | 8 | ||||
-rw-r--r-- | parts/replace/kdevreplace.desktop | 80 | ||||
-rw-r--r-- | parts/replace/replace_part.cpp | 110 | ||||
-rw-r--r-- | parts/replace/replace_part.h | 46 | ||||
-rw-r--r-- | parts/replace/replace_widget.cpp | 486 | ||||
-rw-r--r-- | parts/replace/replace_widget.h | 81 | ||||
-rw-r--r-- | parts/replace/replacedlg.ui | 385 | ||||
-rw-r--r-- | parts/replace/replacedlgimpl.cpp | 188 | ||||
-rw-r--r-- | parts/replace/replacedlgimpl.h | 38 | ||||
-rw-r--r-- | parts/replace/replaceitem.cpp | 147 | ||||
-rw-r--r-- | parts/replace/replaceitem.h | 113 | ||||
-rw-r--r-- | parts/replace/replaceview.cpp | 141 | ||||
-rw-r--r-- | parts/replace/replaceview.h | 54 |
16 files changed, 1920 insertions, 0 deletions
diff --git a/parts/replace/Makefile.am b/parts/replace/Makefile.am new file mode 100644 index 00000000..78a7ab4b --- /dev/null +++ b/parts/replace/Makefile.am @@ -0,0 +1,16 @@ +# Here resides the replace part (search and replace in the entire project) + +INCLUDES = -I$(top_srcdir)/lib/interfaces -I$(top_srcdir)/lib/util $(all_includes) + +kde_module_LTLIBRARIES = libkdevreplace.la +libkdevreplace_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) +libkdevreplace_la_LIBADD = $(top_builddir)/lib/libkdevelop.la +libkdevreplace_la_SOURCES = replace_part.cpp replace_widget.cpp replacedlg.ui replaceitem.cpp replaceview.cpp replacedlgimpl.cpp + +METASOURCES = AUTO + +servicedir = $(kde_servicesdir) +service_DATA = kdevreplace.desktop + +rcdir = $(kde_datadir)/kdevreplace +rc_DATA = kdevpart_replace.rc diff --git a/parts/replace/README b/parts/replace/README new file mode 100644 index 00000000..731741e1 --- /dev/null +++ b/parts/replace/README @@ -0,0 +1,3 @@ +Please read the on-line, automaticaly updated KDevelop API documentation at: +http://www.kdevelop.org +or read the README.dox file. diff --git a/parts/replace/README.dox b/parts/replace/README.dox new file mode 100644 index 00000000..c5953c8a --- /dev/null +++ b/parts/replace/README.dox @@ -0,0 +1,24 @@ +/** \class ReplacePart +This plugin replaces a search pattern with a specified string, after letting the +user preview and choose which replacements should take place. + +The operation is only carried out on files that are part of the current project. + +\authors <a href="mailto:jens.dagerbo AT swipnet.se">Jens Dagerbo</a> aka teatime + +\maintainer <a href="mailto:jens.dagerbo AT swipnet.se">Jens Dagerbo</a> aka teatime + +\feature Replaces a search pattern with a specified string, after letting the +user preview and choose which replacements should take place. + +\todo Better user feedback +\todo Better commenting (doxygen style comments). + + +\warning The operation is only carried out on files that are part of the current project. + +\warning Search/Replace will work on all matches on a line. +There is no (nor will there likely be) a way to limit matching to only some matches on the same line. +In practice this is not a very big problem. + +*/ diff --git a/parts/replace/kdevpart_replace.rc b/parts/replace/kdevpart_replace.rc new file mode 100644 index 00000000..e3818308 --- /dev/null +++ b/parts/replace/kdevpart_replace.rc @@ -0,0 +1,8 @@ +<!DOCTYPE kpartgui> +<kpartplugin name="replace" library="libreplaceplugin" version="1"> +<MenuBar> + <Menu name="edit"> + <Action name="edit_replace_across" group="kdev_edit_find_merge"/> + </Menu> +</MenuBar> +</kpartplugin> diff --git a/parts/replace/kdevreplace.desktop b/parts/replace/kdevreplace.desktop new file mode 100644 index 00000000..13caf5b6 --- /dev/null +++ b/parts/replace/kdevreplace.desktop @@ -0,0 +1,80 @@ +[Desktop Entry] +Type=Service +Exec= +Comment=This plugin is an interactive projectwide "Search and Replace" tool. Search using string or regexp matching, and select the replacements to be made from a preview before the action is finalized. When loaded it appears in the Edit menu. +Comment[ca]=Aquest connector és una eina interactiva de "Recerca i substitució" a tot el projecte. Pot cercar mitjançant patrons o expressions regulars, i seleccionar les substitucions en una vista prèvia, abans de que finalitzi l'acció. Quan està carregat apareix en el menú Edita. +Comment[da]=Dette plugin er et interaktivt projektomfattende "Søg og erstat" værktøj. Søg ved brug af streng eller regexp tilpasning, og vælg erstatninger lavet fra en forhåndsvisning før handlingen blive helt udført. Når det er indlæst er det i redigeringsmenuen. +Comment[de]=Diese Komponente ist ein interaktives Werkzeug zum projektweiten "Suchen und Ersetzen" von Begriffen oder regulären Ausdrücken. Die zu ersetzenden Zeichenketten können in einer Vorschau ausgewählt werden. Erscheint im Menü "Bearbeiten", wenn es geladen ist. +Comment[el]=Αυτό το πρόσθετο είναι ένα εργαλείο αλληλεπίδρασης "Αναζήτησης και αντικατάστασης" για όλο το έργο. Αναζητά χρησιμοποιώντας συμβολοσειρές ή κανονικές εκφράσεις, και επιλέγει τις αντικαταστάσεις από μια προεπισκόπηση πριν να εκτελεστεί η ενέργεια. Όταν φορτωθεί είναι διαθέσιμο από το μενού επεξεργασίας. +Comment[en_GB]=This plugin is an interactive projectwide "Search and Replace" tool. Search using string or regexp matching, and select the replacements to be made from a preview before the action is finalised. When loaded it appears in the Edit menu. +Comment[es]=Este complemento es una herramienta interactiva de «Búsqueda y sustitución» para todo el proyecto. Puede buscar mediante patrones o expresiones regulares, y seleccionar las sustituciones en una previsualización, antes de que finalice la acción. Cuando está cargado aparece en el menú Editar. +Comment[et]=See plugin on kogu projekti hõlmav interaktiivne "otsi ja asenda" vahend. Otsida saab stringe või regulaaravaldiste sobivusi, asendusi saab valida eelvaatluse abil, enne kui need päriselt teoks teha. Kasutamisel kättesaadav redigeerimismenüüst. +Comment[eu]=Plugin hau proiektu mailako "Bilatu eta ordeztu" tresna interaktiboa da. Bila ezazu kate edo regexp bat-egitea erabiliz, eta hautatu egin beharreko ordezkapenak aurrebista batetik ekintza amaitu aurretik. Kargatzean Editatu menuan agertzen da. +Comment[fa]=این وصله یک ابزار گسترۀ پروژۀ تعاملی »جستجو و جایگزینی« میباشد. با استفاده از تطبیق رشته یا عبارت منظم جستجو میکند، و جایگزینهایی را گزینش میکند تا قبل از اتمام کنش، از یک پیشنمایش ایجاد شود. در هنگام بارگذاری در گزینگان ویرایش ظاهر میشود. +Comment[fr]=Ce module externe est un outil de « Recherche et remplacement » à l'échelle du projet. Faites une recherche à l'aide de la correspondance de chaînes ou d'expressions rationnelles, et sélectionnez les remplacements à effectuer à partir d'un aperçu avant que l'action ne soit finalisée. Lorsqu'il est chargé, ce module externe apparaît dans le menu « Édition ». +Comment[gl]=Esta extensión é unha ferramenta interactiva "Procurar e reemprazar" dispoñíbel en todo o proxecto. Busca usando coincidencias con strings ou expresións regulares, e selecciona os reemprazamentos a facer nunha previsualización antes de que as accións finalicen. Cando se carga aparece no menú Editar. +Comment[hu]=Ezzel a bővítőmodullal az egész projektre kiterjedő keresést és cserét lehet végezni. Lehet sztringre és reg. kifejezésre keresni, az elvégzendő műveleteket egy előnézeti ablakban lehet kiválasztani. A modul betöltés után a Szerkesztés menübe kerül. +Comment[it]=Questo plugin è uno strumento interattivo per "Cerca e sostituisci" sui progetti. Cerca tramite stringhe e confronto regexp e seleziona le sostituzioni da compiere da un'anteprima prima che le azioni siano finalizzate. Quando caricato apparirà nel menu Modifica. +Comment[ja]=このプラグインは、プロジェクト規模で検索や置換を行う対話型のツールです。検索は文字列や正規表現の合致を使い、アクションが終了する前にプレビューで作られている置換を選択します。読み込まれると編集メニューに表示されます。 +Comment[ms]=Plugin ini adalah alatan "Cari dan Ganti" serata projek interaktif. Cari menggunakan padanan rentetan atau regexp, dan pilih gantian yang akan dibuat daripada pralihat sebelum tindakan diselesaikan. Apabila dimuatkan ia kelihatan didalam menu Sunting. +Comment[nds]=Dit Moduul is en interaktiv projektwiet "Söken un Utwesseln"-Warktüüch. Du kannst na Tekenkeden oder mit reguleer Utdrück söken un de Ännern in en Vöransicht utsöken, ehr de Akschoon utföhrt warrt. Dukt in't Menü "Bewerken" op, wenn laadt. +Comment[ne]=यो प्लगइन अन्तरक्रियात्मक परियोजनामा "खोजी गरेर प्रतिस्थापन गर्नुहोस्" उपकरण हो । स्ट्रिङ वा regexp मिल्दो प्रयोग गरेर खोजी गर्नुहोस् र कार्य समाप्त गर्नु पूर्व पूर्वावलोकनबाट प्रतिस्थापन गर्नेलाई चयन गर्नुहोस् । लोड भएपछि सम्पादन मेनुमा देखा पर्दछ । +Comment[nl]=Deze plugin biedt een interactieve, projectbrede "zoek en vervang"-tool. U kunt zoeken naar tekens of reguliere expressies en de vervanging kan in een dialoog worden bekeken voordat deze wordt uitgevoerd. Verschijnt in het menu Bewerken. +Comment[pl]=Wtyczka działającego w całym projekcie narzędzia "Znajdź i zamień". Wyszukiwanie odbywa się za pomocą porównywania ciągów lub wyrażen regularnych, a wybór zamienników może być dokonywany przy włączonym podglądzie. Po wczytaniu pojawia się w menu Edycja. +Comment[pt]=Este 'plugin' é uma ferramenta interactiva ao nível do projecto de "Procurar e Substituir". Pode procurar por texto ou por uma expressão regular e seleccionar as substituições a serem feitas, a partir de uma antevisão, antes de a acção terminar. Quando é carregado, aparece no menu Editar. +Comment[pt_BR]=Este plug-in é uma ferramenta interativa de "Procurar e Substituir" por todo o projeto. Procura usando um string ou regexp correspondente, e seleciona as substituições a serem feitas de uma previsão antes da ação ser finalizada. Quando carregado ele aparece no menu Editar. +Comment[ru]=Этот модуль предоставляет интерактивные возможности поиска и замены по файлам в проекте. Сначала проводится поиск по строке или регулярному выражению, далее выбор с предпросмотром и применение замен из списка доступных вариантов. +Comment[sk]=Modul poskytuje interaktívny nástroj pre "Nájsť a Zameniť" v celom projekte.Vyhľadávanie pomocou regexp výrazov a výber nového reťazca z náhľadu pred samotnou zámenou. Po načítaní sa objaví v menu Edit. +Comment[sr]=Овај прикључак је интерактивни „пронађи и замени“ алат широм пројекта. Тражите користећи знаковни низ или рег.из. поклапање, и из прегледа одаберите измене које ће бити извршене пре него што се акција заврши. Када је учитан појављује се у менију „Измени“. +Comment[sr@Latn]=Ovaj priključak je interaktivni „pronađi i zameni“ alat širom projekta. Tražite koristeći znakovni niz ili reg.iz. poklapanje, i iz pregleda odaberite izmene koje će biti izvršene pre nego što se akcija završi. Kada je učitan pojavljuje se u meniju „Izmeni“. +Comment[sv]=Insticksprogrammet är ett interaktivt verktyg för att "söka och ersätta" i hela projektet. Sök med en sträng eller reguljärt uttryck, och välj ersättningen som ska göras från en förhandsgranskning innan åtgärden slutförs. När det laddats visas det i redigeringsmenyn. +Comment[ta]=இந்த சொருகி "Search and Replace" ஒரு சிறந்த திட்ட பணி கருவி. சரத்தை உபயோகித்து தேடுதல் அல்லது ரெக்ஸ்ப் பொருத்துதல், மற்றும் செயல்கள் தீர்மானிப்பதற்கு முன் முன்தோற்றத்தைப் பார்த்து மாற்ற வேண்டியதை தேர்வு செய். +Comment[tg]=Ин модул барои ковтукови интерактивӣ ва ҷой иваз намудан дар лоиҳаро имкон медиҳад.Аввал ковтуков дар сатр оғоз меёбад ва ё дар баёноти ботартиб, баъд аз он интихоби пеш аз намоиш ва истифода барии ҷой ивазкунӣ аз рӯйхати вариантҳои имконпазир гузаронида мешавад. +Comment[tr]=Bu eklenti projenin tamamında "Ara ve Değiştir" aracıdır. Dizgi veya regexp eşleşmesi ara ve işlem sona ermeden bir önizlemeden yapılacak değişiklikleri seç. Yüklendiğinde Düzenle menüsünde durur. +Comment[zh_CN]=这个插件是面向真个工程的“查找和替换”工具。 使用字符串或正则表达式匹配,并在操作完成前提供选择替换预览。启动后显示在编辑菜单中。 +Comment[zh_TW]=這個外掛程式是一個專案的「搜尋與取代」互動工具。使用字串或正規表示式來搜尋,並選擇是否要取代。載入後可以在「編輯」選單中找到。 +Name=KDevReplace +Name[da]=KDevelop Erstat +Name[nds]=KDevelop-Utwesseln +Name[sk]=KDev zameniť +Name[sv]=KDevelop ersätt +Name[zh_TW]=KDevelop 取代 +GenericName=Replace Part +GenericName[ca]=Part per a la substitució +GenericName[da]=Erstatningspart +GenericName[de]=Ersetzen-Komponente +GenericName[el]=Τμήμα αντικατάστασης +GenericName[es]=Servicio de sustitución +GenericName[et]=Asendamise komponent +GenericName[eu]=Ordeztu partea +GenericName[fa]=جزء جایگزینی +GenericName[fr]=Outil de remplacement +GenericName[gl]='Part' reemprazar +GenericName[hi]=रीप्लेस पार्ट +GenericName[hu]=Cserélés +GenericName[it]=Componente per sostituire +GenericName[ja]=置換 +GenericName[ms]=Ganti Bahagian +GenericName[nds]=Utwessel-Komponent +GenericName[ne]=प्रतिस्थापन भाग +GenericName[nl]=Zoeken en vervangen +GenericName[pl]=Program do zastępowania +GenericName[pt]=Parte de Substituição +GenericName[pt_BR]=Parte Substituir +GenericName[ru]=Замена по проекту +GenericName[sk]=Part zameniť +GenericName[sl]=Del za zamenjave +GenericName[sr]=Део за замену +GenericName[sr@Latn]=Deo za zamenu +GenericName[sv]=Ersättning +GenericName[ta]=மாற்றுப் பகுதி +GenericName[tg]=Ҷой иваз намудан бо лоиҳа +GenericName[tr]=Değiştirme Bileşeni +GenericName[zh_CN]=替换模块 +GenericName[zh_TW]=取代元件 +Icon=kdevelop +ServiceTypes=KDevelop/Plugin +X-KDevelop-Scope=Global +X-KDE-Library=libkdevreplace +X-KDevelop-Version=5 +X-KDevelop-Properties=FileReplace diff --git a/parts/replace/replace_part.cpp b/parts/replace/replace_part.cpp new file mode 100644 index 00000000..6e1312ed --- /dev/null +++ b/parts/replace/replace_part.cpp @@ -0,0 +1,110 @@ +/*************************************************************************** + * Copyright (C) 2003 by Jens Dagerbo * + * jens.dagerbo@swipnet.se * + * * + * 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 "replace_part.h" + +#include <qwhatsthis.h> + +#include <kaction.h> +#include <kiconloader.h> +#include <klocale.h> +#include <kdevgenericfactory.h> +#include <kdevplugininfo.h> +#include <kdebug.h> +#include <kstringhandler.h> +#include <kdevcore.h> +#include <kdevmainwindow.h> + +#include "replace_widget.h" + +static const KDevPluginInfo data("kdevreplace"); + +typedef KDevGenericFactory<ReplacePart> ReplaceFactory; +K_EXPORT_COMPONENT_FACTORY(libkdevreplace, ReplaceFactory(data)) + +ReplacePart::ReplacePart(QObject *parent, const char *name, const QStringList& ) + : KDevPlugin( &data, parent, name ? name : "ReplacePart" ) +{ + setInstance(ReplaceFactory::instance()); + setXMLFile("kdevpart_replace.rc"); + + m_widget = new ReplaceWidget(this); + m_widget->setIcon( SmallIcon("filefind") ); + m_widget->setCaption(i18n("Replace")); + + QWhatsThis::add + (m_widget, i18n("<b>Replace</b><p>" + "This window shows a preview of a string replace " + "operation. Uncheck a line to exclude that replacement. " + "Uncheck a file to exclude the whole file from the " + "operation. " + "Clicking on a line in the list will automatically " + "open the corresponding source file and set the " + "cursor to the line with the match." )); + + mainWindow()->embedOutputView( m_widget, i18n("Replace"), i18n("Project wide string replacement") ); + mainWindow()->setViewAvailable( m_widget, false ); + + action = new KAction(i18n("Find-Select-Replace..."), 0, + CTRL+SHIFT+Key_R, this, SLOT(slotReplace()), actionCollection(), "edit_replace_across"); + action->setToolTip( i18n("Project wide string replacement") ); + action->setWhatsThis( i18n("<b>Find-Select-Replace</b><p>" + "Opens the project wide string replacement dialog. There you " + "can enter a string or a regular expression which is then " + "searched for within all files in the locations " + "you specify. Matches will be displayed in the <b>Replace</b> window, you " + "can replace them with the specified string, exclude them from replace operation or cancel the whole replace.") ); + + connect( core(), SIGNAL(contextMenu(QPopupMenu *, const Context *)), this, SLOT(contextMenu(QPopupMenu *, const Context *)) ); + connect( core(), SIGNAL(projectOpened()), this, SLOT(enableAction())); + connect( core(), SIGNAL(projectClosed()), this, SLOT(disableAction())); +} + +void ReplacePart::enableAction() +{ + action->setEnabled(true); +} + +void ReplacePart::disableAction() +{ + action->setEnabled(false); +} + +ReplacePart::~ReplacePart() +{ + if ( m_widget ) + mainWindow()->removeView( m_widget ); + delete m_widget; +} + +void ReplacePart::slotReplace() +{ + m_widget->showDialog(); +} + +void ReplacePart::contextMenu(QPopupMenu *popup, const Context *context) +{ + if (!context->hasType( Context::EditorContext )) + return; + + const EditorContext *econtext = static_cast<const EditorContext*>(context); + QString ident = econtext->currentWord(); + if (!ident.isEmpty()) { + m_popupstr = ident; + QString squeezed = KStringHandler::csqueeze(ident, 30); + int id = popup->insertItem( i18n("Replace Project Wide: %1").arg(squeezed), + this, SLOT(slotReplace()) ); + popup->setWhatsThis(id, i18n("<b>Replace Project Wide</b><p>Opens the find in files dialog " + "and sets the pattern to the text under the cursor.")); + popup->insertSeparator(); + } +} + +#include "replace_part.moc" diff --git a/parts/replace/replace_part.h b/parts/replace/replace_part.h new file mode 100644 index 00000000..35a293ab --- /dev/null +++ b/parts/replace/replace_part.h @@ -0,0 +1,46 @@ +/*************************************************************************** + * Copyright (C) 2003 by Jens Dagerbo * + * jens.dagerbo@swipnet.se * + * * + * 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 __KDEVPART_REPLACE_H__ +#define __KDEVPART_REPLACE_H__ + + +#include <qguardedptr.h> +#include <kdevplugin.h> +#include <qpopupmenu.h> + + +class ReplaceWidget; +class KAction; +class Context; + +class ReplacePart : public KDevPlugin +{ + Q_OBJECT + +public: + ReplacePart(QObject *parent, const char *name, const QStringList &); + ~ReplacePart(); + +public slots: + void slotReplace(); + void contextMenu(QPopupMenu *popup, const Context *context); + void enableAction(); + void disableAction(); +private: + QGuardedPtr<ReplaceWidget> m_widget; + QString m_popupstr; + KAction* action; + +}; + + +#endif diff --git a/parts/replace/replace_widget.cpp b/parts/replace/replace_widget.cpp new file mode 100644 index 00000000..24078943 --- /dev/null +++ b/parts/replace/replace_widget.cpp @@ -0,0 +1,486 @@ +/*************************************************************************** + * Copyright (C) 2003 by Jens Dagerbo * + * jens.dagerbo@swipnet.se * + * * + * 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. * + * * + ***************************************************************************/ + +//BEGIN Includes + +#include <dcopclient.h> +#include <kapplication.h> +#include <kparts/part.h> +#include <kparts/componentfactory.h> +#include <klibloader.h> +#include <ktrader.h> +#include <kurl.h> +#include <kurlrequester.h> +#include <klineedit.h> +#include <kdebug.h> +#include <ktexteditor/editinterface.h> +#include <ktexteditor/editor.h> +#include <ktexteditor/document.h> +#include <ktexteditor/viewcursorinterface.h> +#include <ktexteditor/selectioninterface.h> +#include <kdevpartcontroller.h> +#include <kdevcore.h> +#include <kdevmainwindow.h> +#include <kdevproject.h> +#include <kdevpartcontroller.h> +#include <kcombobox.h> +#include <klocale.h> +#include <kstdguiitem.h> + +#include <qlayout.h> +#include <qpushbutton.h> +#include <qlineedit.h> +#include <qradiobutton.h> +#include <qstringlist.h> +#include <qptrlist.h> +#include <qregexp.h> +#include <qdialog.h> +#include <qfile.h> +#include <qdir.h> +#include <qtextstream.h> +#include <qdatastream.h> + +#include <sys/types.h> +#include <unistd.h> + +#include "replace_part.h" +#include "replace_widget.h" +#include "replacedlgimpl.h" +#include "replaceitem.h" +#include "replaceview.h" + +//END Includes + +ReplaceWidget::ReplaceWidget(ReplacePart *part) + : QWidget(0, "replace widget"), m_part( part ), + m_dialog( new ReplaceDlgImpl( this, "replace widget" ) ), + _terminateOperation( false ) +{ + // setup outputview + QVBoxLayout * layout = new QVBoxLayout( this ); + QHBoxLayout * buttonlayout = new QHBoxLayout( layout ); + + _cancel = new KPushButton( KStdGuiItem::cancel(), this ); + _replace = new KPushButton( KGuiItem(i18n("Replace"),"filefind"), this ); + + _cancel->setEnabled( false ); + _replace->setEnabled( false ); + + buttonlayout->addWidget( _replace ); + buttonlayout->addWidget( _cancel ); + + _listview = new ReplaceView( this ); + layout->addWidget( _listview ); + + // setup signals + connect( m_dialog->find_button, SIGNAL( clicked() ), SLOT( find() ) ); + + connect( _replace, SIGNAL( clicked() ), SLOT( replace() ) ); + connect( _cancel, SIGNAL( clicked() ), SLOT( clear() ) ); + connect( _listview, SIGNAL( editDocument( const QString &, int ) ), SLOT( editDocument( const QString &, int ) ) ); + + connect( m_part->core(), SIGNAL( stopButtonClicked( KDevPlugin * ) ), SLOT( stopButtonClicked( KDevPlugin * ) ) ); +} + +//BEGIN Slots + +void ReplaceWidget::showDialog() +{ + if ( ! m_part->project() ) + return; /// @todo feedback? + + QString currentWord; + KParts::ReadOnlyPart *part = dynamic_cast<KParts::ReadOnlyPart*> ( m_part->partController()->activePart() ); + if ( part ) + { + if ( part->url().isLocalFile() ) + { + calledUrl = part->url().path(); + cursorPos ( part, &calledCol, &calledLine ); + + KTextEditor::EditInterface* editIface = dynamic_cast<KTextEditor::EditInterface*>( m_part->partController()->activePart() ); + QString str = editIface->textLine ( calledCol ); + + int i; + uint start, end; + for (i =calledLine; i< str.length();i++){ + if ( ! (str[i].isLetter() || str[i].isNumber() || str[i] == '_' ) ){ + break; + } + } + end=i; + for ( i = calledLine; i >= 0; --i ){ + if ( ! ( str[i].isLetter() ||str[i].isNumber()|| str[i] == '_' ) ){ + i+=1; + break; + } + } + start = i < 0 ? 0 : i; + currentWord = str.mid ( start, end-start ); + } + } + m_dialog->show ( m_part->project()->projectDirectory() + "/" + m_part->project()->activeDirectory() + "/" ); + + KTextEditor::SelectionInterface *sel_iface + = dynamic_cast<KTextEditor::SelectionInterface*> ( m_part->partController()->activePart() ); + if ( sel_iface && sel_iface->hasSelection() ) + { + m_dialog->find_combo->setCurrentText ( sel_iface->selection() ); + } + else + { + m_dialog->find_combo->setCurrentText ( currentWord ); + } +} + + +void ReplaceWidget::find() +{ + _listview->clear(); + m_part->mainWindow()->raiseView( this ); + m_part->mainWindow()->setViewAvailable( this, true ); + + _listview->setReplacementData( m_dialog->expressionPattern(), m_dialog->replacementString() ); + + if ( showReplacements() ) + { + _cancel->setEnabled( true ); + _replace->setEnabled( true ); + } + else + { + clear(); + m_part->mainWindow()->setViewAvailable( this, false ); + } +} + +void ReplaceWidget::replace() +{ + makeReplacements(); + clear(); + m_part->mainWindow()->setViewAvailable( this, false ); +} + +void ReplaceWidget::clear() +{ + _listview->clear(); + + _cancel->setEnabled( false ); + _replace->setEnabled( false ); + + m_part->mainWindow()->setViewAvailable( this, false ); +} + +void ReplaceWidget::editDocument( QString const & file, int line ) +{ + m_part->partController()->editDocument( KURL( file ), line ); +} + +void ReplaceWidget::stopButtonClicked( KDevPlugin * which ) +{ + if ( which != 0 && which != m_part ) + return; + + _terminateOperation = true; +} + +//END Slots + +bool ReplaceWidget::showReplacements() +{ + ReplaceItem::s_listview_done = false; + + m_part->core()->running( m_part, true ); + + bool completed = true; + _terminateOperation = false; + + QStringList files = workFiles(); + QStringList openfiles = openProjectFiles(); + + QStringList::ConstIterator it = files.begin(); + while ( it != files.end() ) + { + if ( shouldTerminate() ) + { + completed = false; + break; + } + + if ( openfiles.contains( *it ) ) + { + if ( KTextEditor::EditInterface * ei = getEditInterfaceForFile( *it ) ) + { + QString buffer = ei->text(); + QTextIStream stream( &buffer ); + _listview->showReplacementsForFile( stream, *it ); + } + } + else + { + QFile file( *it ); + if ( file.open ( IO_ReadOnly ) ) + { + QTextStream stream( &file ); + _listview->showReplacementsForFile( stream, *it ); + } + } + ++it; + + kapp->processEvents( 100 ); + } + + m_part->core()->running( m_part, false ); + + ReplaceItem::s_listview_done = true; + + return completed; +} + + +void ReplaceWidget::cursorPos( KParts::Part *part, uint * line, uint * col ) +{ + if (!part || !part->inherits("KTextEditor::Document")) return; + + KTextEditor::ViewCursorInterface *iface = dynamic_cast<KTextEditor::ViewCursorInterface*>(part->widget()); + if (iface) + { + iface->cursorPositionReal( line, col ); + } +} + +void ReplaceWidget::setCursorPos( KParts::Part *part, uint line, uint col ) +{ + if (!part || !part->inherits("KTextEditor::Document")) return; + + KTextEditor::ViewCursorInterface *iface = dynamic_cast<KTextEditor::ViewCursorInterface*>(part->widget()); + if (iface) + { + iface->setCursorPositionReal( line, col ); + } +} + + +bool ReplaceWidget::makeReplacements() +{ + uint col=0; + uint line=0; + cursorPos( m_part->partController()->activePart(), &col, &line ); + + m_part->core()->running( m_part, true ); + + bool completed = true; + _terminateOperation = false; + + QStringList openfiles = openProjectFiles(); + QStringList changedFiles; + + ReplaceItem const * fileitem = _listview->firstChild(); + while ( fileitem ) + { + if ( fileitem->isOn() ) + { + QString currentfile = fileitem->file(); + + if ( openfiles.contains( currentfile ) ) + { + if ( KTextEditor::EditInterface * ei = getEditInterfaceForFile( currentfile ) ) + { + QString ibuffer = ei->text(); + QString obuffer; + QTextStream istream( &ibuffer, IO_ReadOnly ); + QTextStream ostream( &obuffer, IO_WriteOnly ); + + _listview->makeReplacementsForFile( istream, ostream, fileitem ); + + ei->setText( obuffer ); + } + } + else + { + QFile file( currentfile ); + QString buffer; + + if ( file.open( IO_ReadOnly ) ) + { + QTextStream istream( &file ); + QTextStream buffer_stream( &buffer, IO_WriteOnly ); + + _listview->makeReplacementsForFile( istream, buffer_stream, fileitem ); + + file.close(); + + if ( file.open( IO_WriteOnly ) ) + { + QTextStream ostream( &file ); + ostream << buffer; + file.close(); + } + } + } + changedFiles << relativeProjectPath( ( currentfile ) ); + } + fileitem = fileitem->nextSibling(); + + kapp->processEvents( 100 ); + } + + // Telling the project about the edited files + if ( ! changedFiles.isEmpty() ) + { + m_part->project()->changedFiles( changedFiles ); + } + + m_part->partController()->saveAllFiles(); + + m_part->core()->running( m_part, false ); + + if ( calledUrl != QString::null ) + { + m_part->partController()->editDocument( calledUrl, calledLine ); + setCursorPos( m_part->partController()->activePart(), calledCol, calledLine ); + } + else{ + setCursorPos( m_part->partController()->activePart(), col, line ); + } + + return completed; +} + +//BEGIN Helpers + +QStringList ReplaceWidget::workFiles() +{ + if ( m_dialog->files_all_radio->isChecked() ) + { + return allProjectFiles(); + } + else if ( m_dialog->files_open_radio->isChecked() ) + { + return openProjectFiles(); + } + return subProjectFiles( m_dialog->path_urlreq->lineEdit()->text() ); +} + +QString ReplaceWidget::relativeProjectPath( QString path ) +{ + QString project = m_part->project()->projectDirectory() + "/"; + if ( path.left( project.length() ) == project ) + { + path = path.mid( project.length() ); + } + return path; +} + +QString ReplaceWidget::fullProjectPath( QString path ) +{ + QString project = m_part->project()->projectDirectory() + "/"; + if ( path.left( project.length() ) != project ) + { + path = project + path; + } + return path; +} + + +QStringList ReplaceWidget::allProjectFiles() +{ + QStringList allfiles = m_part->project()->allFiles(); + + QStringList::iterator it = allfiles.begin(); + while ( it != allfiles.end() ) + { + *it = fullProjectPath( *it ); + ++it; + } + return allfiles; +} + +QStringList ReplaceWidget::subProjectFiles( QString const & subpath ) +{ + QStringList projectfiles = allProjectFiles(); + + QStringList::Iterator it = projectfiles.begin(); + while ( it != projectfiles.end() ) + { + if ( (*it).left( subpath.length() ) != subpath) + { + it = projectfiles.remove( it ); + } + else + { + ++it; + } + } + return projectfiles; +} + +QStringList ReplaceWidget::openProjectFiles() +{ + QStringList projectfiles = allProjectFiles(); + QStringList openfiles; + + if( const QPtrList<KParts::Part> * partlist = m_part-> + partController()->parts() ) + { + QPtrListIterator<KParts::Part> it( *partlist ); + while ( KParts::Part* part = it.current() ) + { + if ( KTextEditor::Editor * ed = dynamic_cast<KTextEditor::Editor *>( part ) ) + { + QString editorpath = ed->url().path(); + if ( projectfiles.contains( editorpath ) ) + { + openfiles.append( editorpath ); + } + } + ++it; + } + } + return openfiles; +} + +KTextEditor::EditInterface * ReplaceWidget::getEditInterfaceForFile( QString const & file ) +{ + if( const QPtrList<KParts::Part> * partlist = m_part-> + partController()->parts() ) + { + QPtrListIterator<KParts::Part> it( *partlist ); + while ( KParts::Part* part = it.current() ) + { + if ( KTextEditor::Editor * ed = dynamic_cast<KTextEditor::Editor *>( part ) ) + { + if ( file == ed->url().path() ) + { + return dynamic_cast<KTextEditor::EditInterface *>( part ); + } + } + ++it; + } + } + return 0; +} + +bool ReplaceWidget::shouldTerminate() +{ + bool b = _terminateOperation; + _terminateOperation = false; + return b; +} + +void ReplaceWidget::focusInEvent( QFocusEvent * /* e*/ ) +{ + _listview->setFocus(); +} + +//END Helpers + +#include "replace_widget.moc" diff --git a/parts/replace/replace_widget.h b/parts/replace/replace_widget.h new file mode 100644 index 00000000..fa5809d5 --- /dev/null +++ b/parts/replace/replace_widget.h @@ -0,0 +1,81 @@ +/*************************************************************************** + * Copyright (C) 2003 by Jens Dagerbo * + * jens.dagerbo@swipnet.se * + * * + * 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 __REPLACE_WIDGET_H__ +#define __REPLACE_WIDGET_H__ + +#include <ktexteditor/editinterface.h> + +#include <qwidget.h> +#include <qstring.h> + +class QPushButton; +class QListViewItem; +class QDialog; + +class ReplacePart; +class ReplaceDlgImpl; +class ReplaceItem; +class ReplaceView; + +class ReplaceWidget : public QWidget +{ + Q_OBJECT + +public: + ReplaceWidget(ReplacePart *part); + +public slots: + void showDialog(); + void stopButtonClicked( KDevPlugin * ); + +protected: + virtual void focusInEvent(QFocusEvent *e); + +private slots: + void find(); + void replace(); + void clear(); + void editDocument( const QString & ,int ); + void setCursorPos( KParts::Part *part, uint line, uint col ); + void cursorPos( KParts::Part *part, uint * line, uint * col ); + +private: + bool showReplacements(); + bool makeReplacements(); + bool shouldTerminate(); + + QString relativeProjectPath( QString ); + QString fullProjectPath( QString ); + + QStringList workFiles(); + QStringList allProjectFiles(); + QStringList subProjectFiles( QString const & ); + QStringList openProjectFiles(); + + KTextEditor::EditInterface * getEditInterfaceForFile( QString const & file ); + + ReplacePart * m_part; + ReplaceDlgImpl * m_dialog; + + ReplaceView * _listview; + QPushButton * _cancel; + QPushButton * _replace; + + uint calledCol; + uint calledLine; + QString calledUrl; + + bool _terminateOperation; +}; + + +#endif diff --git a/parts/replace/replacedlg.ui b/parts/replace/replacedlg.ui new file mode 100644 index 00000000..b1c7db92 --- /dev/null +++ b/parts/replace/replacedlg.ui @@ -0,0 +1,385 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>ReplaceDlg</class> +<widget class="QDialog"> + <property name="name"> + <cstring>ReplaceDlg</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>428</width> + <height>487</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>32767</width> + <height>32767</height> + </size> + </property> + <property name="caption"> + <string>Project Wide String Replacement</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QGroupBox" row="1" column="0"> + <property name="name"> + <cstring>groupBox2</cstring> + </property> + <property name="title"> + <string>Options</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>case_box</cstring> + </property> + <property name="text"> + <string>C&ase sensitive</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QButtonGroup"> + <property name="name"> + <cstring>buttonGroup2</cstring> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="title"> + <string></string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="QRadioButton"> + <property name="name"> + <cstring>strings_all_radio</cstring> + </property> + <property name="text"> + <string>All s&ubstrings</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>strings_wholewords_radio</cstring> + </property> + <property name="text"> + <string>Whole words onl&y</string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout3</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QRadioButton"> + <property name="name"> + <cstring>strings_regexp_radio</cstring> + </property> + <property name="text"> + <string>Regular e&xpression:</string> + </property> + <property name="toolTip" stdset="0"> + <string>Use regexp to specify target</string> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>regexp_button</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>E&dit</string> + </property> + <property name="toolTip" stdset="0"> + <string>Opens the regexp editor. Only enabled if installed.</string> + </property> + </widget> + </hbox> + </widget> + </vbox> + </widget> + <widget class="KHistoryCombo"> + <property name="name"> + <cstring>regexp_combo</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="toolTip" stdset="0"> + <string>Enter the regexp here</string> + </property> + </widget> + </vbox> + </widget> + <widget class="QButtonGroup" row="2" column="0"> + <property name="name"> + <cstring>buttonGroup1</cstring> + </property> + <property name="title"> + <string>Target Files in Project</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QRadioButton"> + <property name="name"> + <cstring>files_all_radio</cstring> + </property> + <property name="text"> + <string>A&ll files</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="toolTip" stdset="0"> + <string>All files in the project will be considered.</string> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>files_open_radio</cstring> + </property> + <property name="text"> + <string>&Open files only</string> + </property> + <property name="toolTip" stdset="0"> + <string>Only open project files will be considered.</string> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>files_path_radio</cstring> + </property> + <property name="text"> + <string>Files under &path:</string> + </property> + <property name="toolTip" stdset="0"> + <string>Only project files in this dir and its subdirs will be considered.</string> + </property> + </widget> + <widget class="KURLRequester"> + <property name="name"> + <cstring>path_urlreq</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + </widget> + </vbox> + </widget> + <widget class="QLayoutWidget" row="3" column="0"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>expression_varning_label</cstring> + </property> + <property name="font"> + <font> + <bold>1</bold> + </font> + </property> + <property name="text"> + <string>Expression is invalid.</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QPushButton"> + <property name="name"> + <cstring>find_button</cstring> + </property> + <property name="text"> + <string>Fi&nd</string> + </property> + <property name="default"> + <bool>true</bool> + </property> + <property name="toolTip" stdset="0"> + <string>Start looking for possible replacement targets.</string> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>cancel_button</cstring> + </property> + <property name="text"> + <string>&Cancel</string> + </property> + </widget> + </hbox> + </widget> + <widget class="QGroupBox" row="0" column="0"> + <property name="name"> + <cstring>groupBox1</cstring> + </property> + <property name="title"> + <string>Strings</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>&Text to find:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>find_combo</cstring> + </property> + </widget> + <widget class="KHistoryCombo" row="1" column="0"> + <property name="name"> + <cstring>find_combo</cstring> + </property> + <property name="toolTip" stdset="0"> + <string>Target string</string> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>&Replacement text:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>replacement_combo</cstring> + </property> + </widget> + <widget class="KHistoryCombo" row="3" column="0"> + <property name="name"> + <cstring>replacement_combo</cstring> + </property> + <property name="toolTip" stdset="0"> + <string>The replacement string</string> + </property> + </widget> + </grid> + </widget> + </grid> +</widget> +<connections> + <connection> + <sender>cancel_button</sender> + <signal>clicked()</signal> + <receiver>ReplaceDlg</receiver> + <slot>reject()</slot> + </connection> + <connection> + <sender>find_button</sender> + <signal>clicked()</signal> + <receiver>ReplaceDlg</receiver> + <slot>accept()</slot> + </connection> + <connection> + <sender>strings_regexp_radio</sender> + <signal>toggled(bool)</signal> + <receiver>regexp_button</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>files_path_radio</sender> + <signal>toggled(bool)</signal> + <receiver>path_urlreq</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>strings_regexp_radio</sender> + <signal>toggled(bool)</signal> + <receiver>find_combo</receiver> + <slot>setDisabled(bool)</slot> + </connection> + <connection> + <sender>strings_regexp_radio</sender> + <signal>toggled(bool)</signal> + <receiver>regexp_combo</receiver> + <slot>setEnabled(bool)</slot> + </connection> +</connections> +<tabstops> + <tabstop>find_combo</tabstop> + <tabstop>replacement_combo</tabstop> + <tabstop>case_box</tabstop> + <tabstop>strings_all_radio</tabstop> + <tabstop>strings_regexp_radio</tabstop> + <tabstop>regexp_button</tabstop> + <tabstop>regexp_combo</tabstop> + <tabstop>files_all_radio</tabstop> + <tabstop>path_urlreq</tabstop> + <tabstop>find_button</tabstop> + <tabstop>cancel_button</tabstop> + <tabstop>strings_wholewords_radio</tabstop> + <tabstop>files_path_radio</tabstop> +</tabstops> +<includes> + <include location="global" impldecl="in implementation">kdialog.h</include> +</includes> +<layoutdefaults spacing="6" margin="11"/> +<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/> +<includehints> + <includehint>kcombobox.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kurlrequester.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kcombobox.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kcombobox.h</includehint> + <includehint>klineedit.h</includehint> +</includehints> +</UI> diff --git a/parts/replace/replacedlgimpl.cpp b/parts/replace/replacedlgimpl.cpp new file mode 100644 index 00000000..59eee128 --- /dev/null +++ b/parts/replace/replacedlgimpl.cpp @@ -0,0 +1,188 @@ +#include <qcheckbox.h> +#include <qradiobutton.h> +#include <qstring.h> +#include <qregexp.h> +#include <qlabel.h> + +#include <ktrader.h> +#include <kparts/componentfactory.h> +#include <kregexpeditorinterface.h> +#include <kurlrequester.h> +#include <kurlcompletion.h> +#include <klineedit.h> +#include <kcombobox.h> +#include <kdebug.h> + +#include "replacedlgimpl.h" + +namespace +{ +/// @todo This is the same function as in ../grepview/grepviewwidget.cpp and +/// should probably be placed in a common place. For now it seemed like too +/// little code to bother with. +QString escape(const QString &str) +{ + QString escaped("[]{}()\\^$?.+-*"); + QString res; + + for (uint i=0; i < str.length(); ++i) + { + if (escaped.find(str[i]) != -1) + res += "\\"; + res += str[i]; + } + + return res; +} +} + + +ReplaceDlgImpl::ReplaceDlgImpl(QWidget* parent, const char* name, bool modal, WFlags fl) + : ReplaceDlg(parent,name, modal,fl), _regexp_dialog( 0 ) + +{ + connect( find_button, SIGNAL( clicked() ), SLOT( saveComboHistories() ) ); + connect( regexp_button, SIGNAL( clicked() ), SLOT( showRegExpEditor() ) ); + connect( find_combo, SIGNAL( textChanged( const QString & ) ), + SLOT( validateFind( const QString & ) ) ); + connect( regexp_combo, SIGNAL( textChanged ( const QString & ) ), + SLOT( validateExpression( const QString & ) ) ); + connect( strings_regexp_radio, SIGNAL( toggled( bool ) ), SLOT( toggleExpression( bool ) ) ); + + // disable the editor button if the regexp editor isn't installed + if ( KTrader::self()->query("KRegExpEditor/KRegExpEditor").isEmpty() ) + { + strings_regexp_radio->disconnect( regexp_button ); + } + + path_urlreq->completionObject()->setMode(KURLCompletion::DirCompletion); + path_urlreq->setMode( KFile::Directory | KFile::LocalOnly ); + + expression_varning_label->hide(); +} + +ReplaceDlgImpl::~ReplaceDlgImpl() +{} + +void ReplaceDlgImpl::show( QString const & path ) +{ + path_urlreq->lineEdit()->setText( path ); + + find_combo->setCurrentText( "" ); + replacement_combo->setCurrentText( "" ); + regexp_combo->setCurrentText( "" ); + + strings_all_radio->setChecked( true ); + find_combo->setFocus(); + + find_button->setEnabled( false ); + + QDialog::show(); +} + + +void ReplaceDlgImpl::showRegExpEditor() +{ + _regexp_dialog = KParts::ComponentFactory::createInstanceFromQuery<QDialog>( "KRegExpEditor/KRegExpEditor" ); + + if ( _regexp_dialog ) + { + KRegExpEditorInterface *editor = + static_cast<KRegExpEditorInterface *>( _regexp_dialog->qt_cast( "KRegExpEditorInterface" ) ); + + editor->setRegExp( regexp_combo->currentText() ); + + if ( _regexp_dialog->exec() == QDialog::Accepted ) + { + regexp_combo->setCurrentText( editor->regExp() ); + } + } +} + +void ReplaceDlgImpl::validateFind( const QString & ) +{ + //kdDebug(0) << "ReplaceWidget::validateFind()" << endl; + + bool x = find_combo->currentText().isEmpty() && ! strings_regexp_radio->isOn(); + find_button->setEnabled( !x ); +} + +void ReplaceDlgImpl::validateExpression( const QString & ) +{ + //kdDebug(0) << "ReplaceWidget::validateExpression()" << endl; + + QString pattern = regexp_combo->currentText(); + QRegExp re( pattern ); + + if ( pattern.isEmpty() || !re.isValid() ) + { + expression_varning_label->show(); + find_button->setEnabled( false ); + } + else + { + expression_varning_label->hide(); + find_button->setEnabled( true ); + } +} + +void ReplaceDlgImpl::toggleExpression( bool on ) +{ + if ( on ) + { + validateExpression( QString() ); + } + else + { + expression_varning_label->hide(); + find_button->setEnabled( true ); + } +} + +void ReplaceDlgImpl::saveComboHistories() +{ + if ( find_combo->isEnabled() && ! find_combo->currentText().isEmpty() ) + { + find_combo->addToHistory( find_combo->currentText() ); + } + + if ( ! replacement_combo->currentText().isEmpty() ) + { + replacement_combo->addToHistory( replacement_combo->currentText() ); + } + + if ( regexp_combo->isEnabled() && ! regexp_combo->currentText().isEmpty() ) + { + regexp_combo->addToHistory( regexp_combo->currentText() ); + } +} + +QRegExp ReplaceDlgImpl::expressionPattern() +{ + QString pattern = escape( find_combo->currentText() ); + + QRegExp re; + re.setCaseSensitive( case_box->isChecked() ); + re.setMinimal( true ); + + if ( strings_wholewords_radio->isChecked() ) + { + pattern = "\\b" + pattern + "\\b"; + } + else if ( strings_regexp_radio->isChecked() ) + { + pattern = regexp_combo->currentText(); + } + + re.setPattern( pattern ); + + return re; +} + +QString ReplaceDlgImpl::replacementString() +{ + return replacement_combo->currentText(); +} + +#include "replacedlgimpl.moc" + diff --git a/parts/replace/replacedlgimpl.h b/parts/replace/replacedlgimpl.h new file mode 100644 index 00000000..38938bed --- /dev/null +++ b/parts/replace/replacedlgimpl.h @@ -0,0 +1,38 @@ + +#ifndef REPLACEDLGIMPL_H +#define REPLACEDLGIMPL_H + +#include "replacedlg.h" + +class QDialog; + +class ReplaceDlgImpl : public ReplaceDlg +{ + Q_OBJECT + +public: + ReplaceDlgImpl(QWidget* parent = 0, const char* name = 0, bool modal = FALSE, WFlags fl = 0 ); + ~ReplaceDlgImpl(); + + QRegExp expressionPattern(); + QString replacementString(); + +public slots: + void show( QString const & path ); + +protected: + +protected slots: + void showRegExpEditor(); + void validateExpression( const QString & ); + void validateFind( const QString & ); + void toggleExpression( bool ); + void saveComboHistories(); + +private: + QDialog * _regexp_dialog; + +}; + +#endif + diff --git a/parts/replace/replaceitem.cpp b/parts/replace/replaceitem.cpp new file mode 100644 index 00000000..bc33211f --- /dev/null +++ b/parts/replace/replaceitem.cpp @@ -0,0 +1,147 @@ +/*************************************************************************** + * Copyright (C) 2003 by Jens Dagerbo * + * jens.dagerbo@swipnet.se * + * * + * 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 <qpainter.h> +#include <qstyle.h> +#include <qpalette.h> +#include <qcheckbox.h> + +#include "replaceitem.h" + +bool ReplaceItem::s_listview_done = false; + + +bool ReplaceItem::hasCheckedChildren() const +{ + ReplaceItem const * item = firstChild(); + while ( item ) + { + if ( item->isOn() ) + { + return true; + } + item = item->nextSibling(); + } + return false; +} + +void ReplaceItem::stateChange( bool state ) +{ + if ( s_listview_done && justClicked() ) + { + setChecked( state ); + } +} + +void ReplaceItem::setChecked( bool checked ) +{ + if ( !isFile() ) // this is a child item + { + if ( checked || !(parent()->hasCheckedChildren())) + { + if ( parent()->isOn() != checked ) + { + parent()->_clicked = false; + parent()->setOn( checked ); + } + } + return; + } + + // this is a parent item, set self and children + ReplaceItem * item = firstChild(); + while ( item ) + { + if ( item->isOn() != checked ) + { + item->_clicked = false; + item->setOn( checked ); + } + item = item->nextSibling(); + } +} + +// code mostly lifted from QCheckListItem::paintCell() +void ReplaceItem::paintCell( QPainter * p, const QColorGroup & cg, int column, int width, int align ) +{ + if ( !p ) + return; + + QListView *lvv = listView(); + if ( !lvv ) + return; + + ReplaceView * lv = static_cast<ReplaceView*>(lvv); + + const BackgroundMode bgmode = lv->viewport()->backgroundMode(); + const QColorGroup::ColorRole crole = QPalette::backgroundRoleFromMode( bgmode ); + + if ( cg.brush( crole ) != lv->colorGroup().brush( crole ) ) + p->fillRect( 0, 0, width, height(), cg.brush( crole ) ); + else + lv->paintEmptyArea( p, QRect( 0, 0, width, height() ) ); + + QFontMetrics fm( lv->fontMetrics() ); + int boxsize = lv->style().pixelMetric(QStyle::PM_CheckListButtonSize, lv); + int marg = lv->itemMargin(); + int r = marg; + + // Draw controller / checkbox / radiobutton --------------------- + int styleflags = QStyle::Style_Default; + if ( isOn() ) + styleflags |= QStyle::Style_On; + else + styleflags |= QStyle::Style_Off; + if ( isSelected() ) + styleflags |= QStyle::Style_Selected; + if ( isEnabled() && lv->isEnabled() ) + styleflags |= QStyle::Style_Enabled; + + int x = 0; + int y = 0; + + x += 3; + + if ( align & AlignVCenter ) + y = ( ( height() - boxsize ) / 2 ) + marg; + + else + y = (fm.height() + 2 + marg - boxsize) / 2; + + lv->style().drawPrimitive(QStyle::PE_CheckListIndicator, p, + QRect(x, y, boxsize, + fm.height() + 2 + marg), + cg, styleflags, QStyleOption(this)); + + r += boxsize + 4; + + // Draw text ---------------------------------------------------- + p->translate( r, 0 ); + p->setPen( QPen( cg.text() ) ); + + QColorGroup mcg = cg; + mcg.setColor( QColorGroup::Text, ( isFile() ? Qt::darkGreen : Qt::blue ) ); + mcg.setColor( QColorGroup::HighlightedText, ( isFile() ? Qt::darkGreen : Qt::blue ) ); + + QListViewItem::paintCell( p, mcg, column, width - r, align ); +} + +void ReplaceItem::activate( int, QPoint const & localPos ) +{ + QListView * lv = listView(); + QCheckBox cb(0); + int boxsize = cb.sizeHint().width(); +//that's KDE-3.1 only int boxsize = lv->style().pixelMetric(QStyle::PM_CheckListButtonSize, lv); + int rightside = lv->itemMargin() + boxsize + ( isFile() ? 0 : lv->treeStepSize() ); + + // _lineclicked indicates if the click was on the line or in the checkbox + _lineclicked = rightside < localPos.x(); +} diff --git a/parts/replace/replaceitem.h b/parts/replace/replaceitem.h new file mode 100644 index 00000000..a6bc8ffb --- /dev/null +++ b/parts/replace/replaceitem.h @@ -0,0 +1,113 @@ +/*************************************************************************** + * Copyright (C) 2003 by Jens Dagerbo * + * jens.dagerbo@swipnet.se * + * * + * 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 __REPLACEITEM_H__ +#define __REPLACEITEM_H__ + + +#include <kdeversion.h> +#include <kdebug.h> + +#include "replaceview.h" + +class ReplaceItem : public QCheckListItem +{ +public: + // the file item + ReplaceItem( ReplaceView * parent, ReplaceItem * after, QString file ) : + QCheckListItem( parent, + after, + file, QCheckListItem::CheckBox ), + _file( file ), _string( file ), _line( 0 ), _isfile( true ), + _lineclicked( false ), _clicked( true ) + { + setOpen( true ); + setOn( true ); + } + + // the line item + ReplaceItem( ReplaceItem * parent, ReplaceItem * after, QString file, QString string, int line ) : + QCheckListItem( parent, + after, + QString::number( line + 1 ) + ": " + string, QCheckListItem::CheckBox ), + _file( file ), _string( string ), _line( line ), _isfile( false ), + _lineclicked( false ), _clicked( true ) + { + setOn( true ); + } + + QString const & file() const + { + return _file; + } + + int line() const + { + return _line; + } + + QString const & string() const + { + return _string; + } + + bool isFile() const + { + return _isfile; + } + + bool justClicked() + { + bool t = _clicked; + _clicked = true; + return t; + } + + bool lineClicked() + { + return _lineclicked; + } + + ReplaceItem * parent() const + { + return static_cast<ReplaceItem*>( QListViewItem::parent() ); + } + + ReplaceItem * firstChild() const + { + return static_cast<ReplaceItem*>( QListViewItem::firstChild() ); + } + + ReplaceItem * nextSibling() const + { + return static_cast<ReplaceItem*>( QListViewItem::nextSibling() ); + } + + void activate( int column, QPoint const & localPos ); + bool hasCheckedChildren() const; + virtual void stateChange( bool state ); + + static bool s_listview_done; + +private: + void paintCell( QPainter * p, const QColorGroup & cg, int column, int width, int align ); + void setChecked( bool checked ); + + QString _file; + QString _string; + int _line; + bool const _isfile; + bool _lineclicked; + bool _clicked; +}; + +#endif + diff --git a/parts/replace/replaceview.cpp b/parts/replace/replaceview.cpp new file mode 100644 index 00000000..7a7505d7 --- /dev/null +++ b/parts/replace/replaceview.cpp @@ -0,0 +1,141 @@ +/*************************************************************************** + * Copyright (C) 2003 by Jens Dagerbo * + * jens.dagerbo@swipnet.se * + * * + * 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 <qheader.h> +#include <qtextstream.h> +#include <qdir.h> +#include <qstringlist.h> +#include <qregexp.h> +#include <qpalette.h> + +#include "replaceitem.h" +#include "replaceview.h" + + + +ReplaceItem * ReplaceView::firstChild() const +{ + return static_cast<ReplaceItem*>( QListView::firstChild() ); +} + + +ReplaceView::ReplaceView( QWidget * parent ) : KListView( parent ), _latestfile( 0 ) +{ + setSorting( -1 ); + addColumn( "" ); + header()->hide(); + setFullWidth(true); + + QPalette pal = palette(); + QColorGroup cg = pal.active(); + cg.setColor( QColorGroup::Highlight, Qt::lightGray ); + pal.setActive( cg ); + setPalette( pal ); + + connect( this, SIGNAL( clicked( QListViewItem * ) ), SLOT( slotClicked( QListViewItem * ) ) ); + connect( this, SIGNAL( mouseButtonPressed( int, QListViewItem *, const QPoint &, int) ), + SLOT( slotMousePressed(int, QListViewItem *, const QPoint &, int) ) ); +} + +void ReplaceView::makeReplacementsForFile( QTextStream & istream, QTextStream & ostream, ReplaceItem const * fileitem ) +{ + int line = 0; + + ReplaceItem const * lineitem = fileitem->firstChild(); + while ( lineitem ) + { + if ( lineitem->isOn() ) + { + while ( line < lineitem->line() ) + { + ostream << istream.readLine() << "\n"; + line++; + } + // this is the hit + ostream << istream.readLine().replace( _regexp, _replacement ) << "\n"; + line++; + } + + lineitem = lineitem->nextSibling(); + } + + while ( !istream.atEnd() ) + { + ostream << istream.readLine() << "\n"; + } +} + +void ReplaceView::showReplacementsForFile( QTextStream & stream, QString const & file ) +{ + ReplaceItem * latestitem = 0; + + int line = 0; + bool firstline = true; + + while ( !stream.atEnd() ) + { + QString s = stream.readLine(); + + if ( s.contains( _regexp ) > 0 ) + { + s.replace( _regexp, _replacement ); + + if ( firstline ) + { + _latestfile = new ReplaceItem( this, _latestfile, file ); + firstline = false; + } + latestitem = new ReplaceItem( _latestfile, latestitem, file, s.stripWhiteSpace(), line ); + _latestfile->insertItem( latestitem ); + } + line++; + } +} + +void ReplaceView::setReplacementData( QRegExp const & re, QString const & replacement ) +{ + _regexp = re; + _replacement = replacement; +} + +void ReplaceView::slotMousePressed(int btn, QListViewItem* i, const QPoint& pos, int col) +{ + kdDebug(0) << "ReplaceView::slotMousePressed()" << endl; + + if ( ReplaceItem * item = dynamic_cast<ReplaceItem*>( i ) ) + { + if ( btn == Qt::RightButton ) + { + // popup menu? + } + else if ( btn == Qt::LeftButton ) + { + // map pos to item/column and call ReplacetItem::activate(pos) + item->activate( col, viewport()->mapFromGlobal( pos ) - QPoint( 0, itemRect(item).top() ) ); + } + } +} + +void ReplaceView::slotClicked( QListViewItem * item ) +{ + kdDebug(0) << "ReplaceView::slotClicked()" << endl; + + if ( ReplaceItem * ri = dynamic_cast<ReplaceItem*>( item ) ) + { + if ( ri->lineClicked() ) + { + kdDebug(0) << "emitting editDocument" << endl; + emit editDocument( ri->file(), ri->line() ); + } + } +} + +#include "replaceview.moc" diff --git a/parts/replace/replaceview.h b/parts/replace/replaceview.h new file mode 100644 index 00000000..02ba60c9 --- /dev/null +++ b/parts/replace/replaceview.h @@ -0,0 +1,54 @@ +/*************************************************************************** + * Copyright (C) 2003 by Jens Dagerbo * + * jens.dagerbo@swipnet.se * + * * + * 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 __REPLACEVIEW_H__ +#define __REPLACEVIEW_H__ + +#include <klistview.h> + +#include <qstring.h> +#include <qregexp.h> + +class QTextStream; +class QWidget; +class ReplaceItem; + +class ReplaceView : public KListView +{ + Q_OBJECT + +signals: + void editDocument( const QString &, int ); + +public: + ReplaceView( QWidget *); + ReplaceItem * firstChild() const; + void setReplacementData( QRegExp const &, QString const & ); + void showReplacementsForFile( QTextStream &, QString const & ); + void makeReplacementsForFile( QTextStream & istream, QTextStream & ostream, ReplaceItem const * fileitem ); + +private slots: + void slotMousePressed(int, QListViewItem *, const QPoint &, int); + void slotClicked( QListViewItem * ); + +private: + QRegExp _regexp; + QString _replacement; + ReplaceItem * _latestfile; + +friend class ReplaceItem; + +}; + + + + +#endif |