completed tree state restore function,

visual order of entries will now affect their saving order,
changed the behavior of the entry view header.

git-svn-id: https://svn.code.sf.net/p/keepassx/code/trunk@124 b624d157-de02-0410-bad0-e51aec6abb33
master
tarek_saidi 17 years ago
parent ee97e3c197
commit 28ba242090
  1. 21
      src/Database.cpp
  2. 23
      src/Database.h
  3. 221
      src/StandardDatabase.cpp
  4. 18
      src/StandardDatabase.h
  5. 37
      src/dialogs/PasswordDlg.cpp
  6. 9
      src/dialogs/SettingsDlg.cpp
  7. 43
      src/export/Export_Txt.cpp
  8. 11
      src/export/Export_Txt.h
  9. 3
      src/forms/MainWindow.ui
  10. 9
      src/forms/SettingsDlg.ui
  11. 5
      src/import/Import_KWalletXml.h
  12. 22
      src/lib/EntryView.cpp
  13. 1
      src/lib/EntryView.h
  14. 93
      src/lib/FileDialogs.cpp
  15. 51
      src/lib/FileDialogs.h
  16. 17
      src/lib/GroupView.cpp
  17. 4
      src/lib/GroupView.h
  18. 12
      src/main.cpp
  19. 2
      src/main.h
  20. 104
      src/mainwindow.cpp
  21. 2
      src/mainwindow.h
  22. 2
      src/plugins/interfaces/IFileDialog.h
  23. 305
      src/src.pro

