First commit for 0.2.3, some old functions still need to be ported to the new back-end api, i.e. import and export.
git-svn-id: https://svn.code.sf.net/p/keepassx/code/trunk@104 b624d157-de02-0410-bad0-e51aec6abb33
This commit is contained in:
@@ -42,7 +42,7 @@ typedef struct tKeysymMap{
|
||||
class AutoType:public QObject{
|
||||
public:
|
||||
static QWidget* MainWin;
|
||||
static void perform(CEntry* entry,QString& errors);
|
||||
static void perform(IEntryHandle* entry,QString& errors);
|
||||
private:
|
||||
#ifdef Q_WS_X11
|
||||
static tKeysymMap KeysymMap[];
|
||||
@@ -50,7 +50,7 @@ private:
|
||||
static int getModifiers(Display*,KeySym,int);
|
||||
static void pressModifiers(Display*,int,bool Press=true);
|
||||
static void releaseModifiers(Display*,int);
|
||||
static void templateToKeysyms(const QString& Template, QList<quint16>& KeySymList,CEntry* entry);
|
||||
static void templateToKeysyms(const QString& Template, QList<quint16>& KeySymList,IEntryHandle* entry);
|
||||
static void stringToKeysyms(const QString& string,QList<quint16>& KeySymList);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -23,9 +23,9 @@
|
||||
|
||||
QWidget* AutoType::MainWin=NULL;
|
||||
|
||||
void AutoType::perform(CEntry* entry, QString& err){
|
||||
void AutoType::perform(IEntryHandle* entry, QString& err){
|
||||
QString str;
|
||||
QMessageBox::warning(NULL,tr("Error"),"This feature is not available under Windows");
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,26 +65,28 @@ switch(mods){
|
||||
}
|
||||
|
||||
|
||||
void AutoType::perform(CEntry* entry, QString& err){
|
||||
void AutoType::perform(IEntryHandle* entry, QString& err){
|
||||
struct timespec timeOut,remains;
|
||||
timeOut.tv_sec = 0;
|
||||
timeOut.tv_nsec = 300000000; /* 300 milliseconds */
|
||||
timeOut.tv_nsec = 30000000; /* 300 milliseconds */
|
||||
for(int i=0;i<10;i++)nanosleep(&timeOut, &remains);
|
||||
|
||||
QString str;
|
||||
int c=entry->Additional.count("Auto-Type:");
|
||||
QString comment=entry->comment();
|
||||
int c=comment.count("Auto-Type:");
|
||||
if(c>1){
|
||||
err=tr("More than one 'Auto-Type:' key sequence found.\nAllowed is only one per entry.");
|
||||
return;}
|
||||
if(c==1){
|
||||
int start=entry->Additional.indexOf("Auto-Type:")+10;
|
||||
int start=comment.indexOf("Auto-Type:")+10;
|
||||
int len;
|
||||
if(entry->Additional.size()==10)return;
|
||||
for(len=0;len<entry->Additional.size();len++){
|
||||
if(entry->Additional.size()==(start+len))break;
|
||||
if(entry->Additional.at(start+len)==QChar('\n'))break;}
|
||||
if(comment.size()==10)return;
|
||||
for(len=0;len<comment.size();len++){
|
||||
if(comment.size()==(start+len))break;
|
||||
if(comment.at(start+len)==QChar('\n'))break;
|
||||
}
|
||||
if(!len)return;
|
||||
str=entry->Additional.mid(start,len);
|
||||
str=comment.mid(start,len);
|
||||
}
|
||||
else
|
||||
str="{USERNAME}{TAB}{PASSWORD}{ENTER}";
|
||||
@@ -125,21 +127,21 @@ XCloseDisplay(pDisplay);
|
||||
MainWin->show();
|
||||
}
|
||||
|
||||
void AutoType::templateToKeysyms(const QString& tmpl, QList<quint16>& keys,CEntry* entry){
|
||||
void AutoType::templateToKeysyms(const QString& tmpl, QList<quint16>& keys,IEntryHandle* entry){
|
||||
//tmpl must be lower case!!!
|
||||
if(!tmpl.compare("title")){
|
||||
stringToKeysyms(entry->Title,keys);
|
||||
stringToKeysyms(entry->title(),keys);
|
||||
return;}
|
||||
if(!tmpl.compare("username")){
|
||||
stringToKeysyms(entry->UserName,keys);
|
||||
stringToKeysyms(entry->username(),keys);
|
||||
return;}
|
||||
if(!tmpl.compare("url")){
|
||||
stringToKeysyms(entry->URL,keys);
|
||||
stringToKeysyms(entry->url(),keys);
|
||||
return;}
|
||||
if(!tmpl.compare("password")){
|
||||
entry->Password.unlock();
|
||||
stringToKeysyms(entry->Password.string(),keys);
|
||||
entry->Password.lock();
|
||||
SecString password=entry->password();
|
||||
password.unlock();
|
||||
stringToKeysyms(password,keys);
|
||||
return;
|
||||
}
|
||||
if(!tmpl.compare("space")){
|
||||
@@ -1163,7 +1165,7 @@ return 0;
|
||||
|
||||
#ifdef Q_WS_MAC
|
||||
#include <QMessageBox>
|
||||
void AutoType::perform(CEntry* entry, QString& err){
|
||||
void AutoType::perform(IEntryHandle* entry, QString& err){
|
||||
QMessageBox::warning(NULL,"AutoType","Sorry, but Auto-Type does not work under Mac OS X yet.","OK");
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -32,148 +32,297 @@
|
||||
#include "main.h"
|
||||
#include "PwmConfig.h"
|
||||
#include "EntryView.h"
|
||||
#include "dialogs/EditEntryDlg.h"
|
||||
#include "lib/AutoType.h"
|
||||
|
||||
|
||||
|
||||
KeepassEntryView::KeepassEntryView(QWidget* parent):QTreeWidget(parent){
|
||||
AutoResizeColumns=true;
|
||||
IsSearchGroup=false;
|
||||
int sum=0;
|
||||
for(int i=0;i<NUM_COLUMNS;i++)
|
||||
sum+=config.ColumnSizes[i];
|
||||
for(int i=0;i<NUM_COLUMNS;i++)
|
||||
ColumnSizes << (float)config.ColumnSizes[i]/(float)sum;
|
||||
|
||||
CurrentGroup=0;
|
||||
updateColumns();
|
||||
header()->setResizeMode(QHeaderView::Interactive);
|
||||
header()->setStretchLastSection(false);
|
||||
connect(header(),SIGNAL(sectionResized(int,int,int)),this,SLOT(OnColumnResized(int,int,int)));
|
||||
ContextMenu=new QMenu(this);
|
||||
setAlternatingRowColors(config.AlternatingRowColors);
|
||||
|
||||
|
||||
AutoResizeColumns=true;
|
||||
int sum=0;
|
||||
for(int i=0;i<NUM_COLUMNS;i++)
|
||||
sum+=config.ColumnSizes[i];
|
||||
for(int i=0;i<NUM_COLUMNS;i++)
|
||||
ColumnSizes << (float)config.ColumnSizes[i]/(float)sum;
|
||||
updateColumns();
|
||||
header()->setResizeMode(QHeaderView::Interactive);
|
||||
header()->setStretchLastSection(false);
|
||||
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()));
|
||||
Clipboard=QApplication::clipboard();
|
||||
ContextMenu=new QMenu(this);
|
||||
setAlternatingRowColors(config.AlternatingRowColors);
|
||||
}
|
||||
|
||||
KeepassEntryView::~KeepassEntryView(){
|
||||
for(int i=0;i<ColumnSizes.size();i++){
|
||||
config.ColumnSizes[i]=(int)(ColumnSizes[i]*10000.0f);
|
||||
for(int i=0;i<ColumnSizes.size();i++){
|
||||
config.ColumnSizes[i]=(int)(ColumnSizes[i]*10000.0f);
|
||||
}
|
||||
}
|
||||
|
||||
void KeepassEntryView::OnGroupChanged(IGroupHandle* group){
|
||||
CurrentGroup=group;
|
||||
showGroup(group);
|
||||
}
|
||||
|
||||
void KeepassEntryView::OnShowSearchResults(){
|
||||
CurrentGroup=NULL;
|
||||
showSearchResults();
|
||||
}
|
||||
|
||||
|
||||
void KeepassEntryView::OnItemsChanged(){
|
||||
switch(selectedItems().size()){
|
||||
case 0: emit selectionChanged(NONE);
|
||||
break;
|
||||
case 1: emit selectionChanged(SINGLE);
|
||||
break;
|
||||
default:emit selectionChanged(MULTIPLE);
|
||||
}
|
||||
}
|
||||
|
||||
void KeepassEntryView::OnSaveAttachment(){
|
||||
Q_ASSERT(selectedItems().size()==1);
|
||||
CEditEntryDlg::saveAttachment(((EntryViewItem*)selectedItems()[0])->EntryHandle,this);
|
||||
}
|
||||
|
||||
void KeepassEntryView::OnCloneEntry(){
|
||||
QList<QTreeWidgetItem*> entries=selectedItems();
|
||||
for(int i=0; i<entries.size();i++){
|
||||
Items.append(new EntryViewItem(this));
|
||||
Items.back()->EntryHandle=
|
||||
db->cloneEntry(((EntryViewItem*)entries[i])->EntryHandle);
|
||||
updateEntry(Items.back());
|
||||
}
|
||||
emit fileModified();
|
||||
}
|
||||
|
||||
void KeepassEntryView::OnDeleteEntry(){
|
||||
QList<QTreeWidgetItem*> entries=selectedItems();
|
||||
for(int i=0; i<entries.size();i++){
|
||||
db->deleteEntry(((EntryViewItem*)entries[i])->EntryHandle);
|
||||
Items.removeAt(Items.indexOf((EntryViewItem*)entries[i]));
|
||||
delete entries[i];
|
||||
}
|
||||
emit fileModified();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void KeepassEntryView::updateEntry(EntryViewItem* item){
|
||||
IEntryHandle* entry = item->EntryHandle;
|
||||
int j=0;
|
||||
if(config.Columns[0])item->setText(j++,entry->title());
|
||||
if(config.Columns[1]){
|
||||
if(config.ListView_HideUsernames)
|
||||
item->setText(j++,"******");
|
||||
else
|
||||
item->setText(j++,entry->username());}
|
||||
if(config.Columns[2]){item->setText(j++,entry->url());}
|
||||
if(config.Columns[3]){
|
||||
if(config.ListView_HidePasswords)
|
||||
item->setText(j++,"******");
|
||||
else{
|
||||
SecString password=entry->password();
|
||||
password.unlock();
|
||||
item->setText(j++,password.string());
|
||||
}
|
||||
}
|
||||
if(config.Columns[4]){
|
||||
item->setText(j++,entry->comment().section('\n',0,0));}
|
||||
if(config.Columns[5]){
|
||||
item->setText(j++,entry->expire().dateToString(Qt::LocalDate));}
|
||||
if(config.Columns[6]){
|
||||
item->setText(j++,entry->creation().dateToString(Qt::LocalDate));}
|
||||
if(config.Columns[7]){
|
||||
item->setText(j++,entry->lastMod().dateToString(Qt::LocalDate));}
|
||||
if(config.Columns[8]){
|
||||
item->setText(j++,entry->lastAccess().dateToString(Qt::LocalDate));}
|
||||
if(config.Columns[9]){
|
||||
item->setText(j++,entry->binaryDesc());}
|
||||
item->setIcon(0,db->icon(entry->image()));
|
||||
}
|
||||
|
||||
void KeepassEntryView::editEntry(EntryViewItem* item){
|
||||
CEditEntryDlg dlg(db,item->EntryHandle,this,true);
|
||||
switch(dlg.exec()){
|
||||
case 0: //canceled or no changes
|
||||
break;
|
||||
case 1: //modifications but same group
|
||||
updateEntry(item);
|
||||
emit fileModified();
|
||||
break;
|
||||
case 2: //entry moved to another group
|
||||
delete item;
|
||||
Items.removeAt(Items.indexOf(item));
|
||||
emit fileModified();
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void KeepassEntryView::OnNewEntry(){
|
||||
IEntryHandle* NewEntry=db->newEntry(CurrentGroup);
|
||||
CEditEntryDlg dlg(db,NewEntry,this,true);
|
||||
if(!dlg.exec()){
|
||||
db->deleteLastEntry();
|
||||
}
|
||||
else{
|
||||
Items.append(new EntryViewItem(this));
|
||||
Items.back()->EntryHandle=NewEntry;
|
||||
updateEntry(Items.back());
|
||||
emit fileModified();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void KeepassEntryView::OnEntryActivated(QTreeWidgetItem* item,int Column){
|
||||
int i=0;
|
||||
int c=-1;
|
||||
for(i;i<NUM_COLUMNS;i++){
|
||||
if(config.Columns[i])c++;
|
||||
if(c==Column)break;
|
||||
}
|
||||
if(c==-1)return;
|
||||
switch(i){
|
||||
case 0: editEntry((EntryViewItem*)item);
|
||||
break;
|
||||
case 1: OnUsernameToClipboard();
|
||||
break;
|
||||
case 2: //OnEditOpenUrl();
|
||||
break;
|
||||
case 3: OnPasswordToClipboard();
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void KeepassEntryView::OnEditEntry(){
|
||||
Q_ASSERT(selectedItems().size()==1);
|
||||
editEntry((EntryViewItem*)selectedItems()[0]);
|
||||
}
|
||||
|
||||
void KeepassEntryView::OnUsernameToClipboard(){
|
||||
Clipboard->setText(((EntryViewItem*)selectedItems()[0])->EntryHandle->username(), QClipboard::Clipboard);
|
||||
ClipboardTimer.setSingleShot(true);
|
||||
ClipboardTimer.start(config.ClipboardTimeOut*1000);
|
||||
}
|
||||
|
||||
void KeepassEntryView::OnPasswordToClipboard(){
|
||||
SecString password;
|
||||
password=((EntryViewItem*)selectedItems()[0])->EntryHandle->password();
|
||||
password.unlock();
|
||||
Clipboard->setText(password.string(),QClipboard::Clipboard);
|
||||
ClipboardTimer.setSingleShot(true);
|
||||
ClipboardTimer.start(config.ClipboardTimeOut*1000);
|
||||
}
|
||||
|
||||
void KeepassEntryView::OnClipboardTimeOut(){
|
||||
Clipboard->clear(QClipboard::Clipboard);
|
||||
}
|
||||
|
||||
|
||||
void KeepassEntryView::contextMenuEvent(QContextMenuEvent* e){
|
||||
if(itemAt(e->pos())){
|
||||
EntryViewItem* item=(EntryViewItem*)itemAt(e->pos());
|
||||
if(selectedItems().size()==0){
|
||||
setItemSelected(item,true);}
|
||||
else{
|
||||
bool AlreadySelected=false;
|
||||
for(int i=0;i<selectedItems().size();i++){
|
||||
if(selectedItems()[i]==item){AlreadySelected=true; break;}
|
||||
}
|
||||
if(!AlreadySelected){
|
||||
while(selectedItems().size()){
|
||||
setItemSelected(selectedItems()[0],false);
|
||||
}
|
||||
if(itemAt(e->pos())){
|
||||
EntryViewItem* item=(EntryViewItem*)itemAt(e->pos());
|
||||
if(selectedItems().size()==0){
|
||||
setItemSelected(item,true);
|
||||
}
|
||||
else{
|
||||
if(!isItemSelected(item)){
|
||||
while(selectedItems().size()){
|
||||
setItemSelected(selectedItems()[0],false);
|
||||
}
|
||||
setItemSelected(item,true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{while(selectedItems().size()){
|
||||
setItemSelected(selectedItems()[0],false);}
|
||||
}
|
||||
|
||||
e->accept();
|
||||
ContextMenu->popup(e->globalPos());
|
||||
else
|
||||
{while(selectedItems().size()){
|
||||
setItemSelected(selectedItems()[0],false);}
|
||||
}
|
||||
e->accept();
|
||||
ContextMenu->popup(e->globalPos());
|
||||
}
|
||||
|
||||
void KeepassEntryView::resizeEvent(QResizeEvent* e){
|
||||
resizeColumns();
|
||||
e->accept();
|
||||
}
|
||||
|
||||
void KeepassEntryView::updateItems(){
|
||||
updateItems(CurrentGroup);
|
||||
resizeColumns();
|
||||
e->accept();
|
||||
}
|
||||
|
||||
|
||||
void KeepassEntryView::updateItems(unsigned int GroupID){
|
||||
QList<QTreeWidgetItem*> ItemSelec=selectedItems();
|
||||
QList<quint32> SelectionIDs;
|
||||
for(int i=0; i<ItemSelec.size(); i++)
|
||||
SelectionIDs << ((EntryViewItem*)ItemSelec[i])->pEntry->sID;
|
||||
IsSearchGroup=false;
|
||||
clear();
|
||||
Items.clear();
|
||||
if(!db)return;
|
||||
if(!GroupID)return;
|
||||
CurrentGroup=GroupID;
|
||||
for(int i=0;i<db->numEntries();i++){
|
||||
if(db->entry(i).GroupID==GroupID)
|
||||
setEntry(&db->entry(i));
|
||||
void KeepassEntryView::showSearchResults(){
|
||||
clear();
|
||||
Items.clear();
|
||||
createItems(SearchResults);
|
||||
}
|
||||
if(SelectionIDs.size())
|
||||
|
||||
|
||||
void KeepassEntryView::showGroup(IGroupHandle* group){
|
||||
clear();
|
||||
Items.clear();
|
||||
if(group==NULL)return;
|
||||
QList<IEntryHandle*>entries=db->entries(group);
|
||||
createItems(entries);
|
||||
}
|
||||
|
||||
void KeepassEntryView::createItems(QList<IEntryHandle*>& entries){
|
||||
for(int i=0;i<entries.size();i++){
|
||||
if(!entries[i]->isValid())continue;
|
||||
EntryViewItem* item=new EntryViewItem(this);
|
||||
Items.push_back(item);
|
||||
Items.back()->EntryHandle=entries[i];
|
||||
int j=0;
|
||||
if(config.Columns[0])item->setText(j++,entries[i]->title());
|
||||
if(config.Columns[1]){
|
||||
if(config.ListView_HideUsernames)
|
||||
item->setText(j++,"******");
|
||||
else
|
||||
item->setText(j++,entries[i]->username());}
|
||||
if(config.Columns[2]){item->setText(j++,entries[i]->url());}
|
||||
if(config.Columns[3]){
|
||||
if(config.ListView_HidePasswords)
|
||||
item->setText(j++,"******");
|
||||
else{
|
||||
SecString password=entries[i]->password();
|
||||
password.unlock();
|
||||
item->setText(j++,password.string());
|
||||
}
|
||||
}
|
||||
if(config.Columns[4]){
|
||||
item->setText(j++,entries[i]->comment().section('\n',0,0));}
|
||||
if(config.Columns[5]){
|
||||
item->setText(j++,entries[i]->expire().dateToString(Qt::LocalDate));}
|
||||
if(config.Columns[6]){
|
||||
item->setText(j++,entries[i]->creation().dateToString(Qt::LocalDate));}
|
||||
if(config.Columns[7]){
|
||||
item->setText(j++,entries[i]->lastMod().dateToString(Qt::LocalDate));}
|
||||
if(config.Columns[8]){
|
||||
item->setText(j++,entries[i]->lastAccess().dateToString(Qt::LocalDate));}
|
||||
if(config.Columns[9]){
|
||||
item->setText(j++,entries[i]->binaryDesc());}
|
||||
Items.back()->setIcon(0,db->icon(entries[i]->image()));
|
||||
}
|
||||
}
|
||||
|
||||
void KeepassEntryView::updateIcons(){
|
||||
for(int i=0;i<Items.size();i++){
|
||||
for(int j=0; j<SelectionIDs.size();j++){
|
||||
if(Items[i]->pEntry->sID==SelectionIDs[j]) setItemSelected(Items[i],true);}
|
||||
}
|
||||
Items[i]->setIcon(0,db->icon(Items[i]->EntryHandle->image()));
|
||||
}
|
||||
}
|
||||
|
||||
void KeepassEntryView::showSearchResults(QList<quint32>& results){
|
||||
IsSearchGroup=true;
|
||||
clear();
|
||||
Items.clear();
|
||||
for(int j=0; j<results.size(); j++){
|
||||
for(int i=0; i<db->numEntries();i++){
|
||||
if(db->entry(i).sID == results[j])
|
||||
setEntry(&db->entry(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KeepassEntryView::setEntry(CEntry* entry){
|
||||
EntryViewItem* tmp=NULL;
|
||||
Items.push_back(tmp=new EntryViewItem(this));
|
||||
Items.back()->pEntry=entry;
|
||||
int j=0;
|
||||
if(config.Columns[0]){
|
||||
tmp->setText(j++,entry->Title);}
|
||||
if(config.Columns[1]){
|
||||
if(config.ListView_HideUsernames)
|
||||
tmp->setText(j++,"******");
|
||||
else
|
||||
tmp->setText(j++,entry->UserName);}
|
||||
if(config.Columns[2]){
|
||||
tmp->setText(j++,entry->URL);}
|
||||
if(config.Columns[3]){
|
||||
if(config.ListView_HidePasswords)
|
||||
tmp->setText(j++,"******");
|
||||
else{
|
||||
entry->Password.unlock();
|
||||
tmp->setText(j++,entry->Password.string());
|
||||
entry->Password.lock();}}
|
||||
if(config.Columns[4]){
|
||||
tmp->setText(j++,entry->Additional.section('\n',0,0));}
|
||||
if(config.Columns[5]){
|
||||
tmp->setText(j++,entry->Expire.dateToString(Qt::LocalDate));}
|
||||
if(config.Columns[6]){
|
||||
tmp->setText(j++,entry->Creation.dateToString(Qt::LocalDate));}
|
||||
if(config.Columns[7]){
|
||||
tmp->setText(j++,entry->LastMod.dateToString(Qt::LocalDate));}
|
||||
if(config.Columns[8]){
|
||||
tmp->setText(j++,entry->LastAccess.dateToString(Qt::LocalDate));}
|
||||
if(config.Columns[9]){
|
||||
tmp->setText(j++,entry->BinaryDesc);}
|
||||
Items.back()->setIcon(0,db->icon(entry->ImageID));
|
||||
}
|
||||
void KeepassEntryView::setEntry(IEntryHandle* entry){
|
||||
|
||||
}
|
||||
/*
|
||||
void KeepassEntryView::refreshItems(){
|
||||
EntryViewItem *tmp=NULL;
|
||||
for(int i=0;i<Items.size();i++){
|
||||
tmp=Items[i];
|
||||
CEntry* entry=tmp->pEntry;
|
||||
IEntryHandle* entry=tmp->pEntry;
|
||||
|
||||
int j=0;
|
||||
if(config.Columns[0]){
|
||||
@@ -206,34 +355,34 @@ for(int i=0;i<Items.size();i++){
|
||||
tmp->setText(j++,entry->BinaryDesc);}
|
||||
tmp->setIcon(0,db->icon(entry->ImageID));
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
void KeepassEntryView::updateColumns(){
|
||||
setColumnCount(0);
|
||||
QStringList cols;
|
||||
if(config.Columns[0]){
|
||||
cols << tr("Title");}
|
||||
if(config.Columns[1]){
|
||||
cols << tr("Username");}
|
||||
if(config.Columns[2]){
|
||||
cols << tr("URL");}
|
||||
if(config.Columns[3]){
|
||||
cols << tr("Password");}
|
||||
if(config.Columns[4]){
|
||||
cols << tr("Comments");}
|
||||
if(config.Columns[5]){
|
||||
cols << tr("Expires");}
|
||||
if(config.Columns[6]){
|
||||
cols << tr("Creation");}
|
||||
if(config.Columns[7]){
|
||||
cols << tr("Last Change");}
|
||||
if(config.Columns[8]){
|
||||
cols << tr("Last Access");}
|
||||
if(config.Columns[9]){
|
||||
cols << tr("Attachment");}
|
||||
setHeaderLabels(cols);
|
||||
resizeColumns();
|
||||
setColumnCount(0);
|
||||
QStringList cols;
|
||||
if(config.Columns[0]){
|
||||
cols << tr("Title");}
|
||||
if(config.Columns[1]){
|
||||
cols << tr("Username");}
|
||||
if(config.Columns[2]){
|
||||
cols << tr("URL");}
|
||||
if(config.Columns[3]){
|
||||
cols << tr("Password");}
|
||||
if(config.Columns[4]){
|
||||
cols << tr("Comments");}
|
||||
if(config.Columns[5]){
|
||||
cols << tr("Expires");}
|
||||
if(config.Columns[6]){
|
||||
cols << tr("Creation");}
|
||||
if(config.Columns[7]){
|
||||
cols << tr("Last Change");}
|
||||
if(config.Columns[8]){
|
||||
cols << tr("Last Access");}
|
||||
if(config.Columns[9]){
|
||||
cols << tr("Attachment");}
|
||||
setHeaderLabels(cols);
|
||||
resizeColumns();
|
||||
}
|
||||
|
||||
void KeepassEntryView::resizeColumns(){
|
||||
@@ -315,6 +464,7 @@ QTreeWidget::mousePressEvent(event);
|
||||
}
|
||||
|
||||
void KeepassEntryView::mouseMoveEvent(QMouseEvent *event){
|
||||
/*
|
||||
if(IsSearchGroup)
|
||||
return;
|
||||
if (!(event->buttons() & Qt::LeftButton))
|
||||
@@ -365,8 +515,14 @@ mimeData->setData("keepass/entry",QByteArray((char*)&pDragItems,sizeof(void*)));
|
||||
drag->setMimeData(mimeData);
|
||||
drag->setPixmap(DragPixmap);
|
||||
drag->start();
|
||||
*/
|
||||
}
|
||||
|
||||
void KeepassEntryView::OnAutoType(){
|
||||
Q_ASSERT(selectedItems().size()==1);
|
||||
QString error;
|
||||
AutoType::perform(((EntryViewItem*)selectedItems()[0])->EntryHandle,error);
|
||||
}
|
||||
|
||||
void KeepassEntryView::paintEvent(QPaintEvent * event){
|
||||
QTreeWidget::paintEvent(event);
|
||||
@@ -391,30 +547,34 @@ EntryViewItem::EntryViewItem(QTreeWidgetItem *parent, QTreeWidgetItem *preceding
|
||||
|
||||
|
||||
bool EntryViewItem::operator<(const QTreeWidgetItem& other)const{
|
||||
int SortCol=treeWidget()->sortColumn();
|
||||
if(SortCol < 5 || SortCol==9){ //columns with string values (Title, Username, Password, URL, Comment)
|
||||
if(QString::localeAwareCompare(text(SortCol),other.text(SortCol)) < 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
QDateTime *DateThis;
|
||||
QDateTime *DateOther;
|
||||
|
||||
switch(SortCol){
|
||||
case 5: DateThis=&pEntry->Expire;
|
||||
DateOther=&((EntryViewItem&)other).pEntry->Expire;
|
||||
break;
|
||||
case 6: DateThis=&pEntry->Creation;
|
||||
DateOther=&((EntryViewItem&)other).pEntry->Creation;
|
||||
break;
|
||||
case 7: DateThis=&pEntry->LastMod;
|
||||
DateOther=&((EntryViewItem&)other).pEntry->LastMod;
|
||||
break;
|
||||
case 8: DateThis=&pEntry->LastAccess;
|
||||
DateOther=&((EntryViewItem&)other).pEntry->LastAccess;
|
||||
break;
|
||||
default:Q_ASSERT(false);
|
||||
}
|
||||
return *DateThis < *DateOther;
|
||||
int SortCol=treeWidget()->sortColumn();
|
||||
if(SortCol < 5 || SortCol==9){ //columns with string values (Title, Username, Password, URL, Comment)
|
||||
if(QString::localeAwareCompare(text(SortCol),other.text(SortCol)) < 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
QDateTime DateThis;
|
||||
QDateTime DateOther;
|
||||
|
||||
//@NICHTVERGESSEN
|
||||
return false;
|
||||
/*
|
||||
switch(SortCol){
|
||||
case 5: DateThis=&pEntry->Expire;
|
||||
DateOther=&((EntryViewItem&)other).pEntry->Expire;
|
||||
break;
|
||||
case 6: DateThis=&pEntry->Creation;
|
||||
DateOther=&((EntryViewItem&)other).pEntry->Creation;
|
||||
break;
|
||||
case 7: DateThis=&pEntry->LastMod;
|
||||
DateOther=&((EntryViewItem&)other).pEntry->LastMod;
|
||||
break;
|
||||
case 8: DateThis=&pEntry->LastAccess;
|
||||
DateOther=&((EntryViewItem&)other).pEntry->LastAccess;
|
||||
break;
|
||||
default:Q_ASSERT(false);
|
||||
}
|
||||
return DateThis < DateOther;
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -25,55 +25,79 @@
|
||||
#include <QTreeWidget>
|
||||
#include <QContextMenuEvent>
|
||||
#include <QHeaderView>
|
||||
#include "../PwManager.h"
|
||||
#include <QTimer>
|
||||
#include <QClipboard>
|
||||
#include "../StandardDatabase.h"
|
||||
|
||||
#define NUM_COLUMNS 10
|
||||
|
||||
class EntryViewItem;
|
||||
|
||||
enum SelectionState{NONE,SINGLE,MULTIPLE,SEARCHGROUP};
|
||||
|
||||
class KeepassEntryView:public QTreeWidget{
|
||||
Q_OBJECT
|
||||
public:
|
||||
KeepassEntryView(QWidget* parent=0);
|
||||
~KeepassEntryView();
|
||||
void updateItems(unsigned int group);
|
||||
void updateColumns();
|
||||
void refreshItems();
|
||||
void showSearchResults(QList<quint32>& results);
|
||||
Database* db;
|
||||
vector<EntryViewItem*>Items;
|
||||
QMenu *ContextMenu;
|
||||
private:
|
||||
void setEntry(CEntry* entry);
|
||||
int CurrentGroup;
|
||||
QList<float>ColumnSizes;
|
||||
void resizeColumns();
|
||||
bool AutoResizeColumns;
|
||||
QPoint DragStartPos;
|
||||
QList<QTreeWidgetItem*> DragItems;
|
||||
QPixmap DragPixmap;
|
||||
bool IsSearchGroup;
|
||||
protected:
|
||||
virtual void contextMenuEvent(QContextMenuEvent *event);
|
||||
virtual void paintEvent(QPaintEvent* event);
|
||||
virtual void resizeEvent(QResizeEvent* event);
|
||||
virtual void mousePressEvent(QMouseEvent *event);
|
||||
virtual void mouseMoveEvent(QMouseEvent *event);
|
||||
public slots:
|
||||
void OnColumnResized(int index,int OldSize, int NewSize);
|
||||
void updateItems();
|
||||
Q_OBJECT
|
||||
public:
|
||||
KeepassEntryView(QWidget* parent=0);
|
||||
~KeepassEntryView();
|
||||
void showSearchResults();
|
||||
void showGroup(IGroupHandle* group);
|
||||
void updateColumns();
|
||||
// void showSearchResults(QList<quint32>& results);
|
||||
IDatabase* db;
|
||||
QList<EntryViewItem*>Items;
|
||||
QList<IEntryHandle*> SearchResults;
|
||||
QMenu *ContextMenu;
|
||||
private:
|
||||
void setEntry(IEntryHandle* entry);
|
||||
void updateEntry(EntryViewItem*);
|
||||
void editEntry(EntryViewItem*);
|
||||
void createItems(QList<IEntryHandle*>& entries);
|
||||
|
||||
QClipboard* Clipboard;
|
||||
QTimer ClipboardTimer;
|
||||
QList<float>ColumnSizes;
|
||||
void resizeColumns();
|
||||
bool AutoResizeColumns;
|
||||
QPoint DragStartPos;
|
||||
QList<QTreeWidgetItem*> DragItems;
|
||||
QPixmap DragPixmap;
|
||||
IGroupHandle* CurrentGroup;
|
||||
|
||||
virtual void contextMenuEvent(QContextMenuEvent *event);
|
||||
virtual void paintEvent(QPaintEvent* event);
|
||||
virtual void resizeEvent(QResizeEvent* event);
|
||||
virtual void mousePressEvent(QMouseEvent *event);
|
||||
virtual void mouseMoveEvent(QMouseEvent *event);
|
||||
public slots:
|
||||
void OnColumnResized(int index,int OldSize, int NewSize);
|
||||
void OnGroupChanged(IGroupHandle* group);
|
||||
void OnShowSearchResults();
|
||||
void OnEntryActivated(QTreeWidgetItem*,int);
|
||||
void OnNewEntry();
|
||||
void OnItemsChanged();
|
||||
void updateIcons();
|
||||
void OnUsernameToClipboard();
|
||||
void OnPasswordToClipboard();
|
||||
void OnEditEntry();
|
||||
void OnClipboardTimeOut();
|
||||
void OnCloneEntry();
|
||||
void OnDeleteEntry();
|
||||
void OnSaveAttachment();
|
||||
void OnAutoType();
|
||||
signals:
|
||||
void fileModified();
|
||||
void selectionChanged(SelectionState);
|
||||
};
|
||||
|
||||
|
||||
class EntryViewItem:public QTreeWidgetItem{
|
||||
public:
|
||||
EntryViewItem(QTreeWidget *parent);
|
||||
EntryViewItem(QTreeWidget *parent, QTreeWidgetItem * preceding);
|
||||
EntryViewItem(QTreeWidgetItem *parent);
|
||||
EntryViewItem(QTreeWidgetItem *parent, QTreeWidgetItem * preceding);
|
||||
CEntry* pEntry;
|
||||
virtual bool operator<(const QTreeWidgetItem& other)const;
|
||||
public:
|
||||
EntryViewItem(QTreeWidget *parent);
|
||||
EntryViewItem(QTreeWidget *parent, QTreeWidgetItem * preceding);
|
||||
EntryViewItem(QTreeWidgetItem *parent);
|
||||
EntryViewItem(QTreeWidgetItem *parent, QTreeWidgetItem * preceding);
|
||||
IEntryHandle* EntryHandle;
|
||||
virtual bool operator<(const QTreeWidgetItem& other)const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -36,268 +36,371 @@
|
||||
#include "main.h"
|
||||
#include "EntryView.h"
|
||||
#include "GroupView.h"
|
||||
#include "dialogs/EditGroupDlg.h"
|
||||
#define INSERT_AREA_WIDTH 4
|
||||
|
||||
KeepassGroupView::KeepassGroupView(QWidget* parent):QTreeWidget(parent){
|
||||
InsertionMarker=QLine();
|
||||
db=NULL;
|
||||
LastHoverItem=NULL;
|
||||
setHeaderLabels(QStringList()<<tr("Groups"));
|
||||
ShowSearchGroup=false;
|
||||
ContextMenu=new QMenu(this);
|
||||
ContextMenuSearchGroup=new QMenu(this);
|
||||
|
||||
db=NULL;
|
||||
setHeaderLabels(QStringList()<<tr("Groups"));
|
||||
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*)));
|
||||
}
|
||||
|
||||
void KeepassGroupView::selectSearchGroup(){
|
||||
Q_ASSERT(ShowSearchGroup);
|
||||
setItemSelected(Items.back(),true);
|
||||
}
|
||||
|
||||
void KeepassGroupView:: dragEnterEvent ( QDragEnterEvent * event ){
|
||||
if(event->mimeData()->hasFormat("keepass/group")){
|
||||
DragType=GROUP;
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
if(event->mimeData()->hasFormat("keepass/entry")){
|
||||
DragType=ENTRY;
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void KeepassGroupView::dragMoveEvent( QDragMoveEvent * event ){
|
||||
GroupViewItem* item=(GroupViewItem*)itemAt(event->pos());
|
||||
if(LastHoverItem){
|
||||
QFont f=LastHoverItem->font(0);
|
||||
f.setBold(false);
|
||||
LastHoverItem->setFont(0,f);
|
||||
}
|
||||
|
||||
QLine LastMarker=InsertionMarker;
|
||||
InsertionMarker=QLine();
|
||||
if(isSearchResultGroup(item))
|
||||
event->setAccepted(false);
|
||||
else
|
||||
if(DragType==GROUP){
|
||||
if(item){
|
||||
QRect ItemRect=visualItemRect(item);
|
||||
if(!db->isParentGroup(item->pGroup,DragItem->pGroup) && DragItem!=item){
|
||||
if((ItemRect.height()+ItemRect.y())-event->pos().y() > INSERT_AREA_WIDTH && event->pos().y() > INSERT_AREA_WIDTH){
|
||||
QFont f=item->font(0);
|
||||
f.setBold(true);
|
||||
item->setFont(0,f);
|
||||
LastHoverItem=item;
|
||||
event->setAccepted(true);
|
||||
///@FIXME does not work for top level groups
|
||||
}
|
||||
else{
|
||||
LastHoverItem=NULL;
|
||||
if(event->pos().y() > INSERT_AREA_WIDTH)
|
||||
InsertionMarker=QLine(ItemRect.x(),ItemRect.y()+ItemRect.height()
|
||||
,ItemRect.x()+ItemRect.width(),ItemRect.y()+ItemRect.height());
|
||||
else
|
||||
InsertionMarker=QLine(ItemRect.x(),0,ItemRect.x()+ItemRect.width(),0);
|
||||
}
|
||||
void KeepassGroupView::createItems(){
|
||||
clear();
|
||||
Items.clear();
|
||||
QList<IGroupHandle*> groups=db->groups();
|
||||
for(int i=0;i<groups.size();i++){
|
||||
if(groups[i]->parent()==NULL){
|
||||
Items.append(new GroupViewItem(this));
|
||||
Items.back()->setText(0,groups[i]->title());
|
||||
Items.back()->GroupHandle=groups[i];
|
||||
addChilds(Items.back());
|
||||
}
|
||||
else
|
||||
event->setAccepted(false);
|
||||
}
|
||||
else
|
||||
LastHoverItem=NULL;
|
||||
}
|
||||
else{
|
||||
if(item){
|
||||
QFont f=item->font(0);
|
||||
f.setBold(true);
|
||||
item->setFont(0,f);
|
||||
LastHoverItem=item;
|
||||
event->setAccepted(true);
|
||||
for(int i=0;i<Items.size();i++){
|
||||
Items[i]->setIcon(0,db->icon(Items[i]->GroupHandle->image()));
|
||||
}
|
||||
else{
|
||||
event->setAccepted(false);
|
||||
LastHoverItem=NULL;
|
||||
}
|
||||
}
|
||||
if(!LastMarker.isNull()){
|
||||
///@FIXME
|
||||
//this is a very dirty work-around to force a redraw of items at the last marker position
|
||||
//should be replaced!!!
|
||||
GroupViewItem* i=(GroupViewItem*)itemAt(0,LastMarker.y1());
|
||||
if(i)i->setFont(0,i->font(0));
|
||||
i=(GroupViewItem*)itemAt(0,LastMarker.y1()-1);
|
||||
if(i)i->setFont(0,i->font(0));
|
||||
}
|
||||
update();
|
||||
SearchResultItem=new GroupViewItem();
|
||||
SearchResultItem->setText(0,tr("Search Results"));
|
||||
}
|
||||
|
||||
void KeepassGroupView:: dragLeaveEvent ( QDragLeaveEvent * event ){
|
||||
InsertionMarker=QLine();
|
||||
if(LastHoverItem){
|
||||
QFont f=LastHoverItem->font(0);
|
||||
f.setBold(false);
|
||||
LastHoverItem->setFont(0,f);
|
||||
void KeepassGroupView::updateIcons(){
|
||||
for(int i=0;i<Items.size();i++){
|
||||
Items[i]->setIcon(0,db->icon(Items[i]->GroupHandle->image()));
|
||||
}
|
||||
}
|
||||
update();
|
||||
|
||||
void KeepassGroupView::showSearchResults(){
|
||||
if(topLevelItem(topLevelItemCount()-1)!=SearchResultItem){
|
||||
addTopLevelItem(SearchResultItem);
|
||||
setCurrentItem(SearchResultItem);
|
||||
}
|
||||
emit searchResultsSelected();
|
||||
}
|
||||
|
||||
void KeepassGroupView::addChilds(GroupViewItem* item){
|
||||
QList<IGroupHandle*>childs=item->GroupHandle->childs();
|
||||
if(!childs.size())
|
||||
return;
|
||||
for(int i=0; i<childs.size(); i++){
|
||||
Items.push_back(new GroupViewItem(item));
|
||||
Items.back()->setText(0,childs[i]->title());
|
||||
Items.back()->GroupHandle=childs[i];
|
||||
addChilds(Items.back());
|
||||
}
|
||||
}
|
||||
|
||||
void KeepassGroupView::OnDeleteGroup(){
|
||||
GroupViewItem* item=(GroupViewItem*)currentItem();
|
||||
if(item){
|
||||
db->deleteGroup(item->GroupHandle);
|
||||
delete item;
|
||||
emit fileModified();
|
||||
}
|
||||
}
|
||||
|
||||
void KeepassGroupView::OnHideSearchResults(){
|
||||
takeTopLevelItem(topLevelItemCount()-1);
|
||||
}
|
||||
|
||||
void KeepassGroupView::OnNewGroup(){
|
||||
GroupViewItem* parent=(GroupViewItem*)currentItem();
|
||||
CGroup NewGroup;
|
||||
CEditGroupDialog dlg(db,&NewGroup,parentWidget(),true);
|
||||
if(dlg.exec()){
|
||||
IGroupHandle* group;
|
||||
if(parent){
|
||||
group=db->addGroup(&NewGroup,parent->GroupHandle);
|
||||
Items.append(new GroupViewItem(parent));
|
||||
}
|
||||
else{
|
||||
if(topLevelItemCount()){
|
||||
if(topLevelItem(topLevelItemCount()-1)==SearchResultItem)
|
||||
Items.append(new GroupViewItem(this,topLevelItem(topLevelItemCount()-2)));
|
||||
else
|
||||
Items.append(new GroupViewItem(this,topLevelItem(topLevelItemCount()-1)));
|
||||
}
|
||||
else
|
||||
Items.append(new GroupViewItem(this));
|
||||
group=db->addGroup(&NewGroup,NULL);
|
||||
}
|
||||
Items.back()->GroupHandle=group;
|
||||
Items.back()->setText(0,group->title());
|
||||
Items.back()->setIcon(0,db->icon(group->image()));
|
||||
}
|
||||
emit fileModified();
|
||||
}
|
||||
|
||||
void KeepassGroupView::OnEditGroup(){
|
||||
GroupViewItem* item=(GroupViewItem*)currentItem();
|
||||
CEditGroupDialog dlg(db,item->GroupHandle,parentWidget(),true);
|
||||
int r=dlg.exec();
|
||||
if(r){
|
||||
item->setIcon(0,db->icon(item->GroupHandle->image()));
|
||||
item->setText(0,item->GroupHandle->title());
|
||||
if(r==2)emit fileModified();
|
||||
}
|
||||
}
|
||||
|
||||
void KeepassGroupView::contextMenuEvent(QContextMenuEvent* e){
|
||||
if(!(GroupViewItem*)itemAt(e->pos()))
|
||||
setCurrentItem(NULL);
|
||||
e->accept();
|
||||
if(currentItem()==SearchResultItem)
|
||||
ContextMenuSearchGroup->popup(e->globalPos());
|
||||
else
|
||||
ContextMenu->popup(e->globalPos());
|
||||
}
|
||||
|
||||
void KeepassGroupView::OnCurrentGroupChanged(QTreeWidgetItem* cur,QTreeWidgetItem* prev){
|
||||
if(cur){
|
||||
if(cur==SearchResultItem)
|
||||
emit searchResultsSelected();
|
||||
else
|
||||
emit groupChanged(((GroupViewItem*)cur)->GroupHandle);
|
||||
}
|
||||
else
|
||||
emit groupChanged(NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void KeepassGroupView::dragEnterEvent ( QDragEnterEvent * event ){
|
||||
LastHoverItem=NULL;
|
||||
InsLinePos=-1;
|
||||
|
||||
if(event->mimeData()->hasFormat("application/x-keepassx")){
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void KeepassGroupView::dragLeaveEvent ( QDragLeaveEvent * event ){
|
||||
if(LastHoverItem){
|
||||
LastHoverItem->setBackgroundColor(0,QApplication::palette().color(QPalette::Base));
|
||||
}
|
||||
if(InsLinePos!=-1){
|
||||
int RemoveLine=InsLinePos;
|
||||
InsLinePos=-1;
|
||||
viewport()->update(QRegion(0,RemoveLine-2,viewport()->width(),4));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void KeepassGroupView::dropEvent( QDropEvent * event ){
|
||||
emit fileModified();
|
||||
InsertionMarker=QLine();
|
||||
if(LastHoverItem){
|
||||
QFont f=LastHoverItem->font(0);
|
||||
f.setBold(false);
|
||||
LastHoverItem->setFont(0,f);
|
||||
LastHoverItem=NULL;
|
||||
}
|
||||
GroupViewItem* item=(GroupViewItem*)itemAt(event->pos());
|
||||
if(DragType==GROUP){
|
||||
if(item){
|
||||
QRect ItemRect=visualItemRect(item);
|
||||
if((ItemRect.height()+ItemRect.y())-event->pos().y() > INSERT_AREA_WIDTH && event->pos().y() > INSERT_AREA_WIDTH){
|
||||
db->moveGroup(DragItem->pGroup,item->pGroup);}
|
||||
if(LastHoverItem){
|
||||
LastHoverItem->setBackgroundColor(0,QApplication::palette().color(QPalette::Base));
|
||||
}
|
||||
if(InsLinePos!=-1){
|
||||
int RemoveLine=InsLinePos;
|
||||
InsLinePos=-1;
|
||||
viewport()->update(QRegion(0,RemoveLine-2,viewport()->width(),4));
|
||||
}
|
||||
GroupViewItem* Item=(GroupViewItem*)itemAt(event->pos());
|
||||
if(!Item){
|
||||
qDebug("Append at the end");
|
||||
db->moveGroup(DragItem->GroupHandle,NULL,-1);
|
||||
if(DragItem->parent()){
|
||||
DragItem->parent()->takeChild(DragItem->parent()->indexOfChild(DragItem));
|
||||
}
|
||||
else{
|
||||
if(event->pos().y() > INSERT_AREA_WIDTH){
|
||||
if(db->getNumberOfChilds(item->pGroup) > 0)
|
||||
db->moveGroup(DragItem->pGroup,item->pGroup,0);
|
||||
else
|
||||
db->moveGroupDirectly(DragItem->pGroup,item->pGroup);
|
||||
takeTopLevelItem(indexOfTopLevelItem(DragItem));
|
||||
}
|
||||
insertTopLevelItem(topLevelItemCount(),DragItem);
|
||||
if(topLevelItemCount()>1){
|
||||
if(topLevelItem(topLevelItemCount()-2)==SearchResultItem){
|
||||
takeTopLevelItem(topLevelItemCount()-2);
|
||||
insertTopLevelItem(topLevelItemCount(),SearchResultItem);
|
||||
}
|
||||
}
|
||||
emit fileModified();
|
||||
}
|
||||
else{
|
||||
QRect ItemRect=visualItemRect(Item);
|
||||
if(event->pos().y()>ItemRect.y()+2 && event->pos().y()<ItemRect.y()+ItemRect.height()-2){
|
||||
qDebug("Append as child of '%s'",((char*)Item->text(0).toUtf8().data()));
|
||||
db->moveGroup(DragItem->GroupHandle,Item->GroupHandle,-1);
|
||||
if(DragItem->parent()){
|
||||
DragItem->parent()->takeChild(DragItem->parent()->indexOfChild(DragItem));
|
||||
}
|
||||
else db->moveGroupDirectly(DragItem->pGroup,NULL);
|
||||
}
|
||||
else{
|
||||
takeTopLevelItem(indexOfTopLevelItem(DragItem));
|
||||
}
|
||||
Item->insertChild(Item->childCount(),DragItem);
|
||||
emit fileModified();
|
||||
}
|
||||
else{
|
||||
if(event->pos().y()>ItemRect.y()+2){
|
||||
qDebug("Insert behind sibling '%s'",((char*)Item->text(0).toUtf8().data()));
|
||||
if(DragItem->parent()){
|
||||
DragItem->parent()->takeChild(DragItem->parent()->indexOfChild(DragItem));
|
||||
}
|
||||
else{
|
||||
takeTopLevelItem(indexOfTopLevelItem(DragItem));
|
||||
}
|
||||
if(Item->parent()){
|
||||
int index=Item->parent()->indexOfChild(Item)+1;
|
||||
db->moveGroup(DragItem->GroupHandle,((GroupViewItem*)Item->parent())->GroupHandle,index);
|
||||
Item->parent()->insertChild(index,DragItem);
|
||||
}
|
||||
else{
|
||||
int index=indexOfTopLevelItem(Item)+1;
|
||||
db->moveGroup(DragItem->GroupHandle,NULL,index);
|
||||
insertTopLevelItem(index,DragItem);
|
||||
}
|
||||
emit fileModified();
|
||||
}
|
||||
else{
|
||||
qDebug("Insert before sibling '%s'",((char*)Item->text(0).toUtf8().data()));
|
||||
if(DragItem->parent()){
|
||||
DragItem->parent()->takeChild(DragItem->parent()->indexOfChild(DragItem));
|
||||
}
|
||||
else{
|
||||
takeTopLevelItem(indexOfTopLevelItem(DragItem));
|
||||
}
|
||||
if(Item->parent()){
|
||||
int index=Item->parent()->indexOfChild(Item);
|
||||
db->moveGroup(DragItem->GroupHandle,((GroupViewItem*)Item->parent())->GroupHandle,index);
|
||||
Item->parent()->insertChild(index,DragItem);
|
||||
}
|
||||
else{
|
||||
int index=indexOfTopLevelItem(Item);
|
||||
db->moveGroup(DragItem->GroupHandle,NULL,index);
|
||||
insertTopLevelItem(index,DragItem);
|
||||
}
|
||||
emit fileModified();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else db->moveGroup(DragItem->pGroup,NULL);
|
||||
updateItems();
|
||||
}else{
|
||||
Q_ASSERT(item);
|
||||
QList<QTreeWidgetItem*>* pDragItems=(QList<QTreeWidgetItem*>*)*((QList<QTreeWidgetItem*>**)event->mimeData()->data("keepass/entry").data());
|
||||
for(int i=0;i<pDragItems->size();i++){
|
||||
db->moveEntry(((EntryViewItem*)(*pDragItems)[i])->pEntry,item->pGroup);
|
||||
}
|
||||
emit entryDropped();
|
||||
|
||||
}
|
||||
|
||||
void KeepassGroupView::dragMoveEvent( QDragMoveEvent * event ){
|
||||
if(DragItem){
|
||||
GroupViewItem* Item=(GroupViewItem*)itemAt(event->pos());
|
||||
if(!Item){
|
||||
if(LastHoverItem){
|
||||
LastHoverItem->setBackgroundColor(0,QApplication::palette().color(QPalette::Base));
|
||||
LastHoverItem=NULL;
|
||||
}
|
||||
if(InsLinePos!=-1){
|
||||
int RemoveLine=InsLinePos;
|
||||
InsLinePos=-1;
|
||||
viewport()->update(QRegion(0,RemoveLine-2,viewport()->width(),4));
|
||||
}
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
if(Item==DragItem || Item==SearchResultItem){
|
||||
event->ignore();
|
||||
return;
|
||||
}
|
||||
if(!db->isParent(DragItem->GroupHandle,Item->GroupHandle)){
|
||||
QRect ItemRect=visualItemRect(Item);
|
||||
if(event->pos().y()>ItemRect.y()+2 && event->pos().y()<ItemRect.y()+ItemRect.height()-2){
|
||||
if(InsLinePos!=-1){
|
||||
int RemoveLine=InsLinePos;
|
||||
InsLinePos=-1;
|
||||
viewport()->update(QRegion(0,RemoveLine-2,viewport()->width(),4));
|
||||
}
|
||||
if(LastHoverItem != Item){
|
||||
if(LastHoverItem){
|
||||
LastHoverItem->setBackgroundColor(0,QApplication::palette().color(QPalette::Base));
|
||||
}
|
||||
Item->setBackgroundColor(0,QApplication::palette().color(QPalette::Highlight));
|
||||
LastHoverItem=Item;
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(LastHoverItem){
|
||||
LastHoverItem->setBackgroundColor(0,QApplication::palette().color(QPalette::Base));
|
||||
LastHoverItem=NULL;
|
||||
}
|
||||
if(InsLinePos!=-1){
|
||||
int RemoveLine=InsLinePos;
|
||||
InsLinePos=-1;
|
||||
viewport()->update(QRegion(0,RemoveLine-2,viewport()->width(),4));
|
||||
}
|
||||
if(event->pos().y()>ItemRect.y()+2){
|
||||
InsLinePos=ItemRect.y()+ItemRect.height();
|
||||
}
|
||||
else{
|
||||
InsLinePos=ItemRect.y();
|
||||
}
|
||||
InsLineStart=ItemRect.x();
|
||||
viewport()->update(QRegion(0,InsLinePos-2,viewport()->width(),4));
|
||||
}
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
event->ignore();
|
||||
}
|
||||
|
||||
void KeepassGroupView::paintEvent(QPaintEvent* event){
|
||||
|
||||
QTreeWidget::paintEvent(event);
|
||||
if(InsLinePos != -1){
|
||||
QPainter painter(viewport());
|
||||
painter.setBrush(QBrush(QColor(0,0,0),Qt::Dense4Pattern));
|
||||
painter.setPen(Qt::NoPen);
|
||||
painter.drawRect(InsLineStart,InsLinePos-2,viewport()->width(),4);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void KeepassGroupView::mousePressEvent(QMouseEvent *event){
|
||||
//save event position - maybe this is the start of a drag
|
||||
if (event->button() == Qt::LeftButton)
|
||||
DragStartPos = event->pos();
|
||||
//call base function
|
||||
QTreeWidget::mousePressEvent(event);
|
||||
if (event->button() == Qt::LeftButton)
|
||||
DragStartPos = event->pos();
|
||||
QTreeWidget::mousePressEvent(event);
|
||||
}
|
||||
|
||||
void KeepassGroupView::mouseMoveEvent(QMouseEvent *event){
|
||||
if (!(event->buttons() & Qt::LeftButton))
|
||||
return;
|
||||
if ((event->pos() - DragStartPos).manhattanLength() < QApplication::startDragDistance())
|
||||
return;
|
||||
DragItem=(GroupViewItem*)itemAt(DragStartPos);
|
||||
if (isSearchResultGroup(DragItem))
|
||||
return;
|
||||
if (!(event->buttons() & Qt::LeftButton))
|
||||
return;
|
||||
if ((event->pos() - DragStartPos).manhattanLength()
|
||||
< QApplication::startDragDistance())
|
||||
return;
|
||||
|
||||
DragItem=(GroupViewItem*)itemAt(event->pos());
|
||||
if(!DragItem)return;
|
||||
|
||||
if(DragItem==SearchResultItem){
|
||||
qDebug("SearchGroup");
|
||||
DragItem=NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
setCurrentItem(DragItem);
|
||||
|
||||
QDrag *drag = new QDrag(this);
|
||||
QFontMetrics fontmet(DragItem->font(0));
|
||||
int DragPixmHeight=16;
|
||||
if(fontmet.height()>16)DragPixmHeight=fontmet.height();
|
||||
DragPixmap = QPixmap(fontmet.width(DragItem->text(0))+19,DragPixmHeight);
|
||||
DragPixmap.fill(QColor(255,255,255));
|
||||
QPainter painter(&DragPixmap);
|
||||
painter.setPen(QColor(0,0,0));
|
||||
painter.setFont(DragItem->font(0));
|
||||
painter.drawPixmap(0,0,DragItem->icon(0).pixmap(QSize(16,16)));
|
||||
painter.drawText(19,DragPixmHeight-fontmet.strikeOutPos(),DragItem->text(0));
|
||||
QMimeData *mimeData = new QMimeData;
|
||||
mimeData->setData("keepass/group",QByteArray((char*)&(DragItem->pGroup),sizeof(void*)));
|
||||
drag->setMimeData(mimeData);
|
||||
drag->setPixmap(DragPixmap);
|
||||
drag->start();
|
||||
}
|
||||
QMimeData *mimeData = new QMimeData;
|
||||
|
||||
void KeepassGroupView::updateItems(){
|
||||
|
||||
clear();
|
||||
Items.clear();
|
||||
for(int i=0; i<db->numGroups();i++){
|
||||
if(db->group(i).Level==0){
|
||||
if(Items.size()) Items.push_back(new GroupViewItem(this,getLastSameLevelItem(0)));
|
||||
else Items.push_back(new GroupViewItem(this));
|
||||
Items.back()->setText(0,db->group(i).Name);
|
||||
Items.back()->pGroup=&db->group(i);
|
||||
}
|
||||
else{
|
||||
if(db->group(i).Level>db->group(i-1).Level){
|
||||
Items.push_back(new GroupViewItem(Items.back(),getLastSameLevelItem(db->group(i).Level)));
|
||||
Items.back()->setText(0,db->group(i).Name);
|
||||
Items.back()->pGroup=&db->group(i);
|
||||
}
|
||||
if(db->group(i).Level<=db->group(i-1).Level){
|
||||
GroupItemItr j;
|
||||
for(j=Items.end()-1;j!=Items.begin();j--){
|
||||
if((*j)->pGroup->Level<db->group(i).Level)break;}
|
||||
Items.push_back(new GroupViewItem((*j),getLastSameLevelItem(db->group(i).Level)));
|
||||
Items.back()->setText(0,db->group(i).Name);
|
||||
Items.back()->pGroup=&db->group(i);
|
||||
}
|
||||
}
|
||||
Items.back()->setIcon(0,db->icon(db->group(i).ImageID));
|
||||
}
|
||||
|
||||
for(int i=0;i<Items.size();i++){
|
||||
setItemExpanded(Items[i],Items[i]->pGroup->UI_ItemIsExpanded);
|
||||
}
|
||||
if(ShowSearchGroup){
|
||||
Items.push_back(new GroupViewItem(this));
|
||||
Items.back()->setText(0,tr("Search Results"));
|
||||
Items.back()->pGroup=NULL;
|
||||
QFont f=Items.back()->font(0);
|
||||
f.setItalic(true);
|
||||
f.setBold(true);
|
||||
Items.back()->setFont(0,f);
|
||||
}
|
||||
mimeData->setData("text/plain;charset=UTF-8",DragItem->text(0).toUtf8());
|
||||
mimeData->setData("application/x-keepassx",QString("drag-type=group").toUtf8());
|
||||
drag->setMimeData(mimeData);
|
||||
|
||||
Qt::DropAction dropAction = drag->start(Qt::MoveAction);
|
||||
}
|
||||
|
||||
|
||||
|
||||
GroupViewItem* KeepassGroupView::getLastSameLevelItem(int level){
|
||||
for(int i=Items.size()-1;i>=0;i--){
|
||||
if(Items[i]->pGroup->Level==level){
|
||||
return Items[i];}
|
||||
}
|
||||
|
||||
return Items.back();
|
||||
|
||||
}
|
||||
|
||||
void KeepassGroupView::paintEvent(QPaintEvent* event){
|
||||
QTreeWidget::paintEvent(event);
|
||||
QPainter painter(viewport());
|
||||
QPen pen(QColor(100,100,100));
|
||||
pen.setWidth(2);
|
||||
pen.setStyle(Qt::DotLine);
|
||||
painter.setPen(pen);
|
||||
//qDebug("UPDATE: (%i,%i) %ix%i",event->rect().x(),event->rect().y(),event->rect().width(),event->rect().height());
|
||||
if(!InsertionMarker.isNull()){
|
||||
painter.drawLine(InsertionMarker);
|
||||
}
|
||||
}
|
||||
|
||||
bool KeepassGroupView::isSearchResultGroup(GroupViewItem* item){
|
||||
if(ShowSearchGroup && (item == Items.back()))return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
void KeepassGroupView::contextMenuEvent(QContextMenuEvent* e){
|
||||
if(!(GroupViewItem*)itemAt(e->pos()) && selectedItems().size()){
|
||||
setItemSelected(selectedItems()[0],false);
|
||||
}
|
||||
e->accept();
|
||||
if(isSearchResultGroup((GroupViewItem*)itemAt(e->pos())))
|
||||
ContextMenuSearchGroup->popup(e->globalPos());
|
||||
else
|
||||
ContextMenu->popup(e->globalPos());
|
||||
GroupViewItem::GroupViewItem():QTreeWidgetItem(){
|
||||
}
|
||||
|
||||
GroupViewItem::GroupViewItem(QTreeWidget *parent):QTreeWidgetItem(parent){
|
||||
|
||||
@@ -23,60 +23,65 @@
|
||||
#include <QTreeWidget>
|
||||
#include <QLine>
|
||||
#include <QContextMenuEvent>
|
||||
#include "../PwManager.h"
|
||||
#include "../StandardDatabase.h"
|
||||
|
||||
class GroupViewItem;
|
||||
typedef vector<GroupViewItem*>::iterator GroupItemItr;
|
||||
|
||||
class KeepassGroupView:public QTreeWidget{
|
||||
Q_OBJECT
|
||||
public:
|
||||
KeepassGroupView(QWidget* parent=0);
|
||||
bool isSearchResultGroup(GroupViewItem* item);
|
||||
void selectSearchGroup();
|
||||
Database *db;
|
||||
bool ShowSearchGroup; //needs a "updateItems()" after a change!
|
||||
vector<GroupViewItem*>Items;
|
||||
QMenu *ContextMenu;
|
||||
QMenu *ContextMenuSearchGroup;
|
||||
|
||||
public slots:
|
||||
void updateItems();
|
||||
|
||||
signals:
|
||||
void fileModified();
|
||||
void entryDropped();
|
||||
|
||||
protected:
|
||||
virtual void dragEnterEvent ( QDragEnterEvent * event );
|
||||
virtual void dragMoveEvent ( QDragMoveEvent * event );
|
||||
virtual void dragLeaveEvent ( QDragLeaveEvent * event );
|
||||
virtual void dropEvent ( QDropEvent * event );
|
||||
virtual void mousePressEvent(QMouseEvent *event);
|
||||
virtual void mouseMoveEvent(QMouseEvent *event);
|
||||
virtual void paintEvent ( QPaintEvent * event );
|
||||
virtual void contextMenuEvent(QContextMenuEvent *event);
|
||||
|
||||
private:
|
||||
QLine InsertionMarker;
|
||||
QPoint DragStartPos;
|
||||
QPixmap DragPixmap;
|
||||
GroupViewItem* DragItem;
|
||||
GroupViewItem* LastHoverItem;
|
||||
GroupViewItem* getLastSameLevelItem(int level);
|
||||
enum tDragType{GROUP,ENTRY};
|
||||
tDragType DragType;
|
||||
Q_OBJECT
|
||||
public:
|
||||
KeepassGroupView(QWidget* parent=0);
|
||||
IDatabase *db;
|
||||
QList<GroupViewItem*>Items;
|
||||
QMenu *ContextMenu;
|
||||
QMenu *ContextMenuSearchGroup;
|
||||
GroupViewItem* SearchResultItem;
|
||||
void createItems();
|
||||
void showSearchResults();
|
||||
|
||||
private:
|
||||
virtual void dragEnterEvent ( QDragEnterEvent * event );
|
||||
virtual void dragMoveEvent ( QDragMoveEvent * event );
|
||||
virtual void dragLeaveEvent ( QDragLeaveEvent * event );
|
||||
virtual void dropEvent ( QDropEvent * event );
|
||||
virtual void mousePressEvent(QMouseEvent *event);
|
||||
virtual void mouseMoveEvent(QMouseEvent *event);
|
||||
virtual void paintEvent ( QPaintEvent * event );
|
||||
virtual void contextMenuEvent(QContextMenuEvent *event);
|
||||
void addChilds(GroupViewItem* item);
|
||||
QPoint DragStartPos;
|
||||
GroupViewItem* DragItem;
|
||||
GroupViewItem* LastHoverItem;
|
||||
int InsLinePos;
|
||||
int InsLineStart;
|
||||
|
||||
public slots:
|
||||
void OnCurrentGroupChanged(QTreeWidgetItem*,QTreeWidgetItem*);
|
||||
void OnDeleteGroup();
|
||||
void OnNewGroup();
|
||||
void OnEditGroup();
|
||||
void updateIcons();
|
||||
void OnHideSearchResults();
|
||||
// void OnItemExpanded(QTreeWidgetItem*);
|
||||
// void OnItemCollapsed(QTreeWidgetItem*);
|
||||
|
||||
signals:
|
||||
void groupChanged(IGroupHandle* NewGroup);
|
||||
void searchResultsSelected();
|
||||
void fileModified();
|
||||
};
|
||||
|
||||
|
||||
class GroupViewItem:public QTreeWidgetItem{
|
||||
public:
|
||||
GroupViewItem(QTreeWidget *parent);
|
||||
GroupViewItem(QTreeWidget *parent, QTreeWidgetItem * preceding);
|
||||
GroupViewItem(QTreeWidgetItem *parent);
|
||||
GroupViewItem(QTreeWidgetItem *parent, QTreeWidgetItem * preceding);
|
||||
CGroup* pGroup;
|
||||
public:
|
||||
GroupViewItem();
|
||||
GroupViewItem(QTreeWidget *parent);
|
||||
GroupViewItem(QTreeWidget *parent, QTreeWidgetItem * preceding);
|
||||
GroupViewItem(QTreeWidgetItem *parent);
|
||||
GroupViewItem(QTreeWidgetItem *parent, QTreeWidgetItem * preceding);
|
||||
IGroupHandle* GroupHandle;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -21,7 +21,8 @@
|
||||
#include "SecString.h"
|
||||
#include <iostream>
|
||||
#include "crypto/arcfour.h"
|
||||
#include "random.h"
|
||||
#include "crypto/yarrow.h"
|
||||
|
||||
using namespace std;
|
||||
CArcFour SecString::RC4;
|
||||
|
||||
@@ -101,7 +102,7 @@ for(int i=0; i<str.length(); i++){
|
||||
void SecString::generateSessionKey(){
|
||||
CArcFour arc;
|
||||
unsigned char* sessionkey=new unsigned char[32];
|
||||
getRandomBytes(sessionkey,32,1,false);
|
||||
randomize(sessionkey,32);
|
||||
RC4.setKey(sessionkey,32);
|
||||
delete [] sessionkey;
|
||||
}
|
||||
@@ -25,26 +25,37 @@
|
||||
#include <qglobal.h>
|
||||
#include "crypto/arcfour.h"
|
||||
|
||||
//! QString based class with in-memory encryption of its content.
|
||||
/*!
|
||||
This class can hold a QString object in an encrypted buffer. To get access to the string it is neccassary to unlock the SecString object.
|
||||
*/
|
||||
class SecString{
|
||||
public:
|
||||
SecString();
|
||||
~SecString();
|
||||
void setString(QString& str, bool DelSrc=false);
|
||||
void lock();
|
||||
void unlock();
|
||||
const QString& string();
|
||||
operator QString();
|
||||
int length();
|
||||
|
||||
static void overwrite(unsigned char* str,int len);
|
||||
static void overwrite(QString& str);
|
||||
static void generateSessionKey();
|
||||
|
||||
SecString();
|
||||
~SecString();
|
||||
/*! Sets the content of the object.
|
||||
The SecString is locked after this operation.
|
||||
\param Source The string which should be set as content of the SecString.
|
||||
\param DelSrc Set this parameter TRUE if you want that SecString overwrites an deletes the source string.*/
|
||||
void setString(QString& Source, bool DelSrc=false);
|
||||
/*! Locks the string.
|
||||
That means that the unencrypted string will be overwritten and deleted and only the encrypted buffer remains.
|
||||
It is forbidden to call the function string() when the SecString is locked.*/
|
||||
void lock();
|
||||
void unlock();
|
||||
const QString& string();
|
||||
operator QString();
|
||||
int length();
|
||||
|
||||
static void overwrite(unsigned char* str,int len);
|
||||
static void overwrite(QString& str);
|
||||
static void generateSessionKey();
|
||||
|
||||
private:
|
||||
bool locked;
|
||||
static CArcFour RC4;
|
||||
QByteArray crypt;
|
||||
QString plain;
|
||||
bool locked;
|
||||
static CArcFour RC4;
|
||||
QByteArray crypt;
|
||||
QString plain;
|
||||
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user