dolphin/kfind/kftabdlg.cpp
Stephen Kelly ed2872074e Simplify some Qt module style includes.
This is the easiest way to transition to Qt5.
2012-04-10 00:20:22 +02:00

966 lines
31 KiB
C++

/*******************************************************************
* kftabdlg.cpp
*
* 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. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************/
#include "kftabdlg.h"
#include <QButtonGroup>
#include <QRadioButton>
#include <QLabel>
#include <QLayout>
#include <QCheckBox>
#include <QWhatsThis>
#include <QPushButton>
#include <QApplication>
#include <QDesktopWidget>
#include <kcalendarsystem.h>
#include <kglobal.h>
#include <kcombobox.h>
#include <kurlcombobox.h>
#include <kurlcompletion.h>
#include <klineedit.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <KNumInput>
#include <kfiledialog.h>
#include <kregexpeditorinterface.h>
#include <kservicetypetrader.h>
#include <kparts/componentfactory.h>
#include <kstandarddirs.h>
#include "kdatecombo.h"
#include "kquery.h"
// Static utility functions
static void save_pattern(KComboBox *, const QString &, const QString &);
#define SPECIAL_TYPES 7
struct LessMimeType_ByComment
{
bool operator()(const KMimeType::Ptr& lhs, const KMimeType::Ptr& rhs) const
{
return lhs->comment() < rhs->comment();
}
};
KfindTabWidget::KfindTabWidget(QWidget *parent)
: KTabWidget( parent ), regExpDialog(0)
{
// This validator will be used for all numeric edit fields
//KDigitValidator *digitV = new KDigitValidator(this);
// ************ Page One ************
pages[0] = new QWidget;
pages[0]->setObjectName( QLatin1String( "page1" ) );
nameBox = new KComboBox(pages[0]);
nameBox->setEditable( true );
nameBox->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); // allow smaller than widest entry
QLabel * namedL = new QLabel(i18nc("this is the label for the name textfield","&Named:"), pages[0]);
namedL->setBuddy( nameBox );
namedL->setObjectName( QLatin1String( "named" ) );
namedL->setToolTip( i18n("You can use wildcard matching and \";\" for separating multiple names") );
dirBox = new KUrlComboBox(KUrlComboBox::Directories, pages[0]);
dirBox->setEditable( true );
dirBox->setCompletionObject(new KUrlCompletion(KUrlCompletion::DirCompletion));
dirBox->setAutoDeleteCompletionObject(true);
dirBox->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); // allow smaller than widest entry
QLabel * lookinL = new QLabel(i18n("Look &in:"), pages[0]);
lookinL->setBuddy( dirBox );
lookinL->setObjectName( QLatin1String( "lookin" ) );
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]);
hiddenFilesCb = new QCheckBox(i18n("Show &hidden files"), pages[0]);
// Setup
subdirsCb->setChecked(true);
caseSensCb->setChecked(false);
useLocateCb->setChecked(false);
hiddenFilesCb->setChecked(false);
if(KStandardDirs::findExe("locate").isEmpty())
useLocateCb->setEnabled(false);
nameBox->setDuplicatesEnabled(false);
nameBox->setFocus();
dirBox->setDuplicatesEnabled(false);
nameBox->setInsertPolicy(QComboBox::InsertAtTop);
dirBox->setInsertPolicy(QComboBox::InsertAtTop);
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 between the 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>");
nameBox->setWhatsThis(nameWhatsThis);
namedL->setWhatsThis(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>");
useLocateCb->setWhatsThis(whatsfileindex);
// Layout
QGridLayout *grid = new QGridLayout( pages[0] );
grid->setMargin( KDialog::marginHint() );
grid->setSpacing( KDialog::spacingHint() );
QVBoxLayout *subgrid = new QVBoxLayout();
grid->addWidget( namedL, 0, 0 );
grid->addWidget( nameBox, 0, 1, 1, 3 );
grid->addWidget( lookinL, 1, 0 );
grid->addWidget( dirBox, 1, 1 );
grid->addWidget( browseB, 1, 2);
grid->setColumnStretch(1,1);
grid->addLayout( subgrid, 2, 1, 1, 2 );
QHBoxLayout * layoutOne = new QHBoxLayout();
layoutOne->addWidget( subdirsCb );
layoutOne->addWidget( hiddenFilesCb );
QHBoxLayout * layoutTwo = new QHBoxLayout();
layoutTwo->addWidget( caseSensCb);
layoutTwo->addWidget( useLocateCb );
subgrid->addLayout( layoutOne );
subgrid->addLayout( layoutTwo );
subgrid->addStretch(1);
// Signals
connect( browseB, SIGNAL(clicked()),
this, SLOT(getDirectory()) );
connect( nameBox, SIGNAL(returnPressed()),
this, SIGNAL(startSearch()));
connect( dirBox, SIGNAL(returnPressed()),
this, SIGNAL(startSearch()));
// ************ Page Two
pages[1] = new QWidget;
pages[1]->setObjectName( QLatin1String( "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(pages[1]); // text set in updateDateLabels
andL = new QLabel(i18n("and"), pages[1]);
andL->setObjectName( QLatin1String( "and" ) );
betweenType = new KComboBox( pages[1] );
betweenType->setObjectName( QLatin1String( "comboBetweenType" ) );
betweenType->addItems(QVector<QString>(5).toList()); // texts set in updateDateLabels
betweenType->setCurrentIndex(1);
updateDateLabels(1, 1);
QDate dt = KGlobal::locale()->calendar()->addYears(QDate::currentDate(), -1);
fromDate = new KDateCombo(dt, pages[1] );
fromDate->setObjectName( QLatin1String( "fromDate" ) );
toDate = new KDateCombo(pages[1] );
toDate->setObjectName( QLatin1String( "toDate" ) );
timeBox = new KIntSpinBox( pages[1] );
timeBox->setRange( 1, 60 );
timeBox->setSingleStep( 1 );
timeBox->setObjectName( QLatin1String( "timeBox" ) );
sizeBox =new KComboBox( pages[1] );
sizeBox->setObjectName( QLatin1String( "sizeBox" ) );
QLabel * sizeL =new QLabel(i18n("File &size is:"), pages[1]);
sizeL->setBuddy( sizeBox );
sizeEdit=new KIntSpinBox(pages[1] );
sizeEdit->setRange( 0, INT_MAX );
sizeEdit->setSingleStep( 1 );
sizeEdit->setObjectName( QLatin1String( "sizeEdit" ) );
sizeEdit->setValue(1);
sizeUnitBox =new KComboBox( pages[1] );
sizeUnitBox->setObjectName( QLatin1String( "sizeUnitBox" ) );
m_usernameBox = new KComboBox( pages[1] );
m_usernameBox->setEditable( true );
m_usernameBox->setObjectName( QLatin1String( "m_combo1" ));
QLabel *usernameLabel= new QLabel(i18n("Files owned by &user:"),pages[1]);
usernameLabel->setBuddy( m_usernameBox );
m_groupBox = new KComboBox( pages[1] );
m_groupBox->setEditable( true );
m_groupBox->setObjectName( QLatin1String( "m_combo2" ) );
QLabel *groupLabel= new QLabel(i18n("Owned by &group:"),pages[1]);
groupLabel->setBuddy( m_groupBox );
sizeBox ->addItem( i18nc("file size isn't considered in the search","(none)") );
sizeBox ->addItem( i18n("At Least") );
sizeBox ->addItem( i18n("At Most") );
sizeBox ->addItem( i18n("Equal To") );
sizeUnitBox ->addItem( i18np("Byte", "Bytes", 1) );
sizeUnitBox ->addItem( i18n("KiB") );
sizeUnitBox ->addItem( i18n("MiB") );
sizeUnitBox ->addItem( i18n("GiB") );
sizeUnitBox ->setCurrentIndex(1);
int tmp = sizeEdit->fontMetrics().width(" 000000000 ");
sizeEdit->setMinimumSize(tmp, sizeEdit->sizeHint().height());
m_usernameBox->setDuplicatesEnabled(false);
m_groupBox->setDuplicatesEnabled(false);
m_usernameBox->setInsertPolicy(QComboBox::InsertAtTop);
m_groupBox->setInsertPolicy(QComboBox::InsertAtTop);
// Setup
rb[0]->setChecked(true);
bg->addButton( rb[0] );
bg->addButton( rb[1] );
// Layout
QGridLayout *grid1 = new QGridLayout( pages[1] );
grid1->setMargin( KDialog::marginHint() );
grid1->setSpacing( KDialog::spacingHint() );
grid1->addWidget(findCreated, 0, 0, 1, 3 );
grid1->addItem( new QSpacerItem(KDialog::spacingHint(), 0), 0, 0 );
grid1->addWidget(rb[0], 1, 1 );
grid1->addWidget(fromDate, 1, 2 );
grid1->addWidget(andL, 1, 3, Qt::AlignHCenter );
grid1->addWidget(toDate, 1, 4 );
grid1->addWidget(rb[1], 2, 1 );
grid1->addWidget(timeBox, 2, 2, 1, 2);
grid1->addWidget(betweenType, 2, 4 );
grid1->addWidget(sizeL,3,0,1,2);
grid1->addWidget(sizeBox,3,2);
grid1->addWidget(sizeEdit,3,3);
grid1->addWidget(sizeUnitBox,3,4);
grid1->addWidget(usernameLabel,4,0,1,2);
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->setColumnStretch(c,1);
grid1->setRowStretch(6,1);
// Connect
connect( findCreated, SIGNAL(toggled(bool)), SLOT(fixLayout()) );
connect( bg, SIGNAL(buttonClicked(QAbstractButton*)), this, SLOT(fixLayout()) );
connect( sizeBox, SIGNAL(activated(int)), this, SLOT(slotSizeBoxChanged(int)));
connect( timeBox, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateDateLabelsForNumber(int)));
connect( betweenType, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdateDateLabelsForType(int)));
connect( sizeEdit, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateByteComboBox(int)));
// ************ Page Three
pages[2] = new QWidget;
pages[2]->setObjectName( QLatin1String( "page3" ) );
typeBox =new KComboBox( pages[2] );
typeBox->setObjectName( QLatin1String( "typeBox" ) );
typeBox->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); // allow smaller than widest entry
QLabel * typeL =new QLabel( i18nc("label for the file type combobox","File &type:"), pages[2] );
typeL->setBuddy( typeBox );
textEdit=new KLineEdit(pages[2]);
textEdit->setClearButtonShown(true);
textEdit->setObjectName( QLatin1String( "textEdit" ) );
QLabel * textL =new QLabel(i18n("C&ontaining text:"), pages[2]);
textL->setBuddy( textEdit );
connect( textEdit, SIGNAL(returnPressed(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>");
textEdit->setToolTip(containingtext);
textL->setWhatsThis(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>");
binaryContextCb->setToolTip(binaryTooltip);
QPushButton* editRegExp = 0;
if ( !KServiceTypeTrader::self()->query("KRegExpEditor/KRegExpEditor").isEmpty() ) {
// The editor is available, so lets use it.
editRegExp = new QPushButton(i18n("&Edit..."), pages[2]);
editRegExp->setObjectName( QLatin1String( "editRegExp" ) );
}
metainfokeyEdit=new KLineEdit(pages[2]);
metainfoEdit=new KLineEdit(pages[2]);
QLabel * textMetaInfo = new QLabel(i18nc("as in search for", "fo&r:"), pages[2]);
textMetaInfo->setBuddy( metainfoEdit );
QLabel * textMetaKey = new QLabel(i18n("Search &metainfo sections:"), pages[2]);
textMetaKey->setBuddy( metainfokeyEdit );
// Setup
typeBox->addItem(i18n("All Files & Folders"));
typeBox->addItem(i18n("Files"));
typeBox->addItem(i18n("Folders"));
typeBox->addItem(i18n("Symbolic Links"));
typeBox->addItem(i18n("Special Files (Sockets, Device Files, ...)"));
typeBox->addItem(i18n("Executable Files"));
typeBox->addItem(i18n("SUID Executable Files"));
typeBox->addItem(i18n("All Images"));
typeBox->addItem(i18n("All Video"));
typeBox->addItem(i18n("All Sounds"));
initMimeTypes();
initSpecialMimeTypes();
for ( KMimeType::List::ConstIterator it = m_types.constBegin();
it != m_types.constEnd(); ++it )
{
KMimeType::Ptr typ = *it;
// TODO: needs to move to thread (increases startup time to bizzare amount)
// and replaced with a better concept 16x16 icons don't cut the cheese
// typeBox->addItem(KIconLoader::global()->loadMimeTypeIcon( typ->iconName(), KIconLoader::Small ), typ->comment());
typeBox->addItem(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] );
grid2->setMargin( KDialog::marginHint() );
grid2->setSpacing( KDialog::spacingHint() );
grid2->addWidget( typeL, 0, 0 );
grid2->addWidget( textL, 1, 0 );
grid2->addWidget( typeBox, 0, 1, 1, 3 );
grid2->addWidget( 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, Qt::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], i18nc("tab name: search by contents","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>");
textMetaInfo->setWhatsThis(whatsmetainfo);
metainfoEdit->setToolTip(whatsmetainfo);
textMetaKey->setWhatsThis(whatsmetainfokey);
metainfokeyEdit->setToolTip(whatsmetainfokey);
fixLayout();
loadHistory();
}
KfindTabWidget::~KfindTabWidget()
{
delete pages[0];
delete pages[1];
delete pages[2];
delete bg;
}
void KfindTabWidget::setURL( const KUrl & url )
{
KConfigGroup conf(KGlobal::config(), "History");
m_url = url;
QStringList sl = conf.readPathEntry("Directories", QStringList());
dirBox->clear(); // make sure there is no old Stuff in there
if(!sl.isEmpty()) {
dirBox->addItems(sl);
// If the _searchPath already exists in the list we do not
// want to add it again
int indx = sl.indexOf(m_url.prettyUrl());
if(indx == -1) {
dirBox->insertItem(0, m_url.prettyUrl()); // make it the first one
dirBox->setCurrentIndex(0);
}
else
dirBox->setCurrentIndex(indx);
}
else {
QDir m_dir("/lib");
dirBox ->insertItem( 0, m_url.prettyUrl() );
dirBox ->addItem( "file:" + QDir::homePath() );
dirBox ->addItem( "file:/" );
dirBox ->addItem( "file:/usr" );
if (m_dir.exists())
dirBox ->addItem( "file:/lib" );
dirBox ->addItem( "file:/home" );
dirBox ->addItem( "file:/etc" );
dirBox ->addItem( "file:/var" );
dirBox ->addItem( "file:/mnt" );
dirBox->setCurrentIndex(0);
}
}
void KfindTabWidget::initMimeTypes()
{
KMimeType::List sortedList;
foreach ( const KMimeType::Ptr &type, KMimeType::allMimeTypes() )
{
if ( (!type->comment().isEmpty())
&& (!type->name().startsWith( QString("kdedevice/") ))
&& (!type->name().startsWith( QString("all/") )) )
sortedList.append(type);
}
qSort( sortedList.begin(), sortedList.end(), LessMimeType_ByComment() );
m_types += sortedList;
}
void KfindTabWidget::initSpecialMimeTypes()
{
const KMimeType::List tmp = KMimeType::allMimeTypes();
for ( KMimeType::List::ConstIterator it = tmp.constBegin(); it != tmp.constEnd(); ++it )
{
const KMimeType* type = (*it).data();
if(!type->comment().isEmpty()) {
if(type->name().startsWith( QString("image/") ))
m_ImageTypes.append(type->name());
else if(type->name().startsWith( QString("video/") ))
m_VideoTypes.append(type->name());
else if(type->name().startsWith( QString("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
KConfigGroup conf(KGlobal::config(), "History");
QStringList sl = conf.readEntry("Patterns", QStringList());
if(!sl.isEmpty())
nameBox->addItems(sl);
else
nameBox->addItem("*");
sl = conf.readPathEntry("Directories", QStringList());
if(!sl.isEmpty()) {
dirBox->addItems(sl);
// If the _searchPath already exists in the list we do not
// want to add it again
int indx = sl.indexOf(m_url.prettyUrl());
if(indx == -1) {
dirBox->insertItem(0, m_url.prettyUrl()); // make it the first one
dirBox->setCurrentIndex(0);
}
else
dirBox->setCurrentIndex(indx);
}
else {
QDir m_dir("/lib");
dirBox ->insertItem( 0, m_url.prettyUrl() );
dirBox ->addItem( "file:" + QDir::homePath() );
dirBox ->addItem( "file:/" );
dirBox ->addItem( "file:/usr" );
if (m_dir.exists())
dirBox ->addItem( "file:/lib" );
dirBox ->addItem( "file:/home" );
dirBox ->addItem( "file:/etc" );
dirBox ->addItem( "file:/var" );
dirBox ->addItem( "file:/mnt" );
dirBox ->setCurrentIndex(0);
}
}
void KfindTabWidget::slotEditRegExp()
{
if ( ! regExpDialog )
regExpDialog = KServiceTypeTrader::createInstanceFromQuery<KDialog>( "KRegExpEditor/KRegExpEditor", QString(), this );
KRegExpEditorInterface *iface = qobject_cast<KRegExpEditorInterface *>( regExpDialog );
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->setCurrentIndex(1);
typeBox ->setCurrentIndex(0);
sizeBox ->setCurrentIndex(0);
sizeUnitBox ->setCurrentIndex(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.isEmpty()) {
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().trimmed()));
for (int idx=0; idx<dirBox->count(); idx++)
if (dirBox->itemText(idx)==dirBox->currentText())
itemAlreadyContained=true;
if (!itemAlreadyContained)
dirBox->addItem(dirBox->currentText().trimmed(),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->itemText(idx)==nameBox->currentText())
itemAlreadyContained=true;
if (!itemAlreadyContained)
nameBox->addItem(nameBox->currentText(),0);
query->setRecursive(subdirsCb->isChecked());
switch (sizeUnitBox->currentIndex())
{
case 0:
sizeunit = 1; //one byte
break;
case 2:
sizeunit = 1048576; //1Mi
break;
case 3:
sizeunit = 1073741824; //1Gi
break;
case 1: // fall to default case
default:
sizeunit=1024; //1Ki
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->setCurrentIndex(0);
size = INT_MAX;
}
else
return;
}
#endif
// set range mode and size value
query->setSizeRange(sizeBox->currentIndex(),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(QDateTime(q1));
time_t time2 = epoch.secsTo(QDateTime(q2.addDays(1))) - 1; // Include the last day
query->setTimeRange(time1, time2);
}
else
{
time_t cur = time(NULL);
time_t minutes = cur;
switch (betweenType->currentIndex())
{
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->currentIndex());
int id = typeBox->currentIndex()-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( QStringList() += m_types[id]->name() );
}
}
else
{
query->setMimeType( QStringList() );
}
//Metainfo
query->setMetaInfo(metainfoEdit->text(), metainfokeyEdit->text());
//Use locate to speed-up search ?
query->setUseFileIndex(useLocateCb->isChecked());
query->setShowHiddenFiles(hiddenFilesCb->isChecked());
query->setContext(textEdit->text(), caseContextCb->isChecked(),
binaryContextCb->isChecked(), regexpContentCb->isChecked());
}
QString KfindTabWidget::date2String(const QDate & date) {
return(KGlobal::locale()->formatDate(date, KLocale::ShortDate));
}
QDate &KfindTabWidget::string2Date(const QString & str, QDate *qd) {
return *qd = KGlobal::locale()->readDate(str);
}
void KfindTabWidget::getDirectory()
{
QString result =
KFileDialog::getExistingDirectory( dirBox->currentText().trimmed(),
this );
if (!result.isEmpty())
{
for (int i = 0; i < dirBox->count(); i++)
if (result == dirBox->itemText(i)) {
dirBox->setCurrentIndex(i);
return;
}
dirBox->insertItem(0, result);
dirBox->setCurrentIndex(0);
}
}
void KfindTabWidget::beginSearch()
{
/// dirlister->openUrl(KUrl(dirBox->currentText().trimmed()));
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);
andL->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());
andL->setEnabled(rb[0]->isEnabled());
timeBox->setEnabled(rb[1]->isChecked());
betweenType->setEnabled(rb[1]->isChecked());
}
// Size box on page three
sizeEdit->setEnabled(sizeBox->currentIndex() != 0);
sizeUnitBox->setEnabled(sizeBox->currentIndex() != 0);
}
bool KfindTabWidget::isSearchRecursive()
{
return subdirsCb->isChecked();
}
void KfindTabWidget::slotUpdateDateLabelsForNumber(int value)
{
updateDateLabels(betweenType->currentIndex(), value);
}
void KfindTabWidget::slotUpdateDateLabelsForType(int index)
{
updateDateLabels(index, timeBox->value());
}
void KfindTabWidget::updateDateLabels(int type, int value)
{
QString typeKey(type == 0 ? 'i' : type == 1 ? 'h' : type == 2 ? 'd' : type == 3 ? 'm' : 'y');
rb[1]->setText(ki18ncp("during the previous minute(s)/hour(s)/...; "
"dynamic context 'type': 'i' minutes, 'h' hours, 'd' days, 'm' months, 'y' years",
"&during the previous", "&during the previous").subs(value).inContext("type", typeKey).toString());
betweenType->setItemText(0, i18ncp("use date ranges to search files by modified time", "minute", "minutes", value));
betweenType->setItemText(1, i18ncp("use date ranges to search files by modified time", "hour", "hours", value));
betweenType->setItemText(2, i18ncp("use date ranges to search files by modified time", "day", "days", value));
betweenType->setItemText(3, i18ncp("use date ranges to search files by modified time", "month", "months", value));
betweenType->setItemText(4, i18ncp("use date ranges to search files by modified time", "year", "years", value));
}
void KfindTabWidget::slotUpdateByteComboBox(int value)
{
sizeUnitBox->setItemText(0, i18np("Byte", "Bytes", value) );
}
/**
Digit validator. Allows only digits to be typed.
**/
KDigitValidator::KDigitValidator( QWidget * parent )
: QValidator( parent )
{
r = new QRegExp("^[0-9]*$");
}
KDigitValidator::~KDigitValidator()
{
delete r;
}
QValidator::State KDigitValidator::validate( QString & input, int & ) const
{
if (r->indexIn(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(KComboBox *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->itemText(obj->currentIndex());
sl.append(cur);
for (int i = 0; i < obj->count(); i++) {
if( cur != obj->itemText(i) ) {
sl.append(obj->itemText(i));
}
}
KConfigGroup conf(KGlobal::config(), 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 = KTabWidget::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"