@ -1,6 +1,6 @@
/***************************************************************************
* Copyright (C) 2005 by Tarek Saidi *
* mail@tarek-saidi.de *
* Copyright (C) 2005-2007 by Tarek Saidi *
* tarek.saidi@arcor.de *
* *
* 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 *
@ -87,18 +87,19 @@ else return date().toString(format);
CEntry::CEntry(){
Image=0;
GroupId=0;
Creation=QDateTime::currentDateTime();
LastMod=QDateTime::currentDateTime();
LastAccess=QDateTime::currentDateTime();
Expire=QDateTime(QDate(2999,12,28),QTime(23,59,59)); //Never
Binary=QByteArray();
Image=0;
GroupId=0;
Creation=QDateTime::currentDateTime();
LastMod=QDateTime::currentDateTime();
LastAccess=QDateTime::currentDateTime();
Expire=QDateTime(QDate(2999,12,28),QTime(23,59,59)); //Never
Binary=QByteArray();
}
CGroup::CGroup(){
Image=0;
Image=0;
IsExpanded=false;
}

@ -103,6 +103,7 @@ public:
quint32 Image;
QString Title;
bool operator==(const CGroup& other) const;
bool IsExpanded;
};
@ -144,14 +145,25 @@ public:
virtual KpxDateTime expire()=0;
virtual QByteArray binary()=0;
virtual quint32 binarySize()=0;
//! \return the index of the entry amongst the entries of its group. The index of the first entry is 0.
virtual int index()const=0;
virtual int visualIndex()const=0;
/*! Sets the visual index of an entry. The indices of all other entries in the same group get automaticly readjusted by this function.
\param index The new visual index.
*/
virtual void setVisualIndex(int index)=0;
/*! Sets the visual index of an entry. The indices of all other entries in the same group need to be adjusted manually!
This function is optimal to avoid readjustion overhead when sorting items.
\param index The new visual index.
*/
virtual void setVisualIndexDirectly(int index)=0;
/*! Tests the validity of the handle.
\return TRUE if the handle is valid and FALSE if the handle is invalid e.g. because the associated entry was deleted.*/
virtual bool isValid()const=0;
virtual bool operator<(const IEntryHandle*& other)=0;
};
@ -218,6 +230,9 @@ public:
/*! \return the level of the group in the group tree. This level is tantamount to the number of parents that the group has. */
virtual int level()=0;
virtual bool expanded()=0;
virtual void setExpanded(bool)=0;
};
@ -225,7 +240,7 @@ public:
/*!
This is the common base interface for databases. Every database class must implement this interface necessarily.
*/
class IDatabase{
class IDatabase:public QObject{
public:
virtual ~IDatabase(){};

@ -1,5 +1,5 @@
/***************************************************************************
* Copyright (C) 2005-2006 by Tarek Saidi *
* Copyright (C) 2005-2007 by Tarek Saidi *
* keepassx@gmail.com *
* *
* This program is free software; you can redistribute it and/or modify *
@ -17,6 +17,7 @@
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "global.h"
#include <iostream>
#include <time.h>
@ -38,6 +39,19 @@ using namespace std;
#define UNEXP_ERROR error=QString("Unexpected error in: %1, Line:%2").arg(__FILE__).arg(__LINE__);
const QDateTime Date_Never(QDate(2999,12,28),QTime(23,59,59));
bool EntryHandleLessThan(const IEntryHandle* This,const IEntryHandle* Other){
if(!This->isValid() && Other->isValid())return true;
if(This->isValid() && !Other->isValid())return false;
if(!This->isValid() && !Other->isValid())return false;
return This->visualIndex()<Other->visualIndex();
}
bool StdEntryLessThan(const StandardDatabase::StdEntry& This,const StandardDatabase::StdEntry& Other){
return This.Index<Other.Index;
}
QString StandardDatabase::getError(){
@ -89,8 +103,15 @@ int StandardDatabase::numIcons(){
bool StandardDatabase::parseMetaStream(const StdEntry& entry){
if(entry.Comment=="KPX_CUSTOM_ICONS_3")
return parseCustomIconsMetaStream(entry.Binary);
qDebug("%s",entry.Comment.toUtf8().data());
if(entry.Comment=="KPX_GROUP_TREE_STATE"){
parseGroupTreeStateMetaStream(entry.Binary);
return true;}
if(entry.Comment=="KPX_CUSTOM_ICONS_3"){
parseCustomIconsMetaStream(entry.Binary);
return true;}
if(entry.Comment=="KPX_CUSTOM_ICONS_2")
return parseCustomIconsMetaStreamV2(entry.Binary);
@ -123,58 +144,98 @@ bool StandardDatabase::parseCustomIconsMetaStreamV2(const QByteArray& dta){
return true;
}
bool StandardDatabase::parseCustomIconsMetaStream(const QByteArray& dta){
qDebug("CuIcMeSt v3 found.");
//Rev 3
quint32 NumIcons,NumEntries,NumGroups,offset;
memcpyFromLEnd32(&NumIcons,dta.data());
memcpyFromLEnd32(&NumEntries,dta.data()+4);
memcpyFromLEnd32(&NumGroups,dta.data()+8);
offset=12;
CustomIcons.clear();
for(int i=0;i<NumIcons;i++){
CustomIcons << QPixmap();
quint32 Size;
memcpyFromLEnd32(&Size,dta.data()+offset);
if(offset+Size > dta.size()){
CustomIcons.clear();
return false;}
offset+=4;
if(!CustomIcons.back().loadFromData((const unsigned char*)dta.data()+offset,Size,"PNG")){
CustomIcons.clear();
return false;}
offset+=Size;
if(offset > dta.size()){
CustomIcons.clear();
return false;}
}
for(int i=0;i<NumEntries;i++){
quint32 Icon;
KpxUuid EntryUuid;
EntryUuid.fromRaw(dta.data()+offset);
offset+=16;
memcpyFromLEnd32(&Icon,dta.data()+offset);
offset+=4;
StdEntry* entry=getEntry(EntryUuid);
if(entry){
entry->OldImage=entry->Image;
entry->Image=Icon;
void StandardDatabase::parseCustomIconsMetaStream(const QByteArray& dta){
//Rev 3
quint32 NumIcons,NumEntries,NumGroups,offset;
memcpyFromLEnd32(&NumIcons,dta.data());
memcpyFromLEnd32(&NumEntries,dta.data()+4);
memcpyFromLEnd32(&NumGroups,dta.data()+8);
offset=12;
CustomIcons.clear();
for(int i=0;i<NumIcons;i++){
CustomIcons << QPixmap();
quint32 Size;
memcpyFromLEnd32(&Size,dta.data()+offset);
if(offset+Size > dta.size()){
CustomIcons.clear();
qWarning("Discarded metastream KPX_CUSTOM_ICONS_3 because of a parsing error.");
return;}
offset+=4;
if(!CustomIcons.back().loadFromData((const unsigned char*)dta.data()+offset,Size,"PNG")){
CustomIcons.clear();
qWarning("Discarded metastream KPX_CUSTOM_ICONS_3 because of a parsing error.");
return;}
offset+=Size;
if(offset > dta.size()){
CustomIcons.clear();
qWarning("Discarded metastream KPX_CUSTOM_ICONS_3 because of a parsing error.");
return;}
}
}
for(int i=0;i<NumGroups;i++){
quint32 GroupId,Icon;
memcpyFromLEnd32(&GroupId,dta.data()+offset);
offset+=4;
memcpyFromLEnd32(&Icon,dta.data()+offset);
offset+=4;
StdGroup* Group=getGroup(GroupId);
if(Group){
Group->OldImage=Group->Image;
Group->Image=Icon;
for(int i=0;i<NumEntries;i++){
quint32 Icon;
KpxUuid EntryUuid;
EntryUuid.fromRaw(dta.data()+offset);
offset+=16;
memcpyFromLEnd32(&Icon,dta.data()+offset);
offset+=4;
StdEntry* entry=getEntry(EntryUuid);
if(entry){
entry->OldImage=entry->Image;
entry->Image=Icon;
}
}
for(int i=0;i<NumGroups;i++){
quint32 GroupId,Icon;
memcpyFromLEnd32(&GroupId,dta.data()+offset);
offset+=4;
memcpyFromLEnd32(&Icon,dta.data()+offset);
offset+=4;
StdGroup* Group=getGroup(GroupId);
if(Group){
Group->OldImage=Group->Image;
Group->Image=Icon;
}
}
return;
}
void StandardDatabase::parseGroupTreeStateMetaStream(const QByteArray& dta){
if(dta.size()<4){qWarning("Discarded metastream KPX_GROUP_TREE_STATE because of a parsing error."); return;}
quint32 Num;
memcpyFromLEnd32(&Num,dta.data());
if(Num*5!=dta.size()-4){qWarning("Discarded metastream KPX_GROUP_TREE_STATE because of a parsing error."); return;}
TreeStateMetaStream.clear();
for(int i=0;i<Num;i++){
quint32 GroupID;
quint8 IsExpanded;
memcpyFromLEnd32(&GroupID,dta.data()+4+5*i);
memcpy(&IsExpanded,dta.data()+8+5*i,1);
TreeStateMetaStream.insert(GroupID,(bool)IsExpanded);
}
return;
}
return true;
void StandardDatabase::createGroupTreeStateMetaStream(StdEntry* e){
e->BinaryDesc="bin-stream";
e->Title="Meta-Info";
e->Username="SYSTEM";
e->Comment="KPX_GROUP_TREE_STATE";
e->Url="$";
e->OldImage=0;
e->Image=0;
if(Groups.size())e->GroupId=Groups[0].Id;
QByteArray bin;
quint32 Num=Groups.size();
bin.resize(Num*5+4);
memcpyToLEnd32(bin.data(),&Num);
for(int i=0;i<Num;i++){
memcpyToLEnd32(bin.data()+4+5*i,&Groups[i].Id);
if(Groups[i].IsExpanded)
bin.data()[8+5*i]=1;
else
bin.data()[8+5*i]=0;
}
e->Binary=bin;
}
StandardDatabase::StdEntry* StandardDatabase::getEntry(const KpxUuid& uuid){
@ -319,11 +380,16 @@ bool StandardDatabase::createGroupTree(QList<quint32>& Levels){
Groups[i].Parent->Childs.append(&Groups[i]);
}
QList<int> EntryIndexCounter;
for(int i=0;i<Groups.size();i++)EntryIndexCounter << 0;
for(int e=0;e<Entries.size();e++){
for(int g=0;g<Groups.size();g++){
if(Entries[e].GroupId==Groups[g].Id){
Groups[g].Entries.append(&Entries[e]);
Entries[e].Group=&Groups[g];
Entries[e].Index=EntryIndexCounter[g];
EntryIndexCounter[g]++;
}
}
}
@ -335,7 +401,7 @@ void StandardDatabase::createHandles(){
for(int i=0;i<Groups.size();i++){
GroupHandles.append(GroupHandle(this));
Groups[i].Handle=&GroupHandles.back();
GroupHandles.back().Group=&Groups[i];
GroupHandles.back().Group=&Groups[i];
}
for(int i=0;i<Entries.size();i++){
EntryHandles.append(EntryHandle(this));
@ -344,6 +410,21 @@ void StandardDatabase::createHandles(){
}
}
void StandardDatabase::restoreGroupTreeState(){
if(settings->value("GroupTreeState","ExpandAll")=="ExpandAll"){
for(int i=0;i<Groups.size();i++){
Groups[i].IsExpanded=true;
}
}
else
if(settings->value("GroupTreeState","ExpandAll")=="Restore"){
for(int i=0;i<Groups.size();i++){
if(TreeStateMetaStream.contains(Groups[i].Id))
Groups[i].IsExpanded=TreeStateMetaStream.value(Groups[i].Id);
}
}
}
bool StandardDatabase::load(QString filename){
unsigned long total_size,crypto_size;
quint32 Signature1,Signature2,Version,NumGroups,NumEntries,Flags;
@ -511,6 +592,7 @@ for(int i=0;i<Entries.size();i++){
UnknownMetaStreams << Entries[i];
Entries.removeAt(i);
i--;}
}
int* EntryIndices=new int[Groups.size()];
@ -526,6 +608,7 @@ for(int g=0;g<Groups.size();g++){
}
delete [] EntryIndices;
createHandles();
restoreGroupTreeState();
return true;
}
@ -727,20 +810,15 @@ QList<IEntryHandle*> StandardDatabase::entries(){
return handles;
}
bool StandardDatabase::EntryHandle::operator<(const IEntryHandle*& other){
if(!isValid() && other->isValid())return true;
if(isValid() && !other->isValid())return false;
if(!isValid() && !other->isValid())return false;
return index()<other->index();
}
QList<IEntryHandle*> StandardDatabase::entries(IGroupHandle* group){
QList<IEntryHandle*> handles;
for(int i=0; i<EntryHandles.size(); i++){
if(EntryHandles[i].isValid() && (EntryHandles[i].group()==group))
handles.append(&EntryHandles[i]);
}
qSort(handles.begin(),handles.end());
qSort(handles.begin(),handles.end(),EntryHandleLessThan);
foreach(IEntryHandle* h,handles){qDebug("+ %s (%i)",h->title().toUtf8().data(),(int)h->isValid());}
return handles;
}
@ -859,9 +937,18 @@ KpxDateTime StandardDatabase::EntryHandle::lastAccess(){return Entry->LastAccess
KpxDateTime StandardDatabase::EntryHandle::expire(){return Entry->Expire;}
QByteArray StandardDatabase::EntryHandle::binary(){return Entry->Binary;}
quint32 StandardDatabase::EntryHandle::binarySize(){return Entry->Binary.size();}
int StandardDatabase::EntryHandle::index()const{return Entry->Index;}
int StandardDatabase::EntryHandle::visualIndex()const{return Entry->Index;}
void StandardDatabase::EntryHandle::setVisualIndexDirectly(int i){Entry->Index=i;}
bool StandardDatabase::EntryHandle::isValid()const{return valid;}
void StandardDatabase::EntryHandle::setVisualIndex(int index){
QList<IEntryHandle*>Entries=pDB->entries(Entry->Group->Handle);
Entries.move(visualIndex(),index);
for(int i=0;i<Entries.size();i++){
dynamic_cast<StandardDatabase::EntryHandle*>(Entries[i])->Entry->Index=index;
}
}
StandardDatabase::EntryHandle::EntryHandle(StandardDatabase* db){
pDB=db;
ListIndex=0;
@ -876,8 +963,8 @@ quint32 StandardDatabase::GroupHandle::oldImage(){return Group->OldImage;}
quint32 StandardDatabase::GroupHandle::image(){return Group->Image;}
int StandardDatabase::GroupHandle::index(){return Group->Index;}
void StandardDatabase::GroupHandle::setTitle(const QString& Title){Group->Title=Title;}
void StandardDatabase::GroupHandle::setExpanded(bool IsExpanded){Group->IsExpanded=IsExpanded;}
bool StandardDatabase::GroupHandle::expanded(){return Group->IsExpanded;}
void StandardDatabase::GroupHandle::setImage(const quint32& New)
{
if(Group->Image < pDB->builtinIcons() && New >= pDB->builtinIcons())
@ -1003,6 +1090,8 @@ bool StandardDatabase::save(){
QList<StdEntry> MetaStreams;
MetaStreams << StdEntry();
createCustomIconsMetaStream(&MetaStreams.back());
MetaStreams << StdEntry();
createGroupTreeStateMetaStream(&MetaStreams.back());
FileSize=DB_HEADER_SIZE;
// Get the size of all groups (94 Byte + length of the name string)
@ -1048,7 +1137,9 @@ bool StandardDatabase::save(){
else if(Algorithm == Twofish_Cipher) Flags |= PWM_FLAG_TWOFISH;
Version = PWM_DBVER_DW;
NumGroups = Groups.size();
NumEntries = Entries.size()+UnknownMetaStreams.size()+1;
NumEntries = Entries.size()+UnknownMetaStreams.size()+MetaStreams.size();
qSort(Entries.begin(),Entries.end(),StdEntryLessThan);
randomize(FinalRandomSeed,16);
randomize(TransfRandomSeed,32);

@ -1,5 +1,5 @@
/***************************************************************************
* Copyright (C) 2005-2006 by Tarek Saidi *
* Copyright (C) 2005-2007 by Tarek Saidi *
* keepassx@gmail.com *
* *
* This program is free software; you can redistribute it and/or modify *
@ -38,6 +38,7 @@
#include <QTime>
#include <QStringList>
#include <QPixmap>
#include <QMap>
#include "lib/SecString.h"
#include "Database.h"
@ -73,7 +74,9 @@ public:
virtual KpxUuid uuid();
virtual IGroupHandle* group();
virtual quint32 image();
virtual int index() const;
virtual int visualIndex() const;
virtual void setVisualIndex(int i);
virtual void setVisualIndexDirectly(int i);
quint32 oldImage();
virtual QString title();
virtual QString url();
@ -88,7 +91,6 @@ public:
virtual QByteArray binary();
virtual quint32 binarySize();
virtual bool isValid() const;
virtual bool operator<(const IEntryHandle*& other);
private:
void invalidate(){valid=false;}
bool valid;
@ -113,6 +115,8 @@ public:
virtual int index();
virtual void setIndex(int index);
virtual int level();
virtual bool expanded();
virtual void setExpanded(bool IsExpanded);
private:
void invalidate(){valid=false;}
bool valid;
@ -193,9 +197,12 @@ private:
void dateToPackedStruct5(const QDateTime& datetime, unsigned char* dst);
bool isMetaStream(StdEntry& Entry);
bool parseMetaStream(const StdEntry& Entry);
bool parseCustomIconsMetaStream(const QByteArray& data);
void parseCustomIconsMetaStream(const QByteArray& data);
bool parseCustomIconsMetaStreamV1(const QByteArray& data);
bool parseCustomIconsMetaStreamV2(const QByteArray& data);
void parseGroupTreeStateMetaStream(const QByteArray& data);
void createCustomIconsMetaStream(StdEntry* e);
void createGroupTreeStateMetaStream(StdEntry* e);
bool readEntryField(StdEntry* entry, quint16 FieldType, quint32 FieldSize, quint8 *pData);
bool readGroupField(StdGroup* group,QList<quint32>& Levels,quint16 FieldType, quint32 FieldSize, quint8 *pData);
bool createGroupTree(QList<quint32>& Levels);
@ -206,12 +213,12 @@ private:
quint32 getNewGroupId();
void serializeEntries(QList<StdEntry>& EntryList,char* buffer,unsigned int& pos);
void serializeGroups(QList<StdGroup>& GroupList,char* buffer,unsigned int& pos);
void createCustomIconsMetaStream(StdEntry* e);
void appendChildsToGroupList(QList<StdGroup*>& list,StdGroup& group);
void appendChildsToGroupList(QList<IGroupHandle*>& list,StdGroup& group);
bool searchStringContains(const QString& search, const QString& string,bool Cs, bool RegExp);
void getEntriesRecursive(IGroupHandle* Group, QList<IEntryHandle*>& EntryList);
void rebuildIndices(QList<StdGroup*>& list);
void restoreGroupTreeState();
StdEntry* getEntry(const KpxUuid& uuid);
StdEntry* getEntry(EntryHandle* handle);
@ -231,6 +238,7 @@ private:
QString error;
bool KeyError;
QList<StdEntry> UnknownMetaStreams;
QMap<quint32,bool> TreeStateMetaStream;
unsigned int KeyTransfRounds;
CryptAlgorithm Algorithm;
quint8 RawMasterKey[32];

@ -18,9 +18,6 @@
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "main.h"
#include "PwmConfig.h"
#include "PasswordDlg.h"
#include <QFileDialog>
#include <QDir>
#include <QStringList>
@ -29,6 +26,12 @@
#include <QComboBox>
#include <QPushButton>
#include <QMessageBox>
#include <QStringList>
#include "main.h"
#include "PwmConfig.h"
#include "PasswordDlg.h"
#include "lib/FileDialogs.h"
CPasswordDialog::CPasswordDialog(QWidget* parent,IDatabase* DB,bool ShowExitButton,bool ChangeKeyMode)
@ -127,27 +130,23 @@ void CPasswordDialog::setStateBoth(){
void CPasswordDialog::OnButtonBrowse()
{
QFileDialog FileDlg(this,tr("Select a Key File"),QDir::homePath());
FileDlg.setFilters(QStringList()<<tr("All Files (*)") << tr("Key Files (*.key)"));
FileDlg.setFileMode(QFileDialog::ExistingFile);
if(!FileDlg.exec())return;
if(!FileDlg.selectedFiles().size())return;
QFile file(FileDlg.selectedFiles()[0]);
if(file.exists()){
Combo_Dirs->setEditText(FileDlg.selectedFiles()[0]);
return;
QString filename=KpxFileDialogs::openExistingFile(this,"PasswordDlg",tr("Select a Key File"),
QStringList() << tr("All Files (*)") << tr("Key Files (*.key)"));
if(filename!=QString()){
Combo_Dirs->setEditText(filename);
}
QMessageBox::warning(this,tr("Error"),tr("Unexpected Error: File does not exist."),tr("OK"),"","",0,0);
return;
}
void CPasswordDialog::OnButtonBrowse_Set()
{
QFileDialog FileDlg(this,tr("Select a Key File"),QDir::homePath());
FileDlg.setFilters(QStringList()<<tr("All Files (*)") << tr("Key Files (*.key)"));
FileDlg.setFileMode(QFileDialog::AnyFile);
if(!FileDlg.exec())return;
if(!FileDlg.selectedFiles().size())return;
Combo_Dirs->setEditText(FileDlg.selectedFiles()[0]);
QString filename=KpxFileDialogs::saveFile(this,"PasswordDlg",tr("Select a Key File"),
QStringList() << tr("All Files (*)") << tr("Key Files (*.key)"),
false);
if(filename!=QString()){
Combo_Dirs->setEditText(filename);
}
return;
}
void CPasswordDialog::OnCancel()

@ -107,6 +107,10 @@ CSettingsDlg::CSettingsDlg(QWidget* parent):QDialog(parent,Qt::Dialog)
case CConfig::KDE: Radio_IntPlugin_Kde->setChecked(true); break;
}
if(settings->value("GroupTreeState","ExpandAll")=="ExpandAll")Radio_GroupTreeExpand->setChecked(true);
if(settings->value("GroupTreeState","ExpandAll")=="Restore")Radio_GroupTreeRestore->setChecked(true);
if(settings->value("GroupTreeState","ExpandAll")=="ExpandNone")Radio_GroupTreeDoNothing->setChecked(true);
if(!PluginsModified)
Label_IntPlugin_Info->hide();
}
@ -167,6 +171,11 @@ void CSettingsDlg::apply(){
if(Radio_IntPlugin_None->isChecked())config.IntegrPlugin=CConfig::NONE;
if(Radio_IntPlugin_Gnome->isChecked())config.IntegrPlugin=CConfig::GNOME;
if(Radio_IntPlugin_Kde->isChecked())config.IntegrPlugin=CConfig::KDE;
if(Radio_GroupTreeExpand->isChecked())settings->setValue("GroupTreeState","ExpandAll");
if(Radio_GroupTreeDoNothing->isChecked())settings->setValue("GroupTreeState","ExpandNone");
if(Radio_GroupTreeRestore->isChecked())settings->setValue("GroupTreeState","Restore");
}
void CSettingsDlg::OnTextColor()

@ -1,5 +1,5 @@
/***************************************************************************
* Copyright (C) 2005-2006 by Tarek Saidi *
* Copyright (C) 2005-2007 by Tarek Saidi *
* tarek.saidi@arcor.de *
* *
* This program is free software; you can redistribute it and/or modify *
@ -21,9 +21,9 @@
#include <QString>
#include <QFile>
#include "main.h"
#include "../lib/SecString.h"
#include "lib/SecString.h"
#include "Export_Txt.h"
/*
QString EntryTemplate=QString("\n\
Title: %1\n\
@ -37,27 +37,22 @@ QString GroupTemplate=QString("\n\
*** Group: %1 ***\n\
");
bool Export_Txt::exportFile(const QString& filename,StandardDatabase* db,QString& err){
QFile file(filename);
if(!file.open(QIODevice::Truncate | QIODevice::WriteOnly)){
err+=tr("Could not open file (FileError=%1)").arg(file.error());
return false;
}
for(int g=0;g<db->numGroups();g++){
file.write(GroupTemplate.arg(db->group(g).Name).toUtf8());
for(int e=0;e<db->numEntries();e++){
if(db->group(g).ID==db->entry(e).GroupID){
db->entry(e).Password.unlock();
file.write(EntryTemplate.arg(db->entry(e).Title)
.arg(db->entry(e).UserName)
.arg(db->entry(e).URL)
.arg(db->entry(e).Password.string())
.arg(db->entry(e).Additional.replace('\n',"\n "))
QString Export_Txt::exportDatabase(QWidget* GuiParent, IDatabase* db, QIODevice* file){
QList<IGroupHandle*> groups=db->sortedGroups();
for(int g=0;g<groups.size();g++){
file->write(GroupTemplate.arg(groups[g]->title()).toUtf8());
QList<IEntryHandle*> entries=db->entries(groups[g]);
for(int e=0;e<entries.size();e++){
SecString password=entries[e]->password();
password.unlock();
file->write(EntryTemplate.arg(entries[e]->title())
.arg(entries[e]->username())
.arg(entries[e]->url())
.arg(password.string())
.arg(entries[e]->comment().replace('\n',"\n "))
.toUtf8());
db->entry(e).Password.lock();
password.lock();
}
}
}
file.close();
}*/
return QString();
}

@ -19,13 +19,14 @@
***************************************************************************/
#ifndef _EXPORT_TXT_H_
#define _EXPORT_TXT_H_
#include <QObject>
#include "StandardDatabase.h"
class Export_Txt:public QObject{
public:
bool exportFile(const QString& filename,StandardDatabase* db,QString& err);
#include <QObject>
#include "IExport.h"
class Export_Txt:public QObject, public IExport{
public:
virtual QString exportDatabase(QWidget* GuiParent, IDatabase* Database, QIODevice* Dest);
virtual QString name(){return QString("Txt");}
};
#endif

@ -77,9 +77,6 @@
<property name="rootIsDecorated" >
<bool>false</bool>
</property>
<property name="sortingEnabled" >
<bool>true</bool>
</property>
</widget>
</widget>
</item>

@ -62,7 +62,7 @@
<enum>QTabWidget::Rounded</enum>
</property>
<property name="currentIndex" >
<number>3</number>
<number>4</number>
</property>
<widget class="QWidget" name="tab" >
<attribute name="title" >
@ -915,6 +915,13 @@
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="checkBox_VerifyAfterSaving" >
<property name="text" >
<string>Verify database content and structure after saving</string>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >

@ -1,6 +1,6 @@
/***************************************************************************
* Copyright (C) 2005 by Tarek Saidi *
* mail@tarek-saidi.de *
* Copyright (C) 2007 by Tarek Saidi *
* tarek.saidi@arcor.de *
* *
* 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 *
@ -17,6 +17,7 @@
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef _IMPORT_KWALLET_H_
#define _IMPORT_KWALLET_H_
#include <qstring.h>

@ -47,9 +47,11 @@ KeepassEntryView::KeepassEntryView(QWidget* parent):QTreeWidget(parent){
updateColumns();
header()->setResizeMode(QHeaderView::Interactive);
header()->setStretchLastSection(false);
header()->setClickable(true);
connect(header(),SIGNAL(sectionResized(int,int,int)),this,SLOT(OnColumnResized(int,int,int)));
connect(this,SIGNAL(itemSelectionChanged()),this,SLOT(OnItemsChanged()));
connect(&ClipboardTimer, SIGNAL(timeout()), this, SLOT(OnClipboardTimeOut()));
connect(header(),SIGNAL(sectionClicked(int)),this,SLOT(OnHeaderSectionClicked(int)));
Clipboard=QApplication::clipboard();
ContextMenu=new QMenu(this);
setAlternatingRowColors(config.AlternatingRowColors);
@ -82,6 +84,22 @@ void KeepassEntryView::OnItemsChanged(){
}
}
void KeepassEntryView::OnHeaderSectionClicked(int index){
if(header()->isSortIndicatorShown() && header()->sortIndicatorSection()==index){
header()->setSortIndicator(index,header()->sortIndicatorOrder() ? Qt::DescendingOrder : Qt::AscendingOrder);
sortItems(index,header()->sortIndicatorOrder());
}
else{
header()->setSortIndicator(index,Qt::AscendingOrder);
header()->setSortIndicatorShown(true);
sortItems(index,Qt::AscendingOrder);
}
for(int i=0;i<Items.size();i++){
Items[i]->EntryHandle->setVisualIndexDirectly(indexOfTopLevelItem(Items[i]));
}
}
void KeepassEntryView::OnSaveAttachment(){
Q_ASSERT(selectedItems().size()==1);
CEditEntryDlg::saveAttachment(((EntryViewItem*)selectedItems()[0])->EntryHandle,this);
@ -268,7 +286,8 @@ void KeepassEntryView::showGroup(IGroupHandle* group){
createItems(entries);
}
void KeepassEntryView::createItems(QList<IEntryHandle*>& entries){
void KeepassEntryView::createItems(QList<IEntryHandle*>& entries){
header()->setSortIndicatorShown(false);
for(int i=0;i<entries.size();i++){
if(!entries[i]->isValid())continue;
EntryViewItem* item=new EntryViewItem(this);
@ -304,6 +323,7 @@ void KeepassEntryView::createItems(QList<IEntryHandle*>& entries){
if(config.Columns[9]){
item->setText(j++,entries[i]->binaryDesc());}
Items.back()->setIcon(0,db->icon(entries[i]->image()));
qDebug("%s : %i",entries[i]->title().toUtf8().data(),entries[i]->visualIndex());
}
}

@ -70,6 +70,7 @@ class KeepassEntryView:public QTreeWidget{
virtual void mouseMoveEvent(QMouseEvent *event);
public slots:
void OnColumnResized(int index,int OldSize, int NewSize);
void OnHeaderSectionClicked(int index);
void OnGroupChanged(IGroupHandle* group);
void OnShowSearchResults();
void OnEntryActivated(QTreeWidgetItem*,int);

@ -1,5 +1,5 @@
/***************************************************************************
* Copyright (C) 2005-2006 by Tarek Saidi *
* Copyright (C) 2005-2007 by Tarek Saidi *
* tarek.saidi@arcor.de *
* *
* This program is free software; you can redistribute it and/or modify *
@ -18,11 +18,15 @@
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "FileDialogs.h"
#include <QDir>
#include <QSettings>
#include "main.h"
#include "FileDialogs.h"
IFileDialog* KpxFileDialogs::iFileDialog=NULL;
QtStandardFileDialogs DefaultQtDlgs;
FileDlgHistory fileDlgHistory;
void KpxFileDialogs::setPlugin(IFileDialog* plugin){
iFileDialog=plugin;
@ -30,26 +34,37 @@ void KpxFileDialogs::setPlugin(IFileDialog* plugin){
QString KpxFileDialogs::openExistingFile(QWidget* Parent, const QString& Name, const QString& Title,const QStringList& Filters,const QString& Dir)
{
QString dir;
if(iFileDialog==NULL)iFileDialog=dynamic_cast<IFileDialog*>(&DefaultQtDlgs);
//Load History here!
return iFileDialog->openExistingFileDialog(Parent,Title,QDir::homePath(),Filters);
if(Dir==QString()) dir=fileDlgHistory.getDir(Name);
else dir=Dir;
QString result = iFileDialog->openExistingFileDialog(Parent,Title,dir,Filters);
if(result!=QString()){
fileDlgHistory.set(Name,result.left(result.lastIndexOf("/")+1),iFileDialog->getLastFilter());
}
return result;
}
QStringList KpxFileDialogs::openExistingFiles(QWidget* Parent, const QString& Name, const QString& Title,const QStringList& Filters,const QString& Dir)
{
if(iFileDialog==NULL)iFileDialog=dynamic_cast<IFileDialog*>(&DefaultQtDlgs);
//Load History here!
return iFileDialog->openExistingFilesDialog(Parent,Title,QString(),Filters);
QStringList results=iFileDialog->openExistingFilesDialog(Parent,Title,QString(),Filters);
if(results.size()){
fileDlgHistory.set(Name,results[0].left(results[0].lastIndexOf("/")+1),iFileDialog->getLastFilter());
}
return results;
}
QString KpxFileDialogs::saveFile(QWidget* Parent, const QString& Name, const QString& Title,const QStringList& Filters,bool OverWriteWarn, const QString& Dir)
{
if(iFileDialog==NULL)iFileDialog=dynamic_cast<IFileDialog*>(&DefaultQtDlgs);
//Load History here!
return iFileDialog->saveFileDialog(Parent,Title,QString(),Filters,OverWriteWarn);
QString result = iFileDialog->saveFileDialog(Parent,Title,QString(),Filters,OverWriteWarn);
if(result!=QString()){
fileDlgHistory.set(Name,result.left(result.lastIndexOf("/")+1),iFileDialog->getLastFilter());
}
return result;
}
QString QtStandardFileDialogs::openExistingFileDialog(QWidget* parent,QString title,QString dir,QStringList Filters){
@ -58,6 +73,7 @@ QString QtStandardFileDialogs::openExistingFileDialog(QWidget* parent,QString ti
FileDlg.setFileMode(QFileDialog::ExistingFile);
if(!FileDlg.exec())return QString();
if(!FileDlg.selectedFiles().size())return QString();
LastFilter=FileDlg.filters().indexOf(FileDlg.selectedFilter());
return FileDlg.selectedFiles()[0];
}
@ -66,6 +82,7 @@ QStringList QtStandardFileDialogs::openExistingFilesDialog(QWidget* parent,QStri
FileDlg.setFilters(Filters);
FileDlg.setFileMode(QFileDialog::ExistingFiles);
if(!FileDlg.exec())return QStringList();
LastFilter=FileDlg.filters().indexOf(FileDlg.selectedFilter());
return FileDlg.selectedFiles();
}
@ -76,7 +93,65 @@ QString QtStandardFileDialogs::saveFileDialog(QWidget* parent,QString title,QStr
FileDlg.setAcceptMode(QFileDialog::AcceptSave);
FileDlg.setConfirmOverwrite(ShowOverwriteWarning);
if(!FileDlg.exec())return QString();
LastFilter=FileDlg.filters().indexOf(FileDlg.selectedFilter());
return FileDlg.selectedFiles()[0];
}
int QtStandardFileDialogs::getLastFilter(){
return LastFilter;
}
QString FileDlgHistory::getDir(const QString& name){
Entry e=History.value(name);
if(e.isNull())
return QDir::homePath();
else
return e.Dir;
}
int FileDlgHistory::getFilter(const QString& name){
Entry e=History.value(name);
if(e.isNull())
return 0;
else
return e.Filter;
}
void FileDlgHistory::set(const QString& name,const QString& dir, int filter){
History[name]=Entry();
History[name].Dir=dir;
History[name].Filter=filter;
}
void FileDlgHistory::save(){
if(settings->value("General/SaveFileDlgHistory",QVariant(true)).toBool()){
settings->beginGroup("FileDlgHistory");
for(int i=0;i<History.size();i++){
QStringList entry;
entry << History.keys()[i]
<< History.values()[i].Dir
<< QString::number(History.values()[i].Filter);
settings->setValue(QString("ENTRY%1").arg(i),QVariant(entry));
}
settings->endGroup();
}
}
void FileDlgHistory::load(){
if(settings->value("General/SaveFileDlgHistory",QVariant(true)).toBool()){
settings->beginGroup("FileDlgHistory");
QStringList keys=settings->childKeys();
for(int i=0;i<keys.size();i++){
Entry entry;
QStringList value=settings->value(QString("ENTRY%1").arg(i)).toStringList();
entry.Dir=value[1];
entry.Filter=value[2].toInt();
History[value[0]]=entry;
}
settings->endGroup();
}
else{
settings->remove("FileDlgHistory");
}
}

@ -1,5 +1,5 @@
/***************************************************************************
* Copyright (C) 2005-2006 by Tarek Saidi *
* Copyright (C) 2005-2007 by Tarek Saidi *
* tarek.saidi@arcor.de *
* *
* This program is free software; you can redistribute it and/or modify *
@ -23,27 +23,31 @@
#include <QObject>
#include <QFileDialog>
#include <QList>
#include <QHash>
#include "plugins/interfaces/IFileDialog.h"
/*
class FileDlgHistory{
class HistoryEntry{
public:
QString DlgId;
QString Dir;
int Filter;
QString toString();
void fromString(const QString& str);
};
public:
void set(const QString& DlgId,const QString& Dir,int Filter);
int getFilter(const QString& DlgId);
QString getDir(const QString& DlgId);
void clear();
QString getDir(const QString& name);
int getFilter(const QString& name);
void set(const QString& name,const QString& dir,int filter);
void save();
void load();
private:
QList
class Entry{
public:
Entry(){Filter=-1;}
QString Dir;
int Filter;
bool isNull(){if(Filter==-1)return true;
else return false;}
};
QHash<QString,Entry>History;
};
*/
class KpxFileDialogs{
public:
@ -71,14 +75,17 @@ class KpxFileDialogs{
class QtStandardFileDialogs:public QObject,public IFileDialog{
Q_OBJECT
public:
QString openExistingFileDialog(QWidget* parent,QString title,QString dir,QStringList Filters);
QStringList openExistingFilesDialog(QWidget* parent,QString title,QString dir,QStringList Filters);
QString saveFileDialog(QWidget* parent,QString title,QString dir,QStringList Filters,bool ShowOverwriteWarning);
Q_OBJECT
public:
QString openExistingFileDialog(QWidget* parent,QString title,QString dir,QStringList Filters);
QStringList openExistingFilesDialog(QWidget* parent,QString title,QString dir,QStringList Filters);
QString saveFileDialog(QWidget* parent,QString title,QString dir,QStringList Filters,bool ShowOverwriteWarning);
int getLastFilter();
private:
int LastFilter;
};
extern FileDlgHistory fileDlgHistory;
#endif

@ -1,5 +1,5 @@
/***************************************************************************
* Copyright (C) 2005 by Tarek Saidi *
* Copyright (C) 2005-2007 by Tarek Saidi *
* tarek.saidi@arcor.de *
* *
* This program is free software; you can redistribute it and/or modify *
@ -46,8 +46,8 @@ KeepassGroupView::KeepassGroupView(QWidget* parent):QTreeWidget(parent){
ContextMenu=new QMenu(this);
ContextMenuSearchGroup=new QMenu(this);
connect(this,SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),this,SLOT(OnCurrentGroupChanged(QTreeWidgetItem*,QTreeWidgetItem*)));
// connect(this,SIGNAL(itemExpanded(QTreeWidgetItem*)),this,SLOT(OnItemExpanded(QTreeWidgetItem*)));
// connect(this,SIGNAL(itemCollapsed(QTreeWidgetItem*)),this,SLOT(OnItemCollapsed(QTreeWidgetItem*)));
connect(this,SIGNAL(itemExpanded(QTreeWidgetItem*)),this,SLOT(OnItemExpanded(QTreeWidgetItem*)));
connect(this,SIGNAL(itemCollapsed(QTreeWidgetItem*)),this,SLOT(OnItemCollapsed(QTreeWidgetItem*)));
}
@ -59,12 +59,13 @@ void KeepassGroupView::createItems(){
if(groups[i]->parent()==NULL){
Items.append(new GroupViewItem(this));
Items.back()->setText(0,groups[i]->title());
Items.back()->GroupHandle=groups[i];
Items.back()->GroupHandle=groups[i];
addChilds(Items.back());
}
}
for(int i=0;i<Items.size();i++){
Items[i]->setIcon(0,db->icon(Items[i]->GroupHandle->image()));
Items[i]->setExpanded(Items[i]->GroupHandle->expanded());
}
SearchResultItem=new GroupViewItem();
SearchResultItem->setText(0,tr("Search Results"));
@ -398,6 +399,14 @@ void KeepassGroupView::mouseMoveEvent(QMouseEvent *event){
Qt::DropAction dropAction = drag->start(Qt::MoveAction);
}
void KeepassGroupView::OnItemExpanded(QTreeWidgetItem* item){
dynamic_cast<GroupViewItem*>(item)->GroupHandle->setExpanded(true);
}
void KeepassGroupView::OnItemCollapsed(QTreeWidgetItem* item){
dynamic_cast<GroupViewItem*>(item)->GroupHandle->setExpanded(false);
}
GroupViewItem::GroupViewItem():QTreeWidgetItem(){

@ -62,8 +62,8 @@ class KeepassGroupView:public QTreeWidget{
void OnEditGroup();
void updateIcons();
void OnHideSearchResults();
// void OnItemExpanded(QTreeWidgetItem*);
// void OnItemCollapsed(QTreeWidgetItem*);
void OnItemExpanded(QTreeWidgetItem*);
void OnItemCollapsed(QTreeWidgetItem*);
signals:
void groupChanged(IGroupHandle* NewGroup);

@ -1,6 +1,6 @@
/***************************************************************************
* Copyright (C) 2005-2006 by Tarek Saidi *
* tarek@linux *
* Copyright (C) 2005-2007 by Tarek Saidi *
* tarek.saidi@arcor.de *
* *
* 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 *
@ -38,6 +38,7 @@
#include "lib/FileDialogs.h"
#include "main.h"
#include "lib/FileDialogs.h"
#include "PwmConfig.h"
#include "StandardDatabase.h"
#include "mainwindow.h"
@ -56,6 +57,7 @@ using namespace std;
#define CSTR(x)(x.toUtf8().data())
CConfig config;
QSettings* settings;
QString AppDir;
QString PluginLoadError;
bool TrActive;
@ -113,6 +115,9 @@ int main(int argc, char **argv)
config.loadFromIni(IniFilename);}
settings = new QSettings(QDir::homePath()+"/.keepassx/config",QSettings::IniFormat);
fileDlgHistory.load();