1 /***************************************************************************
2 * Copyright (C) 2005-2006 by Tarek Saidi *
3 * tarek.saidi@arcor.de *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; version 2 of the License. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
21 #include <QFileDialog>
22 #include "SelectIconDlg.h"
23 #include "PasswordGenDlg.h"
24 #include "EditEntryDlg.h"
25 #include "CalendarDlg.h"
27 #ifdef GLOBAL_AUTOTYPE
28 #include "TargetWindowDlg.h"
31 CEditEntryDlg::CEditEntryDlg(IDatabase* _db, IEntryHandle* _entry,QWidget* parent, bool newEntry)
41 QMenu *ExpirePresetsMenu=new QMenu();
43 setGeometry( config->dialogGeometry(this) );
45 connect(Edit_Title, SIGNAL(textChanged(const QString&)), this, SLOT( OnTitleTextChanged(const QString&)));
46 connect(Edit_Password_w, SIGNAL(editingFinished()), this, SLOT(OnPasswordwLostFocus()));
47 connect(Edit_Password_w, SIGNAL(textChanged(const QString&)), this, SLOT( OnPasswordwTextChanged()));
48 connect(Edit_Password, SIGNAL(textChanged(const QString&)), this, SLOT( OnPasswordTextChanged()));
49 connect(ButtonEchoMode, SIGNAL(clicked()), this, SLOT( ChangeEchoMode()));
50 connect(buttonBox->button(QDialogButtonBox::Cancel), SIGNAL(clicked()), this, SLOT( OnButtonCancel()));
51 connect(ButtonOpenAttachment, SIGNAL(clicked()), this, SLOT( OnNewAttachment()));
52 connect(ButtonDeleteAttachment, SIGNAL(clicked()), this, SLOT( OnDeleteAttachment()));
53 connect(ButtonSaveAttachment, SIGNAL(clicked()), this, SLOT( OnSaveAttachment()));
54 connect(ButtonGenPw, SIGNAL(clicked()), this, SLOT( OnButtonGenPw()));
55 connect(buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()),this,SLOT(OnButtonOK()));
56 connect(CheckBox_ExpiresNever,SIGNAL(stateChanged(int)),this,SLOT(OnCheckBoxExpiresNeverChanged(int)));
57 connect(Button_Icons,SIGNAL(clicked()),this,SLOT(OnButtonIcons()));
58 connect(ExpirePresetsMenu,SIGNAL(triggered(QAction*)),this,SLOT(OnExpirePreset(QAction*)));
59 connect(ButtonExpirePresets,SIGNAL(triggered(QAction*)),this,SLOT(OnCalendar(QAction*)));
60 connect(this, SIGNAL(finished(int)), this, SLOT(OnClose()));
62 // QAction::data() contains the time until expiration in days.
63 ExpirePresetsMenu->addAction(tr("Today"))->setData(0);
64 ExpirePresetsMenu->addSeparator();
65 ExpirePresetsMenu->addAction(tr("1 Week"))->setData(7);
66 ExpirePresetsMenu->addAction(tr("2 Weeks"))->setData(14);
67 ExpirePresetsMenu->addAction(tr("3 Weeks"))->setData(21);
68 ExpirePresetsMenu->addSeparator();
69 ExpirePresetsMenu->addAction(tr("1 Month"))->setData(30);
70 ExpirePresetsMenu->addAction(tr("3 Months"))->setData(90);
71 ExpirePresetsMenu->addAction(tr("6 Months"))->setData(180);
72 ExpirePresetsMenu->addSeparator();
73 ExpirePresetsMenu->addAction(tr("1 Year"))->setData(365);
74 ButtonExpirePresets->setMenu(ExpirePresetsMenu);
75 QAction* actionCalendar = new QAction(tr("Calendar..."),ButtonExpirePresets);
76 actionCalendar->setData(-1);
77 ButtonExpirePresets->setDefaultAction(actionCalendar);
79 IconIndex = entry->image();
80 Button_Icons->setIcon(db->icon(IconIndex));
82 ButtonOpenAttachment->setIcon(getIcon("fileopen"));
83 ButtonDeleteAttachment->setIcon(getIcon("filedelete"));
84 ButtonSaveAttachment->setIcon(getIcon("filesave"));
85 ButtonExpirePresets->setIcon(getIcon("clock"));
87 OnTitleTextChanged(entry->title());
88 setWindowIcon(db->icon(IconIndex));
89 Edit_Title->setText(entry->title());
90 Edit_UserName->setText(entry->username());
91 Edit_URL->setText(entry->url());
92 SecString Password=entry->password();
94 Edit_Password->setText(Password.string());
95 Edit_Password_w->setText(Password.string());
97 if(!config->showPasswords())
100 ButtonEchoMode->setIcon(getIcon("pwd_show"));
102 // MX-COMMENT: This call is not needed. Both Passwords fields will always have the same value
103 OnPasswordwLostFocus();
104 int bits=(Password.length()*8);
105 Label_Bits->setText(tr("%1 Bit").arg(QString::number(bits)));
108 Progress_Quali->setValue(100*bits/128);
109 Edit_Attachment->setText(entry->binaryDesc());
110 Edit_Comment->setPlainText(entry->comment());
113 if(!entry->binarySize()){
114 ButtonSaveAttachment->setDisabled(true);
115 ButtonDeleteAttachment->setDisabled(true);
116 Label_AttachmentSize->setText("");
119 Label_AttachmentSize->setText(entry->friendlySize());
121 if(entry->expire()==Date_Never){
122 DateTime_Expire->setDisabled(true);
123 CheckBox_ExpiresNever->setChecked(true);
126 DateTime_Expire->setDateTime(entry->expire());
130 QToolButton* buttonTools = new QToolButton(buttonBox);
131 buttonTools->setText("Tools");
132 buttonTools->setPopupMode(QToolButton::InstantPopup);
133 QMenu* menuTools = new QMenu(buttonTools);
134 connect(menuTools->addAction("Auto-Type: Customize Sequence"), SIGNAL(triggered(bool)), SLOT(OnCustomizeSequence()));
135 #ifdef GLOBAL_AUTOTYPE
136 connect(menuTools->addAction("Auto-Type: Select target window"), SIGNAL(triggered(bool)), SLOT(OnSelectTarget()));
138 buttonTools->setMenu(menuTools);
139 buttonBox->addButton(buttonTools, QDialogButtonBox::ResetRole); // ResetRole: workaround to display button on the left
143 CEditEntryDlg::~CEditEntryDlg(){
146 void CEditEntryDlg::resizeEvent(QResizeEvent *event){
147 createBanner(&BannerPixmap,getPixmap("keepassx"),pNewEntry?tr("New Entry"):tr("Edit Entry"),width());
148 QDialog::resizeEvent(event);
153 void CEditEntryDlg::paintEvent(QPaintEvent *event){
154 QDialog::paintEvent(event);
155 QPainter painter(this);
156 painter.setClipRegion(event->region());
157 painter.drawPixmap(QPoint(0,0),BannerPixmap);
160 void CEditEntryDlg::InitGroupComboBox(){
162 groups=db->sortedGroups();
163 for(int i=0;i<groups.size();i++){
164 Space.fill(' ', 2 * (groups[i]->level()));
165 Combo_Group->insertItem(i,db->icon(groups[i]->image()),Space+groups[i]->title());
166 if(groups[i]==entry->group()){
167 Combo_Group->setCurrentIndex(i);
173 void CEditEntryDlg::OnButtonOK()
175 bool EntryMoved=false;
176 if(QString::compare(Edit_Password->text(),Edit_Password_w->text())!=0){
177 QMessageBox::warning(NULL,tr("Warning"),tr("Password and password repetition are not equal.\nPlease check your input."),tr("OK"));
181 if(CheckBox_ExpiresNever->checkState()==Qt::Checked){
182 DateTime_Expire->setDateTime(Date_Never);
185 if(DateTime_Expire->dateTime()!=entry->expire())
187 if(entry->title()!=Edit_Title->text())
189 if(entry->username()!=Edit_UserName->text())
191 if(entry->url()!=Edit_URL->text())
193 if(entry->comment()!=Edit_Comment->toPlainText())
195 SecString pw=entry->password();
197 QString password=pw.string();
198 if(password!=Edit_Password->text())
202 if(entry->image()!=IconIndex)
206 QDateTime now = QDateTime::currentDateTime();
207 entry->setExpire(DateTime_Expire->dateTime());
208 entry->setLastAccess(now);
209 entry->setLastMod(now);
210 entry->setTitle(Edit_Title->text());
211 entry->setUsername(Edit_UserName->text());
212 entry->setUrl(Edit_URL->text());
214 QString password=Edit_Password->text();
215 pw.setString(password,true);
216 entry->setPassword(pw);
217 entry->setComment(Edit_Comment->toPlainText());
218 entry->setImage(IconIndex);
220 if(Combo_Group->currentIndex()!=GroupIndex){
221 db->moveEntry(entry,groups[Combo_Group->currentIndex()]);
233 void CEditEntryDlg::OnButtonCancel()
235 entry->setLastAccess(QDateTime::currentDateTime());
239 void CEditEntryDlg::ChangeEchoMode()
241 if(Edit_Password->echoMode()==QLineEdit::Normal){
242 Edit_Password->setEchoMode(QLineEdit::Password);
243 Edit_Password_w->setEchoMode(QLineEdit::Password);
244 ButtonEchoMode->setIcon(getIcon("pwd_hide"));
248 Edit_Password->setEchoMode(QLineEdit::Normal);
249 Edit_Password_w->setEchoMode(QLineEdit::Normal);
250 ButtonEchoMode->setIcon(getIcon("pwd_show"));
254 void CEditEntryDlg::OnTitleTextChanged(const QString& txt)
256 setWindowTitle((txt=="") ? tr("[Untitled Entry]") : txt);
259 void CEditEntryDlg::OnPasswordTextChanged()
261 Edit_Password_w->setText(QString());
262 int bits=(Edit_Password->text().length()*8);
263 Label_Bits->setText(QString::number(bits)+" Bit");
264 if(bits>128)bits=128;
265 Progress_Quali->setValue(100*bits/128);
268 void CEditEntryDlg::OnPasswordwTextChanged()
270 if(QString::compare(Edit_Password_w->text(),Edit_Password->text().mid(0,(Edit_Password_w->text().length())))!=0){
272 palette.setColor(Edit_Password_w->backgroundRole(),QColor(255,125,125));
273 Edit_Password_w->setPalette(palette);
276 Edit_Password_w->setPalette(QApplication::palette());
280 void CEditEntryDlg::OnPasswordwLostFocus()
282 if (QString::compare(Edit_Password_w->text(),Edit_Password->text())!=0){
284 palette.setColor(Edit_Password_w->backgroundRole(),QColor(255,125,125));
285 Edit_Password_w->setPalette(palette);
288 Edit_Password_w->setPalette(QApplication::palette ());
292 void CEditEntryDlg::OnNewAttachment()
294 QString filename=QFileDialog::getOpenFileName(this,tr("Add Attachment..."),QDir::homePath());
295 if(filename=="")return;
296 QFile file(filename);
297 if(!file.open(QIODevice::ReadOnly)){
299 QMessageBox::warning(NULL,tr("Error"),tr("Could not open file."),tr("OK"));
303 entry->setBinary(file.readAll());
305 QFileInfo info(filename);
306 entry->setBinaryDesc(info.fileName());
307 Edit_Attachment->setText(entry->binaryDesc());
308 Label_AttachmentSize->setText(entry->friendlySize());
309 ButtonOpenAttachment->setEnabled(true);
310 ButtonSaveAttachment->setEnabled(true);
311 ButtonDeleteAttachment->setEnabled(true);
314 void CEditEntryDlg::OnSaveAttachment(){
315 saveAttachment(entry,this);
318 void CEditEntryDlg::saveAttachment(IEntryHandle* pEntry, QWidget* ParentWidget)
320 if(!pEntry->binarySize()){
321 QMessageBox::information(NULL,tr("Error"),tr("The chosen entry has no attachment or it is empty."),tr("OK"));
324 QFileDialog FileDlg(ParentWidget,tr("Save Attachment..."),QDir::homePath());
325 FileDlg.selectFile(pEntry->binaryDesc());
326 FileDlg.setAcceptMode(QFileDialog::AcceptSave);
327 if(!FileDlg.exec())return;
328 QString filename=FileDlg.selectedFiles()[0];
329 QFile file(filename);
330 if(!file.open(QIODevice::WriteOnly | QIODevice::Truncate)){
331 QMessageBox::critical(NULL,tr("Error"),tr("Could not open file."),tr("OK"));
335 int r=file.write(pEntry->binary());
338 QMessageBox::critical(NULL,tr("Error"),tr("Error while writing the file."),tr("OK"));
341 if(r!=pEntry->binarySize()){
343 QMessageBox::critical(NULL,tr("Error"),tr("Error while writing the file."),tr("OK"));
349 void CEditEntryDlg::OnDeleteAttachment()
351 int r=QMessageBox::warning(this,tr("Delete Attachment?"),
352 tr("You are about to delete the attachment of this entry.\nAre you sure?"),
353 tr("Yes"),tr("No, Cancel"),NULL,1,1);
356 entry->setBinary(QByteArray());
357 entry->setBinaryDesc("");
358 Edit_Attachment->setText("");
359 Label_AttachmentSize->setText("");
360 ButtonOpenAttachment->setEnabled(true);
361 ButtonSaveAttachment->setDisabled(true);
362 ButtonDeleteAttachment->setDisabled(true);
366 void CEditEntryDlg::OnButtonGenPw()
368 CGenPwDialog dlg(this,false);
370 Edit_Password->setText(dlg.Edit_dest->text());
371 Edit_Password_w->setText(dlg.Edit_dest->text());
377 void CEditEntryDlg::OnCheckBoxExpiresNeverChanged(int state){
378 if(state==Qt::Unchecked)
379 DateTime_Expire->setDisabled(false);
381 DateTime_Expire->setDisabled(true);
384 void CEditEntryDlg::OnButtonIcons(){
385 // CSelectIconDlg dlg(db,Combo_IconPicker->currentIndex(),this);
386 CSelectIconDlg dlg(db, IconIndex, this);
391 Button_Icons->setIcon(db->icon(IconIndex));
392 setWindowIcon(db->icon(IconIndex));
396 void CEditEntryDlg::OnExpirePreset(QAction* action){
397 CheckBox_ExpiresNever->setChecked(false);
398 int days = action->data().toInt();
403 DateTime_Expire->setDate(QDate::currentDate().addMonths(days/30));
406 DateTime_Expire->setDate(QDate::currentDate().addYears(1));
409 DateTime_Expire->setDate(QDate::currentDate().addDays(days));
411 DateTime_Expire->setTime(QTime(0,0,0));
414 void CEditEntryDlg::OnCalendar(QAction* action){
415 if (action->data().toInt()!=-1)
418 CalendarDialog dlg(this);
419 if(dlg.exec()==QDialog::Accepted){
420 CheckBox_ExpiresNever->setChecked(false);
421 DateTime_Expire->setDate(dlg.calendarWidget->selectedDate());
422 DateTime_Expire->setTime(QTime(0,0,0));
426 void CEditEntryDlg::OnClose(){
427 config->setDialogGeometry(this);
431 void CEditEntryDlg::OnCustomizeSequence(){
433 QString text = Edit_Comment->toPlainText();
436 Edit_Comment->setPlainText(text.append("Auto-Type: {USERNAME}{TAB}{PASSWORD}{ENTER}"));
440 void CEditEntryDlg::OnSelectTarget(){
441 #ifdef GLOBAL_AUTOTYPE
442 TargetWindowDlg dlg(this);
443 if (dlg.exec() && !dlg.windowTitle().isEmpty()){
444 QString text = Edit_Comment->toPlainText();
447 Edit_Comment->setPlainText(text.append("Auto-Type-Window: "+dlg.windowTitle()));