23
23
#include "bytearrayviewprofilemanager.h"
26
#include "bytearrayviewprofilelock.h"
29
#include <KStandardDirs>
30
#include <KConfigGroup>
35
#include <QtCore/QFileInfo>
36
#include <QtCore/QDir>
37
#include <QtCore/QUuid>
43
static const QStringList viewProfileFileNameFilter =
44
QStringList() << QLatin1String( "*.obavp" ) << QLatin1String( "*.olock" );
45
static const QString viewProfileFileSuffix = QLatin1String( ".obavp" );
46
static const QString viewProfileSubDir = QLatin1String( "okteta/viewprofiles" );
47
static const int DefaultNoOfBytesPerLine = 16;
48
static const int DefaultNoOfBytesPerGroup = 4;
49
static const int DefaultLayoutStyle = 0;
50
static const int DefaultViewModus = 0;
51
static const int DefaultVisibleByteArrayCodings = 3;
52
static const int DefaultValueCoding = 0;
53
static const QString DefaultCharCoding;
55
static QList<ByteArrayViewProfile::Id>
56
viewProfileIds( const QList<ByteArrayViewProfile>& viewProfiles )
58
QList<ByteArrayViewProfile::Id> result;
59
result.reserve(viewProfiles.count());
61
foreach( const ByteArrayViewProfile& viewProfile, viewProfiles )
62
result.append( viewProfile.id() );
67
static QList<ByteArrayViewProfile::Id>
68
lockedViewProfileIds( const ByteArrayViewProfileFileInfoLookup& viewProfileFileInfoLookup )
70
QList<ByteArrayViewProfile::Id> result;
72
ByteArrayViewProfileFileInfoLookup::ConstIterator end =
73
viewProfileFileInfoLookup.constEnd();
74
for( ByteArrayViewProfileFileInfoLookup::ConstIterator it =
75
viewProfileFileInfoLookup.constBegin();
79
if( it.value().isLocked() )
80
result.append( it.key() );
87
updateLockStatus( ByteArrayViewProfileFileInfoLookup& viewProfileFileInfoLookup,
88
const QList<ByteArrayViewProfile::Id>& lockedViewProfileIds,
89
const QList<ByteArrayViewProfile::Id>& unlockedViewProfileIds )
91
if( lockedViewProfileIds.isEmpty() && unlockedViewProfileIds.isEmpty() )
94
ByteArrayViewProfileFileInfoLookup::Iterator end =
95
viewProfileFileInfoLookup.end();
96
for( ByteArrayViewProfileFileInfoLookup::Iterator it = viewProfileFileInfoLookup.begin();
102
if( lockedViewProfileIds.contains(it.key()) )
104
else if( unlockedViewProfileIds.contains(it.key()) )
109
it.value().setLocked( isLocked );
114
viewProfileFilePath( const ByteArrayViewProfile::Id& viewProfileId )
116
return KGlobal::dirs()->saveLocation( "data", viewProfileSubDir ) + viewProfileId + viewProfileFileSuffix;
120
viewProfileFileName( const ByteArrayViewProfile::Id& viewProfileId )
122
return viewProfileId + viewProfileFileSuffix;
125
// TODO: add global lock
126
// TODO: make calls async
127
// TODO: only load view profiles on demand
28
128
ByteArrayViewProfileManager::ByteArrayViewProfileManager()
32
void ByteArrayViewProfileManager::addViewProfiles( const QList<ByteArrayViewProfile>& viewProfiles )
34
mViewProfiles << viewProfiles;
36
emit viewProfilesAdded( viewProfiles );
130
mViewProfileFileWatcher = new KDirWatch( this );
131
connect( mViewProfileFileWatcher, SIGNAL(dirty(QString)),
132
SLOT(onViewProfilesFolderChanged(QString)) );
134
// get all folder where viewProfiles could be stored
135
const KStandardDirs* const standardDirs = KGlobal::dirs();
136
const QStringList dataFolderPaths = standardDirs->resourceDirs( "data" );
138
foreach( const QString& dataFolderPath, dataFolderPaths )
140
const QString viewProfileFolderPath = dataFolderPath + viewProfileSubDir;
141
// watch folder for changes
142
mViewProfileFileWatcher->addDir( viewProfileFolderPath, KDirWatch::WatchDirOnly );
143
kDebug() << "adding Dir"<<viewProfileFolderPath;
145
// read current files
146
onViewProfilesFolderChanged( viewProfileFolderPath );
150
if( ! mViewProfiles.isEmpty() )
151
mDefaultViewProfileId = mViewProfiles.at(0).id();
153
// report any problems with existing view profiles?
157
ByteArrayViewProfileManager::viewProfilesCount() const
159
return mViewProfiles.count();
163
QList<ByteArrayViewProfile>
164
ByteArrayViewProfileManager::viewProfiles() const
166
return mViewProfiles;
170
ByteArrayViewProfileManager::viewProfile( const ByteArrayViewProfile::Id& viewProfileId ) const
172
ByteArrayViewProfile result;
174
foreach( const ByteArrayViewProfile& viewProfile, mViewProfiles )
176
if( viewProfile.id() == viewProfileId )
178
result = viewProfile;
186
ByteArrayViewProfile::Id
187
ByteArrayViewProfileManager::defaultViewProfileId() const
189
return mDefaultViewProfileId;
193
ByteArrayViewProfileManager::defaultViewProfile() const
195
return viewProfile( mDefaultViewProfileId );
199
ByteArrayViewProfileManager::isViewProfileLocked( const ByteArrayViewProfile::Id& viewProfileId ) const
203
// search in all folders for the info
204
foreach( const ByteArrayViewProfileFileInfoLookup& viewProfileFileInfoLookup, mViewProfileFileInfoLookupPerFolder )
206
ByteArrayViewProfileFileInfoLookup::ConstIterator it =
207
viewProfileFileInfoLookup.find( viewProfileId );
208
if( it != viewProfileFileInfoLookup.constEnd() )
210
result = it->isLocked();
218
void ByteArrayViewProfileManager::saveViewProfiles( QList<ByteArrayViewProfile>& viewProfiles )
220
//TODO: do not save if locked by someone else -> needs passing of our lock? or just registering our own and check?
221
// create and set unique id
222
for( QList<ByteArrayViewProfile>::Iterator it = viewProfiles.begin(); it != viewProfiles.end(); ++it )
224
ByteArrayViewProfile& viewProfile = *it;
225
const ByteArrayViewProfile::Id viewProfileId = viewProfile.id();
226
const ByteArrayViewProfile::Id oldViewProfileId = viewProfile.id();
229
if( ! viewProfileId.isEmpty() )
232
QList<ByteArrayViewProfile>::ConstIterator existingIt = mViewProfiles.constBegin();
233
QList<ByteArrayViewProfile>::ConstIterator existingEnd = mViewProfiles.constEnd();
234
for( ; existingIt != existingEnd; ++existingIt )
236
if( viewProfileId == existingIt->id() )
244
// set new uuid for non-existing
246
viewProfile.setId( QUuid::createUuid().toString() );
248
kDebug() << "going to save"<<viewProfile.viewProfileTitle()<<viewProfile.id()<<oldViewProfileId;
249
saveViewProfile( viewProfile );
255
ByteArrayViewProfileManager::removeViewProfiles( const QList<ByteArrayViewProfile::Id>& viewProfileIds )
257
foreach( const ByteArrayViewProfile::Id& viewProfileId, viewProfileIds )
259
removeViewProfile( viewProfileId );
265
ByteArrayViewProfileManager::setDefaultViewProfile( const ByteArrayViewProfile::Id& viewProfileId )
268
if( mDefaultViewProfileId == viewProfileId )
271
bool isExisting = false;
272
foreach( const ByteArrayViewProfile& viewProfile, mViewProfiles )
274
if( viewProfile.id() == viewProfileId )
283
mDefaultViewProfileId = viewProfileId;
284
emit defaultViewProfileChanged( mDefaultViewProfileId );
288
ByteArrayViewProfileLock
289
ByteArrayViewProfileManager::createLock( const ByteArrayViewProfile::Id& viewProfileId )
291
const QString viewProfileFilePath = filePathOfViewProfile( viewProfileId );
293
return ByteArrayViewProfileLock( viewProfileFilePath, viewProfileId );
298
ByteArrayViewProfileManager::lockViewProfile( const Kasten::ByteArrayViewProfile::Id& viewProfileId )
302
const QString viewProfileFilePath = filePathOfViewProfile( viewProfileId );
305
if( not viewProfileFilePath.isEmpty() )
307
const QString lockFilePath = viewProfileFileLockPath( viewProfileFilePath );
308
KLockFile::Ptr lock = new KLockFile( lockFilePath );
309
const KLockFile::LockResult lockResult =
310
lock->lock(KLockFile::NoBlockFlag | KLockFile::ForceFlag);
311
isSuccessfull = (lockResult == KLockFile::LockOK );
314
// try to create lock file
315
return isSuccessfull;
319
// ByteArrayViewProfileManager::unlockViewProfile( const Kasten::ByteArrayViewProfile::Id& viewProfileId )
321
// const QString filePath = filePathOfViewProfile( viewProfileId );
323
// if( filePath.isEmpty() )
328
ByteArrayViewProfileManager::loadViewProfile( const QString& absoluteFilePath ) const
330
kDebug() << "Loading" << QFileInfo(absoluteFilePath).baseName() << absoluteFilePath;
331
ByteArrayViewProfile result;
333
KConfig configFile( absoluteFilePath, KConfig::SimpleConfig );
334
// TODO: version check
336
result.setId( QFileInfo(absoluteFilePath).baseName() );
338
KConfigGroup generalConfigGroup = configFile.group( "General" );
339
result.setViewProfileTitle( generalConfigGroup.readEntry("Title") );
341
KConfigGroup layoutConfigGroup = configFile.group( "Layout" );
342
result.setNoOfBytesPerLine( layoutConfigGroup.readEntry("NoOfBytesPerLine", DefaultNoOfBytesPerLine) );
343
result.setNoOfGroupedBytes( layoutConfigGroup.readEntry("NoOfBytesPerGroup", DefaultNoOfBytesPerGroup) );
344
result.setLayoutStyle( layoutConfigGroup.readEntry("LayoutStyle", DefaultLayoutStyle) );
346
KConfigGroup displayConfigGroup = configFile.group( "Display" );
347
result.setOffsetColumnVisible( displayConfigGroup.readEntry("OffsetColumnVisible", true) );
348
result.setViewModus( displayConfigGroup.readEntry("ViewModus", DefaultViewModus) );
349
result.setVisibleByteArrayCodings( displayConfigGroup.readEntry("VisibleByteArrayCodings", DefaultVisibleByteArrayCodings) );
351
KConfigGroup interpretationConfigGroup = configFile.group( "Interpretation" );
353
KConfigGroup valuesConfigGroup = interpretationConfigGroup.group( "Values" );
354
result.setValueCoding( valuesConfigGroup.readEntry("Coding", DefaultValueCoding) );
356
KConfigGroup charsConfigGroup = interpretationConfigGroup.group( "Chars" );
357
result.setCharCoding( charsConfigGroup.readEntry("Coding", DefaultCharCoding) );
358
result.setShowsNonprinting( charsConfigGroup.readEntry("NonprintingShown", false) );
359
result.setSubstituteChar( charsConfigGroup.readEntry("SubstituteChar", ".").at(0) );
360
result.setUndefinedChar( charsConfigGroup.readEntry("UndefinedChar", "?").at(0) );
366
ByteArrayViewProfileManager::saveViewProfile( const ByteArrayViewProfile& viewProfile ) const
368
kDebug() << "------------------ Saving"<<viewProfile.id();
370
const QString fileName = viewProfileFilePath( viewProfile.id() );
371
KConfig configFile( fileName, KConfig::SimpleConfig );
373
KConfigGroup generalConfigGroup = configFile.group( "General" );
374
generalConfigGroup.writeEntry( "Title", viewProfile.viewProfileTitle() );
376
KConfigGroup layoutConfigGroup = configFile.group( "Layout" );
377
layoutConfigGroup.writeEntry( "NoOfBytesPerLine", viewProfile.noOfBytesPerLine() );
378
layoutConfigGroup.writeEntry( "NoOfBytesPerGroup", viewProfile.noOfGroupedBytes() );
379
layoutConfigGroup.writeEntry( "LayoutStyle", viewProfile.layoutStyle() );
381
KConfigGroup displayConfigGroup = configFile.group( "Display" );
382
displayConfigGroup.writeEntry( "OffsetColumnVisible", viewProfile.offsetColumnVisible() );
383
displayConfigGroup.writeEntry( "ViewModus", viewProfile.viewModus() );
384
displayConfigGroup.writeEntry( "VisibleByteArrayCodings", viewProfile.visibleByteArrayCodings() );
386
KConfigGroup interpretationConfigGroup = configFile.group( "Interpretation" );
388
KConfigGroup valuesConfigGroup = interpretationConfigGroup.group( "Values" );
389
valuesConfigGroup.writeEntry( "Coding", viewProfile.valueCoding() );
391
KConfigGroup charsConfigGroup = interpretationConfigGroup.group( "Chars" );
392
charsConfigGroup.writeEntry( "Coding", viewProfile.charCodingName() );
393
charsConfigGroup.writeEntry( "NonprintingShown", viewProfile.showsNonprinting() );
394
charsConfigGroup.writeEntry( "SubstituteChar", QString(viewProfile.substituteChar()) );
395
charsConfigGroup.writeEntry( "UndefinedChar", QString(viewProfile.undefinedChar()) );
397
kDebug() << "------------------ Saved"<<viewProfile.id();
401
ByteArrayViewProfileManager::removeViewProfile( const ByteArrayViewProfile::Id& viewProfileId )
403
const QString filePath = filePathOfViewProfile( viewProfileId );
404
kDebug() << "------------------ Removing"<<viewProfileId<<filePath;
405
if( ! filePath.isEmpty() )
406
QFile::remove( filePath );
410
ByteArrayViewProfileManager::filePathOfViewProfile( const ByteArrayViewProfile::Id& viewProfileId ) const
414
for( QHash<QString, ByteArrayViewProfileFileInfoLookup>::ConstIterator foldersIt =
415
mViewProfileFileInfoLookupPerFolder.constBegin();
416
foldersIt != mViewProfileFileInfoLookupPerFolder.constEnd() && result.isEmpty();
419
const ByteArrayViewProfileFileInfoLookup& fileInfoList = foldersIt.value();
420
for( ByteArrayViewProfileFileInfoLookup::ConstIterator folderIt = fileInfoList.constBegin();
421
folderIt != fileInfoList.constEnd();
424
if( folderIt.key() == viewProfileId )
426
result = foldersIt.key() + QLatin1Char('/') + viewProfileFileName( viewProfileId );
436
ByteArrayViewProfileManager::onViewProfilesFolderChanged( const QString& viewProfileFolderPath )
438
kDebug() << "looking into folder"<< viewProfileFolderPath;
439
ByteArrayViewProfileFileInfoLookup& viewProfileFileInfoLookup =
440
mViewProfileFileInfoLookupPerFolder[viewProfileFolderPath];
442
// TODO: reparse for new, removed and changed files
443
// assume all are removed and unlocked in the beginning
444
QList<ByteArrayViewProfile::Id> removedViewProfileIds = viewProfileFileInfoLookup.keys();
445
QList<ByteArrayViewProfile> newViewProfiles;
446
QList<ByteArrayViewProfile> changedViewProfiles;
448
QList<ByteArrayViewProfile::Id> newUnlockedViewProfileIds = lockedViewProfileIds(viewProfileFileInfoLookup);
449
QList<ByteArrayViewProfile::Id> newLockedViewProfileIds;
450
kDebug() << "old profiles:" << removedViewProfileIds;
451
kDebug() << "locked profiles:" << newUnlockedViewProfileIds;
452
// iterate all files in folder
453
const QFileInfoList viewProfileFileInfoList =
454
QDir( viewProfileFolderPath ).entryInfoList( viewProfileFileNameFilter, QDir::Files );
456
foreach( const QFileInfo& viewProfileFileInfo, viewProfileFileInfoList )
459
if( viewProfileFileInfo.suffix() == QLatin1String("olock") )
461
const ByteArrayViewProfile::Id lockedViewProfileId = viewProfileFileInfo.baseName();
462
// if not in old locks, is a new lock
463
if( ! newUnlockedViewProfileIds.removeOne(lockedViewProfileId) )
464
newLockedViewProfileIds.append( lockedViewProfileId );
468
// not a viewprofile file ?
469
if( viewProfileFileInfo.suffix() != QLatin1String("obavp") )
472
// all other files assumed to be viewProfile files
473
// TODO: check validness
474
const QDateTime fileInfoLastModified = viewProfileFileInfo.lastModified();
475
const ByteArrayViewProfile::Id viewProfileId = viewProfileFileInfo.baseName();
476
ByteArrayViewProfileFileInfoLookup::Iterator infoIt =
477
viewProfileFileInfoLookup.find( viewProfileId );
478
const bool isKnown = ( infoIt != viewProfileFileInfoLookup.end() );
482
removedViewProfileIds.removeOne( viewProfileId );
485
if( fileInfoLastModified == infoIt->lastModified() )
489
infoIt->setLastModified( fileInfoLastModified );
493
ByteArrayViewProfileFileInfo info( fileInfoLastModified, false );
494
viewProfileFileInfoLookup.insert( viewProfileId, info );
497
kDebug() <<"going to load"<<viewProfileId;
499
// TODO: check validness
500
const ByteArrayViewProfile viewProfile = loadViewProfile( viewProfileFileInfo.absoluteFilePath() );
503
QList<ByteArrayViewProfile>::Iterator it = mViewProfiles.begin();
504
QList<ByteArrayViewProfile>::Iterator end = mViewProfiles.end();
505
for( ; it != end; ++it )
507
if( it->id() == viewProfileId )
515
newViewProfiles.append( viewProfile );
516
changedViewProfiles.append( viewProfile );
519
// remove all removed viewprofiles
521
QList<ByteArrayViewProfile>::Iterator it = mViewProfiles.begin();
522
while( it != mViewProfiles.end() )
524
// contained in removed?
525
if( removedViewProfileIds.contains(it->id()) )
526
it = mViewProfiles.erase(it);
531
foreach( const ByteArrayViewProfile::Id& viewProfileId, removedViewProfileIds )
533
viewProfileFileInfoLookup.remove( viewProfileId );
534
if( viewProfileId == mDefaultViewProfileId )
535
mDefaultViewProfileId.clear();
536
// TODO: how to select new one?
539
// add new viewprofiles
540
mViewProfiles.append( newViewProfiles );
541
// if there was no default viewprofile before, set default to first
542
const bool isDefaultViewProfileChanged = ( mDefaultViewProfileId.isEmpty() && ! mViewProfiles.isEmpty() );
543
if( isDefaultViewProfileChanged )
544
mDefaultViewProfileId = mViewProfiles.at(0).id();
547
updateLockStatus( viewProfileFileInfoLookup, newLockedViewProfileIds, newUnlockedViewProfileIds );
549
kDebug() << "new profiles:" << viewProfileFileInfoLookup.keys();
552
if( ! changedViewProfiles.isEmpty() )
553
emit viewProfilesChanged( changedViewProfiles );
554
kDebug() << "changed profiles" << viewProfileIds(changedViewProfiles);
555
if( ! removedViewProfileIds.isEmpty() )
556
emit viewProfilesRemoved( removedViewProfileIds );
557
kDebug() << "removed profiles" << removedViewProfileIds;
559
if( ! newUnlockedViewProfileIds.isEmpty() )
560
emit viewProfilesUnlocked( newUnlockedViewProfileIds );
561
kDebug() << "unlocked profiles" << newUnlockedViewProfileIds;
562
if( ! newLockedViewProfileIds.isEmpty() )
563
emit viewProfilesLocked( newLockedViewProfileIds );
564
kDebug() << "locked profiles" << newLockedViewProfileIds;
565
if( isDefaultViewProfileChanged )
566
emit defaultViewProfileChanged( mDefaultViewProfileId );
39
570
ByteArrayViewProfileManager::~ByteArrayViewProfileManager()