00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
#include <iostream>
00020
00021
#include <qfile.h>
00022
#include <qptrlist.h>
00023
00024
#include <kaboutdata.h>
00025
#include <kapplication.h>
00026
#include <kcmdlineargs.h>
00027
#include <kfilemetainfo.h>
00028
#include <klocale.h>
00029
#include <kpropertiesdialog.h>
00030
00031
#include "fileprops.h"
00032
00033
#define KFILEVERSION "0.2"
00034
#define INDENT "\t"
00035
00036
using namespace std;
00037
00038
static QString beatifyValue(
const QString& value )
00039 {
00040
if ( value.
isNull() )
00041
return QString(
"(no value for key available)");
00042
else if ( value.
isEmpty() )
00043
return QString(
"(empty)");
00044
00045
return value;
00046 }
00047
00048 FileProps::FileProps(
const QString& path,
const QStringList& suppliedGroups )
00049 : m_dirty( false )
00050 {
00051 m_info =
new KFileMetaInfo(path, QString::null, KFileMetaInfo::Everything);
00052 m_userSuppliedGroups = !suppliedGroups.isEmpty();
00053 m_groupsToUse = m_userSuppliedGroups ? suppliedGroups : m_info->groups();
00054 }
00055
00056 FileProps::~FileProps()
00057 {
00058 sync();
00059
delete m_info;
00060 }
00061
00062
bool FileProps::sync()
00063 {
00064
if ( !m_dirty )
00065
return true;
00066
00067
return m_info->applyChanges();
00068 }
00069
00070
bool FileProps::isValid()
const
00071
{
00072
return m_info->isValid();
00073 }
00074
00075
QStringList FileProps::supportedGroups()
const
00076
{
00077
return m_info->supportedGroups();
00078 }
00079
00080
QStringList FileProps::availableGroups()
const
00081
{
00082
return m_info->groups();
00083 }
00084
00085
QStringList FileProps::supportedKeys(
const QString& group )
const
00086
{
00087
KFileMetaInfoGroup g = m_info->group( group );
00088
return g.
supportedKeys();
00089 }
00090
00091
QStringList FileProps::availableKeys(
const QString& group )
const
00092
{
00093
KFileMetaInfoGroup g = m_info->group( group );
00094
QStringList allKeys = g.
keys();
00095
QStringList ret;
00096 QStringList::ConstIterator it = allKeys.begin();
00097
for ( ; it != allKeys.end(); ++it )
00098 {
00099
if ( g.
item( *it ).
isValid() )
00100 ret.append( *it );
00101 }
00102
00103
return ret;
00104 }
00105
00106
QStringList FileProps::preferredKeys(
const QString& group )
const
00107
{
00108
KFileMetaInfoGroup g = m_info->group( group );
00109
return g.
preferredKeys();
00110 }
00111
00112
QString FileProps::getValue(
const QString& group,
00113
const QString& key )
const
00114
{
00115
KFileMetaInfoGroup g = m_info->group( group );
00116
return FileProps::createKeyValue( g, key );
00117 }
00118
00119
bool FileProps::setValue(
const QString& group,
00120
const QString& key,
const QString &value )
00121 {
00122
KFileMetaInfoGroup g = m_info->group( group );
00123
bool wasAdded =
false;
00124
if ( !g.
isValid() )
00125 {
00126
if ( m_info->addGroup( group ) )
00127 {
00128 wasAdded =
true;
00129 g = m_info->group( group );
00130 }
00131
else
00132
return false;
00133 }
00134
00135
bool ok = g[
key].setValue( value );
00136
00137
if ( !ok && wasAdded )
00138 (
void) m_info->removeGroup( group );
00139
00140 m_dirty |= ok;
00141
return ok;
00142 }
00143
00144
QStringList FileProps::allValues(
const QString& group )
const
00145
{
00146
KFileMetaInfoGroup g = m_info->group( group );
00147
return FileProps::createKeyValueList( g, g.
keys() );
00148 }
00149
00150
QStringList FileProps::preferredValues(
const QString& group )
const
00151
{
00152
KFileMetaInfoGroup g = m_info->group( group );
00153
return FileProps::createKeyValueList( g, g.
preferredKeys() );
00154 }
00155
00156
00157
00158
00159
QString FileProps::createKeyValue(
const KFileMetaInfoGroup& g,
00160
const QString& key )
00161 {
00162
static const int MAX_SPACE = 25;
00163
KFileMetaInfoItem item = g.
item( key );
00164
00165
QString result(
"%1");
00166 result = result.
arg( (item.
isValid() ? item.
translatedKey() :
key) + ":",
00167 -MAX_SPACE );
00168 result.
append( beatifyValue( item.
string() ) );
00169
00170
QString group(
"%1");
00171 group = group.
arg( g.
translatedName() +
":", -MAX_SPACE );
00172 result.
prepend( group );
00173
00174
return result;
00175 }
00176
00177
00178
QStringList FileProps::createKeyValueList(
const KFileMetaInfoGroup& g,
00179
const QStringList& keys )
00180 {
00181
QStringList result;
00182 QStringList::ConstIterator it = keys.begin();
00183
00184
for ( ; it != keys.end(); ++it )
00185 result.append( FileProps::createKeyValue( g, *it ) );
00186
00187
return result;
00188 }
00189
00192
00193
00194
00195
00196
00197
static KCmdLineOptions options[] =
00198 {
00199 {
"m", 0, 0 },
00200 {
"nomimetype",
I18N_NOOP(
"Don't print the mimetype of the given file(s)"), 0 },
00201
00202 {
"ls", 0, 0 },
00203 {
"listsupported <mimetype>",
00204
I18N_NOOP(
"List all supported metadata keys of the given file(s). "
00205
"If mimetype is not specified, the mimetype of the given "
00206
"files is used." ),
"file" },
00207
00208 {
"lp", 0, 0 },
00209 {
"listpreferred <mimetype>",
00210
I18N_NOOP(
"List all preferred metadata keys of the given file(s). "
00211
"If mimetype is not specified, the mimetype of the given "
00212
"files is used." ),
"file" },
00213
00214 {
"la", 0, 0 },
00215 {
"listavailable",
00216
I18N_NOOP(
"List all metadata keys which have a value in the given "
00217
"file(s)."), 0 },
00218
00219 {
"sm", 0, 0 },
00220 {
"supportedMimetypes",
00221
I18N_NOOP(
"Prints all mimetypes for which metadata support is "
00222
"available."), 0 },
00223
00224 {
"q", 0, 0 },
00225 {
"quiet",
00226
I18N_NOOP(
"Don't print a warning when more than one file was given "
00227
"and they don't have all the same mimetype."), 0 },
00228
00229 {
"av", 0, 0 },
00230 {
"allValues",
00231
I18N_NOOP(
"Prints all metadata values, available in the given "
00232
"file(s)."), 0 },
00233
00234 {
"pv", 0, 0 },
00235 {
"preferredValues",
00236
I18N_NOOP(
"Prints the preferred metadata values, available in the "
00237
"given file(s)."), 0 },
00238
00239 {
"dialog",
00240
I18N_NOOP(
"Opens a KDE properties dialog to allow viewing and "
00241
"modifying of metadata of the given file(s)"), 0 },
00242
00243 {
"getValue <key>",
00244
I18N_NOOP(
"Prints the value for 'key' of the given file(s). 'key' "
00245
"may also be a comma-separated list of keys"), 0 },
00246
00247 {
"setValue <key=value>",
00248
I18N_NOOP(
"Attempts to set the value 'value' for the metadata key "
00249
"'key' for the given file(s)"), 0 },
00250
00251 {
"!groups <arguments>",
I18N_NOOP(
"The group to get values from or set values to."),
00252 0 },
00253
00254 {
"+[files]",
00255
I18N_NOOP(
"The file (or a number of files) to operate on."), 0 },
00256 KCmdLineLastOption
00257 };
00258
00259
00260
00261
00262
00263
00264
static void printSupportedMimeTypes()
00265 {
00266
QStringList allMimeTypes = KFileMetaInfoProvider::self()->supportedMimeTypes();
00267
if ( allMimeTypes.isEmpty() )
00268 {
00269 cout <<
00270 i18n(
"No support for metadata extraction found.").local8Bit()
00271 <<
endl;
00272
return;
00273 }
00274
00275 cout << i18n(
"Supported MimeTypes:").local8Bit() <<
endl;
00276
00277 QStringList::ConstIterator it = allMimeTypes.begin();
00278
for ( ; it != allMimeTypes.end(); it++ )
00279 cout << (*it).local8Bit() <<
endl;
00280 }
00281
00282
00283
static KFileItemList * fileItemList(
const KCmdLineArgs *args )
00284 {
00285
KFileItemList * items =
new KFileItemList();
00286 items->
setAutoDelete(
true );
00287
for (
int i = 0; i < args->
count(); i++ )
00288 items->
append(
new KFileItem( KFileItem::Unknown,
00289 KFileItem::Unknown,
00290 args->
url( i ) ));
00291
return items;
00292 }
00293
00294
static void showPropertiesDialog(
const KCmdLineArgs *args )
00295 {
00296 KFileItemList *items = fileItemList( args );
00297
new KPropertiesDialog( *items, 0L,
"props dialog",
true );
00298
delete items;
00299 }
00300
00301
static void printMimeTypes(
const KCmdLineArgs *args )
00302 {
00303
for (
int i = 0; i < args->
count(); i++ )
00304 {
00305
KURL url = args->
url( i );
00306 KMimeType::Ptr mt =
KMimeType::findByURL( url );
00307 cout << args->
arg(i) <<
": " << mt->comment().local8Bit() <<
" ("
00308 << mt->name().local8Bit() <<
")" <<
endl;
00309 }
00310 }
00311
00312
static void printList(
const QStringList& list )
00313 {
00314 QStringList::ConstIterator it = list.begin();
00315
for ( ; it != list.end(); ++it )
00316 cout << (*it).local8Bit() <<
endl;
00317 cout <<
endl;
00318 }
00319
00320
static void processMetaDataOptions(
const QPtrList<FileProps> propList,
00321
KCmdLineArgs *args )
00322 {
00323
00324
00325
00326
QString line(
"-- -------------------------------------------------------");
00327 FileProps *props;
00328
QPtrListIterator<FileProps> it( propList );
00329
for ( ; (props = it.
current()); ++it )
00330 {
00331
QString file = props->fileName() +
" ";
00332
QString fileString = line.
replace( 3, file.
length(), file );
00333 cout <<
QFile::encodeName( fileString ) <<
endl;
00334
00335
if ( args->
isSet(
"listsupported" ) )
00336 {
00337 cout <<
"=Supported Keys=" <<
endl;
00338 printList( props->supportedKeys() );
00339 }
00340
if ( args->
isSet(
"listpreferred" ) )
00341 {
00342 cout <<
"=Preferred Keys=" <<
endl;
00343 printList( props->preferredKeys() );
00344 }
00345
if ( args->
isSet(
"listavailable" ) )
00346 {
00347 cout <<
"=Available Keys=" <<
endl;
00348
QStringList groups = props->availableGroups();
00349 QStringList::ConstIterator git = groups.begin();
00350
for ( ; git != groups.end(); ++git )
00351 {
00352 cout <<
"Group: " << (*git).local8Bit() <<
endl;
00353 printList( props->availableKeys( *git ) );
00354 }
00355 }
00356
00357
00358
00359
00360
if ( args->
isSet(
"getValue" ) )
00361 {
00362 cout <<
"=Value=" <<
endl;
00363
QString key =
QString::fromLocal8Bit( args->
getOption(
"getValue"));
00364 QStringList::ConstIterator git = props->groupsToUse().begin();
00365
for ( ; git != props->groupsToUse().end(); ++git )
00366 cout << props->getValue( *git, key ).local8Bit() <<
endl;
00367 }
00368
00369
if ( args->
isSet(
"setValue" ) )
00370 {
00371
00372
QString cmd =
QString::fromLocal8Bit( args->
getOption(
"setValue"));
00373
QString key = cmd.
section(
'=', 0, 0 );
00374
QString value = cmd.
section(
'=', 1 );
00375
00376
00377
00378
QStringList groups = props->userSuppliedGroups() ?
00379 props->groupsToUse() :
00380 props->supportedGroups();
00381
00382 QStringList::ConstIterator git = groups.begin();
00383
for ( ; git != groups.end(); ++git )
00384 props->setValue( *git, key, value );
00385 }
00386
00387
if ( args->
isSet(
"allValues" ) )
00388 {
00389 cout <<
"=All Values=" <<
endl;
00390
QStringList groups = props->availableGroups();
00391 QStringList::ConstIterator group = groups.begin();
00392
for ( ; group != groups.end(); ++group )
00393 printList( props->allValues( *group ) );
00394 }
00395
if ( args->
isSet(
"preferredValues" ) && !args->
isSet(
"allValues") )
00396 {
00397 cout <<
"=Preferred Values=" <<
endl;
00398
QStringList groups = props->availableGroups();
00399 QStringList::ConstIterator group = groups.begin();
00400
for ( ; group != groups.end(); ++group )
00401 printList( props->preferredValues( *group ) );
00402 }
00403 }
00404
00405 }
00406
00407
int main(
int argc,
char **argv )
00408 {
00409
KAboutData about(
00410
"kfile",
I18N_NOOP(
"kfile" ), KFILEVERSION,
00411
I18N_NOOP(
"A commandline tool to read and modify metadata of files." ),
00412 KAboutData::License_LGPL,
"(c) 2002, Carsten Pfeiffer",
00413 0 ,
"http://devel-home.kde.org/~pfeiffer/",
00414
"pfeiffer@kde.org" );
00415
00416 about.
addAuthor(
"Carsten Pfeiffer", 0,
"pfeiffer@kde.org",
00417
"http://devel-home.kde.org/~pfeiffer/" );
00418
00419
KCmdLineArgs::init( argc, argv, &about );
00420
00421
KCmdLineArgs::addCmdLineOptions( options );
00422
00423
KCmdLineArgs *args =
KCmdLineArgs::parsedArgs();
00424
bool useGUI = args->
isSet(
"dialog" );
00425
00426
KApplication app( useGUI, useGUI );
00427
00428
QPtrList<FileProps> m_props;
00429 m_props.
setAutoDelete(
true );
00430
00431
bool quiet = args->
isSet(
"quiet" );
00432
00433
if ( args->
isSet(
"supportedMimetypes" ) )
00434 printSupportedMimeTypes();
00435
00436
int files = args->
count();
00437
if ( files == 0 )
00438
KCmdLineArgs::usage( i18n(
"No files specified") );
00439
00440
if ( args->
isSet(
"dialog" ) )
00441 {
00442 showPropertiesDialog( args );
00443
return true;
00444 }
00445
00446
QStringList groupsToUse;
00447 QCStringList suppliedGroups = args->
getOptionList(
"groups" );
00448 QCStringList::ConstIterator it = suppliedGroups.begin();
00449
for ( ; it != suppliedGroups.end(); ++it )
00450 groupsToUse.append( QString::fromLocal8Bit( (*it) ) );
00451
00452
QString mimeType;
00453
00454
for (
int i = 0; i < files; i++ )
00455 {
00456
if ( args->
isSet(
"mimetype" ) )
00457 printMimeTypes( args );
00458
00459 FileProps *props =
new FileProps( args->
url(i).
path(), groupsToUse );
00460
if ( props->isValid() )
00461 m_props.
append( props );
00462
else
00463 {
00464
if ( !quiet )
00465 {
00466 cerr << args->
arg(i) <<
": " <<
00467 i18n(
"Cannot determine metadata").local8Bit() <<
endl;
00468 }
00469
delete props;
00470 }
00471 }
00472
00473
00474 processMetaDataOptions( m_props, args );
00475
00476 m_props.
clear();
00477 cout.flush();
00478
00479
return 0;
00480 }