1/* This file is part of the KDE libraries
2 Copyright (C) 2002,2003 Carsten Pfeiffer <pfeiffer@kde.org>
3
4 library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation, version 2.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public License
14 along with this library; see the file COPYING.LIB. If not, write to
15 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 Boston, MA 02110-1301, USA.
17*/
18
19#include "fileprops.h"
20
21#include <iostream>
22
23#include <QtCore/QFile>
24
25#include <kaboutdata.h>
26#include <kapplication.h>
27#include <kcmdlineargs.h>
28#include <kfilemetainfo.h>
29#include <klocale.h>
30#include <kpropertiesdialog.h>
31#include <kdebug.h>
32
33#define KFILEVERSION "0.2"
34#define INDENT "\t"
35
36using namespace std;
37
38static QString beatifyValue( const QString& value )
39{
40 if ( value.isNull() )
41 return QString("(no value for key available)");
42 else if ( value.isEmpty() )
43 return QString("(empty)");
44
45 return value;
46}
47
48FileProps::FileProps( const QString& path )
49 : m_dirty( false )
50{
51 m_info = new KFileMetaInfo(path, QString(), KFileMetaInfo::Everything);
52}
53
54FileProps::~FileProps()
55{
56 sync();
57 delete m_info;
58}
59
60bool FileProps::sync()
61{
62 if ( !m_dirty )
63 return true;
64
65 return m_info->applyChanges();
66}
67
68bool FileProps::isValid() const
69{
70 return m_info->isValid();
71}
72
73QStringList FileProps::supportedKeys() const
74{
75 return QStringList();
76}
77
78QStringList FileProps::availableKeys() const
79{
80 return m_info->keys();
81}
82
83QString FileProps::getValue( const QString& key ) const
84{
85 return FileProps::createKeyValue( m_info->item(key) );
86}
87
88bool FileProps::setValue( const QString& key, const QString &value )
89{
90 bool ok = m_info->item(key).setValue( value );
91 m_dirty |= ok;
92 return ok;
93}
94
95QStringList FileProps::allValues() const
96{
97 return FileProps::createKeyValueList( m_info->items().values() );
98}
99
100// static helper:
101// creates strings like
102// "group: translatedKey: value"
103QString FileProps::createKeyValue( const KFileMetaInfoItem& item )
104{
105 static const int MAX_SPACE = 25;
106
107 QString result("%1");
108 result = result.arg(item.name() + ':', -MAX_SPACE );
109 result.append( beatifyValue( item.value().toString() ) );
110
111 return result;
112}
113
114// static
115QStringList FileProps::createKeyValueList( const KFileMetaInfoItemList& items )
116{
117 QStringList result;
118 KFileMetaInfoItemList::ConstIterator it = items.begin();
119
120 for ( ; it != items.end(); ++it )
121 result.append( FileProps::createKeyValue( *it ) );
122
123 return result;
124}
125
126///////////////////////////////////////////////////////////////////
127///////////////////////////////////////////////////////////////////
128
129
130
131// kfile --mimetype --listsupported --listavailable --listwritable --getValue "key" --setValue "key=value" --allValues --dialog --quiet file [file...]
132// "key" may be a list of keys, separated by commas
133
134//
135// helper functions
136//
137
138// Caller needs to delete the items in the list after use!
139static KFileItemList fileItemList( const KCmdLineArgs *args )
140{
141 KFileItemList items;
142 for ( int i = 0; i < args->count(); i++ )
143 items.append( KFileItem( KFileItem::Unknown,
144 KFileItem::Unknown,
145 args->url( i ) ));
146 return items;
147}
148
149static void showPropertiesDialog( const KCmdLineArgs *args ) {
150 const KFileItemList items = fileItemList( args );
151 KPropertiesDialog::showDialog( items, 0, true );
152}
153/*
154static void printMimeTypes( const KCmdLineArgs *args )
155{
156 for ( int i = 0; i < args->count(); i++ )
157 {
158 KUrl url = args->url( i );
159 KMimeType::Ptr mt = KMimeType::findByUrl( url );
160 kDebug() << args->arg(i) << ": " << mt->comment().toLocal8Bit() << " ("
161 << mt->name().toLocal8Bit() << ")" << endl;
162 }
163}*/
164
165static void printList( const QStringList& list )
166{
167 QStringList::ConstIterator it = list.begin();
168 for ( ; it != list.end(); ++it )
169 kDebug() << (*it).toLocal8Bit();
170 kDebug();
171}
172
173static void processMetaDataOptions( const QList<FileProps *> propList,
174 KCmdLineArgs *args )
175{
176// kfile --mimetype --listsupported --listavailable --listwritable --getValue "key" --setValue "key=value" --allValues --dialog --quiet file [file...]
177// "key" may be a list of keys, separated by commas
178
179 QString line("-- -------------------------------------------------------");
180 foreach ( FileProps *props, propList )
181 {
182 QString file = props->fileName() + ' ';
183 QString fileString = line;
184 fileString.replace( 3, file.length(), file );
185 kDebug() << QFile::encodeName( fileString );
186
187 if ( args->isSet( "listsupported" ) )
188 {
189 kDebug() << "=Supported Keys=";
190 printList( props->supportedKeys() );
191 }
192 if ( args->isSet( "listavailable" ) )
193 {
194 kDebug() << "=Available Keys=";
195 printList( props->availableKeys() );
196 }
197// if ( args->isSet( "listwritable" ) )
198// {
199// kDebug() << "TODO :)";
200// }
201 if ( args->isSet( "getValue" ) )
202 {
203 kDebug() << "=Value=";
204 QString key = args->getOption("getValue");
205 kDebug() << props->getValue( key ).toLocal8Bit();
206 }
207
208 if ( args->isSet( "setValue" ) )
209 {
210 // separate key and value from the line "key=value"
211 QString cmd = args->getOption("setValue");
212 QString key = cmd.section( '=', 0, 0 );
213 QString value = cmd.section( '=', 1 );
214
215 props->setValue(key, value);
216 }
217
218 if ( args->isSet( "allValues" ) )
219 {
220 kDebug() << "=All Values=";
221 printList( props->allValues() );
222 }
223 }
224
225}
226
227int main( int argc, char **argv )
228{
229 KAboutData about(
230 "kfile", 0, ki18n( "kfile" ), KFILEVERSION,
231 ki18n("A command-line tool to read and modify metadata of files."),
232 KAboutData::License_LGPL, ki18n("(c) 2002, Carsten Pfeiffer"),
233 ki18n(0 /*text*/), "http://devel-home.kde.org/~pfeiffer/",
234 "pfeiffer@kde.org" );
235
236 about.addAuthor( ki18n("Carsten Pfeiffer"), KLocalizedString(), "pfeiffer@kde.org",
237 "http://devel-home.kde.org/~pfeiffer/" );
238
239 KCmdLineArgs::init( argc, argv, &about );
240
241
242 KCmdLineOptions options;
243
244 options.add("m"); // short option for --mimetype
245 options.add("nomimetype", ki18n("Do not print the mimetype of the given file(s)"));
246 options.add("ls"); // short option for --listsupported
247 options.add("listsupported", ki18n("List all supported metadata keys." ));
248 options.add("la"); // short option for --listavailable
249 options.add("listavailable", ki18n("List all metadata keys which have a value in the given "
250 "file(s)."));
251 options.add("q"); // short option for --quiet
252 options.add("quiet", ki18n("Do not print a warning when more than one file was given "
253 "and they do not all have the same mimetype."));
254 options.add("av"); // short option for --allValues
255 options.add("allValues", ki18n("Prints all metadata values, available in the given "
256 "file(s)."));
257 options.add("dialog", ki18n("Opens a KDE properties dialog to allow viewing and "
258 "modifying of metadata of the given file(s)"));
259 options.add("getValue <key>", ki18n("Prints the value for 'key' of the given file(s). 'key' "
260 "may also be a comma-separated list of keys"));
261 options.add("setValue <key=value>", ki18n("Attempts to set the value 'value' for the metadata key "
262 "'key' for the given file(s)"));
263 options.add("+[files]", ki18n("The file (or a number of files) to operate on."));
264 KCmdLineArgs::addCmdLineOptions( options );
265
266 KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
267 bool useGUI = args->isSet( "dialog" );
268
269 KApplication app( useGUI );
270
271 QList<FileProps *> m_props;
272
273 bool quiet = args->isSet( "quiet" );
274
275 int files = args->count();
276 if ( files == 0 ) {
277 KCmdLineArgs::usageError( i18n("No files specified") ); // exit()s
278 }
279
280 if ( args->isSet( "dialog" ) ) {
281 showPropertiesDialog( args );
282 return 0;
283 }
284
285 QString mimeType;
286
287 for ( int i = 0; i < files; i++ ) {
288 //if ( args->isSet( "mimetype" ) )
289 //printMimeTypes( args );
290
291 FileProps *props = new FileProps( args->url(i).path());
292 if ( props->isValid() ) {
293 m_props.append( props );
294 } else {
295 if ( !quiet ) {
296 kWarning() << args->arg(i) << ": " <<
297 i18n("Cannot determine metadata").toLocal8Bit() << endl;
298 }
299 delete props;
300 }
301 }
302
303
304 processMetaDataOptions( m_props, args );
305
306 qDeleteAll(m_props); // force destruction/sync of props
307
308 return 0;
309}
310