diff options
Diffstat (limited to 'kfind')
39 files changed, 4008 insertions, 0 deletions
diff --git a/kfind/AUTHORS b/kfind/AUTHORS new file mode 100644 index 000000000..cf0c32eb6 --- /dev/null +++ b/kfind/AUTHORS @@ -0,0 +1,18 @@ +kfind has been developed by : + + Eric Coquelle <coquelle@caramail.com> + Beppe Grimaldi <grimalkin@ciaoweb.it> + Martin Hartig + Stephan Kulow <coolo@kde.org> + Mario Weilguni <mweilguni@sime.com> + Alex Zepeda <zipzippy@sonic.net> + Miroslav Fl�r <flidr@kky.zcu.cz> + Harri Porten <porten@kde.org> + Dima Rogozin <dima@mercury.co.il> + Carsten Pfeiffer <pfeiffer@kde.org> + Hans Petter Bieker <bieker@kde.org> + Waldo Bastian <bastian@kde.org> + Alexander Neundorf <neundorf@kde.org> + Albert R. Valiev <arkstone@mail.ru> + Clarence Dang <dang@kde.org> + diff --git a/kfind/ChangeLog b/kfind/ChangeLog new file mode 100644 index 000000000..c13408a52 --- /dev/null +++ b/kfind/ChangeLog @@ -0,0 +1,141 @@ +Fri Jul 30 22:33:25 1999 Carsten Pfeiffer <pfeiffer@kde.org> + + * kfwin.cpp, kfwin.h: The listview items show a mini-pixmap, like those + in kfiledialog. For now, they're static icons (only folder and document + icons), maybe we can show the correct icons for the mimetypes, later. + + Also introduced drag-support, you can drag files from the list. + + * kftabdlg.cpp: accept Key_Enter to start the search, too. + +1999-06-13 Harri Porten <porten@kde.org> + + * kftabdlg.cpp: introduced flexible geometry managment. Patch provided + by Dima Rogozin <dima@mercury.co.il>. + +1999-04-30 Harri Porten <porten@kde.org> + + * kftabdlg.cpp: Default to '*' when no filenames are specified and + allow case insensitive text search. Patch provided by Dima Rogozin + <dima@mercury.co.il>. + +1999-04-06 Harri Porten <porten@kde.org> + + * kfind.cpp: replaced simple delete and free() with delete [] iBuffer + +1998-12-07 Mario Weilguni <mweilguni@kde.org> + + * made it work with Qt 2.0 + +1998-12-07 Alex Zepeda <garbanzo@hooked.net> + + * kfindtop.cpp: Commented out _height, as it's not used. + +1998-11-30 Miroslav Fldr <flidr@kky.zcu.cz> + + * Dissabled multiple selection in view because it was not fully + handled + * Fixed problem in nameBox, dirBox combos which caused improper + find query generation (it is still neccesary to fix multiplication of + list entries) + +1998-10-23 Alex Zepeda <garbanzo@hooked.net> + + * LICENSE: remove it, it's redundant. + + * kfind/README: Tidy up, and mention inclusion in kdebase. + +ver. 0.4.1: Mario Weilguni <mweilguni@kde.org> + * temporary files are no longer needed + * found files are now shown while searching + * KDE compliant "Help" menu + * max-/min-size box is now disabled per default + * GUI is disabled while searching, makes it easier to see + progress + * kfind compiles now without warnings with -Wall + * result list is now scrollable without having the focus (only page + up and page down) + * moc files are now #included in moc.cpp instead of compiling + separate files. Speeds up compilation and makes binary smaller + * file patterns are remembered between sessions + * introduced new filetypes for searching: files, folders, + symlinks, special files, executables, suid executables + * better keyboard support + +ver. 0.4: Mario Weilguni <mweilguni@kde.org> + * introduced this ChangeLog + * kfind now uses KShellProcess instead of KProcess, makes + regular expression search possible with egrep/xargs + * kftabdlg.cpp: tab-dialog isn't closed anymore if Escape key + is pressed + * kfind can now search for contained text (with egrep) + * "Select All" and "Invert Selection" work now as expected + * "Copy" copies the currently selected items to the X11 selection + * "Unselect All" added for completeness + +ver. 0.3.4: + + o removed some resizing problems + o kfinds icons now uses only 16 color + o mimetype browser removed from preferences + (something like that should be in kcc) + o kfind sets icon for kwmII + +ver. 0.3.3: + + o uses KProcess + o supports other languages then english (at this time german and czech) + +ver. 0.3.2: + + o uses KTopLevelWidget and KToolBar + o new documentations + +ver. 0.3.1: + o new documentation contributed by Mark Roberts + +ver. 0.3: + o entry Open in File menu or doubleclick on file executes default binding + o removed bug causing segfaults + +ver. 0.2.9: + o uses of autoconf + o you can specify searched directory as kfind argument + o added Icon entry in all provided filetypes (some were + missing this entry and kfm didn't liked it) + +ver. 0.2.8: + o kfind is now KDE AWARE application!! + o uses libkde0.7 (=> kmsgbox and ktabctl removed from kfind distribution) + o uses filetypes introduced by Torben Weis for kfm (kfind installs + some more filetypes) + o it is possible to store files in archives + o preferences dialog added + - it is possible to determine filename for results saving + - it is possible to browse available filetypes details + - it is possible to browse available archivers details + (in next version you will be able to change the details) + o calls kfm for properties dialog + o menu entry "remove" removed (kfm properties dialog does the job) + o removed some bugs + +ver. 0.2.6: + o reflects changes made by Martin Hartig (known as version 0.2.1) + +ver. 0.2.5: + o implemented dir selection box (it is actually a littlebit changed + and striped down version of QFileDialog) + o delete, rename, properties functions are implemented + o function "Open containing folder" implemented (it calls KFM) + o search results are now saved in file ~/.kfind-results.html + (I finally recognized this is better choice than plain text file) + o removed nasty bug causing segfaults when compiler optimization were + used + o improved Makefile + +ver. 0.2: + o all in kfind available options work now ;-)) + o better calling of find. It's now separate process => interface isn't + blocked anymore during searching + +ver. 0.1: first official release diff --git a/kfind/Kfind.desktop b/kfind/Kfind.desktop new file mode 100644 index 000000000..96a8e3e5b --- /dev/null +++ b/kfind/Kfind.desktop @@ -0,0 +1,79 @@ +[Desktop Entry] +Exec=kfind %f +Icon=kfind +DocPath=kfind/index.html +Path= +Type=Application +Terminal=false +Name=Find Files/Folders +Name[af]=Soek Lêers/Gidse +Name[ar]=إبحث عن ملفات/مجلّدات +Name[be]=Шукаць файлы/тэчкі +Name[bg]=Търсене на файлове +Name[bn]=ফাইল/ফোল্ডার অনুসন্ধান +Name[br]=Klask restroù/renkelloù +Name[bs]=Pronađi datoteke +Name[ca]=Cerca fitxers i carpetes +Name[cs]=Najít soubory/složky +Name[csb]=Szëkba lopków/katalogów +Name[da]=Find filer/mapper +Name[de]=Dateien/Ordner suchen +Name[el]=Αναζήτηση αρχείων/φακέλων +Name[eo]=Trovu Dosierojn/Dosierujojn +Name[es]=Buscar archivos/carpetas +Name[et]=Failide/kataloogide otsimine +Name[eu]=Bilatu fitxategiak/karpetak +Name[fa]=یافتن پروندهها/پوشهها +Name[fi]=Etsi tiedostoja ja kansioita +Name[fr]=Recherche de fichiers/dossiers +Name[fy]=Triemmen/mappen sykje +Name[ga]=Aimsigh Comhaid/Comhadlanna +Name[gl]=Buscar Ficheiros/Cartafoles +Name[he]=חפש קבצים או תיקיות +Name[hr]=Traži datoteke/mape +Name[hu]=Fájlkereső +Name[is]=Finna skrár/möppur +Name[it]=Trova file/cartelle +Name[ja]=ファイル/フォルダを検索 +Name[ka]=ფაილთა და საქაღალდეთა ძიება +Name[kk]=Файлды не қапшықты табу +Name[km]=រកឯកសារ/ថត +Name[ko]=파일/폴더 찾기 +Name[lt]=Rasti bylas/aplankus +Name[lv]=Meklēt Failus/Mapes +Name[mk]=Пронајди датотеки/папки +Name[ms]=Cari Fail/Folder +Name[nb]=Finn filer/mapper +Name[nds]=Dateien/Ornern söken +Name[ne]=फाइल/फोल्डर फेला पार्नुहोस् +Name[nl]=Bestanden/mappen zoeken +Name[nn]=Finn filer/mapper +Name[pa]=ਫਾਇਲ/ਫੋਲਡਰ ਖੋਜ +Name[pl]=Wyszukiwanie plików/katalogów +Name[pt]=Procurar Ficheiros/Pastas +Name[pt_BR]=Procurar arquivos/pastas +Name[ro]=Caută fișiere/foldere +Name[ru]=Поиск файлов и папок +Name[rw]=Gushaka Amadosiye/Ububiko +Name[se]=Oza fiillaid dahje máhpaid +Name[sk]=Hľadať súbory/priečinky +Name[sl]=Najdi datoteke in mape +Name[sr]=Тражење фајлова/фасцикли +Name[sr@Latn]=Traženje fajlova/fascikli +Name[sv]=Hitta filer eller kataloger +Name[ta]=கோப்புகள்/அடைவுகளைக் கண்டுபிடி +Name[te]=దస్త్రాలు/ఫొల్డర్లను వెతుకు +Name[tg]=Ҷустуҷӯи файлҳо ва феҳрастҳо +Name[th]=ค้นหาแฟ้ม/โฟลเดอร์ +Name[tr]=Dosya/Dizin Bul +Name[tt]=Birem/Törgäk Ezläw +Name[uk]=Пошук файлів та тек +Name[uz]=Fayl/jildlarni qidirish +Name[uz@cyrillic]=Файл/жилдларни қидириш +Name[vi]=Tìm Tập tin/Thư mục +Name[wa]=Trover des fitchîs/ridants +Name[zh_CN]=查找文件/文件夹 +Name[zh_TW]=尋找檔案/資料夾 +X-KDE-StartupNotify=true +OnlyShowIn=KDE; +Categories=Qt;KDE;Core; diff --git a/kfind/Makefile.am b/kfind/Makefile.am new file mode 100644 index 000000000..a4f53b1b7 --- /dev/null +++ b/kfind/Makefile.am @@ -0,0 +1,36 @@ +#Global section +METASOURCES = AUTO +EXTRA_DIST = DESCRIPTION +SUBDIRS = pics +KDE_ICON = kfind +# set the include path for X, qt and KDE +INCLUDES= -I$(top_srcdir)/libkonq $(all_includes) + +noinst_LTLIBRARIES = libkfind_common.la +libkfind_common_la_SOURCES = kftabdlg.cpp kfind.cpp kquery.cpp kdatecombo.cpp + +#This section is kfindpart +kde_module_LTLIBRARIES = libkfindpart.la + +libkfindpart_la_SOURCES = kfindpart.cpp +libkfindpart_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) +libkfindpart_la_LIBADD = libkfind_common.la $(LIB_KPARTS) $(top_builddir)/libkonq/libkonq.la + +noinst_HEADERS = kftabdlg.h kfind.h version.h kquery.h kdatecombo.h + +xdg_apps_DATA = Kfind.desktop + +kde_services_DATA = kfindpart.desktop +kde_servicetypes_DATA = findpart.desktop + +messages: + $(XGETTEXT) *.cpp *.h -o $(podir)/kfindpart.pot + +#And this is for kfind + +bin_PROGRAMS = kfind +kfind_SOURCES = kfwin.cpp kfinddlg.cpp main.cpp +kfind_LDADD = libkfind_common.la $(LIB_KPARTS) + +# the library search path. +kfind_LDFLAGS = $(all_libraries) $(KDE_RPATH) diff --git a/kfind/README b/kfind/README new file mode 100644 index 000000000..7b6c24890 --- /dev/null +++ b/kfind/README @@ -0,0 +1,24 @@ +kfind +===== + +Kfind is a graphical replacement for the utility `find' inspired by +the find utility from NT. + +At this time it is fully functional. All options available in kfind +are working. You can save the results, delete, change properties of +found files/directories and ask konqueror to open the directory +containing this file or execute default binding. + +THANKS +------ + +I want to thank Alexander Sanda <alex@darkstar.ping.at> for making +KTabCtl which is used in Kfind and Torben Weis +<weis@stud.uni-frankfurt.de> for his wonderful file manager konqueror. + + +I hope you will find this program somehow useful and I would +appreciate any suggestions and comments. + + Miroslav Fldr + <flidr@kky.zcu.cz> diff --git a/kfind/TODO b/kfind/TODO new file mode 100644 index 000000000..0bf6ac832 --- /dev/null +++ b/kfind/TODO @@ -0,0 +1,13 @@ +TODO +==== + + o support the more esoterical features of find + +DONE: + + o drag found files to somewhere + o some layout managment + o context menus + o get preference dialog to work + o find pattern history + o support for finding files belonging to somebody diff --git a/kfind/findpart.desktop b/kfind/findpart.desktop new file mode 100644 index 000000000..9b33894e3 --- /dev/null +++ b/kfind/findpart.desktop @@ -0,0 +1,82 @@ +[Desktop Entry] +Type=ServiceType +X-KDE-ServiceType=Konqueror/FindPart +X-KDE-Derived=Browser/View +Name=Find Part +Name[af]=Soek Deel +Name[ar]=ابحث عن جزء +Name[az]=Parça tap +Name[be]=Модуль пошуку +Name[bg]=Търсене на модули +Name[bn]=পার্ট অনুসন্ধান +Name[br]=Kavout perzh +Name[bs]=Nađi dio +Name[ca]=Cerca la part +Name[cs]=Najít soubor +Name[csb]=Mòduł szëkbë +Name[cy]=Canfod Rhan +Name[da]=Find del +Name[de]=Einbettungsfähiges Programm (Komponente) suchen +Name[el]=Part Αναζήτηση +Name[eo]=Trovokomponento +Name[es]=Buscar parte +Name[et]=Failide otsimise komponent +Name[eu]=Bilatu partea +Name[fa]=یافتن جزء +Name[fi]=Etsi osa +Name[fr]=Composant de recherche +Name[fy]=In diel sykje +Name[ga]=Aimsigh Páirt +Name[gl]=Busca +Name[he]=רכיב חיפוש +Name[hi]=हिस्सा ढूंढें +Name[hr]=Pronađi dio +Name[hu]=Keresési objektum +Name[id]=Cari bagian +Name[is]=Finna hluti +Name[it]=Trova parte +Name[ja]=検索パート +Name[ka]=ძიება შემადგენლობის მიხედვით +Name[kk]=Мазмұнынан табу +Name[km]=រកផ្នែក +Name[ko]=찾기 부분 +Name[lo]=ຄັ້ນຫາບາງສ່ວນ +Name[lt]=Surasti dalį +Name[lv]=Meklēt Daļu +Name[mk]=Пронајди дел +Name[mn]=Хэсэг хайх +Name[ms]=Cari Bahagian +Name[mt]=Sib Parti +Name[nb]=Finn del +Name[nds]=Söök-Komponent +Name[ne]=भाग फेला पार्नुहोस् +Name[nl]=Gedeelte zoeken +Name[nn]=Finn del +Name[nso]=Hwetsa Seripa +Name[pa]=ਹਿੱਸੇ ਖੋਜ +Name[pl]=Moduł szukania +Name[pt]=Componente de Pesquisa +Name[pt_BR]=Componente de Busca +Name[ro]=Componentă de căutare +Name[ru]=Поиск по содержимому +Name[rw]=Gushaka Igice +Name[se]=Oza osiid +Name[sk]=Nájsť Part +Name[sl]=Najdi del +Name[sr]=Део за тражење +Name[sr@Latn]=Deo za traženje +Name[sv]=Sökdel +Name[ta]=பகுதி கண்டுபிடி +Name[te]=వెతుకు భాగం +Name[tg]=Қисматро пайдо кунед +Name[th]=ค้นหาบางส่วน +Name[tr]=Parça bul +Name[tt]=Eçtälek Ezläw +Name[uk]=Складова пошуку +Name[ven]=Todani tshipida +Name[vi]=Tìm từng phần +Name[wa]=Trover des pårteyes +Name[xh]=Fumana Indawana +Name[zh_CN]=查找部件 +Name[zh_TW]=尋找組件 +Name[zu]=Thola Ingxenye diff --git a/kfind/hi16-app-kfind.png b/kfind/hi16-app-kfind.png Binary files differnew file mode 100644 index 000000000..f2b60daa7 --- /dev/null +++ b/kfind/hi16-app-kfind.png diff --git a/kfind/hi22-app-kfind.png b/kfind/hi22-app-kfind.png Binary files differnew file mode 100644 index 000000000..647dc2196 --- /dev/null +++ b/kfind/hi22-app-kfind.png diff --git a/kfind/hi32-app-kfind.png b/kfind/hi32-app-kfind.png Binary files differnew file mode 100644 index 000000000..171c2b1d2 --- /dev/null +++ b/kfind/hi32-app-kfind.png diff --git a/kfind/hi48-app-kfind.png b/kfind/hi48-app-kfind.png Binary files differnew file mode 100644 index 000000000..1d472379a --- /dev/null +++ b/kfind/hi48-app-kfind.png diff --git a/kfind/hi64-app-kfind.png b/kfind/hi64-app-kfind.png Binary files differnew file mode 100644 index 000000000..fa5b5f0c4 --- /dev/null +++ b/kfind/hi64-app-kfind.png diff --git a/kfind/kdatecombo.cpp b/kfind/kdatecombo.cpp new file mode 100644 index 000000000..c5f9e4553 --- /dev/null +++ b/kfind/kdatecombo.cpp @@ -0,0 +1,131 @@ +/*********************************************************************** + * + * kdatecombo.cpp + * + ***********************************************************************/ + +#include <qtimer.h> + +#include <kglobal.h> +#include <klocale.h> +#include <kdatepicker.h> +#include <kdatetbl.h> +#include <kdebug.h> + +#include "kdatecombo.h" + +#include "kdatecombo.moc" + +KDateCombo::KDateCombo(QWidget *parent, const char *name ) : QComboBox(FALSE, parent,name) +{ + QDate date = QDate::currentDate(); + initObject(date, parent, name); +} + +KDateCombo::KDateCombo(const QDate & date, QWidget *parent, const char *name) : QComboBox(FALSE, parent,name) +{ + initObject(date, parent, name); +} + +void KDateCombo::initObject(const QDate & date, QWidget *, const char *) +{ + clearValidator(); + popupFrame = new KPopupFrame(this, "popupFrame"); + popupFrame->installEventFilter(this); + datePicker = new KDatePicker(popupFrame, date, "datePicker"); + datePicker->setMinimumSize(datePicker->sizeHint()); + datePicker->installEventFilter(this); + popupFrame->setMainWidget(datePicker); + setDate(date); + + connect(datePicker, SIGNAL(dateSelected(QDate)), this, SLOT(dateEnteredEvent(QDate))); +} + +KDateCombo::~KDateCombo() +{ + delete datePicker; + delete popupFrame; +} + +QString KDateCombo::date2String(const QDate & date) +{ + return(KGlobal::locale()->formatDate(date, true)); +} + +QDate & KDateCombo::string2Date(const QString & str, QDate *qd) +{ + return *qd = KGlobal::locale()->readDate(str); +} + +QDate & KDateCombo::getDate(QDate *currentDate) +{ + return string2Date(currentText(), currentDate); +} + +bool KDateCombo::setDate(const QDate & newDate) +{ + if (newDate.isValid()) + { + if (count()) + clear(); + insertItem(date2String(newDate)); + return TRUE; + } + return FALSE; +} + +void KDateCombo::dateEnteredEvent(QDate newDate) +{ + if (!newDate.isValid()) + newDate = datePicker->date(); + popupFrame->hide(); + setDate(newDate); +} + +void KDateCombo::mousePressEvent (QMouseEvent * e) +{ + if (e->button() & QMouseEvent::LeftButton) + { + if (rect().contains( e->pos())) + { + QDate tempDate; + getDate(& tempDate); + datePicker->setDate(tempDate); + popupFrame->popup(mapToGlobal(QPoint(0, height()))); + //datePicker->setFocus(); + } + } +} + +bool KDateCombo::eventFilter (QObject*, QEvent* e) +{ + if ( e->type() == QEvent::MouseButtonPress ) + { + QMouseEvent *me = (QMouseEvent *)e; + QPoint p = mapFromGlobal( me->globalPos() ); + if (rect().contains( p ) ) + { + QTimer::singleShot(10, this, SLOT(dateEnteredEvent())); + return true; + } + } + else if ( e->type() == QEvent::KeyRelease ) + { + QKeyEvent *k = (QKeyEvent *)e; + //Press return == pick selected date and close the combo + if((k->key()==Qt::Key_Return)||(k->key()==Qt::Key_Enter)) + { + dateEnteredEvent(datePicker->date()); + return true; + } + else if (k->key()==Qt::Key_Escape) + { + popupFrame->hide(); + return true; + } + else + return false; + } + + return false; +} diff --git a/kfind/kdatecombo.h b/kfind/kdatecombo.h new file mode 100644 index 000000000..12f66174a --- /dev/null +++ b/kfind/kdatecombo.h @@ -0,0 +1,49 @@ +/*********************************************************************** + * + * kdatecombo.h + * + ***********************************************************************/ + +#ifndef KDATECOMBO_H +#define KDATECOMBO_H + +#include <qwidget.h> +#include <qcombobox.h> +#include <qdatetime.h> + +/** + *@author Beppe Grimaldi + */ + +class KDatePicker; +class KPopupFrame; + +class KDateCombo : public QComboBox { + Q_OBJECT + +public: + KDateCombo(QWidget *parent=0, const char *name=0); + KDateCombo(const QDate & date, QWidget *parent=0, const char *name=0); + ~KDateCombo(); + + QDate & getDate(QDate *currentDate); + bool setDate(const QDate & newDate); + +private: + KPopupFrame * popupFrame; + KDatePicker * datePicker; + + void initObject(const QDate & date, QWidget *parent, const char *name); + + QString date2String(const QDate &); + QDate & string2Date(const QString &, QDate * ); + +protected: + bool eventFilter (QObject*, QEvent*); + virtual void mousePressEvent (QMouseEvent * e); + +protected slots: + void dateEnteredEvent(QDate d=QDate()); +}; + +#endif diff --git a/kfind/kfind.cpp b/kfind/kfind.cpp new file mode 100644 index 000000000..93c646a91 --- /dev/null +++ b/kfind/kfind.cpp @@ -0,0 +1,192 @@ +/*********************************************************************** + * + * Kfind.cpp + * + * This is KFind, released under GPL + * + * 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. + * + * KFind (c) 1998-2003 The KDE Developers + Martin Hartig + Stephan Kulow <coolo@kde.org> + Mario Weilguni <mweilguni@sime.com> + Alex Zepeda <zipzippy@sonic.net> + Miroslav Fldr <flidr@kky.zcu.cz> + Harri Porten <porten@kde.org> + Dima Rogozin <dima@mercury.co.il> + Carsten Pfeiffer <pfeiffer@kde.org> + Hans Petter Bieker <bieker@kde.org> + Waldo Bastian <bastian@kde.org> + Beppe Grimaldi <grimalkin@ciaoweb.it> + Eric Coquelle <coquelle@caramail.com> + + **********************************************************************/ + +#include <kpushbutton.h> +#include <qlayout.h> +#include <qvbox.h> + +#include <kdialog.h> +#include <kdebug.h> +#include <klocale.h> +#include <kseparator.h> +#include <qlineedit.h> +#include <qcheckbox.h> +#include <kstdguiitem.h> + +#include "kftabdlg.h" +#include "kquery.h" + +#include "kfind.moc" + +Kfind::Kfind(QWidget *parent, const char *name) + : QWidget( parent, name ) +{ + kdDebug() << "Kfind::Kfind " << this << endl; + QBoxLayout * mTopLayout = new QBoxLayout( this, QBoxLayout::LeftToRight, + KDialog::marginHint(), KDialog::spacingHint() ); + + // create tabwidget + tabWidget = new KfindTabWidget( this ); + mTopLayout->addWidget(tabWidget); + + /* + * This is ugly. Might be a KSeparator bug, but it makes a small black + * pixel for me which is visually distracting (GS). + // create separator + KSeparator * mActionSep = new KSeparator( this ); + mActionSep->setFocusPolicy( QWidget::ClickFocus ); + mActionSep->setOrientation( QFrame::VLine ); + mTopLayout->addWidget(mActionSep); + */ + + // create button box + QVBox * mButtonBox = new QVBox( this ); + QVBoxLayout *lay = (QVBoxLayout*)mButtonBox->layout(); + lay->addStretch(1); + mTopLayout->addWidget(mButtonBox); + + mSearch = new KPushButton( KGuiItem(i18n("&Find"), "find"), mButtonBox ); + mButtonBox->setSpacing( (tabWidget->sizeHint().height()-4*mSearch->sizeHint().height()) / 4); + connect( mSearch, SIGNAL(clicked()), this, SLOT( startSearch() ) ); + mStop = new KPushButton( KGuiItem(i18n("Stop"), "stop"), mButtonBox ); + connect( mStop, SIGNAL(clicked()), this, SLOT( stopSearch() ) ); + mSave = new KPushButton( KStdGuiItem::saveAs(), mButtonBox ); + connect( mSave, SIGNAL(clicked()), this, SLOT( saveResults() ) ); + + KPushButton * mClose = new KPushButton( KStdGuiItem::close(), mButtonBox ); + connect( mClose, SIGNAL(clicked()), this, SIGNAL( destroyMe() ) ); + + // react to search requests from widget + connect( tabWidget, SIGNAL(startSearch()), this, SLOT( startSearch() ) ); + + mSearch->setEnabled(true); // Enable "Search" + mStop->setEnabled(false); // Disable "Stop" + mSave->setEnabled(false); // Disable "Save..." + + dirlister=new KDirLister(); +} + +Kfind::~Kfind() +{ + stopSearch(); + dirlister->stop(); + delete dirlister; + kdDebug() << "Kfind::~Kfind" << endl; +} + +void Kfind::setURL( const KURL &url ) +{ + tabWidget->setURL( url ); +} + +void Kfind::startSearch() +{ + tabWidget->setQuery(query); + emit started(); + + //emit resultSelected(false); + //emit haveResults(false); + + mSearch->setEnabled(false); // Disable "Search" + mStop->setEnabled(true); // Enable "Stop" + mSave->setEnabled(false); // Disable "Save..." + + tabWidget->beginSearch(); + + dirlister->openURL(KURL(tabWidget->dirBox->currentText().stripWhiteSpace())); + + query->start(); +} + +void Kfind::stopSearch() +{ + // will call KFindPart::slotResult, which calls searchFinished here + query->kill(); +} + +/* +void Kfind::newSearch() +{ + // WABA: Not used any longer? + stopSearch(); + + tabWidget->setDefaults(); + + emit haveResults(false); + emit resultSelected(false); + + setFocus(); +} +*/ + +void Kfind::searchFinished() +{ + mSearch->setEnabled(true); // Enable "Search" + mStop->setEnabled(false); // Disable "Stop" + // ## TODO mSave->setEnabled(true); // Enable "Save..." + + tabWidget->endSearch(); + setFocus(); +} + + +void Kfind::saveResults() +{ + // TODO +} + +void Kfind::setFocus() +{ + tabWidget->setFocus(); +} + +void Kfind::saveState( QDataStream *stream ) +{ + query->kill(); + *stream << tabWidget->nameBox->currentText(); + *stream << tabWidget->dirBox->currentText(); + *stream << tabWidget->typeBox->currentItem(); + *stream << tabWidget->textEdit->text(); + *stream << (int)( tabWidget->subdirsCb->isChecked() ? 0 : 1 ); +} + +void Kfind::restoreState( QDataStream *stream ) +{ + QString namesearched, dirsearched,containing; + int typeIdx; + int subdirs; + *stream >> namesearched; + *stream >> dirsearched; + *stream >> typeIdx; + *stream >> containing; + *stream >> subdirs; + tabWidget->nameBox->insertItem( namesearched, 0); + tabWidget->dirBox->insertItem ( dirsearched, 0); + tabWidget->typeBox->setCurrentItem(typeIdx); + tabWidget->textEdit->setText ( containing ); + tabWidget->subdirsCb->setChecked( ( subdirs==0 ? true : false )); +} diff --git a/kfind/kfind.h b/kfind/kfind.h new file mode 100644 index 000000000..9bc5d35e5 --- /dev/null +++ b/kfind/kfind.h @@ -0,0 +1,64 @@ +/*********************************************************************** + * + * Kfind.h + * + ***********************************************************************/ + +#ifndef KFIND_H +#define KFIND_H + +#include <qwidget.h> +#include <kfileitem.h> +#include <kdirlister.h> + +class QString; +class KPushButton; + +class KQuery; +class KURL; +class KfindTabWidget; + +class Kfind: public QWidget +{ + Q_OBJECT + +public: + Kfind(QWidget * parent = 0, const char * name = 0); + ~Kfind(); + + void setURL( const KURL &url ); + + void setQuery(KQuery * q) { query = q; } + void searchFinished(); + + void saveState( QDataStream *stream ); + void restoreState( QDataStream *stream ); + +public slots: + void startSearch(); + void stopSearch(); + //void newSearch(); + void saveResults(); + +signals: + void haveResults(bool); + void resultSelected(bool); + + void started(); + void destroyMe(); + +private: + void setFocus(); + KfindTabWidget *tabWidget; + KPushButton *mSearch; + KPushButton *mStop; + KPushButton *mSave; + KQuery *query; + +public: + KDirLister *dirlister; +}; + +#endif + + diff --git a/kfind/kfinddlg.cpp b/kfind/kfinddlg.cpp new file mode 100644 index 000000000..4efafd2de --- /dev/null +++ b/kfind/kfinddlg.cpp @@ -0,0 +1,293 @@ +/*********************************************************************** + * + * Kfinddlg.cpp + * + **********************************************************************/ + +#include <qlayout.h> +#include <qpushbutton.h> + +#include <klocale.h> +#include <kglobal.h> +#include <kguiitem.h> +#include <kstatusbar.h> +#include <kmessagebox.h> +#include <kdebug.h> +#include <kaboutapplication.h> +#include <kstandarddirs.h> + +#include "kftabdlg.h" +#include "kquery.h" +#include "kfwin.h" + +#include "kfinddlg.h" +#include "kfinddlg.moc" + +KfindDlg::KfindDlg(const KURL & url, QWidget *parent, const char *name) + : KDialogBase( Plain, QString::null, + User1 | User2 | Apply | Close | Help, Apply, + parent, name, true, false, + KGuiItem(i18n("Stop"), "stop"), + KStdGuiItem::saveAs()) +{ + QWidget::setCaption( i18n("Find Files/Folders" ) ); + setButtonBoxOrientation(Vertical); + + enableButton(Apply, true); // Enable "Find" + enableButton(User1, false); // Disable "Stop" + enableButton(User2, false); // Disable "Save As..." + + setButtonApply(KGuiItem(i18n("&Find"), "find")); + + isResultReported = false; + + QFrame *frame = plainPage(); + + // create tabwidget + tabWidget = new KfindTabWidget( frame, "dialog"); + tabWidget->setURL( url ); + + // prepare window for find results + win = new KfindWindow(frame,"window"); + + mStatusBar = new KStatusBar(frame); + mStatusBar->insertFixedItem(i18n("AMiddleLengthText..."), 0, true); + setStatusMsg(i18n("Ready.")); + mStatusBar->setItemAlignment(0, AlignLeft | AlignVCenter); + mStatusBar->insertItem(QString::null, 1, 1, true); + mStatusBar->setItemAlignment(1, AlignLeft | AlignVCenter); + + QVBoxLayout *vBox = new QVBoxLayout(frame); + vBox->addWidget(tabWidget, 0); + vBox->addWidget(win, 1); + vBox->addWidget(mStatusBar, 0); + + connect(this, SIGNAL(applyClicked()), + this, SLOT(startSearch())); + connect(this, SIGNAL(user1Clicked()), + this, SLOT(stopSearch())); + connect(this, SIGNAL(user2Clicked()), + win, SLOT(saveResults())); + + connect(win ,SIGNAL(resultSelected(bool)), + this,SIGNAL(resultSelected(bool))); + + query = new KQuery(frame); + connect(query, SIGNAL(addFile(const KFileItem*,const QString&)), + SLOT(addFile(const KFileItem*,const QString&))); + connect(query, SIGNAL(result(int)), SLOT(slotResult(int))); + + dirwatch=NULL; +} + +KfindDlg::~KfindDlg() +{ + stopSearch(); +} + +void KfindDlg::closeEvent(QCloseEvent *) +{ + stopSearch(); + slotClose(); +} + +void KfindDlg::setProgressMsg(const QString &msg) +{ + mStatusBar->changeItem(msg, 1); +} + +void KfindDlg::setStatusMsg(const QString &msg) +{ + mStatusBar->changeItem(msg, 0); +} + + +void KfindDlg::startSearch() +{ + tabWidget->setQuery(query); + + isResultReported = false; + + // Reset count - use the same i18n as below + setProgressMsg(i18n("one file found", "%n files found", 0)); + + emit resultSelected(false); + emit haveResults(false); + + enableButton(Apply, false); // Disable "Find" + enableButton(User1, true); // Enable "Stop" + enableButton(User2, false); // Disable "Save As..." + + if(dirwatch!=NULL) + delete dirwatch; + dirwatch=new KDirWatch(); + connect(dirwatch, SIGNAL(created(const QString&)), this, SLOT(slotNewItems(const QString&))); + connect(dirwatch, SIGNAL(deleted(const QString&)), this, SLOT(slotDeleteItem(const QString&))); + dirwatch->addDir(query->url().path(),true); + +#if 0 + // waba: Watching for updates is disabled for now because even with FAM it causes too + // much problems. See BR68220, BR77854, BR77846, BR79512 and BR85802 + // There are 3 problems: + // 1) addDir() keeps looping on recursive symlinks + // 2) addDir() scans all subdirectories, so it basically does the same as the process that + // is started by KQuery but in-process, undoing the advantages of using a seperate find process + // A solution could be to let KQuery emit all the directories it has searched in. + // Either way, putting dirwatchers on a whole file system is probably just too much. + // 3) FAM has a tendency to deadlock with so many files (See BR77854) This has hopefully + // been fixed in KDirWatch, but that has not yet been confirmed. + + //Getting a list of all subdirs + if(tabWidget->isSearchRecursive() && (dirwatch->internalMethod() == KDirWatch::FAM)) + { + QStringList subdirs=getAllSubdirs(query->url().path()); + for(QStringList::Iterator it = subdirs.begin(); it != subdirs.end(); ++it) + dirwatch->addDir(*it,true); + } +#endif + + win->beginSearch(query->url()); + tabWidget->beginSearch(); + + setStatusMsg(i18n("Searching...")); + query->start(); +} + +void KfindDlg::stopSearch() +{ + query->kill(); +} + +void KfindDlg::newSearch() +{ + // WABA: Not used any longer? + stopSearch(); + + tabWidget->setDefaults(); + + emit haveResults(false); + emit resultSelected(false); + + setFocus(); +} + +void KfindDlg::slotResult(int errorCode) +{ + if (errorCode == 0) + setStatusMsg(i18n("Ready.")); + else if (errorCode == KIO::ERR_USER_CANCELED) + setStatusMsg(i18n("Aborted.")); + else if (errorCode == KIO::ERR_MALFORMED_URL) + { + setStatusMsg(i18n("Error.")); + KMessageBox::sorry( this, i18n("Please specify an absolute path in the \"Look in\" box.")); + } + else if (errorCode == KIO::ERR_DOES_NOT_EXIST) + { + setStatusMsg(i18n("Error.")); + KMessageBox::sorry( this, i18n("Could not find the specified folder.")); + } + else + { + kdDebug()<<"KIO error code: "<<errorCode<<endl; + setStatusMsg(i18n("Error.")); + }; + + enableButton(Apply, true); // Enable "Find" + enableButton(User1, false); // Disable "Stop" + enableButton(User2, true); // Enable "Save As..." + + win->endSearch(); + tabWidget->endSearch(); + setFocus(); + +} + +void KfindDlg::addFile(const KFileItem* item, const QString& matchingLine) +{ + win->insertItem(*item,matchingLine); + + if (!isResultReported) + { + emit haveResults(true); + isResultReported = true; + } + + int count = win->childCount(); + QString str = i18n("one file found", "%n files found", count); + setProgressMsg(str); +} + +void KfindDlg::setFocus() +{ + tabWidget->setFocus(); +} + +void KfindDlg::copySelection() +{ + win->copySelection(); +} + +void KfindDlg::about () +{ + KAboutApplication dlg(this, "about", true); + dlg.exec (); +} + +void KfindDlg::slotDeleteItem(const QString& file) +{ + kdDebug()<<QString("Will remove one item: %1").arg(file)<<endl; + QListViewItem *iter; + QString iterwithpath; + + iter=win->firstChild(); + while( iter ) { + iterwithpath=query->url().path(+1)+iter->text(1)+iter->text(0); + + if(iterwithpath==file) + { + win->takeItem(iter); + break; + } + iter = iter->nextSibling(); + } +} + +void KfindDlg::slotNewItems( const QString& file ) +{ + kdDebug()<<QString("Will add this item")<<endl; + QStringList newfiles; + QListViewItem *checkiter; + QString checkiterwithpath; + + if(file.find(query->url().path(+1))==0) + { + kdDebug()<<QString("Can be added, path OK")<<endl; + checkiter=win->firstChild(); + while( checkiter ) { + checkiterwithpath=query->url().path(+1)+checkiter->text(1)+checkiter->text(0); + if(file==checkiterwithpath) + return; + checkiter = checkiter->nextSibling(); + } + query->slotListEntries(QStringList(file)); + } +} + +QStringList KfindDlg::getAllSubdirs(QDir d) +{ + QStringList dirs; + QStringList subdirs; + + d.setFilter( QDir::Dirs ); + dirs = d.entryList(); + + for(QStringList::Iterator it = dirs.begin(); it != dirs.end(); ++it) + { + if((*it==".")||(*it=="..")) + continue; + subdirs.append(d.path()+"/"+*it); + subdirs+=getAllSubdirs(d.path()+"/"+*it); + } + return subdirs; +} diff --git a/kfind/kfinddlg.h b/kfind/kfinddlg.h new file mode 100644 index 000000000..dd1aa718c --- /dev/null +++ b/kfind/kfinddlg.h @@ -0,0 +1,69 @@ +/*********************************************************************** + * + * KfindDlg.h + * + ***********************************************************************/ + +#ifndef KFINDDLG_H +#define KFINDDLG_H + +#include <kdialogbase.h> +#include <kdirlister.h> +#include <kdirwatch.h> + +class QString; + +class KQuery; +class KURL; +class KFileItem; +class KfindTabWidget; +class KfindWindow; +class KStatusBar; + +class KfindDlg: public KDialogBase +{ +Q_OBJECT + +public: + KfindDlg(const KURL & url, QWidget * parent = 0, const char * name = 0); + ~KfindDlg(); + void copySelection(); + + void setStatusMsg(const QString &); + void setProgressMsg(const QString &); + +private: + void closeEvent(QCloseEvent *); + /*Return a QStringList of all subdirs of d*/ + QStringList getAllSubdirs(QDir d); + +public slots: + void startSearch(); + void stopSearch(); + void newSearch(); + void addFile(const KFileItem* item, const QString& matchingLine); + void setFocus(); + void slotResult(int); +// void slotSearchDone(); + void about (); + void slotDeleteItem(const QString&); + void slotNewItems( const QString& ); + +signals: + void haveResults(bool); + void resultSelected(bool); + +private: + KfindTabWidget *tabWidget; + KfindWindow * win; + + bool isResultReported; + KQuery *query; + KStatusBar *mStatusBar; + KDirLister *dirlister; + KDirWatch *dirwatch; +}; + +#endif + + diff --git a/kfind/kfindpart.cpp b/kfind/kfindpart.cpp new file mode 100644 index 000000000..4f5d8043f --- /dev/null +++ b/kfind/kfindpart.cpp @@ -0,0 +1,213 @@ +/* This file is part of the KDE projects + Copyright (C) 2000 David Faure <faure@kde.org> + + 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. + + 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 General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "kfind.h" +#include "kfindpart.h" +#include "kquery.h" + +#include <kparts/genericfactory.h> +#include <kdebug.h> +#include <klocale.h> + +#include <qdir.h> +#include <kinstance.h> + +class KonqDirPart; + +typedef KParts::GenericFactory<KFindPart> KFindFactory; +K_EXPORT_COMPONENT_FACTORY( libkfindpart, KFindFactory ) + +KFindPart::KFindPart( QWidget * parentWidget, const char *widgetName, + QObject *parent, const char *name , + const QStringList & /*args*/ ) + : KonqDirPart (parent, name )/*KParts::ReadOnlyPart*/ +{ + setInstance( KFindFactory::instance() ); + + setBrowserExtension( new KonqDirPartBrowserExtension( this ) ); + + kdDebug() << "KFindPart::KFindPart " << this << endl; + m_kfindWidget = new Kfind( parentWidget, widgetName ); + m_kfindWidget->setMaximumHeight(m_kfindWidget->minimumSizeHint().height()); + const KFileItem *item = ((KonqDirPart*)parent)->currentItem(); + kdDebug() << "Kfind: currentItem: " << ( item ? item->url().path().local8Bit() : QString("null") ) << endl; + QDir d; + if( item && d.exists( item->url().path() )) + m_kfindWidget->setURL( item->url() ); + + setWidget( m_kfindWidget ); + + connect( m_kfindWidget, SIGNAL(started()), + this, SLOT(slotStarted()) ); + connect( m_kfindWidget, SIGNAL(destroyMe()), + this, SLOT(slotDestroyMe()) ); + connect(m_kfindWidget->dirlister,SIGNAL(deleteItem(KFileItem*)), this, SLOT(removeFile(KFileItem*))); + connect(m_kfindWidget->dirlister,SIGNAL(newItems(const KFileItemList&)), this, SLOT(newFiles(const KFileItemList&))); + //setXMLFile( "kfind.rc" ); + query = new KQuery(this); + connect(query, SIGNAL(addFile(const KFileItem *, const QString&)), + SLOT(addFile(const KFileItem *, const QString&))); + connect(query, SIGNAL(result(int)), + SLOT(slotResult(int))); + + m_kfindWidget->setQuery(query); + m_bShowsResult = false; + + m_lstFileItems.setAutoDelete( true ); +} + +KFindPart::~KFindPart() +{ +} + +KAboutData *KFindPart::createAboutData() +{ + return new KAboutData( "kfindpart", I18N_NOOP( "Find Component" ), "1.0" ); +} + +bool KFindPart::doOpenURL( const KURL &url ) +{ + m_kfindWidget->setURL( url ); + return true; +} + +void KFindPart::slotStarted() +{ + kdDebug() << "KFindPart::slotStarted" << endl; + m_bShowsResult = true; + m_lstFileItems.clear(); // clear our internal list + emit started(); + emit clear(); +} + +void KFindPart::addFile(const KFileItem *item, const QString& /*matchingLine*/) +{ + // item is deleted by caller + // we need to clone it + KFileItem *clonedItem = new KFileItem(*item); + m_lstFileItems.append( clonedItem ); + + KFileItemList lstNewItems; + lstNewItems.append(clonedItem); + emit newItems(lstNewItems); + + /* + win->insertItem(item); + + if (!isResultReported) + { + emit haveResults(true); + isResultReported = true; + } + + */ +} + +/* An item has been removed, so update konqueror's view */ +void KFindPart::removeFile(KFileItem *item) +{ + KFileItem *iter; + KFileItemList listiter; + + emit started(); + emit clear(); + + m_lstFileItems.remove( item ); //not working ? + + for(iter=m_lstFileItems.first(); iter; iter=m_lstFileItems.next() ) { + if(iter->url()!=item->url()) + listiter.append(iter); + } + + emit newItems(listiter); + emit finished(); +} + +void KFindPart::newFiles(const KFileItemList&) +{ + if(m_bShowsResult) + return; + emit started(); + emit clear(); + if (m_lstFileItems.count()) + emit newItems(m_lstFileItems); + emit finished(); +} + +void KFindPart::slotResult(int errorCode) +{ + if (errorCode == 0) + emit finished(); + //setStatusMsg(i18n("Ready.")); + else if (errorCode == KIO::ERR_USER_CANCELED) + emit canceled(); + //setStatusMsg(i18n("Aborted.")); + else + emit canceled(); // TODO ? + //setStatusMsg(i18n("Error.")); + m_bShowsResult=false; + m_kfindWidget->searchFinished(); +} + +void KFindPart::slotDestroyMe() +{ + m_kfindWidget->stopSearch(); + emit clear(); // this is necessary to clear the delayed-mimetypes items list + m_lstFileItems.clear(); // clear our internal list + emit findClosed(); +} + +void KFindPart::saveState( QDataStream& stream ) +{ + KonqDirPart::saveState(stream); + + m_kfindWidget->saveState( &stream ); + //Now we'll save the search result + KFileItem *fileitem=m_lstFileItems.first(); + stream << m_lstFileItems.count(); + while(fileitem!=NULL) + { + stream << *fileitem; + fileitem=m_lstFileItems.next(); + } +} + +void KFindPart::restoreState( QDataStream& stream ) +{ + KonqDirPart::restoreState(stream); + int nbitems; + KURL itemUrl; + + m_kfindWidget->restoreState( &stream ); + + stream >> nbitems; + slotStarted(); + for(int i=0;i<nbitems;i++) + { + KFileItem* item = new KFileItem( KFileItem::Unknown, KFileItem::Unknown, KURL() ); + stream >> *item; + m_lstFileItems.append(item); + } + if (nbitems) + emit newItems(m_lstFileItems); + + emit finished(); +} + +#include "kfindpart.moc" diff --git a/kfind/kfindpart.desktop b/kfind/kfindpart.desktop new file mode 100644 index 000000000..f388003f6 --- /dev/null +++ b/kfind/kfindpart.desktop @@ -0,0 +1,87 @@ +[Desktop Entry] +Type=Service +Name=Find Part +Name[af]=Soek Deel +Name[ar]=ابحث عن جزء +Name[az]=Parça tap +Name[be]=Модуль пошуку +Name[bg]=Търсене на модули +Name[bn]=পার্ট অনুসন্ধান +Name[br]=Kavout perzh +Name[bs]=Nađi dio +Name[ca]=Cerca la part +Name[cs]=Najít soubor +Name[csb]=Mòduł szëkbë +Name[cy]=Canfod Rhan +Name[da]=Find del +Name[de]=Einbettungsfähiges Programm (Komponente) suchen +Name[el]=Part Αναζήτηση +Name[eo]=Trovokomponento +Name[es]=Buscar parte +Name[et]=Failide otsimise komponent +Name[eu]=Bilatu partea +Name[fa]=یافتن جزء +Name[fi]=Etsi osa +Name[fr]=Composant de recherche +Name[fy]=In diel sykje +Name[ga]=Aimsigh Páirt +Name[gl]=Busca +Name[he]=רכיב חיפוש +Name[hi]=हिस्सा ढूंढें +Name[hr]=Pronađi dio +Name[hu]=Keresési objektum +Name[id]=Cari bagian +Name[is]=Finna hluti +Name[it]=Trova parte +Name[ja]=検索パート +Name[ka]=ძიება შემადგენლობის მიხედვით +Name[kk]=Мазмұнынан табу +Name[km]=រកផ្នែក +Name[ko]=찾기 부분 +Name[lo]=ຄັ້ນຫາບາງສ່ວນ +Name[lt]=Surasti dalį +Name[lv]=Meklēt Daļu +Name[mk]=Пронајди дел +Name[mn]=Хэсэг хайх +Name[ms]=Cari Bahagian +Name[mt]=Sib Parti +Name[nb]=Finn del +Name[nds]=Söök-Komponent +Name[ne]=भाग फेला पार्नुहोस् +Name[nl]=Gedeelte zoeken +Name[nn]=Finn del +Name[nso]=Hwetsa Seripa +Name[pa]=ਹਿੱਸੇ ਖੋਜ +Name[pl]=Moduł szukania +Name[pt]=Componente de Pesquisa +Name[pt_BR]=Componente de Busca +Name[ro]=Componentă de căutare +Name[ru]=Поиск по содержимому +Name[rw]=Gushaka Igice +Name[se]=Oza osiid +Name[sk]=Nájsť Part +Name[sl]=Najdi del +Name[sr]=Део за тражење +Name[sr@Latn]=Deo za traženje +Name[sv]=Sökdel +Name[ta]=பகுதி கண்டுபிடி +Name[te]=వెతుకు భాగం +Name[tg]=Қисматро пайдо кунед +Name[th]=ค้นหาบางส่วน +Name[tr]=Parça bul +Name[tt]=Eçtälek Ezläw +Name[uk]=Складова пошуку +Name[ven]=Todani tshipida +Name[vi]=Tìm từng phần +Name[wa]=Trover des pårteyes +Name[xh]=Fumana Indawana +Name[zh_CN]=查找部件 +Name[zh_TW]=尋找組件 +Name[zu]=Thola Ingxenye +MimeType= +ServiceTypes=Konqueror/FindPart +X-KDE-Library=libkfindpart +X-KDE-BrowserView-AllowAsDefault=true +X-KDE-BrowserView-HideFromMenus=true +X-KDE-BrowserView-PassiveMode=true +InitialPreference=10 diff --git a/kfind/kfindpart.h b/kfind/kfindpart.h new file mode 100644 index 000000000..29b133b99 --- /dev/null +++ b/kfind/kfindpart.h @@ -0,0 +1,104 @@ +/* This file is part of the KDE projects + Copyright (C) 2000 David Faure <faure@kde.org> + + 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. + + 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 General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef kfindpart__h +#define kfindpart__h + +#include <kparts/browserextension.h> +#include <kparts/part.h> +#include <kfileitem.h> +#include <kdebug.h> +#include <qptrlist.h> +#include <konq_dirpart.h> + +class KQuery; +class KAboutData; +//added +class KonqPropsView; +class KAction; +class KToggleAction; +class KActionMenu; +class QIconViewItem; +class IconViewBrowserExtension; +//end added + +class KFindPart : public KonqDirPart//KParts::ReadOnlyPart +{ + friend class KFindPartBrowserExtension; + Q_OBJECT + Q_PROPERTY( bool showsResult READ showsResult ) +public: + KFindPart( QWidget * parentWidget, const char *widgetName, + QObject *parent, const char *name, const QStringList & /*args*/ ); + virtual ~KFindPart(); + + static KAboutData *createAboutData(); + + virtual bool doOpenURL( const KURL &url ); + virtual bool doCloseURL() { return true; } + virtual bool openFile() { return false; } + + bool showsResult() const { return m_bShowsResult; } + + virtual void saveState( QDataStream &stream ); + virtual void restoreState( QDataStream &stream ); + + // "Cut" icons : disable those whose URL is in lst, enable the rest //added for konqdirpart + virtual void disableIcons( const KURL::List & ){}; + virtual const KFileItem * currentItem(){return 0;}; + +signals: + // Konqueror connects directly to those signals + void started(); // started a search + void clear(); // delete all items + void newItems(const KFileItemList&); // found this/these item(s) + void finished(); // finished searching + void canceled(); // the user canceled the search + void findClosed(); // close us + void deleteItem( KFileItem *item); + +protected slots: + void slotStarted(); + void slotDestroyMe(); + void addFile(const KFileItem *item, const QString& matchingLine); + /* An item has been removed, so update konqueror's view */ + void removeFile(KFileItem *item); + void slotResult(int errorCode); + void newFiles(const KFileItemList&); + // slots connected to the directory lister //added for konqdirpart +// virtual void slotStarted(); + virtual void slotCanceled(){}; + virtual void slotCompleted(){}; + virtual void slotNewItems( const KFileItemList& ){}; + virtual void slotDeleteItem( KFileItem * ){}; + virtual void slotRefreshItems( const KFileItemList& ){}; + virtual void slotClear(){}; + virtual void slotRedirection( const KURL & ){}; + +private: + Kfind * m_kfindWidget; + KQuery *query; + bool m_bShowsResult; // whether the dirpart shows the results of a search or not + /** + * The internal storage of file items + */ + QPtrList<KFileItem> m_lstFileItems; +}; + +#endif diff --git a/kfind/kfindpart.kdevprj b/kfind/kfindpart.kdevprj new file mode 100644 index 000000000..d9fbfc7e2 --- /dev/null +++ b/kfind/kfindpart.kdevprj @@ -0,0 +1,178 @@ +[./AUTHORS] +dist=true +install=false +install_location= +type=DATA + +[./ChangeLog] +dist=true +install=false +install_location= +type=DATA + +[./Makefile.am] +files=./AUTHORS,./ChangeLog,./README,./TODO,./findpart.desktop,./kfind.cpp,./kfind.h,./kfindpart.cpp,./kfindpart.desktop,./kfindpart.h,./kftabdlg.cpp,./kftabdlg.h,./kquery.cpp,./kquery.h,./version.h,./kfindpart.kdevprj, +sub_dirs=pics, +type=normal + +[./README] +dist=true +install=false +install_location= +type=DATA + +[./TODO] +dist=true +install=false +install_location= +type=DATA + +[./findpart.desktop] +dist=true +install=false +install_location= +type=DATA + +[./kfind.cpp] +dist=true +install=false +install_location= +type=SOURCE + +[./kfind.h] +dist=true +install=false +install_location= +type=HEADER + +[./kfindpart.cpp] +dist=true +install=false +install_location= +type=SOURCE + +[./kfindpart.desktop] +dist=true +install=false +install_location= +type=DATA + +[./kfindpart.h] +dist=true +install=false +install_location= +type=HEADER + +[./kfindpart.kdevprj] +dist=true +install=false +install_location= +type=DATA + +[./kftabdlg.cpp] +dist=true +install=false +install_location= +type=SOURCE + +[./kftabdlg.h] +dist=true +install=false +install_location= +type=HEADER + +[./kquery.cpp] +dist=true +install=false +install_location= +type=SOURCE + +[./kquery.h] +dist=true +install=false +install_location= +type=HEADER + +[./version.h] +dist=true +install=false +install_location= +type=HEADER + +[Config for BinMakefileAm] +addcxxflags= +bin_program=kfindpart +cxxflags= +ldadd= +ldflags= + +[General] +AMChanged=false +author=eric +email=eric@darkstar.fr +kdevprj_version=1.3 +lfv_open_groups= +makefiles=./Makefile.am,pics/Makefile.am, +project_name=kfindpart +project_type=normal_empty +sub_dir= +version= +version_control=CVS +workspace=1 + +[LFV Groups] +Desktop=*.desktop, +GNU=AUTHORS,COPYING,ChangeLog,INSTALL,README,TODO,NEWS, +Headers=*.h,*.hxx,*.hpp,*.H, +Others=*, +Sources=*.cpp,*.c,*.cc,*.C,*.cxx,*.ec,*.ecpp,*.lxx,*.l++,*.ll,*.l, +Translations=*.ts,*.po, +User Interface=*.ui,*.kdevdlg,*.rc, +groups=Headers,Sources,GNU,Translations,User Interface,Desktop,Others + +[pics/Makefile.am] +files=pics/lo22-action-archive.png,pics/lo22-action-delete.png,pics/lo22-action-idea.png,pics/lo22-action-info.png,pics/lo22-action-openfile.png,pics/lo22-action-save.png,pics/lo22-action-search.png, +sub_dirs= +type=normal + +[pics/lo22-action-archive.png] +dist=true +install=false +install_location= +type=DATA + +[pics/lo22-action-delete.png] +dist=true +install=false +install_location= +type=DATA + +[pics/lo22-action-idea.png] +dist=true +install=false +install_location= +type=DATA + +[pics/lo22-action-info.png] +dist=true +install=false +install_location= +type=DATA + +[pics/lo22-action-openfile.png] +dist=true +install=false +install_location= +type=DATA + +[pics/lo22-action-save.png] +dist=true +install=false +install_location= +type=DATA + +[pics/lo22-action-search.png] +dist=true +install=false +install_location= +type=DATA diff --git a/kfind/kfindpart.kdevses b/kfind/kfindpart.kdevses new file mode 100644 index 000000000..ad6d09112 --- /dev/null +++ b/kfind/kfindpart.kdevses @@ -0,0 +1,20 @@ +<?xml version = '1.0' encoding = 'UTF-8'?> +<!DOCTYPE KDevPrjSession> +<KDevPrjSession> + <Mainframe MaximizeMode="0" /> + <DocsAndViews NumberOfDocuments="4" > + <Doc0 CursorPosLine="44" Type="KWriteDoc" NumberOfViews="1" CursorPosCol="0" FileName="/home/eric/kde/kdebase/kfind/kfind.cpp" > + <View0 Top="0" Width="754" Attach="1" Height="388" Left="0" Focus="0" Type="KWriteView" MinMaxMode="0" /> + </Doc0> + <Doc1 CursorPosLine="20" Type="KWriteDoc" NumberOfViews="1" CursorPosCol="0" FileName="/home/eric/kde/kdebase/kfind/kfind.h" > + <View0 Top="0" Width="754" Attach="1" Height="388" Left="0" Focus="0" Type="KWriteView" MinMaxMode="0" /> + </Doc1> + <Doc2 CursorPosLine="31" Type="KWriteDoc" NumberOfViews="1" CursorPosCol="0" FileName="/home/eric/kde/kdebase/kfind/kftabdlg.h" > + <View0 Top="0" Width="754" Attach="1" Height="388" Left="0" Focus="0" Type="KWriteView" MinMaxMode="0" /> + </Doc2> + <Doc3 CursorPosLine="51" Type="KWriteDoc" NumberOfViews="1" CursorPosCol="0" FileName="/home/eric/kde/kdebase/kfind/kftabdlg.cpp" > + <View0 Top="0" Width="754" Attach="1" Height="388" Left="0" Focus="1" Type="KWriteView" MinMaxMode="0" /> + </Doc3> + </DocsAndViews> + <LastCompileConfig>(Default)</LastCompileConfig> +</KDevPrjSession> diff --git a/kfind/kftabdlg.cpp b/kfind/kftabdlg.cpp new file mode 100644 index 000000000..7f8f73f96 --- /dev/null +++ b/kfind/kftabdlg.cpp @@ -0,0 +1,871 @@ +/*********************************************************************** + * + * kftabdlg.cpp + * + **********************************************************************/ + +#include <qbuttongroup.h> +#include <qradiobutton.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qcheckbox.h> +#include <qwhatsthis.h> +#include <qtooltip.h> +#include <qcombobox.h> +#include <qspinbox.h> +#include <qpushbutton.h> +#include <qapplication.h> + +#include <kcalendarsystem.h> +#include <kglobal.h> +#include <kcombobox.h> +#include <klineedit.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kfiledialog.h> +#include <kregexpeditorinterface.h> +#include <kparts/componentfactory.h> +#include <kstandarddirs.h> + +#include "kquery.h" +#include "kftabdlg.h" + +// Static utility functions +static void save_pattern(QComboBox *, const QString &, const QString &); + +#define SPECIAL_TYPES 7 + +class KSortedMimeTypeList : public QPtrList<KMimeType> +{ +public: + KSortedMimeTypeList() { }; + int compareItems(QPtrCollection::Item s1, QPtrCollection::Item s2) + { + KMimeType *item1 = (KMimeType *) s1; + KMimeType *item2 = (KMimeType *) s2; + if (item1->comment() > item2->comment()) return 1; + if (item1->comment() == item2->comment()) return 0; + return -1; + } +}; + +KfindTabWidget::KfindTabWidget(QWidget *parent, const char *name) + : QTabWidget( parent, name ), regExpDialog(0) +{ + // This validator will be used for all numeric edit fields + //KDigitValidator *digitV = new KDigitValidator(this); + + // ************ Page One ************ + + pages[0] = new QWidget( this, "page1" ); + + nameBox = new KComboBox(TRUE, pages[0], "combo1"); + nameBox->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); // allow smaller than widest entry + QLabel * namedL = new QLabel(nameBox, i18n("&Named:"), pages[0], "named"); + QToolTip::add( namedL, i18n("You can use wildcard matching and \";\" for separating multiple names") ); + dirBox = new KComboBox(TRUE, pages[0], "combo2"); + dirBox->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); // allow smaller than widest entry + QLabel * lookinL = new QLabel(dirBox, i18n("Look &in:"), pages[0], "named"); + subdirsCb = new QCheckBox(i18n("Include &subfolders"), pages[0]); + caseSensCb = new QCheckBox(i18n("Case s&ensitive search"), pages[0]); + browseB = new QPushButton(i18n("&Browse..."), pages[0]); + useLocateCb = new QCheckBox(i18n("&Use files index"), pages[0]); + + // Setup + + subdirsCb->setChecked(true); + caseSensCb->setChecked(false); + useLocateCb->setChecked(false); + if(KStandardDirs::findExe("locate")==NULL) + useLocateCb->setEnabled(false); + + nameBox->setDuplicatesEnabled(FALSE); + nameBox->setFocus(); + dirBox->setDuplicatesEnabled(FALSE); + + nameBox->setInsertionPolicy(QComboBox::AtTop); + dirBox->setInsertionPolicy(QComboBox::AtTop); + + const QString nameWhatsThis + = i18n("<qt>Enter the filename you are looking for. <br>" + "Alternatives may be separated by a semicolon \";\".<br>" + "<br>" + "The filename may contain the following special characters:" + "<ul>" + "<li><b>?</b> matches any single character</li>" + "<li><b>*</b> matches zero or more of any characters</li>" + "<li><b>[...]</b> matches any of the characters in braces</li>" + "</ul>" + "<br>" + "Example searches:" + "<ul>" + "<li><b>*.kwd;*.txt</b> finds all files ending with .kwd or .txt</li>" + "<li><b>go[dt]</b> finds god and got</li>" + "<li><b>Hel?o</b> finds all files that start with \"Hel\" and end with \"o\", " + "having one character in between</li>" + "<li><b>My Document.kwd</b> finds a file of exactly that name</li>" + "</ul></qt>"); + QWhatsThis::add(nameBox,nameWhatsThis); + QWhatsThis::add(namedL,nameWhatsThis); + const QString whatsfileindex + = i18n("<qt>This lets you use the files' index created by the <i>slocate</i> " + "package to speed-up the search; remember to update the index from time to time " + "(using <i>updatedb</i>)." + "</qt>"); + QWhatsThis::add(useLocateCb,whatsfileindex); + + // Layout + + QGridLayout *grid = new QGridLayout( pages[0], 3, 2, + KDialog::marginHint(), + KDialog::spacingHint() ); + QBoxLayout *subgrid = new QVBoxLayout( -1 , "subgrid" ); + grid->addWidget( namedL, 0, 0 ); + grid->addMultiCellWidget( nameBox, 0, 0, 1, 2 ); + grid->addWidget( lookinL, 1, 0 ); + grid->addWidget( dirBox, 1, 1 ); + grid->addWidget( browseB, 1, 2); + grid->setColStretch(1,1); + grid->addMultiCellLayout( subgrid, 2, 2, 1, 2 ); + subgrid->addWidget( subdirsCb ); + subgrid->addWidget( caseSensCb); + subgrid->addWidget( useLocateCb ); + subgrid->addStretch(1); + + // Signals + + connect( browseB, SIGNAL(clicked()), + this, SLOT(getDirectory()) ); + + connect( nameBox, SIGNAL(activated(int)), + this, SIGNAL(startSearch())); + + // ************ Page Two + + pages[1] = new QWidget( this, "page2" ); + + findCreated = new QCheckBox(i18n("Find all files created or &modified:"), pages[1]); + bg = new QButtonGroup(); + rb[0] = new QRadioButton(i18n("&between"), pages[1] ); + rb[1] = new QRadioButton(i18n("&during the previous"), pages[1] ); + QLabel * andL = new QLabel(i18n("and"), pages[1], "and"); + betweenType = new KComboBox(FALSE, pages[1], "comboBetweenType"); + betweenType->insertItem(i18n("minute(s)")); + betweenType->insertItem(i18n("hour(s)")); + betweenType->insertItem(i18n("day(s)")); + betweenType->insertItem(i18n("month(s)")); + betweenType->insertItem(i18n("year(s)")); + betweenType->setCurrentItem(1); + + + QDate dt = KGlobal::locale()->calendar()->addYears(QDate::currentDate(), -1); + + fromDate = new KDateCombo(dt, pages[1], "fromDate"); + toDate = new KDateCombo(pages[1], "toDate"); + timeBox = new QSpinBox(1, 60, 1, pages[1], "timeBox"); + + sizeBox =new KComboBox(FALSE, pages[1], "sizeBox"); + QLabel * sizeL =new QLabel(sizeBox,i18n("File &size is:"), pages[1],"size"); + sizeEdit=new QSpinBox(0, INT_MAX, 1, pages[1], "sizeEdit" ); + sizeEdit->setValue(1); + sizeUnitBox =new KComboBox(FALSE, pages[1], "sizeUnitBox"); + + m_usernameBox = new KComboBox( true, pages[1], "m_combo1"); + QLabel *usernameLabel= new QLabel(m_usernameBox,i18n("Files owned by &user:"),pages[1]); + m_groupBox = new KComboBox( true, pages[1], "m_combo2"); + QLabel *groupLabel= new QLabel(m_groupBox,i18n("Owned by &group:"),pages[1]); + + sizeBox ->insertItem( i18n("(none)") ); + sizeBox ->insertItem( i18n("At Least") ); + sizeBox ->insertItem( i18n("At Most") ); + sizeBox ->insertItem( i18n("Equal To") ); + + sizeUnitBox ->insertItem( i18n("Bytes") ); + sizeUnitBox ->insertItem( i18n("KB") ); + sizeUnitBox ->insertItem( i18n("MB") ); + sizeUnitBox ->insertItem( i18n("GB") ); + sizeUnitBox ->setCurrentItem(1); + + int tmp = sizeEdit->fontMetrics().width(" 000000000 "); + sizeEdit->setMinimumSize(tmp, sizeEdit->sizeHint().height()); + + m_usernameBox->setDuplicatesEnabled(FALSE); + m_groupBox->setDuplicatesEnabled(FALSE); + m_usernameBox->setInsertionPolicy(QComboBox::AtTop); + m_groupBox->setInsertionPolicy(QComboBox::AtTop); + + + // Setup + timeBox->setButtonSymbols(QSpinBox::PlusMinus); + rb[0]->setChecked(true); + bg->insert( rb[0] ); + bg->insert( rb[1] ); + + // Layout + + QGridLayout *grid1 = new QGridLayout( pages[1], 5, 6, + KDialog::marginHint(), + KDialog::spacingHint() ); + + grid1->addMultiCellWidget(findCreated, 0, 0, 0, 3 ); + grid1->addColSpacing(0, KDialog::spacingHint()); + + grid1->addWidget(rb[0], 1, 1 ); + grid1->addWidget(fromDate, 1, 2 ); + grid1->addWidget(andL, 1, 3, AlignHCenter ); + grid1->addWidget(toDate, 1, 4 ); + + grid1->addWidget(rb[1], 2, 1 ); + grid1->addMultiCellWidget(timeBox, 2, 2, 2, 3); + grid1->addWidget(betweenType, 2, 4 ); + + grid1->addMultiCellWidget(sizeL,3,3,0,1); + grid1->addWidget(sizeBox,3,2); + grid1->addWidget(sizeEdit,3,3); + grid1->addWidget(sizeUnitBox,3,4); + + grid1->addMultiCellWidget(usernameLabel,4,4,0,1); + grid1->addWidget(m_usernameBox,4,2); + grid1->addWidget(groupLabel,4,3); + grid1->addWidget(m_groupBox,4,4); + + for (int c=1; c<=4; c++) + grid1->setColStretch(c,1); + + grid1->setRowStretch(6,1); + + // Connect + connect( findCreated, SIGNAL(toggled(bool)), SLOT(fixLayout()) ); + connect( bg, SIGNAL(clicked(int)), this, SLOT(fixLayout()) ); + connect( sizeBox, SIGNAL(highlighted(int)), this, SLOT(slotSizeBoxChanged(int))); + + + // ************ Page Three + + pages[2] = new QWidget( this, "page3" ); + + typeBox =new KComboBox(FALSE, pages[2], "typeBox"); + typeBox->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); // allow smaller than widest entry + QLabel * typeL =new QLabel(typeBox, i18n("File &type:"), pages[2], "type"); + textEdit=new KLineEdit(pages[2], "textEdit" ); + QLabel * textL =new QLabel(textEdit, i18n("C&ontaining text:"), pages[2], "text"); + + connect( textEdit, SIGNAL(returnPressed(const QString &)), SIGNAL( startSearch())); + + const QString containingtext + = i18n("<qt>If specified, only files that contain this text" + " are found. Note that not all file types from the list" + " above are supported. Please refer to the documentation" + " for a list of supported file types." + "</qt>"); + QToolTip::add(textEdit,containingtext); + QWhatsThis::add(textL,containingtext); + + caseContextCb =new QCheckBox(i18n("Case s&ensitive"), pages[2]); + binaryContextCb =new QCheckBox(i18n("Include &binary files"), pages[2]); + regexpContentCb =new QCheckBox(i18n("Regular e&xpression"), pages[2]); + + const QString binaryTooltip + = i18n("<qt>This lets you search in any type of file, " + "even those that usually do not contain text (for example " + "program files and images).</qt>"); + QToolTip::add(binaryContextCb,binaryTooltip); + + QPushButton* editRegExp = 0; + if ( !KTrader::self()->query("KRegExpEditor/KRegExpEditor").isEmpty() ) { + // The editor is available, so lets use it. + editRegExp = new QPushButton(i18n("&Edit..."), pages[2], "editRegExp"); + } + + metainfokeyEdit=new KLineEdit(pages[2], "textEdit" ); + metainfoEdit=new KLineEdit(pages[2], "textEdit" ); + QLabel * textMetaInfo = new QLabel(metainfoEdit, i18n("fo&r:"), pages[2], "text"); + QLabel * textMetaKey = new QLabel(metainfokeyEdit, i18n("Search &metainfo sections:"), pages[2], "text"); + + // Setup + typeBox->insertItem(i18n("All Files & Folders")); + typeBox->insertItem(i18n("Files")); + typeBox->insertItem(i18n("Folders")); + typeBox->insertItem(i18n("Symbolic Links")); + typeBox->insertItem(i18n("Special Files (Sockets, Device Files, ...)")); + typeBox->insertItem(i18n("Executable Files")); + typeBox->insertItem(i18n("SUID Executable Files")); + typeBox->insertItem(i18n("All Images")); + typeBox->insertItem(i18n("All Video")); + typeBox->insertItem(i18n("All Sounds")); + + initMimeTypes(); + initSpecialMimeTypes(); + + for ( KMimeType::List::ConstIterator it = m_types.begin(); + it != m_types.end(); ++it ) + { + KMimeType::Ptr typ = *it; + typeBox->insertItem(typ->pixmap( KIcon::Small ), typ->comment()); + } + + if ( editRegExp ) { + // The editor was available, so lets use it. + connect( regexpContentCb, SIGNAL(toggled(bool) ), editRegExp, SLOT(setEnabled(bool)) ); + editRegExp->setEnabled(false); + connect( editRegExp, SIGNAL(clicked()), this, SLOT( slotEditRegExp() ) ); + } + else + regexpContentCb->hide(); + + // Layout + tmp = sizeEdit->fontMetrics().width(" 00000 "); + sizeEdit->setMinimumSize(tmp, sizeEdit->sizeHint().height()); + + QGridLayout *grid2 = new QGridLayout( pages[2], 5, 4, + KDialog::marginHint(), + KDialog::spacingHint() ); + grid2->addWidget( typeL, 0, 0 ); + grid2->addWidget( textL, 1, 0 ); + grid2->addMultiCellWidget( typeBox, 0, 0, 1, 3 ); + grid2->addMultiCellWidget( textEdit, 1, 1, 1, 3 ); + grid2->addWidget( regexpContentCb, 2, 2); + grid2->addWidget( caseContextCb, 2, 1 ); + grid2->addWidget( binaryContextCb, 3, 1); + + grid2->addWidget( textMetaKey, 4, 0 ); + grid2->addWidget( metainfokeyEdit, 4, 1 ); + grid2->addWidget( textMetaInfo, 4, 2, AlignHCenter ); + grid2->addWidget( metainfoEdit, 4, 3 ); + + metainfokeyEdit->setText("*"); + + if ( editRegExp ) { + // The editor was available, so lets use it. + grid2->addWidget( editRegExp, 2, 3 ); + } + + addTab( pages[0], i18n("Name/&Location") ); + addTab( pages[2], i18n("C&ontents") ); + addTab( pages[1], i18n("&Properties") ); + + + // Setup + const QString whatsmetainfo + = i18n("<qt>Search within files' specific comments/metainfo<br>" + "These are some examples:<br>" + "<ul>" + "<li><b>Audio files (mp3...)</b> Search in id3 tag for a title, an album</li>" + "<li><b>Images (png...)</b> Search images with a special resolution, comment...</li>" + "</ul>" + "</qt>"); + const QString whatsmetainfokey + = i18n("<qt>If specified, search only in this field<br>" + "<ul>" + "<li><b>Audio files (mp3...)</b> This can be Title, Album...</li>" + "<li><b>Images (png...)</b> Search only in Resolution, Bitdepth...</li>" + "</ul>" + "</qt>"); + QWhatsThis::add(textMetaInfo,whatsmetainfo); + QToolTip::add(metainfoEdit,whatsmetainfo); + QWhatsThis::add(textMetaKey,whatsmetainfokey); + QToolTip::add(metainfokeyEdit,whatsmetainfokey); + + + fixLayout(); + loadHistory(); +} + +KfindTabWidget::~KfindTabWidget() +{ + delete pages[0]; + delete pages[1]; + delete pages[2]; +} + +void KfindTabWidget::setURL( const KURL & url ) +{ + KConfig *conf = KGlobal::config(); + conf->setGroup("History"); + m_url = url; + QStringList sl = conf->readPathListEntry("Directories"); + dirBox->clear(); // make sure there is no old Stuff in there + + if(!sl.isEmpty()) { + dirBox->insertStringList(sl); + // If the _searchPath already exists in the list we do not + // want to add it again + int indx = sl.findIndex(m_url.prettyURL()); + if(indx == -1) + dirBox->insertItem(m_url.prettyURL(), 0); // make it the first one + else + dirBox->setCurrentItem(indx); + } + else { + QDir m_dir("/lib"); + dirBox ->insertItem( m_url.prettyURL() ); + dirBox ->insertItem( "file:" + QDir::homeDirPath() ); + dirBox ->insertItem( "file:/" ); + dirBox ->insertItem( "file:/usr" ); + if (m_dir.exists()) + dirBox ->insertItem( "file:/lib" ); + dirBox ->insertItem( "file:/home" ); + dirBox ->insertItem( "file:/etc" ); + dirBox ->insertItem( "file:/var" ); + dirBox ->insertItem( "file:/mnt" ); + } +} + +void KfindTabWidget::initMimeTypes() +{ + KMimeType::List tmp = KMimeType::allMimeTypes(); + KSortedMimeTypeList sortedList; + for ( KMimeType::List::ConstIterator it = tmp.begin(); + it != tmp.end(); ++it ) + { + KMimeType * type = *it; + if ((!type->comment().isEmpty()) + && (!type->name().startsWith("kdedevice/")) + && (!type->name().startsWith("all/"))) + sortedList.append(type); + } + sortedList.sort(); + for ( KMimeType *type = sortedList.first(); type; type = sortedList.next()) + { + m_types.append(type); + } +} + +void KfindTabWidget::initSpecialMimeTypes() +{ + KMimeType::List tmp = KMimeType::allMimeTypes(); + + for ( KMimeType::List::ConstIterator it = tmp.begin(); it != tmp.end(); ++it ) + { + KMimeType * type = *it; + + if(!type->comment().isEmpty()) { + if(type->name().startsWith("image/")) + m_ImageTypes.append(type->name()); + else if(type->name().startsWith("video/")) + m_VideoTypes.append(type->name()); + else if(type->name().startsWith("audio/")) + m_AudioTypes.append(type->name()); + } + } +} + +void KfindTabWidget::saveHistory() +{ + save_pattern(nameBox, "History", "Patterns"); + save_pattern(dirBox, "History", "Directories"); +} + +void KfindTabWidget::loadHistory() +{ + // Load pattern history + KConfig *conf = KGlobal::config(); + conf->setGroup("History"); + QStringList sl = conf->readListEntry("Patterns"); + if(!sl.isEmpty()) + nameBox->insertStringList(sl); + else + nameBox->insertItem("*"); + + sl = conf->readPathListEntry("Directories"); + if(!sl.isEmpty()) { + dirBox->insertStringList(sl); + // If the _searchPath already exists in the list we do not + // want to add it again + int indx = sl.findIndex(m_url.prettyURL()); + if(indx == -1) + dirBox->insertItem(m_url.prettyURL(), 0); // make it the first one + else + dirBox->setCurrentItem(indx); + } + else { + QDir m_dir("/lib"); + dirBox ->insertItem( m_url.prettyURL() ); + dirBox ->insertItem( "file:" + QDir::homeDirPath() ); + dirBox ->insertItem( "file:/" ); + dirBox ->insertItem( "file:/usr" ); + if (m_dir.exists()) + dirBox ->insertItem( "file:/lib" ); + dirBox ->insertItem( "file:/home" ); + dirBox ->insertItem( "file:/etc" ); + dirBox ->insertItem( "file:/var" ); + dirBox ->insertItem( "file:/mnt" ); + } +} + +void KfindTabWidget::slotEditRegExp() +{ + if ( ! regExpDialog ) + regExpDialog = KParts::ComponentFactory::createInstanceFromQuery<QDialog>( "KRegExpEditor/KRegExpEditor", QString::null, this ); + + KRegExpEditorInterface *iface = static_cast<KRegExpEditorInterface *>( regExpDialog->qt_cast( "KRegExpEditorInterface" ) ); + if ( !iface ) + return; + + iface->setRegExp( textEdit->text() ); + bool ok = regExpDialog->exec(); + if ( ok ) + textEdit->setText( iface->regExp() ); +} + +void KfindTabWidget::setFocus() +{ + nameBox->setFocus(); + nameBox->lineEdit()->selectAll(); +} + +void KfindTabWidget::slotSizeBoxChanged(int index) +{ + sizeEdit->setEnabled((bool)(index != 0)); + sizeUnitBox->setEnabled((bool)(index != 0)); +} + +void KfindTabWidget::setDefaults() +{ + QDate dt = KGlobal::locale()->calendar()->addYears(QDate::currentDate(), -1); + + fromDate ->setDate(dt); + toDate ->setDate(QDate::currentDate()); + + timeBox->setValue(1); + betweenType->setCurrentItem(1); + + typeBox ->setCurrentItem(0); + sizeBox ->setCurrentItem(0); + sizeUnitBox ->setCurrentItem(1); + sizeEdit->setValue(1); +} + +/* + Checks if dates are correct and popups a error box + if they are not. +*/ +bool KfindTabWidget::isDateValid() +{ + // All files + if ( !findCreated->isChecked() ) return TRUE; + + if (rb[1]->isChecked()) + { + if (timeBox->value() > 0 ) return TRUE; + + KMessageBox::sorry(this, i18n("Unable to search within a period which is less than a minute.")); + return FALSE; + } + + // If we can not parse either of the dates or + // "from" date is bigger than "to" date return FALSE. + QDate hi1, hi2; + + QString str; + if ( ! fromDate->getDate(&hi1).isValid() || + ! toDate->getDate(&hi2).isValid() ) + str = i18n("The date is not valid."); + else if ( hi1 > hi2 ) + str = i18n("Invalid date range."); + else if ( QDate::currentDate() < hi1 ) + str = i18n("Unable to search dates in the future."); + + if (!str.isNull()) { + KMessageBox::sorry(0, str); + return FALSE; + } + return TRUE; +} + +void KfindTabWidget::setQuery(KQuery *query) +{ + KIO::filesize_t size; + KIO::filesize_t sizeunit; + bool itemAlreadyContained(false); + // only start if we have valid dates + if (!isDateValid()) return; + + query->setPath(KURL(dirBox->currentText().stripWhiteSpace())); + + for (int idx=0; idx<dirBox->count(); idx++) + if (dirBox->text(idx)==dirBox->currentText()) + itemAlreadyContained=true; + + if (!itemAlreadyContained) + dirBox->insertItem(dirBox->currentText().stripWhiteSpace(),0); + + QString regex = nameBox->currentText().isEmpty() ? "*" : nameBox->currentText(); + query->setRegExp(regex, caseSensCb->isChecked()); + itemAlreadyContained=false; + for (int idx=0; idx<nameBox->count(); idx++) + if (nameBox->text(idx)==nameBox->currentText()) + itemAlreadyContained=true; + + if (!itemAlreadyContained) + nameBox->insertItem(nameBox->currentText(),0); + + query->setRecursive(subdirsCb->isChecked()); + + switch (sizeUnitBox->currentItem()) + { + case 0: + sizeunit = 1; //one byte + break; + case 2: + sizeunit = 1048576; //1M + break; + case 3: + sizeunit = 1073741824; //1GB + break; + case 1: //fall to default case + default: + sizeunit = 1024; //1k + break; + } + size = sizeEdit->value() * sizeunit; + +// TODO: troeder: do we need this check since it is very unlikely- +// to exceed ULLONG_MAX with INT_MAX * 1024^3.- +// Or is there an arch where this can happen? +#if 0 + if (size < 0) // overflow + if (KMessageBox::warningYesNo(this, i18n("Size is too big. Set maximum size value?"), i18n("Error"),i18n("Set"),i18n("Do Not Set")) + == KMessageBox::Yes) + { + sizeEdit->setValue(INT_MAX); + sizeUnitBox->setCurrentItem(0); + size = INT_MAX; + } + else + return; +#endif + + // set range mode and size value + query->setSizeRange(sizeBox->currentItem(),size,0); + + // dates + QDateTime epoch; + epoch.setTime_t(0); + + // Add date predicate + if (findCreated->isChecked()) { // Modified + if (rb[0]->isChecked()) { // Between dates + QDate q1, q2; + fromDate->getDate(&q1); + toDate->getDate(&q2); + + // do not generate negative numbers .. find doesn't handle that + time_t time1 = epoch.secsTo(q1); + time_t time2 = epoch.secsTo(q2.addDays(1)) - 1; // Include the last day + + query->setTimeRange(time1, time2); + } + else + { + time_t cur = time(NULL); + time_t minutes = cur; + + switch (betweenType->currentItem()) + { + case 0: // minutes + minutes = timeBox->value(); + break; + case 1: // hours + minutes = 60 * timeBox->value(); + break; + case 2: // days + minutes = 60 * 24 * timeBox->value(); + break; + case 3: // months + minutes = 60 * 24 * (time_t)(timeBox->value() * 30.41667); + break; + case 4: // years + minutes = 12 * 60 * 24 * (time_t)(timeBox->value() * 30.41667); + break; + } + + query->setTimeRange(cur - minutes * 60, 0); + } + } + else + query->setTimeRange(0, 0); + + query->setUsername( m_usernameBox->currentText() ); + query->setGroupname( m_groupBox->currentText() ); + + query->setFileType(typeBox->currentItem()); + + int id = typeBox->currentItem()-10; + + if ((id >= -3) && (id < (int) m_types.count())) + { + switch(id) + { + case -3: + query->setMimeType( m_ImageTypes ); + break; + case -2: + query->setMimeType( m_VideoTypes ); + break; + case -1: + query->setMimeType( m_AudioTypes ); + break; + default: + query->setMimeType( m_types[id]->name() ); + } + } + else + { + query->setMimeType( QString::null ); + } + + //Metainfo + query->setMetaInfo(metainfoEdit->text(), metainfokeyEdit->text()); + + //Use locate to speed-up search ? + query->setUseFileIndex(useLocateCb->isChecked()); + + query->setContext(textEdit->text(), caseContextCb->isChecked(), + binaryContextCb->isChecked(), regexpContentCb->isChecked()); +} + +QString KfindTabWidget::date2String(const QDate & date) { + return(KGlobal::locale()->formatDate(date, true)); +} + +QDate &KfindTabWidget::string2Date(const QString & str, QDate *qd) { + return *qd = KGlobal::locale()->readDate(str); +} + +void KfindTabWidget::getDirectory() +{ + QString result = + KFileDialog::getExistingDirectory( dirBox->text(dirBox->currentItem()).stripWhiteSpace(), + this ); + + if (!result.isEmpty()) + { + for (int i = 0; i < dirBox->count(); i++) + if (result == dirBox->text(i)) { + dirBox->setCurrentItem(i); + return; + } + dirBox->insertItem(result, 0); + dirBox->setCurrentItem(0); + } +} + +void KfindTabWidget::beginSearch() +{ +/// dirlister->openURL(KURL(dirBox->currentText().stripWhiteSpace())); + + saveHistory(); + setEnabled( FALSE ); +} + +void KfindTabWidget::endSearch() +{ + setEnabled( TRUE ); +} + +/* + Disables/enables all edit fields depending on their + respective check buttons. +*/ +void KfindTabWidget::fixLayout() +{ + int i; + // If "All files" is checked - disable all edits + // and second radio group on page two + + if(! findCreated->isChecked()) { + fromDate->setEnabled(FALSE); + toDate->setEnabled(FALSE); + timeBox->setEnabled(FALSE); + for(i=0; i<2; i++) + rb[i]->setEnabled(FALSE); + betweenType->setEnabled(FALSE); + } + else { + for(i=0; i<2; i++) + rb[i]->setEnabled(TRUE); + + fromDate->setEnabled(rb[0]->isChecked()); + toDate->setEnabled(rb[0]->isChecked()); + timeBox->setEnabled(rb[1]->isChecked()); + betweenType->setEnabled(rb[1]->isChecked()); + } + + // Size box on page three + sizeEdit->setEnabled(sizeBox->currentItem() != 0); + sizeUnitBox->setEnabled(sizeBox->currentItem() != 0); +} + +bool KfindTabWidget::isSearchRecursive() +{ + return subdirsCb->isChecked(); +} + + +/** + Digit validator. Allows only digits to be typed. +**/ +KDigitValidator::KDigitValidator( QWidget * parent, const char *name ) + : QValidator( parent, name ) +{ + r = new QRegExp("^[0-9]*$"); +} + +KDigitValidator::~KDigitValidator() +{ + delete r; +} + +QValidator::State KDigitValidator::validate( QString & input, int & ) const +{ + if (r->search(input) < 0) { + // Beep on user if he enters non-digit + QApplication::beep(); + return QValidator::Invalid; + } + else + return QValidator::Acceptable; +} + +//******************************************************* +// Static utility functions +//******************************************************* +static void save_pattern(QComboBox *obj, + const QString & group, const QString & entry) +{ + // QComboBox allows insertion of items more than specified by + // maxCount() (QT bug?). This API call will truncate list if needed. + obj->setMaxCount(15); + + // make sure the current item is saved first so it will be the + // default when started next time + QStringList sl; + QString cur = obj->currentText(); + sl.append(cur); + for (int i = 0; i < obj->count(); i++) { + if( cur != obj->text(i) ) { + sl.append(obj->text(i)); + } + } + + KConfig *conf = KGlobal::config(); + conf->setGroup(group); + conf->writePathEntry(entry, sl); +} + +QSize KfindTabWidget::sizeHint() const +{ + // #44662: avoid a huge default size when the comboboxes have very large items + // Like in minicli, we changed the combobox size policy so that they can resize down, + // and then we simply provide a reasonable size hint for the whole window, depending + // on the screen width. + QSize sz = QTabWidget::sizeHint(); + KfindTabWidget* me = const_cast<KfindTabWidget*>( this ); + const int screenWidth = qApp->desktop()->screenGeometry(me).width(); + if ( sz.width() > screenWidth / 2 ) + sz.setWidth( screenWidth / 2 ); + return sz; +} + +#include "kftabdlg.moc" diff --git a/kfind/kftabdlg.h b/kfind/kftabdlg.h new file mode 100644 index 000000000..3ead70c99 --- /dev/null +++ b/kfind/kftabdlg.h @@ -0,0 +1,136 @@ +/*********************************************************************** + * + * kftabdlg.h + * + ***********************************************************************/ + +#ifndef KFTABDLG_H +#define KFTABDLG_H + +#include <qtabwidget.h> +#include <qvalidator.h> // for KDigitValidator + +#include <kurl.h> +#include <kmimetype.h> + +#include "kdatecombo.h" + +class QButtonGroup; +class QPushButton; +class QRadioButton; +class QCheckBox; +class QLineEdit; +class QString; +class QDate; +class QRegExp; +class QDialog; +class QComboBox; +class QSpinBox; + +class KfDirDialog; + +class KfindTabWidget: public QTabWidget +{ + Q_OBJECT + +public: + KfindTabWidget(QWidget * parent = 0, const char *name=0); + virtual ~KfindTabWidget(); + void initMimeTypes(); + void initSpecialMimeTypes(); + void setQuery(class KQuery * query); + void setDefaults(); + + void beginSearch(); + void endSearch(); + void loadHistory(); + void saveHistory(); + bool isSearchRecursive(); + + void setURL( const KURL & url ); + + virtual QSize sizeHint() const; + +public slots: + void setFocus(); + +private slots: + void getDirectory(); + void fixLayout(); + void slotSizeBoxChanged(int); + void slotEditRegExp(); + +signals: + void startSearch(); + +protected: +public: + QComboBox *nameBox; + QComboBox *dirBox; + // for first page + QCheckBox *subdirsCb; + QCheckBox *useLocateCb; + // for third page + QComboBox *typeBox; + QLineEdit * textEdit; + QCheckBox *caseSensCb; + QComboBox *m_usernameBox; + QComboBox *m_groupBox; + //for fourth page + QLineEdit *metainfoEdit; + QLineEdit *metainfokeyEdit; + +private: + bool isDateValid(); + + QString date2String(const QDate &); + QDate &string2Date(const QString &, QDate * ); + + QWidget *pages[3]; + + //1st page + QPushButton *browseB; + + KfDirDialog *dirselector; + + //2nd page + QCheckBox *findCreated; + QComboBox *betweenType; + QButtonGroup *bg; + QRadioButton *rb[2]; + KDateCombo * fromDate; + KDateCombo * toDate; + QSpinBox *timeBox; + + //3rd page + QComboBox *sizeBox; + QComboBox *sizeUnitBox; + QSpinBox *sizeEdit; + QCheckBox *caseContextCb; + QCheckBox *binaryContextCb; + QCheckBox *regexpContentCb; + QDialog *regExpDialog; + + KURL m_url; + + KMimeType::List m_types; + QStringList m_ImageTypes; + QStringList m_VideoTypes; + QStringList m_AudioTypes; +}; + +class KDigitValidator : public QValidator +{ + Q_OBJECT + +public: + KDigitValidator(QWidget * parent, const char *name = 0 ); + ~KDigitValidator(); + + QValidator::State validate(QString & input, int &) const; + + private: + QRegExp *r; +}; + +#endif diff --git a/kfind/kfwin.cpp b/kfind/kfwin.cpp new file mode 100644 index 000000000..9eca22f19 --- /dev/null +++ b/kfind/kfwin.cpp @@ -0,0 +1,434 @@ +/*********************************************************************** + * + * Kfwin.cpp + * + **********************************************************************/ + +#include <stdlib.h> +#include <stdio.h> +#include <pwd.h> +#include <grp.h> +#include <sys/types.h> +#include <unistd.h> +#include <errno.h> +#include <sys/stat.h> +#include <time.h> + +#include <qtextstream.h> +#include <qfileinfo.h> +#include <qdir.h> +#include <qclipboard.h> +#include <qpixmap.h> +#include <qdragobject.h> + +#include <kfiledialog.h> +#include <klocale.h> +#include <kapplication.h> +#include <krun.h> +#include <kprocess.h> +#include <kpropertiesdialog.h> +#include <kstandarddirs.h> +#include <kmessagebox.h> +#include <kmimetype.h> +#include <kglobal.h> +#include <kpopupmenu.h> +#include <kio/netaccess.h> +#include <kurldrag.h> +#include <qptrlist.h> +#include <kdebug.h> +#include <kiconloader.h> + +#include "kfwin.h" + +#include "kfwin.moc" + +template class QPtrList<KfFileLVI>; + +// Permission strings +static const char* perm[4] = { + I18N_NOOP( "Read-write" ), + I18N_NOOP( "Read-only" ), + I18N_NOOP( "Write-only" ), + I18N_NOOP( "Inaccessible" ) }; +#define RW 0 +#define RO 1 +#define WO 2 +#define NA 3 + +KfFileLVI::KfFileLVI(KfindWindow* lv, const KFileItem &item, const QString& matchingLine) + : QListViewItem(lv), + fileitem(item) +{ + fileInfo = new QFileInfo(item.url().path()); + + QString size = KGlobal::locale()->formatNumber(item.size(), 0); + + QDateTime dt; + dt.setTime_t(item.time(KIO::UDS_MODIFICATION_TIME)); + QString date = KGlobal::locale()->formatDateTime(dt); + + int perm_index; + if(fileInfo->isReadable()) + perm_index = fileInfo->isWritable() ? RW : RO; + else + perm_index = fileInfo->isWritable() ? WO : NA; + + // Fill the item with data + setText(0, item.url().fileName(false)); + setText(1, lv->reducedDir(item.url().directory(false))); + setText(2, size); + setText(3, date); + setText(4, i18n(perm[perm_index])); + setText(5, matchingLine); + + // put the icon into the leftmost column + setPixmap(0, item.pixmap(16)); +} + +KfFileLVI::~KfFileLVI() +{ + delete fileInfo; +} + +QString KfFileLVI::key(int column, bool) const +{ + switch (column) { + case 2: + // Returns size in bytes. Used for sorting + return QString().sprintf("%010d", fileInfo->size()); + case 3: + // Returns time in secs from 1/1/1970. Used for sorting + return QString().sprintf("%010ld", fileitem.time(KIO::UDS_MODIFICATION_TIME)); + } + + return text(column); +} + +KfindWindow::KfindWindow( QWidget *parent, const char *name ) + : KListView( parent, name ) +,m_baseDir("") +,m_menu(0) +{ + setSelectionMode( QListView::Extended ); + setShowSortIndicator( TRUE ); + + addColumn(i18n("Name")); + addColumn(i18n("In Subfolder")); + addColumn(i18n("Size")); + setColumnAlignment(2, AlignRight); + addColumn(i18n("Modified")); + setColumnAlignment(3, AlignRight); + addColumn(i18n("Permissions")); + setColumnAlignment(4, AlignRight); + + addColumn(i18n("First Matching Line")); + setColumnAlignment(5, AlignLeft); + + // Disable autoresize for all columns + // Resizing is done by resetColumns() function + for (int i = 0; i < 6; i++) + setColumnWidthMode(i, Manual); + + resetColumns(true); + + connect( this, SIGNAL(selectionChanged()), + this, SLOT( selectionHasChanged() )); + + connect(this, SIGNAL(contextMenu(KListView *, QListViewItem*,const QPoint&)), + this, SLOT(slotContextMenu(KListView *,QListViewItem*,const QPoint&))); + + connect(this, SIGNAL(executed(QListViewItem*)), + this, SLOT(slotExecute(QListViewItem*))); + setDragEnabled(true); + +} + + +QString KfindWindow::reducedDir(const QString& fullDir) +{ + if (fullDir.find(m_baseDir)==0) + { + QString tmp=fullDir.mid(m_baseDir.length()); + return tmp; + }; + return fullDir; +} + +void KfindWindow::beginSearch(const KURL& baseUrl) +{ + kdDebug()<<QString("beginSearch in: %1").arg(baseUrl.path())<<endl; + m_baseDir=baseUrl.path(+1); + haveSelection = false; + clear(); +} + +void KfindWindow::endSearch() +{ +} + +void KfindWindow::insertItem(const KFileItem &item, const QString& matchingLine) +{ + new KfFileLVI(this, item, matchingLine); +} + +// copy to clipboard aka X11 selection +void KfindWindow::copySelection() +{ + QDragObject *drag_obj = dragObject(); + + if (drag_obj) + { + QClipboard *cb = kapp->clipboard(); + cb->setData(drag_obj); + } +} + +void KfindWindow::saveResults() +{ + QListViewItem *item; + + KFileDialog *dlg = new KFileDialog(QString::null, QString::null, this, + "filedialog", true); + dlg->setOperationMode (KFileDialog::Saving); + + dlg->setCaption(i18n("Save Results As")); + + QStringList list; + + list << "text/plain" << "text/html"; + + dlg->setOperationMode(KFileDialog::Saving); + + dlg->setMimeFilter(list, QString("text/plain")); + + dlg->exec(); + + KURL u = dlg->selectedURL(); + KMimeType::Ptr mimeType = dlg->currentFilterMimeType(); + delete dlg; + + if (!u.isValid() || !u.isLocalFile()) + return; + + QString filename = u.path(); + + QFile file(filename); + + if ( !file.open(IO_WriteOnly) ) + KMessageBox::error(parentWidget(), + i18n("Unable to save results.")); + else { + QTextStream stream( &file ); + stream.setEncoding( QTextStream::Locale ); + + if ( mimeType->name() == "text/html") { + stream << QString::fromLatin1("<HTML><HEAD>\n" + "<!DOCTYPE %1>\n" + "<TITLE>%2</TITLE></HEAD>\n" + "<BODY><H1>%3</H1>" + "<DL><p>\n") + .arg(i18n("KFind Results File")) + .arg(i18n("KFind Results File")) + .arg(i18n("KFind Results File")); + + item = firstChild(); + while(item != NULL) + { + QString path=((KfFileLVI*)item)->fileitem.url().url(); + QString pretty=((KfFileLVI*)item)->fileitem.url().htmlURL(); + stream << QString::fromLatin1("<DT><A HREF=\"") << path + << QString::fromLatin1("\">") << pretty + << QString::fromLatin1("</A>\n"); + + item = item->nextSibling(); + } + stream << QString::fromLatin1("</DL><P></BODY></HTML>\n"); + } + else { + item = firstChild(); + while(item != NULL) + { + QString path=((KfFileLVI*)item)->fileitem.url().url(); + stream << path << endl; + item = item->nextSibling(); + } + } + + file.close(); + KMessageBox::information(parentWidget(), + i18n("Results were saved to file\n")+ + filename); + } +} + +// This function is called when selection is changed (both selected/deselected) +// It notifies the parent about selection status and enables/disables menubar +void KfindWindow::selectionHasChanged() +{ + emit resultSelected(true); + + QListViewItem *item = firstChild(); + while(item != 0L) + { + if(isSelected(item)) { + emit resultSelected( true ); + haveSelection = true; + return; + } + + item = item->nextSibling(); + } + + haveSelection = false; + emit resultSelected(false); +} + +void KfindWindow::deleteFiles() +{ + QString tmp = i18n("Do you really want to delete the selected file?", + "Do you really want to delete the %n selected files?",selectedItems().count()); + if (KMessageBox::warningContinueCancel(parentWidget(), tmp, "", KGuiItem( i18n("&Delete"), "editdelete")) == KMessageBox::Cancel) + return; + + // Iterate on all selected elements + QPtrList<QListViewItem> selected = selectedItems(); + for ( uint i = 0; i < selected.count(); i++ ) { + KfFileLVI *item = (KfFileLVI *) selected.at(i); + KFileItem file = item->fileitem; + + KIO::NetAccess::del(file.url(), this); + } + selected.setAutoDelete(true); +} + +void KfindWindow::fileProperties() +{ + // This dialog must be modal because it parent dialog is modal as well. + // Non-modal property dialog will hide behind the main window + (void) new KPropertiesDialog( &((KfFileLVI *)currentItem())->fileitem, this, + "propDialog", true); +} + +void KfindWindow::openFolder() +{ + KFileItem fileitem = ((KfFileLVI *)currentItem())->fileitem; + KURL url = fileitem.url(); + url.setFileName(QString::null); + + (void) new KRun(url); +} + +void KfindWindow::openBinding() +{ + ((KfFileLVI*)currentItem())->fileitem.run(); +} + +void KfindWindow::slotExecute(QListViewItem* item) +{ + if (item==0) + return; + ((KfFileLVI*)item)->fileitem.run(); +} + +// Resizes KListView to occupy all visible space +void KfindWindow::resizeEvent(QResizeEvent *e) +{ + KListView::resizeEvent(e); + resetColumns(false); + clipper()->repaint(); +} + +QDragObject * KfindWindow::dragObject() +{ + KURL::List uris; + QPtrList<QListViewItem> selected = selectedItems(); + + // create a list of URIs from selection + for ( uint i = 0; i < selected.count(); i++ ) + { + KfFileLVI *item = (KfFileLVI *) selected.at( i ); + if (item) + { + uris.append( item->fileitem.url() ); + } + } + + if ( uris.count() <= 0 ) + return 0; + + QUriDrag *ud = new KURLDrag( uris, (QWidget *) this, "kfind uridrag" ); + + const QPixmap *pix = currentItem()->pixmap(0); + if ( pix && !pix->isNull() ) + ud->setPixmap( *pix ); + + return ud; +} + +void KfindWindow::resetColumns(bool init) +{ + QFontMetrics fm = fontMetrics(); + if (init) + { + setColumnWidth(2, QMAX(fm.width(columnText(2)), fm.width("0000000")) + 15); + QString sampleDate = + KGlobal::locale()->formatDateTime(QDateTime::currentDateTime()); + setColumnWidth(3, QMAX(fm.width(columnText(3)), fm.width(sampleDate)) + 15); + setColumnWidth(4, QMAX(fm.width(columnText(4)), fm.width(i18n(perm[RO]))) + 15); + setColumnWidth(5, QMAX(fm.width(columnText(5)), fm.width("some text")) + 15); + } + + int free_space = visibleWidth() - + columnWidth(2) - columnWidth(3) - columnWidth(4) - columnWidth(5); + +// int name_w = QMIN((int)(free_space*0.5), 150); +// int dir_w = free_space - name_w; + int name_w = QMAX((int)(free_space*0.5), fm.width("some long filename")); + int dir_w = name_w; + + setColumnWidth(0, name_w); + setColumnWidth(1, dir_w); +} + +void KfindWindow::slotContextMenu(KListView *,QListViewItem *item,const QPoint&p) +{ + if (!item) return; + int count = selectedItems().count(); + + if (count == 0) + { + return; + }; + + if (m_menu==0) + m_menu = new KPopupMenu(this); + else + m_menu->clear(); + + if (count == 1) + { + //menu = new KPopupMenu(item->text(0), this); + m_menu->insertTitle(item->text(0)); + m_menu->insertItem(SmallIcon("fileopen"),i18n("Menu item", "Open"), this, SLOT(openBinding())); + m_menu->insertItem(SmallIcon("window_new"),i18n("Open Folder"), this, SLOT(openFolder())); + m_menu->insertSeparator(); + m_menu->insertItem(SmallIcon("editcopy"),i18n("Copy"), this, SLOT(copySelection())); + m_menu->insertItem(SmallIcon("editdelete"),i18n("Delete"), this, SLOT(deleteFiles())); + m_menu->insertSeparator(); + m_menu->insertItem(i18n("Open With..."), this, SLOT(slotOpenWith())); + m_menu->insertSeparator(); + m_menu->insertItem(i18n("Properties"), this, SLOT(fileProperties())); + } + else + { + m_menu->insertTitle(i18n("Selected Files")); + m_menu->insertItem(SmallIcon("editcopy"),i18n("Copy"), this, SLOT(copySelection())); + m_menu->insertItem(SmallIcon("editdelete"),i18n("Delete"), this, SLOT(deleteFiles())); + } + m_menu->popup(p, 1); +} + +void KfindWindow::slotOpenWith() +{ + KRun::displayOpenWithDialog( KURL::split(((KfFileLVI*)currentItem())->fileitem.url()) ); +} diff --git a/kfind/kfwin.h b/kfind/kfwin.h new file mode 100644 index 000000000..0d55c8f6a --- /dev/null +++ b/kfind/kfwin.h @@ -0,0 +1,75 @@ +/*********************************************************************** + * + * Kfwin.h + * + ***********************************************************************/ + +#ifndef KFWIN_H +#define KFWIN_H + +#include <klistview.h> +#include <kfileitem.h> +#include <kurl.h> + +class KfArchiver; +class QPixmap; +class QFileInfo; +class KPopupMenu; +class KfindWindow; + +class KfFileLVI : public QListViewItem +{ + public: + KfFileLVI(KfindWindow* lv, const KFileItem &item,const QString& matchingLine); + ~KfFileLVI(); + + QString key(int column, bool) const; + + QFileInfo *fileInfo; + KFileItem fileitem; +}; + +class KfindWindow: public KListView +{ + Q_OBJECT +public: + KfindWindow( QWidget * parent = 0, const char * name = 0 ); + + void beginSearch(const KURL& baseUrl); + void endSearch(); + + void insertItem(const KFileItem &item, const QString& matchingLine); + + QString reducedDir(const QString& fullDir); + +public slots: + void copySelection(); + void slotContextMenu(KListView *,QListViewItem *item,const QPoint&p); + +private slots: + void deleteFiles(); + void fileProperties(); + void openFolder(); + void saveResults(); + void openBinding(); + void selectionHasChanged(); + void slotExecute(QListViewItem*); + void slotOpenWith(); + +protected: + virtual void resizeEvent(QResizeEvent *e); + + virtual QDragObject *dragObject(); + +signals: + void resultSelected(bool); + +private: + QString m_baseDir; + KPopupMenu *m_menu; + bool haveSelection; + bool m_pressed; + void resetColumns(bool init); +}; + +#endif diff --git a/kfind/kquery.cpp b/kfind/kquery.cpp new file mode 100644 index 000000000..5d5446fc6 --- /dev/null +++ b/kfind/kquery.cpp @@ -0,0 +1,527 @@ +#include <stdlib.h> + +#include <qfileinfo.h> +#include <kdebug.h> +#include <kfileitem.h> +#include <kfilemetainfo.h> +#include <kapplication.h> +#include <kmessagebox.h> +#include <klocale.h> +#include <kstandarddirs.h> +#include <kzip.h> + +#include "kquery.h" + +KQuery::KQuery(QObject *parent, const char * name) + : QObject(parent, name), + m_sizemode(0), m_sizeboundary1(0), m_sizeboundary2(0), + m_timeFrom(0), m_timeTo(0), + job(0), m_insideCheckEntries(false), m_result(0) +{ + m_regexps.setAutoDelete(true); + m_fileItems.setAutoDelete(true); + processLocate = new KProcess(this); + connect(processLocate,SIGNAL(receivedStdout(KProcess*, char*, int)),this,SLOT(slotreceivedSdtout(KProcess*,char*,int))); + connect(processLocate,SIGNAL(receivedStderr(KProcess*, char*, int)),this,SLOT(slotreceivedSdterr(KProcess*,char*,int))); + connect(processLocate,SIGNAL(processExited(KProcess*)),this,SLOT(slotendProcessLocate(KProcess*))); + + // Files with these mime types can be ignored, even if + // findFormatByFileContent() in some cases may claim that + // these are text files: + ignore_mimetypes.append("application/pdf"); + ignore_mimetypes.append("application/postscript"); + + // PLEASE update the documentation when you add another + // file type here: + ooo_mimetypes.append("application/vnd.sun.xml.writer"); + ooo_mimetypes.append("application/vnd.sun.xml.calc"); + ooo_mimetypes.append("application/vnd.sun.xml.impress"); + // OASIS mimetypes, used by OOo-2.x and KOffice >= 1.4 + //ooo_mimetypes.append("application/vnd.oasis.opendocument.chart"); + //ooo_mimetypes.append("application/vnd.oasis.opendocument.graphics"); + //ooo_mimetypes.append("application/vnd.oasis.opendocument.graphics-template"); + //ooo_mimetypes.append("application/vnd.oasis.opendocument.formula"); + //ooo_mimetypes.append("application/vnd.oasis.opendocument.image"); + ooo_mimetypes.append("application/vnd.oasis.opendocument.presentation-template"); + ooo_mimetypes.append("application/vnd.oasis.opendocument.presentation"); + ooo_mimetypes.append("application/vnd.oasis.opendocument.spreadsheet-template"); + ooo_mimetypes.append("application/vnd.oasis.opendocument.spreadsheet"); + ooo_mimetypes.append("application/vnd.oasis.opendocument.text-template"); + ooo_mimetypes.append("application/vnd.oasis.opendocument.text"); + // KOffice-1.3 mimetypes + koffice_mimetypes.append("application/x-kword"); + koffice_mimetypes.append("application/x-kspread"); + koffice_mimetypes.append("application/x-kpresenter"); +} + +KQuery::~KQuery() +{ +} + +void KQuery::kill() +{ + if (job) + job->kill(false); + if (processLocate->isRunning()) + processLocate->kill(); + m_fileItems.clear(); +} + +void KQuery::start() +{ + m_fileItems.clear(); + if(m_useLocate) //use "locate" instead of the internal search method + { + m_url.cleanPath(); + processLocate->clearArguments(); + *processLocate << "locate"; + *processLocate << m_url.path(1).latin1(); + bufferLocate=NULL; + bufferLocateLength=0; + processLocate->start(KProcess::NotifyOnExit,KProcess::AllOutput); + return; + } + + if (m_recursive) + job = KIO::listRecursive( m_url, false ); + else + job = KIO::listDir( m_url, false ); + + connect(job, SIGNAL(entries(KIO::Job *, const KIO::UDSEntryList &)), + SLOT(slotListEntries(KIO::Job *, const KIO::UDSEntryList &))); + connect(job, SIGNAL(result(KIO::Job *)), SLOT(slotResult(KIO::Job *))); + connect(job, SIGNAL(canceled(KIO::Job *)), SLOT(slotCanceled(KIO::Job *))); +} + +void KQuery::slotResult( KIO::Job * _job ) +{ + if (job != _job) return; + job = 0; + + m_result=_job->error(); + checkEntries(); +} + +void KQuery::slotCanceled( KIO::Job * _job ) +{ + if (job != _job) return; + job = 0; + + m_fileItems.clear(); + m_result=KIO::ERR_USER_CANCELED; + checkEntries(); +} + +void KQuery::slotListEntries(KIO::Job*, const KIO::UDSEntryList& list) +{ + KFileItem * file = 0; + KIO::UDSEntryListConstIterator end = list.end(); + for (KIO::UDSEntryListConstIterator it = list.begin(); it != end; ++it) + { + file = new KFileItem(*it, m_url, true, true); + m_fileItems.enqueue(file); + } + checkEntries(); +} + +void KQuery::checkEntries() +{ + if (m_insideCheckEntries) + return; + m_insideCheckEntries=true; + metaKeyRx=new QRegExp(m_metainfokey,true,true); + KFileItem * file = 0; + while ((file=m_fileItems.dequeue())) + { + processQuery(file); + delete file; + } + delete metaKeyRx; + m_insideCheckEntries=false; + if (job==0) + emit result(m_result); +} + +/* List of files found using slocate */ +void KQuery::slotListEntries( QStringList list ) +{ + KFileItem * file = 0; + metaKeyRx=new QRegExp(m_metainfokey,true,true); + + QStringList::Iterator it = list.begin(); + QStringList::Iterator end = list.end(); + + for (; it != end; ++it) + { + file = new KFileItem( KFileItem::Unknown, KFileItem::Unknown, KURL::fromPathOrURL(*it)); + processQuery(file); + delete file; + } + + delete metaKeyRx; +} + +/* Check if file meets the find's requirements*/ +void KQuery::processQuery( KFileItem* file) +{ + QRegExp *filename_match; + + if ( file->name() == "." || file->name() == ".." ) + return; + + bool matched=false; + + for ( filename_match = m_regexps.first(); !matched && filename_match; filename_match = m_regexps.next() ) + { + matched |= filename_match->isEmpty() || + (filename_match->exactMatch( file->url().fileName( true ) ) ); + } + if (!matched) + return; + + switch( m_sizemode ) + { + case 1: // "at least" + if ( file->size() < m_sizeboundary1 ) return; + break; + case 2: // "at most" + if ( file->size() > m_sizeboundary1 ) return; + break; + case 3: // "equal" + if ( file->size() != m_sizeboundary1 ) return; + break; + case 4: // "between" + if ( (file->size() < m_sizeboundary1) || (file->size() > m_sizeboundary2) ) return; + break; + case 0: // "none" -> fall to default + default: + break; + } + + // make sure it's in the correct date range + // what about 0 times? + if ( m_timeFrom && m_timeFrom > file->time(KIO::UDS_MODIFICATION_TIME) ) + return; + if ( m_timeTo && m_timeTo < file->time(KIO::UDS_MODIFICATION_TIME) ) + return; + + // username / group match + if ( (!m_username.isEmpty()) && (m_username != file->user()) ) + return; + if ( (!m_groupname.isEmpty()) && (m_groupname != file->group()) ) + return; + + // file type + switch (m_filetype) + { + case 0: + break; + case 1: // plain file + if ( !S_ISREG( file->mode() ) ) + return; + break; + case 2: + if ( !file->isDir() ) + return; + break; + case 3: + if ( !file->isLink() ) + return; + break; + case 4: + if ( !S_ISCHR ( file->mode() ) && !S_ISBLK ( file->mode() ) && + !S_ISFIFO( file->mode() ) && !S_ISSOCK( file->mode() ) ) + return; + break; + case 5: // binary + if ( (file->permissions() & 0111) != 0111 || file->isDir() ) + return; + break; + case 6: // suid + if ( (file->permissions() & 04000) != 04000 ) // fixme + return; + break; + default: + if (!m_mimetype.isEmpty() && !m_mimetype.contains(file->mimetype())) + return; + } + + // match datas in metainfo... + if ((!m_metainfo.isEmpty()) && (!m_metainfokey.isEmpty())) + { + bool foundmeta=false; + QString filename = file->url().path(); + + if(filename.startsWith("/dev/")) + return; + + KFileMetaInfo metadatas(filename); + KFileMetaInfoItem metaitem; + QStringList metakeys; + QString strmetakeycontent; + + if(metadatas.isEmpty()) + return; + + metakeys=metadatas.supportedKeys(); + for ( QStringList::Iterator it = metakeys.begin(); it != metakeys.end(); ++it ) + { + if (!metaKeyRx->exactMatch(*it)) + continue; + metaitem=metadatas.item(*it); + strmetakeycontent=metaitem.string(); + if(strmetakeycontent.find(m_metainfo)!=-1) + { + foundmeta=true; + break; + } + } + if (!foundmeta) + return; + } + + // match contents... + QString matchingLine; + if (!m_context.isEmpty()) + { + + if( !m_search_binary && ignore_mimetypes.findIndex(file->mimetype()) != -1 ) { + kdDebug() << "ignoring, mime type is in exclusion list: " << file->url() << endl; + return; + } + + bool found = false; + bool isZippedOfficeDocument=false; + int matchingLineNumber=0; + + // FIXME: doesn't work with non local files + + QString filename; + QTextStream* stream=0; + QFile qf; + QRegExp xmlTags; + QByteArray zippedXmlFileContent; + + // KWord's and OpenOffice.org's files are zipped... + if( ooo_mimetypes.findIndex(file->mimetype()) != -1 || + koffice_mimetypes.findIndex(file->mimetype()) != -1 ) + { + KZip zipfile(file->url().path()); + KZipFileEntry *zipfileEntry; + + if(zipfile.open(IO_ReadOnly)) + { + const KArchiveDirectory *zipfileContent = zipfile.directory(); + + if( koffice_mimetypes.findIndex(file->mimetype()) != -1 ) + zipfileEntry = (KZipFileEntry*)zipfileContent->entry("maindoc.xml"); + else + zipfileEntry = (KZipFileEntry*)zipfileContent->entry("content.xml"); //for OpenOffice.org + + if(!zipfileEntry) { + kdWarning() << "Expected XML file not found in ZIP archive " << file->url() << endl; + return; + } + + zippedXmlFileContent = zipfileEntry->data(); + xmlTags.setPattern("<.*>"); + xmlTags.setMinimal(true); + stream = new QTextStream(zippedXmlFileContent, IO_ReadOnly); + stream->setEncoding(QTextStream::UnicodeUTF8); + isZippedOfficeDocument = true; + } else { + kdWarning() << "Cannot open supposed ZIP file " << file->url() << endl; + } + } else if( !m_search_binary && !file->mimetype().startsWith("text/") && + file->url().isLocalFile() ) { + KMimeType::Format f = KMimeType::findFormatByFileContent(file->url().path()); + if ( !f.text ) { + kdDebug() << "ignoring, not a text file: " << file->url() << endl; + return; + } + } + + if(!isZippedOfficeDocument) //any other file or non-compressed KWord + { + filename = file->url().path(); + if(filename.startsWith("/dev/")) + return; + qf.setName(filename); + qf.open(IO_ReadOnly); + stream=new QTextStream(&qf); + stream->setEncoding(QTextStream::Locale); + } + + while ( ! stream->atEnd() ) + { + QString str = stream->readLine(); + matchingLineNumber++; + + if (str.isNull()) break; + if(isZippedOfficeDocument) + str.replace(xmlTags, ""); + + if (m_regexpForContent) + { + if (m_regexp.search(str)>=0) + { + matchingLine=QString::number(matchingLineNumber)+": "+str; + found = true; + break; + } + } + else + { + if (str.find(m_context, 0, m_casesensitive) != -1) + { + matchingLine=QString::number(matchingLineNumber)+": "+str; + found = true; + break; + } + } + kapp->processEvents(); + } + delete stream; + + if (!found) + return; + } + emit addFile(file,matchingLine); +} + +void KQuery::setContext(const QString & context, bool casesensitive, + bool search_binary, bool useRegexp) +{ + m_context = context; + m_casesensitive = casesensitive; + m_search_binary = search_binary; + m_regexpForContent=useRegexp; + m_regexp.setWildcard(!m_regexpForContent); + m_regexp.setCaseSensitive(casesensitive); + if (m_regexpForContent) + m_regexp.setPattern(m_context); +} + +void KQuery::setMetaInfo(const QString &metainfo, const QString &metainfokey) +{ + m_metainfo=metainfo; + m_metainfokey=metainfokey; +} + +void KQuery::setMimeType(const QStringList &mimetype) +{ + m_mimetype = mimetype; +} + +void KQuery::setFileType(int filetype) +{ + m_filetype = filetype; +} + +void KQuery::setSizeRange(int mode, KIO::filesize_t value1, KIO::filesize_t value2) +{ + m_sizemode = mode; + m_sizeboundary1 = value1; + m_sizeboundary2 = value2; +} + +void KQuery::setTimeRange(time_t from, time_t to) +{ + m_timeFrom = from; + m_timeTo = to; +} + +void KQuery::setUsername(QString username) +{ + m_username = username; +} + +void KQuery::setGroupname(QString groupname) +{ + m_groupname = groupname; +} + + +void KQuery::setRegExp(const QString ®exp, bool caseSensitive) +{ + QRegExp *regExp; + QRegExp sep(";"); + QStringList strList=QStringList::split( sep, regexp, false); +// QRegExp globChars ("[\\*\\?\\[\\]]", TRUE, FALSE); + + m_regexps.clear(); +// m_regexpsContainsGlobs.clear(); + for ( QStringList::ConstIterator it = strList.begin(); it != strList.end(); ++it ) { + regExp = new QRegExp((*it),caseSensitive,true); +// m_regexpsContainsGlobs.append(regExp->pattern().contains(globChars)); + m_regexps.append(regExp); + } +} + +void KQuery::setRecursive(bool recursive) +{ + m_recursive = recursive; +} + +void KQuery::setPath(const KURL &url) +{ + m_url = url; +} + +void KQuery::setUseFileIndex(bool useLocate) +{ + m_useLocate=useLocate; +} + +void KQuery::slotreceivedSdterr(KProcess* ,char* str,int) +{ + KMessageBox::error(NULL, QString(str), i18n("Error while using locate")); +} + +void KQuery::slotreceivedSdtout(KProcess*,char* str,int l) +{ + int i; + + bufferLocateLength+=l; + str[l]='\0'; + bufferLocate=(char*)realloc(bufferLocate,sizeof(char)*(bufferLocateLength)); + for (i=0;i<l;i++) + bufferLocate[bufferLocateLength-l+i]=str[i]; +} + +void KQuery::slotendProcessLocate(KProcess*) +{ + QString qstr; + QStringList strlist; + int i,j,k; + + if((bufferLocateLength==0)||(bufferLocate==NULL)) + { + emit result(0); + return; + } + + i=0; + do + { + j=1; + while(bufferLocate[i]!='\n') + { + i++; + j++; + } + qstr=""; + for(k=0;k<j-1;k++) + qstr.append(bufferLocate[k+i-j+1]); + strlist.append(qstr); + i++; + + }while(i<bufferLocateLength); + bufferLocateLength=0; + free(bufferLocate); + bufferLocate=NULL; + slotListEntries(strlist ); + emit result(0); +} + +#include "kquery.moc" diff --git a/kfind/kquery.h b/kfind/kquery.h new file mode 100644 index 000000000..c7e81fcfe --- /dev/null +++ b/kfind/kquery.h @@ -0,0 +1,102 @@ +#ifndef KQUERY_H +#define KQUERY_H + +#include <time.h> + +#include <qobject.h> +#include <qregexp.h> +#include <qptrqueue.h> +#include <qdir.h> +#include <qstringlist.h> + +#include <kio/job.h> +#include <kurl.h> +#include <kprocess.h> + +class KFileItem; + +class KQuery : public QObject +{ + Q_OBJECT + + public: + KQuery(QObject *parent = 0, const char * name = 0); + ~KQuery(); + + void setSizeRange( int mode, KIO::filesize_t value1, KIO::filesize_t value2 ); + void setTimeRange( time_t from, time_t to ); + void setRegExp( const QString ®exp, bool caseSensitive ); + void setRecursive( bool recursive ); + void setPath(const KURL & url ); + void setFileType( int filetype ); + void setMimeType( const QStringList & mimetype ); + void setContext( const QString & context, bool casesensitive, + bool search_binary, bool useRegexp ); + void setUsername( QString username ); + void setGroupname( QString groupname ); + void setMetaInfo(const QString &metainfo, const QString &metainfokey); + void setUseFileIndex(bool); + + void start(); + void kill(); + const KURL& url() {return m_url;}; + + private: + /* Check if file meets the find's requirements*/ + inline void processQuery(KFileItem*); + + public slots: + /* List of files found using slocate */ + void slotListEntries(QStringList); + protected slots: + /* List of files found using KIO */ + void slotListEntries(KIO::Job *, const KIO::UDSEntryList &); + void slotResult(KIO::Job *); + void slotCanceled(KIO::Job *); + void slotreceivedSdtout(KProcess*,char*,int); + void slotreceivedSdterr(KProcess*,char*,int); + void slotendProcessLocate(KProcess*); + + signals: + void addFile(const KFileItem *filename, const QString& matchingLine); + void result(int); + + private: + void checkEntries(); + + int m_filetype; + int m_sizemode; + KIO::filesize_t m_sizeboundary1; + KIO::filesize_t m_sizeboundary2; + KURL m_url; + time_t m_timeFrom; + time_t m_timeTo; + QRegExp m_regexp;// regexp for file content + bool m_recursive; + QStringList m_mimetype; + QString m_context; + QString m_username; + QString m_groupname; + QString m_metainfo; + QString m_metainfokey; + bool m_casesensitive; + bool m_search_binary; + bool m_regexpForContent; + bool m_useLocate; + char* bufferLocate; + int bufferLocateLength; + QStringList locateList; + KProcess *processLocate; + QPtrList<QRegExp> m_regexps;// regexps for file name +// QValueList<bool> m_regexpsContainsGlobs; // what should this be good for ? Alex + KIO::ListJob *job; + bool m_insideCheckEntries; + QPtrQueue<KFileItem> m_fileItems; + QRegExp* metaKeyRx; + int m_result; + QStringList ignore_mimetypes; + QStringList ooo_mimetypes; // OpenOffice.org mimetypes + QStringList koffice_mimetypes; +}; + +#endif diff --git a/kfind/main.cpp b/kfind/main.cpp new file mode 100644 index 000000000..a92f0ddcd --- /dev/null +++ b/kfind/main.cpp @@ -0,0 +1,65 @@ +#include <qdir.h> +#include <qfile.h> + +#include <kapplication.h> +#include <klocale.h> +#include <kcmdlineargs.h> +#include <kaboutdata.h> +#include <kopenwith.h> + +#include "kfinddlg.h" +#include "version.h" + +static const char description[] = + I18N_NOOP("KDE file find utility"); + +static KCmdLineOptions options[] = +{ + { "+[searchpath]", I18N_NOOP("Path(s) to search"), 0 }, + KCmdLineLastOption +}; + +int main( int argc, char ** argv ) +{ + KLocale::setMainCatalogue("kfindpart"); + KAboutData aboutData( "kfind", I18N_NOOP("KFind"), + KFIND_VERSION, description, KAboutData::License_GPL, + I18N_NOOP("(c) 1998-2003, The KDE Developers")); + + aboutData.addAuthor("Eric Coquelle", I18N_NOOP("Current Maintainer"), "coquelle@caramail.com"); + aboutData.addAuthor("Mark W. Webb", I18N_NOOP("Developer"), "markwebb@adelphia.net"); + aboutData.addAuthor("Beppe Grimaldi", I18N_NOOP("UI Design & more search options"), "grimalkin@ciaoweb.it"); + aboutData.addAuthor("Martin Hartig"); + aboutData.addAuthor("Stephan Kulow", 0, "coolo@kde.org"); + aboutData.addAuthor("Mario Weilguni",0, "mweilguni@sime.com"); + aboutData.addAuthor("Alex Zepeda",0, "zipzippy@sonic.net"); + aboutData.addAuthor("Miroslav Fl�r",0, "flidr@kky.zcu.cz"); + aboutData.addAuthor("Harri Porten",0, "porten@kde.org"); + aboutData.addAuthor("Dima Rogozin",0, "dima@mercury.co.il"); + aboutData.addAuthor("Carsten Pfeiffer",0, "pfeiffer@kde.org"); + aboutData.addAuthor("Hans Petter Bieker", 0, "bieker@kde.org"); + aboutData.addAuthor("Waldo Bastian", I18N_NOOP("UI Design"), "bastian@kde.org"); + aboutData.addAuthor("Alexander Neundorf", 0, "neundorf@kde.org"); + aboutData.addAuthor("Clarence Dang", 0, "dang@kde.org"); + + KCmdLineArgs::init( argc, argv, &aboutData ); + KCmdLineArgs::addCmdLineOptions( options ); + + KApplication app; + + KCmdLineArgs *args= KCmdLineArgs::parsedArgs(); + + KURL url; + if (args->count() > 0) + url = args->url(0); + if (url.isEmpty()) + url = QDir::currentDirPath(); + if (url.isEmpty()) + url = QDir::homeDirPath(); + args->clear(); + + KfindDlg kfinddlg(url, 0, "dialog"); + return kfinddlg.exec(); +} + + diff --git a/kfind/pics/Makefile.am b/kfind/pics/Makefile.am new file mode 100644 index 000000000..0d31d2cf2 --- /dev/null +++ b/kfind/pics/Makefile.am @@ -0,0 +1,2 @@ +kfind_pics_datadir = $(kde_datadir)/kfindpart/icons +kfind_pics_data_ICON = AUTO diff --git a/kfind/pics/lo22-action-archive.png b/kfind/pics/lo22-action-archive.png Binary files differnew file mode 100644 index 000000000..54e73c2f9 --- /dev/null +++ b/kfind/pics/lo22-action-archive.png diff --git a/kfind/pics/lo22-action-delete.png b/kfind/pics/lo22-action-delete.png Binary files differnew file mode 100644 index 000000000..1018d6e22 --- /dev/null +++ b/kfind/pics/lo22-action-delete.png diff --git a/kfind/pics/lo22-action-idea.png b/kfind/pics/lo22-action-idea.png Binary files differnew file mode 100644 index 000000000..e348d48b6 --- /dev/null +++ b/kfind/pics/lo22-action-idea.png diff --git a/kfind/pics/lo22-action-info.png b/kfind/pics/lo22-action-info.png Binary files differnew file mode 100644 index 000000000..41aec81ef --- /dev/null +++ b/kfind/pics/lo22-action-info.png diff --git a/kfind/pics/lo22-action-openfile.png b/kfind/pics/lo22-action-openfile.png Binary files differnew file mode 100644 index 000000000..bdf6c55d9 --- /dev/null +++ b/kfind/pics/lo22-action-openfile.png diff --git a/kfind/pics/lo22-action-save.png b/kfind/pics/lo22-action-save.png Binary files differnew file mode 100644 index 000000000..4ae7ad4cd --- /dev/null +++ b/kfind/pics/lo22-action-save.png diff --git a/kfind/pics/lo22-action-search.png b/kfind/pics/lo22-action-search.png Binary files differnew file mode 100644 index 000000000..2ed5031c4 --- /dev/null +++ b/kfind/pics/lo22-action-search.png diff --git a/kfind/version.h b/kfind/version.h new file mode 100644 index 000000000..24f2c33c1 --- /dev/null +++ b/kfind/version.h @@ -0,0 +1,3 @@ +#ifndef KFIND_VERSION +#define KFIND_VERSION "2.0" +#endif |