summaryrefslogtreecommitdiffabout
Side-by-side diff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--pwmanager/pwmanager/commentbox.cpp10
-rw-r--r--pwmanager/pwmanager/commentbox.h4
-rw-r--r--pwmanager/pwmanager/listviewpwm.cpp8
-rw-r--r--pwmanager/pwmanager/listviewpwm.h1
-rw-r--r--pwmanager/pwmanager/pwm.cpp2
-rw-r--r--pwmanager/pwmanager/pwmdoc.cpp58
-rw-r--r--pwmanager/pwmanager/pwmdoc.h2
-rw-r--r--pwmanager/pwmanager/pwmview.cpp2
-rw-r--r--pwmanager/pwmanager/pwmviewstyle_0.cpp20
-rw-r--r--pwmanager/pwmanager/pwmviewstyle_0.h4
-rw-r--r--pwmanager/pwmanager/pwmviewstyle_1.cpp19
-rw-r--r--pwmanager/pwmanager/pwmviewstyle_1.h2
12 files changed, 121 insertions, 11 deletions
diff --git a/pwmanager/pwmanager/commentbox.cpp b/pwmanager/pwmanager/commentbox.cpp
index 51f88b2..5416856 100644
--- a/pwmanager/pwmanager/commentbox.cpp
+++ b/pwmanager/pwmanager/commentbox.cpp
@@ -1,283 +1,283 @@
/***************************************************************************
* *
* copyright (C) 2004 by Michael Buesch *
* email: mbuesch@freenet.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 *
* as published by the Free Software Foundation. *
* *
***************************************************************************/
/***************************************************************************
* copyright (C) 2004 by Ulf Schenk
* This file is originaly based on version 1.0.1 of pwmanager
* and was modified to run on embedded devices that run microkde
*
* $Id$
**************************************************************************/
#include "commentbox.h"
#include "pwmexception.h"
#include "htmlgen.h"
#include <klocale.h>
#ifndef PWM_EMBEDDED
#include <khtml_part.h>
#include <khtmlview.h>
#include <qtextedit.h>
#else
#include <qmultilineedit.h>
#endif
#ifndef PWM_EMBEDDED
CommentBox::CommentBox(QWidget *_parentWidget)
{
PWM_ASSERT(_parentWidget);
parentWidget = _parentWidget;
textDta = 0;
htmlDta = 0;
mode = mode_notSet;
setFont( prefs->mViewFont );
}
CommentBox::~CommentBox()
{
clearText();
clearHtml();
}
void CommentBox::clear()
{
clearText();
clearHtml();
mode = mode_notSet;
this->hide();
}
void CommentBox::clearText()
{
delete_ifnot_null(textDta);
}
void CommentBox::clearHtml()
{
delete_ifnot_null(htmlDta);
}
void CommentBox::setText(const QString &text)
{
switchTo(mode_text);
PWM_ASSERT(textDta);
textDta->setText( text);
if (!textDta->isVisible())
textDta->show();
}
bool CommentBox::getText(QString *text)
{
if (mode != mode_text)
return false;
PWM_ASSERT(text);
if (!textDta) {
*text = "";
return true;
}
*text = textDta->text();
return true;
}
void CommentBox::setHtml(QString code)
{
switchTo(mode_html);
PWM_ASSERT(htmlDta);
if (!HtmlGen::replaceSSDummy(&code))
printWarn("CommentBox::setHtml(): replaceSSDummy() failed!");
htmlDta->begin();
htmlDta->write(code);
htmlDta->end();
htmlDta->show();
}
void CommentBox::setContent(const QString &dta)
{
// if there's no data, hide the comment-box
if (dta.isEmpty()) {
clear();
return;
}
if (HtmlGen::isHtml(dta)) {
setHtml(dta);
return;
}
// we assume it's plain text
setText(dta);
}
void CommentBox::switchTo(commentBoxMode newMode)
{
if (newMode == mode)
return;
// cleanup old mode
switch (mode) {
case mode_text:
clearText();
break;
case mode_html:
clearHtml();
break;
default:
break;
}
// setup new mode
switch (newMode) {
case mode_text:
textDta = new QTextEdit(parentWidget);
textDta->setTextFormat(Qt::PlainText);
textDta->setReadOnly(true);
textDta->show();
break;
case mode_html:
htmlDta = new KHTMLPart(parentWidget, 0,
parentWidget);
htmlDta->show();
break;
default:
BUG();
break;
}
mode = newMode;
}
void CommentBox::show()
{
switch (mode) {
case mode_text:
PWM_ASSERT(textDta);
textDta->show();
break;
case mode_html:
PWM_ASSERT(htmlDta);
htmlDta->show();
break;
default:
break;
}
}
void CommentBox::hide()
{
switch (mode) {
case mode_text:
PWM_ASSERT(textDta);
textDta->hide();
break;
case mode_html:
PWM_ASSERT(htmlDta);
htmlDta->hide();
break;
default:
break;
}
}
void CommentBox::resize(const QSize &size)
{
switch (mode) {
case mode_text:
PWM_ASSERT(textDta);
textDta->resize(size);
break;
case mode_html:
PWM_ASSERT(htmlDta);
htmlDta->view()->resize(size);
break;
default:
break;
}
}
QSize CommentBox::size()
{
switch (mode) {
case mode_text:
PWM_ASSERT(textDta);
return textDta->size();
break;
case mode_html:
PWM_ASSERT(htmlDta);
return htmlDta->view()->size();
break;
default:
break;
}
return QSize();
}
////////////////////////////////////////////////////////////////////////
#else
CommentBox::CommentBox(QWidget *_parentWidget)
- : QMultiLineEdit(_parentWidget)
+ : QTextBrowser(_parentWidget)
{
- this->setReadOnly(true);
+ //this->setReadOnly(true);
setFocusPolicy( QWidget::ClickFocus );
}
CommentBox::~CommentBox()
{
}
void CommentBox::clear()
{
this->hide();
}
void CommentBox::setText(const QString &text)
{
- QMultiLineEdit::setText( text);
- if (!this->isVisible())
- this->show();
+ QTextBrowser::setText( text);
+ if (!isVisible())
+ show();
}
bool CommentBox::getText(QString *text)
{
*text = this->text();
return true;
}
void CommentBox::setContent(const QString &dta)
{
// if there's no data, hide the comment-box
if (dta.isEmpty()) {
clear();
return;
}
// we assume it's plain text
setText(dta);
}
#endif
diff --git a/pwmanager/pwmanager/commentbox.h b/pwmanager/pwmanager/commentbox.h
index 352867c..3103353 100644
--- a/pwmanager/pwmanager/commentbox.h
+++ b/pwmanager/pwmanager/commentbox.h
@@ -1,124 +1,124 @@
/***************************************************************************
* *
* copyright (C) 2004 by Michael Buesch *
* email: mbuesch@freenet.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 *
* as published by the Free Software Foundation. *
* *
***************************************************************************/
/***************************************************************************
* copyright (C) 2004 by Ulf Schenk
* This file is originaly based on version 1.0.1 of pwmanager
* and was modified to run on embedded devices that run microkde
*
* $Id$
**************************************************************************/
#ifndef COMMENTBOX_H
#define COMMENTBOX_H
#include <qstring.h>
#include <qsize.h>
class QWidget;
class QTextEdit;
class KHTMLPart;
#ifndef PWM_EMBEDDED
class CommentBox
{
protected:
enum commentBoxMode
{
mode_notSet = 0,
mode_text,
mode_html
};
public:
CommentBox(QWidget *_parentWidget);
~CommentBox();
/** clear all data in the comment box */
void clear();
/** show the comment box */
void show();
/** hide the comment box */
void hide();
/** resize the comment box */
void resize(const QSize &size);
void resize(int w, int h)
{ resize(QSize(w, h)); }
/** get the size of the comment box */
QSize size();
/** if neccessary switch to text-mode and
* insert this text into the comment box
*/
void setText(const QString &text);
/** get the text of the comment box.
* If it's not in text-mode it returns false
*/
bool getText(QString *text);
/** if neccessary switch to HTML-mode and
* insert this html code into the comment box
*/
void setHtml(QString code);
/** checks "dta" for its type, sets the correct
* mode and writes "dta" to the comment box
*/
void setContent(const QString &dta);
protected:
/** switch the current mode */
void switchTo(commentBoxMode newMode);
/** clear all text data */
void clearText();
/** clear all HTML data */
void clearHtml();
protected:
/** parent widget for this comment box */
QWidget *parentWidget;
/** current comment box usage type */
commentBoxMode mode;
/** if the comment box is a normal textbox, data is stored here */
QTextEdit *textDta;
/** if the comment box is a HTML box, data is stored here */
KHTMLPart *htmlDta;
};
#else
-#include <qmultilineedit.h>
+#include <qtextbrowser.h>
/** Implementation of the advanced HTML comment box */
//US ENH: CommentBox must be derived from QWidget, to allow the splitter to set a initial size
// without conflicting with the two display modes
-class CommentBox : public QMultiLineEdit
+class CommentBox : public QTextBrowser
{
public:
CommentBox(QWidget *_parentWidget);
~CommentBox();
/** clear all data in the comment box */
void clear();
/** if neccessary switch to text-mode and
* insert this text into the comment box
*/
void setText(const QString &text);
/** get the text of the comment box.
* If it's not in text-mode it returns false
*/
bool getText(QString *text);
/** if neccessary switch to HTML-mode and
* insert this html code into the comment box
*/
void setContent(const QString &dta);
};
#endif
#endif
diff --git a/pwmanager/pwmanager/listviewpwm.cpp b/pwmanager/pwmanager/listviewpwm.cpp
index 85e788c..8d46fff 100644
--- a/pwmanager/pwmanager/listviewpwm.cpp
+++ b/pwmanager/pwmanager/listviewpwm.cpp
@@ -1,113 +1,121 @@
/***************************************************************************
* *
* copyright (C) 2004 by Michael Buesch *
* email: mbuesch@freenet.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 *
* as published by the Free Software Foundation. *
* *
***************************************************************************/
/***************************************************************************
* copyright (C) 2004 by Ulf Schenk
* This file is originaly based on version 1.0.1 of pwmanager
* and was modified to run on embedded devices that run microkde
*
* $Id$
**************************************************************************/
#include "listviewpwm.h"
#include "pwmexception.h"
#include "pwmview.h"
#include <qpainter.h>
#include <qpixmap.h>
#include <kiconloader.h>
#ifdef PWM_EMBEDDED
#include <kglobal.h>
#endif
ListViewPwM::ListViewPwM(QWidget *parent, const char *name)
: KListView(parent, name)
{
// setResizeMode(QListView::AllColumns);
setAllColumnsShowFocus (true );
}
bool ListViewPwM::event(QEvent *e)
{
if (e->type() == QEvent::LayoutHint)
emit layoutChanged();
+ if (e->type() == QEvent::KeyPress) {
+ QKeyEvent* ke = (QKeyEvent*) e;
+ if ( ke->key() == Qt::Key_Space) {
+ emit toggleOverview();
+ return true;
+ }
+
+ }
return KListView::event(e);
}
QPixmap * ListViewItemPwM::onPix = 0;
QPixmap * ListViewItemPwM::offPix = 0;
ListViewItemPwM::ListViewItemPwM(QListView *parent)
: QCheckListItem(parent, "", QCheckListItem::CheckBox)
{
if (!onPix) {
PWM_ASSERT(!offPix);
KIconLoader* picons;
#ifndef PWM_EMBEDDED
KIconLoader il;
picons = &il;
#else
picons = KGlobal::iconLoader();
#endif
KIconLoader il;
#ifndef PWM_EMBEDDED
static QPixmap onP(picons->loadIcon("button_ok", KIcon::Small));
#else
static QPixmap onP(picons->loadIcon("decrypted", KIcon::Small));
#endif
onPix = &onP;
static QPixmap offP(picons->loadIcon("encrypted", KIcon::Small));
offPix = &offP;
}
}
void ListViewItemPwM::paintCell(QPainter *p, const QColorGroup &cg,
int column, int width, int align)
{
// qDebug("ListViewItemPwM::paintCell column=%i", column);
if (!p)
return;
//US BUG:
if (column != COLUMN_DESC) {
QCheckListItem::paintCell(p, cg, column, width, align);
return;
}
QPixmap *curPix = isOn() ? onPix : offPix;
int pixSpace = curPix->width();
pixSpace += 4;
#ifndef PWM_EMBEDDED
QRect window(p->viewport());
// clear the rectangle (we have to clear it first. see QT doc)
p->eraseRect(0, 0, pixSpace, window.height());
// now draw the pixmap
int y = (height() - curPix->height()) / 2;
p->drawPixmap(1, y, *curPix);
window.moveLeft(pixSpace);
p->setViewport(window);
#else
p->eraseRect(0, 0, pixSpace, height());
// now draw the pixmap
int y = (height() - curPix->height()) / 2;
p->drawPixmap(1, y, *curPix);
p->translate( pixSpace, 0 );
#endif
QListViewItem::paintCell(p, cg, column, width - pixSpace, align);
}
#ifndef PWM_EMBEDDED
#include "listviewpwm.moc"
#endif
diff --git a/pwmanager/pwmanager/listviewpwm.h b/pwmanager/pwmanager/listviewpwm.h
index e6471c6..840ee73 100644
--- a/pwmanager/pwmanager/listviewpwm.h
+++ b/pwmanager/pwmanager/listviewpwm.h
@@ -1,57 +1,58 @@
/***************************************************************************
* *
* copyright (C) 2004 by Michael Buesch *
* email: mbuesch@freenet.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 *
* as published by the Free Software Foundation. *
* *
***************************************************************************/
/***************************************************************************
* copyright (C) 2004 by Ulf Schenk
* This file is originaly based on version 1.0.1 of pwmanager
* and was modified to run on embedded devices that run microkde
*
* $Id$
**************************************************************************/
#ifndef __LISTVIEW_H
#define __LISTVIEW_H
#include <klistview.h>
/** PwManager implementation of the list view.
* Derived from KListView.
*/
class ListViewPwM : public KListView
{
Q_OBJECT
public:
ListViewPwM(QWidget *parent = 0, const char *name = 0);
signals:
void layoutChanged();
+ void toggleOverview();
protected:
virtual bool event(QEvent *e);
};
class ListViewItemPwM : public QCheckListItem
{
public:
ListViewItemPwM(QListView *parent);
protected:
void paintCell(QPainter *p, const QColorGroup &cg,
int column, int width, int align);
protected:
/** pixmap to display for an item with state "on" */
static QPixmap *onPix;
/** pixmap to display for an item with state "off" */
static QPixmap *offPix;
};
#endif
diff --git a/pwmanager/pwmanager/pwm.cpp b/pwmanager/pwmanager/pwm.cpp
index aed8ec0..9187380 100644
--- a/pwmanager/pwmanager/pwm.cpp
+++ b/pwmanager/pwmanager/pwm.cpp
@@ -1,1515 +1,1515 @@
/***************************************************************************
* *
* copyright (C) 2003, 2004 by Michael Buesch *
* email: mbuesch@freenet.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 *
* as published by the Free Software Foundation. *
* *
***************************************************************************/
/***************************************************************************
* copyright (C) 2004 by Ulf Schenk
* This file is originaly based on version 1.0.1 of pwmanager
* and was modified to run on embedded devices that run microkde
*
* $Id$
**************************************************************************/
#include <klocale.h>
#include <klistview.h>
#include <ktoolbar.h>
#include <kfiledialog.h>
#include <kiconloader.h>
#include <kmessagebox.h>
#include <qstatusbar.h>
#ifndef PWM_EMBEDDED
#include <kmenubar.h>
#include <kstatusbar.h>
#include <dcopclient.h>
#include "configwndimpl.h"
#include "configuration.h"
#else
#include <qmenubar.h>
#include <qmessagebox.h>
#include <pwmprefs.h>
#include <kpimglobalprefs.h>
#include <kcmconfigs/kcmpwmconfig.h>
#include <kcmconfigs/kcmkdepimconfig.h>
#include <kcmultidialog.h>
#include "editcategory.h"
#endif
#ifndef DESKTOP_VERSION
#include <qpe/global.h>
#endif
#include <qpixmap.h>
#include <qcheckbox.h>
#include <qspinbox.h>
#include <qlineedit.h>
#include <qfileinfo.h>
#include <qclipboard.h>
#include <stdio.h>
#include "pwm.h"
#include "pwminit.h"
#include "pwmprint.h"
#include "addentrywndimpl.h"
#include "globalstuff.h"
#include "findwndimpl.h"
#include "csv.h"
#ifdef CONFIG_KWALLETIF
# include "kwalletif.h"
# include "kwalletemu.h"
#endif
#ifdef CONFIG_KEYCARD
# include "pwmkeycard.h"
#endif
#define DEFAULT_SIZE (QSize(700, 400))
// Button IDs for "file" popup menu
enum {
BUTTON_POPUP_FILE_NEW = 0,
BUTTON_POPUP_FILE_OPEN,
BUTTON_POPUP_FILE_CLOSE,
BUTTON_POPUP_FILE_SAVE,
BUTTON_POPUP_FILE_SAVEAS,
BUTTON_POPUP_FILE_EXPORT,
BUTTON_POPUP_FILE_IMPORT,
BUTTON_POPUP_FILE_PRINT,
BUTTON_POPUP_FILE_QUIT
};
// Button IDs for "manage" popup menu
enum {
BUTTON_POPUP_MANAGE_ADD = 0,
BUTTON_POPUP_MANAGE_EDIT,
BUTTON_POPUP_MANAGE_DEL,
BUTTON_POPUP_MANAGE_CHANGEMP
};
// Button IDs for chipcard popup menu
enum {
#ifdef CONFIG_KEYCARD
BUTTON_POPUP_CHIPCARD_GENNEW = 0,
BUTTON_POPUP_CHIPCARD_DEL,
BUTTON_POPUP_CHIPCARD_READID,
BUTTON_POPUP_CHIPCARD_SAVEBACKUP,
BUTTON_POPUP_CHIPCARD_REPLAYBACKUP
#else // CONFIG_KEYCARD
BUTTON_POPUP_CHIPCARD_NO = 0
#endif // CONFIG_KEYCARD
};
// Button IDs for "view" popup menu
enum {
BUTTON_POPUP_VIEW_FIND = 0,
BUTTON_POPUP_VIEW_LOCK,
BUTTON_POPUP_VIEW_DEEPLOCK,
BUTTON_POPUP_VIEW_UNLOCK
};
// Button IDs for "options" popup menu
enum {
BUTTON_POPUP_OPTIONS_CONFIG = 0
#ifdef PWM_EMBEDDED
,BUTTON_POPUP_OPTIONS_CATEGORY
#endif
};
// Button IDs for "export" popup menu (in "file" popup menu)
enum {
BUTTON_POPUP_EXPORT_TEXT = 0,
BUTTON_POPUP_EXPORT_GPASMAN,
BUTTON_POPUP_EXPORT_CSV
#ifdef CONFIG_KWALLETIF
,BUTTON_POPUP_EXPORT_KWALLET
#endif
};
// Button IDs for "import" popup menu (in "file" popup menu)
enum {
BUTTON_POPUP_IMPORT_TEXT = 0,
BUTTON_POPUP_IMPORT_GPASMAN,
BUTTON_POPUP_IMPORT_CSV
#ifdef CONFIG_KWALLETIF
,BUTTON_POPUP_IMPORT_KWALLET
#endif
};
#ifdef PWM_EMBEDDED
// Button IDs for "help" popup menu
enum {
BUTTON_POPUP_HELP_LICENSE = 0,
BUTTON_POPUP_HELP_FAQ,
BUTTON_POPUP_HELP_ABOUT,
BUTTON_POPUP_HELP_SYNC,
BUTTON_POPUP_HELP_WHATSNEW
};
#endif
// Button IDs for toolbar
enum {
BUTTON_TOOL_NEW = 0,
BUTTON_TOOL_OPEN,
BUTTON_TOOL_SAVE,
BUTTON_TOOL_SAVEAS,
BUTTON_TOOL_PRINT,
BUTTON_TOOL_ADD,
BUTTON_TOOL_EDIT,
BUTTON_TOOL_DEL,
BUTTON_TOOL_FIND,
BUTTON_TOOL_LOCK,
BUTTON_TOOL_DEEPLOCK,
BUTTON_TOOL_UNLOCK
};
PwM::PwM(PwMInit *_init, PwMDoc *doc,
bool virginity,
QWidget *parent, const char *name)
: KMainWindow(parent, "HALLO")
, forceQuit (false)
, forceMinimizeToTray (false)
{
syncManager = 0;
virgin = !virginity;
init = _init;
connect(doc, SIGNAL(docClosed(PwMDoc *)),
this, SLOT(docClosed(PwMDoc *)));
initMenubar();
initToolbar();
initMetrics();
setVirgin(virginity);
setFocusPolicy(QWidget::WheelFocus);
#ifndef PWM_EMBEDDED
statusBar()->show();
#endif
view = makeNewListView(doc);
setCentralWidget(view);
updateCaption();
showStatMsg(i18n("Ready."));
}
PwM::~PwM()
{
//qDebug("PwM::~PwM() %x", this);
disconnect(curDoc(), SIGNAL(docClosed(PwMDoc *)),
this, SLOT(docClosed(PwMDoc *)));
conf()->confWndMainWndSize(size());
//LR closing of windows changed
//needed for fastload option on PDA
//emit closed(this);
//qDebug("PwM::~PwM() emited closed(this)");
delete view;
delete syncManager;
}
void PwM::initMenubar()
{
KIconLoader* picons;
#ifndef PWM_EMBEDDED
KIconLoader icons;
picons = &icons;
#else
picons = KGlobal::iconLoader();
syncPopup = new KPopupMenu(this);
syncManager = new KSyncManager((QWidget*)this, (KSyncInterface*)this, KSyncManager::PWMPI, PWMPrefs::instance(), syncPopup);
syncManager->setBlockSave(false);
connect ( syncPopup, SIGNAL( activated ( int ) ), syncManager, SLOT (slotSyncMenu( int ) ) );
syncManager->fillSyncMenu();
#endif
filePopup = new KPopupMenu(this);
importPopup = new KPopupMenu(filePopup);
exportPopup = new KPopupMenu(filePopup);
managePopup = new KPopupMenu(this);
#ifdef CONFIG_KEYCARD
chipcardPopup = new KPopupMenu(this);
#endif // CONFIG_KEYCARD
viewPopup = new KPopupMenu(this);
optionsPopup = new KPopupMenu(this);
// "file" popup menu
filePopup->insertItem(QIconSet(picons->loadIcon("filenew", KIcon::Small)),
i18n("&New"), this,
SLOT(new_slot()), 0, BUTTON_POPUP_FILE_NEW);
filePopup->insertItem(QIconSet(picons->loadIcon("fileopen", KIcon::Small)),
i18n("&Open"), this,
SLOT(open_slot()), 0, BUTTON_POPUP_FILE_OPEN);
filePopup->insertItem(QIconSet(picons->loadIcon("fileclose", KIcon::Small)),
i18n("&Close"), this,
SLOT(close_slot()), 0, BUTTON_POPUP_FILE_CLOSE);
filePopup->insertSeparator();
filePopup->insertItem(QIconSet(picons->loadIcon("pencil", KIcon::Small)),
i18n("&Add password"), this,
SLOT(addPwd_slot()), 0,
BUTTON_POPUP_MANAGE_ADD);
filePopup->insertSeparator();
filePopup->insertItem(QIconSet(picons->loadIcon("filesave", KIcon::Small)),
i18n("&Save"), this,
SLOT(save_slot()), 0, BUTTON_POPUP_FILE_SAVE);
filePopup->insertItem(QIconSet(picons->loadIcon("filesaveas", KIcon::Small)),
i18n("Save &as..."),
this, SLOT(saveAs_slot()), 0,
BUTTON_POPUP_FILE_SAVEAS);
filePopup->insertSeparator();
// "file/export" popup menu
exportPopup->insertItem(i18n("&Text-file..."), this,
SLOT(exportToText()), 0, BUTTON_POPUP_EXPORT_TEXT);
exportPopup->insertItem(i18n("&Gpasman / Kpasman ..."), this,
SLOT(exportToGpasman()), 0, BUTTON_POPUP_EXPORT_GPASMAN);
exportPopup->insertItem(i18n("&CSV (Comma Separated Value) ..."), this,
SLOT(exportToCsv()), 0, BUTTON_POPUP_EXPORT_CSV);
#ifdef CONFIG_KWALLETIF
exportPopup->insertItem(i18n("&KWallet..."), this,
SLOT(exportToKWallet()), 0, BUTTON_POPUP_EXPORT_KWALLET);
#endif
filePopup->insertItem(QIconSet(picons->loadIcon("fileexport", KIcon::Small)),
i18n("E&xport"), exportPopup,
BUTTON_POPUP_FILE_EXPORT);
// "file/import" popup menu
importPopup->insertItem(i18n("&Text-file..."), this,
SLOT(importFromText()), 0, BUTTON_POPUP_IMPORT_TEXT);
importPopup->insertItem(i18n("&Gpasman / Kpasman ..."), this,
SLOT(importFromGpasman()), 0, BUTTON_POPUP_IMPORT_GPASMAN);
importPopup->insertItem(i18n("&CSV (Comma Separated Value) ..."), this,
SLOT(importCsv()), 0, BUTTON_POPUP_IMPORT_CSV);
#ifdef CONFIG_KWALLETIF
importPopup->insertItem(i18n("&KWallet..."), this,
SLOT(importKWallet()), 0, BUTTON_POPUP_IMPORT_KWALLET);
#endif
filePopup->insertItem(QIconSet(picons->loadIcon("fileimport", KIcon::Small)),
i18n("I&mport"), importPopup,
BUTTON_POPUP_FILE_IMPORT);
filePopup->insertSeparator();
#if 0
filePopup->insertItem(QIconSet(picons->loadIcon("fileprint", KIcon::Small)),
i18n("&Print..."), this,
SLOT(print_slot()), 0, BUTTON_POPUP_FILE_PRINT);
filePopup->insertSeparator();
#endif
filePopup->insertItem(QIconSet(picons->loadIcon("exit", KIcon::Small)),
i18n("&Quit"), this,
SLOT(quitButton_slot()), 0, BUTTON_POPUP_FILE_QUIT);
menuBar()->insertItem(i18n("&File"), filePopup);
// "manage" popup menu
managePopup->insertItem(QIconSet(picons->loadIcon("pencil", KIcon::Small)),
i18n("&Add password"), this,
SLOT(addPwd_slot()), 0,
BUTTON_POPUP_MANAGE_ADD);
managePopup->insertSeparator();
managePopup->insertItem(QIconSet(picons->loadIcon("edit", KIcon::Small)),
i18n("&Edit"), this, SLOT(editPwd_slot()), 0,
BUTTON_POPUP_MANAGE_EDIT);
managePopup->insertItem(QIconSet(picons->loadIcon("editdelete", KIcon::Small)),
i18n("&Delete"), this, SLOT(deletePwd_slot()),
0, BUTTON_POPUP_MANAGE_DEL);
managePopup->insertSeparator();
managePopup->insertItem(QIconSet(picons->loadIcon("rotate", KIcon::Small)),
i18n("Change &Master Password"), this,
SLOT(changeMasterPwd_slot()), 0,
BUTTON_POPUP_MANAGE_CHANGEMP);
menuBar()->insertItem(i18n("&Manage"), managePopup);
// "chipcard" popup menu
#ifdef CONFIG_KEYCARD
chipcardPopup->insertItem(QIconSet(picons->loadIcon("filenew", KIcon::Small)),
i18n("&Generate new key-card"), this,
SLOT(genNewCard_slot()), 0,
BUTTON_POPUP_CHIPCARD_GENNEW);
chipcardPopup->insertItem(QIconSet(picons->loadIcon("editdelete", KIcon::Small)),
i18n("&Erase key-card"), this,
SLOT(eraseCard_slot()), 0,
BUTTON_POPUP_CHIPCARD_DEL);
chipcardPopup->insertItem(QIconSet(picons->loadIcon("", KIcon::Small)),
i18n("Read card-&ID"), this,
SLOT(readCardId_slot()), 0,
BUTTON_POPUP_CHIPCARD_READID);
chipcardPopup->insertSeparator();
chipcardPopup->insertItem(QIconSet(picons->loadIcon("2rightarrow", KIcon::Small)),
i18n("&Make card backup-image"), this,
SLOT(makeCardBackup_slot()), 0,
BUTTON_POPUP_CHIPCARD_SAVEBACKUP);
chipcardPopup->insertItem(QIconSet(picons->loadIcon("2leftarrow", KIcon::Small)),
i18n("&Replay card backup-image"), this,
SLOT(replayCardBackup_slot()), 0,
BUTTON_POPUP_CHIPCARD_REPLAYBACKUP);
menuBar()->insertItem(i18n("&Chipcard manager"), chipcardPopup);
#endif // CONFIG_KEYCARD
// "view" popup menu
viewPopup->insertItem(QIconSet(picons->loadIcon("find", KIcon::Small)),
i18n("&Find"), this,
SLOT(find_slot()), 0, BUTTON_POPUP_VIEW_FIND);
viewPopup->insertSeparator();
viewPopup->insertItem(QIconSet(picons->loadIcon("halfencrypted", KIcon::Small)),
i18n("&Lock all entries"), this,
SLOT(lockWnd_slot()), 0,
BUTTON_POPUP_VIEW_LOCK);
viewPopup->insertItem(QIconSet(picons->loadIcon("encrypted", KIcon::Small)),
i18n("&Deep-lock all entries"), this,
SLOT(deepLockWnd_slot()), 0,
BUTTON_POPUP_VIEW_DEEPLOCK);
viewPopup->insertItem(QIconSet(picons->loadIcon("decrypted", KIcon::Small)),
i18n("&Unlock all entries"), this,
SLOT(unlockWnd_slot()), 0,
BUTTON_POPUP_VIEW_UNLOCK);
menuBar()->insertItem(i18n("&View"), viewPopup);
// "options" popup menu
optionsPopup->insertItem(QIconSet(picons->loadIcon("configure", KIcon::Small)),
i18n("&Configure..."), this,
SLOT(config_slot()),0,
BUTTON_POPUP_OPTIONS_CONFIG);
menuBar()->insertItem(i18n("&Options"), optionsPopup);
// "help" popup menu
#ifndef PWM_EMBEDDED
helpPopup = helpMenu(QString::null, false);
#else
optionsPopup->insertItem(QIconSet(picons->loadIcon("configure", KIcon::Small)),
i18n("C&ategories..."), this,
SLOT(category_slot()),0,
BUTTON_POPUP_OPTIONS_CATEGORY);
menuBar()->insertItem(i18n("&Sync"), syncPopup);
helpPopup = new KPopupMenu(this);
helpPopup->insertItem(i18n("&License"), this,
SLOT(showLicense_slot()), 0,
BUTTON_POPUP_HELP_LICENSE);
helpPopup->insertItem(i18n("&Faq"), this,
SLOT(faq_slot()), 0,
BUTTON_POPUP_HELP_FAQ);
helpPopup->insertItem(i18n("&About PwManager"), this,
SLOT(createAboutData_slot()), 0,
BUTTON_POPUP_HELP_ABOUT);
helpPopup->insertItem(i18n("&Sync HowTo"), this,
SLOT(syncHowTo_slot()), 0,
BUTTON_POPUP_HELP_SYNC);
helpPopup->insertItem(i18n("&What's New"), this,
SLOT(whatsnew_slot()), 0,
BUTTON_POPUP_HELP_WHATSNEW);
#endif
menuBar()->insertItem(i18n("&Help"), helpPopup);
}
void PwM::initToolbar()
{
KIconLoader* picons;
#ifndef PWM_EMBEDDED
KIconLoader icons;
picons = &icons;
#else
picons = KGlobal::iconLoader();
#endif
#if 0
toolBar()->insertButton(picons->loadIcon("filenew", KIcon::Toolbar),
BUTTON_TOOL_NEW, SIGNAL(clicked(int)), this,
SLOT(new_slot()), true, i18n("New"));
#endif
toolBar()->insertButton(picons->loadIcon("fileopen", KIcon::Toolbar),
BUTTON_TOOL_OPEN, SIGNAL(clicked(int)), this,
SLOT(open_slot()), true, i18n("Open"));
toolBar()->insertButton(picons->loadIcon("pencil", KIcon::Toolbar),
BUTTON_TOOL_ADD, SIGNAL(clicked(int)), this,
SLOT(addPwd_slot()), true,
i18n("Add password"));
toolBar()->insertSeparator();
toolBar()->insertButton(picons->loadIcon("find", KIcon::Toolbar),
BUTTON_TOOL_FIND, SIGNAL(clicked(int)), this,
SLOT(find_slot()), true, i18n("Find entry"));
toolBar()->insertSeparator();
toolBar()->insertButton(picons->loadIcon("filesave", KIcon::Toolbar),
BUTTON_TOOL_SAVE, SIGNAL(clicked(int)), this,
SLOT(save_slot()), true, i18n("Save"));
#if 0
toolBar()->insertButton(picons->loadIcon("filesaveas", KIcon::Toolbar),
BUTTON_TOOL_SAVEAS, SIGNAL(clicked(int)), this,
SLOT(saveAs_slot()), true, i18n("Save as"));
#endif
#if 0
toolBar()->insertButton(picons->loadIcon("fileprint", KIcon::Toolbar),
BUTTON_TOOL_PRINT, SIGNAL(clicked(int)), this,
SLOT(print_slot()), true, i18n("Print..."));
#endif
toolBar()->insertSeparator();
toolBar()->insertButton(picons->loadIcon("edit", KIcon::Toolbar),
BUTTON_TOOL_EDIT, SIGNAL(clicked(int)), this,
SLOT(editPwd_slot()), true,
i18n("Edit password"));
toolBar()->insertButton(picons->loadIcon("editdelete", KIcon::Toolbar),
BUTTON_TOOL_DEL, SIGNAL(clicked(int)), this,
SLOT(deletePwd_slot()), true,
i18n("Delete password"));
toolBar()->insertSeparator();
toolBar()->insertButton(picons->loadIcon("halfencrypted", KIcon::Toolbar),
BUTTON_TOOL_LOCK, SIGNAL(clicked(int)), this,
SLOT(lockWnd_slot()), true,
i18n("Lock all entries"));
toolBar()->insertButton(picons->loadIcon("encrypted", KIcon::Toolbar),
BUTTON_TOOL_DEEPLOCK, SIGNAL(clicked(int)), this,
SLOT(deepLockWnd_slot()), true,
i18n("Deep-Lock all entries"));
toolBar()->insertButton(picons->loadIcon("decrypted", KIcon::Toolbar),
BUTTON_TOOL_UNLOCK, SIGNAL(clicked(int)), this,
SLOT(unlockWnd_slot()), true,
i18n("Unlock all entries"));
}
void PwM::initMetrics()
{
QSize s = conf()->confWndMainWndSize();
if (s.isValid())
resize(s);
else
resize(DEFAULT_SIZE);
}
void PwM::updateCaption()
{
setPlainCaption(curDoc()->getTitle() + " - " PROG_NAME " " PACKAGE_VER);
}
void PwM::hideEvent(QHideEvent *)
{
if (isMinimized()) {
if (init->tray()) {
forceMinimizeToTray = true;
close();
}
int mmlock = conf()->confGlobMinimizeLock();
switch (mmlock) {
case 0: // don't lock anything
break;
case 1: { // normal lock
curDoc()->lockAll(true);
break;
} case 2: { // deep-lock
curDoc()->deepLock();
break;
} default:
WARN();
}
}
}
void PwM::setVirgin(bool v)
{
if (virgin == v)
return;
virgin = v;
filePopup->setItemEnabled(BUTTON_POPUP_FILE_SAVE, !v);
filePopup->setItemEnabled(BUTTON_POPUP_FILE_SAVEAS, !v);
filePopup->setItemEnabled(BUTTON_POPUP_FILE_EXPORT, !v);
filePopup->setItemEnabled(BUTTON_POPUP_FILE_PRINT, !v);
managePopup->setItemEnabled(BUTTON_POPUP_MANAGE_EDIT, !v);
managePopup->setItemEnabled(BUTTON_POPUP_MANAGE_DEL, !v);
managePopup->setItemEnabled(BUTTON_POPUP_MANAGE_CHANGEMP, !v);
viewPopup->setItemEnabled(BUTTON_POPUP_VIEW_LOCK, !v);
viewPopup->setItemEnabled(BUTTON_POPUP_VIEW_DEEPLOCK, !v);
viewPopup->setItemEnabled(BUTTON_POPUP_VIEW_UNLOCK, !v);
viewPopup->setItemEnabled(BUTTON_POPUP_VIEW_FIND, !v);
toolBar()->setItemEnabled(BUTTON_TOOL_SAVE, !v);
toolBar()->setItemEnabled(BUTTON_TOOL_SAVEAS, !v);
toolBar()->setItemEnabled(BUTTON_TOOL_PRINT, !v);
toolBar()->setItemEnabled(BUTTON_TOOL_EDIT, !v);
toolBar()->setItemEnabled(BUTTON_TOOL_DEL, !v);
toolBar()->setItemEnabled(BUTTON_TOOL_LOCK, !v);
toolBar()->setItemEnabled(BUTTON_TOOL_DEEPLOCK, !v);
toolBar()->setItemEnabled(BUTTON_TOOL_UNLOCK, !v);
toolBar()->setItemEnabled(BUTTON_TOOL_FIND, !v);
}
void PwM::new_slot()
{
init->createMainWnd();
}
//US ENH
void PwM::open_slot()
{
open_slot("");
}
void PwM::open_slot(QString fn)
{
openDoc(fn);
}
PwMDoc * PwM::openDoc(QString filename, bool openDeepLocked)
{
if (!isVirgin()) {
// open the document in a new window.
PwM *newInstance = init->createMainWnd();
PwMDoc *newDoc = newInstance->openDoc(filename, openDeepLocked);
if (!newDoc) {
newInstance->setForceQuit(true);
delete_and_null(newInstance);
}
return newDoc;
}
if (!curDoc()->openDocUi(curDoc(), filename, openDeepLocked))
return 0;
showStatMsg(i18n("Successfully opened file."));
updateCaption();
setVirgin(false);
return curDoc();
}
PwMView * PwM::makeNewListView(PwMDoc *doc)
{
PwMView *ret = new PwMView(this, this, doc);
ret->setFont(conf()->confGlobEntryFont());
ret->show();
return ret;
}
void PwM::close_slot()
{
close();
}
void PwM::quitButton_slot()
{
init->shutdownApp(0);
}
void PwM::save_slot()
{
save();
}
bool PwM::save()
{
if (!curDoc()->saveDocUi(curDoc()))
return false;
showStatMsg(i18n("Successfully saved data."));
updateCaption();
return true;
}
void PwM::saveAs_slot()
{
saveAs();
}
bool PwM::saveAs()
{
if (!curDoc()->saveAsDocUi(curDoc()))
return false;
showStatMsg(i18n("Successfully saved data."));
updateCaption();
return true;
}
//US ENH : changed code to run with older MOC
void PwM::addPwd_slot()
{
addPwd_slot1(0, 0);
}
void PwM::addPwd_slot1(QString *pw, PwMDoc *_doc)
{
PwMDoc *doc;
if (_doc) {
doc = _doc;
} else {
doc = curDoc();
}
PWM_ASSERT(doc);
doc->timer()->getLock(DocTimer::id_autoLockTimer);
#ifndef PWM_EMBEDDED
AddEntryWndImpl w;
#else
AddEntryWndImpl w(doc, this, "addentrywndimpl");
#endif
w.setCaption( i18n ("Add new password") );
vector<string> catList;
doc->getCategoryList(&catList);
unsigned i, size = catList.size();
for (i = 0; i < size; ++i) {
w.addCategory(catList[i].c_str());
}
w.setCurrCategory(view->getCurrentCategory());
if (pw)
w.pwLineEdit->setText(*pw);
tryAgain:
w.descLineEdit->setFocus();
if (w.exec() == 1)
{
PwMDataItem d;
//US BUG: to initialize all values of curEntr with meaningfulldata,
// we call clear on it. Reason: Metadata will be uninitialized otherwise.
// another option would be to create a constructor for PwMDataItem
d.clear(true);
d.desc = w.getDescription().latin1();
d.name = w.getUsername().latin1();
d.pw = w.getPassword().latin1();
d.comment = w.getComment().latin1();
d.url = w.getUrl().latin1();
d.launcher = w.getLauncher().latin1();
PwMerror ret = doc->addEntry(w.getCategory(), &d);
if (ret == e_entryExists) {
KMessageBox::error(this,
i18n
("An entry with this \"Description\",\n"
"does already exist.\n"
"Please select another description."),
i18n("entry already exists."));
goto tryAgain;
} else if (ret == e_maxAllowedEntr) {
KMessageBox::error(this, i18n("The maximum possible number of\nentries"
"has been reached.\nYou can't add more entries."),
i18n("maximum number of entries"));
doc->timer()->putLock(DocTimer::id_autoLockTimer);
return;
}
}
setVirgin(false);
doc->timer()->putLock(DocTimer::id_autoLockTimer);
}
//US ENH : changed code to run with older MOC
void PwM::editPwd_slot()
{
editPwd_slot3(0,0,0);
}
void PwM::editPwd_slot1(const QString *category)
{
editPwd_slot3(category, 0, 0);
}
void PwM::editPwd_slot3(const QString *category, const int *index,
PwMDoc *_doc)
{
PwMDoc *doc;
if (_doc) {
doc = _doc;
} else {
doc = curDoc();
}
PWM_ASSERT(doc);
if (doc->isDocEmpty())
return;
if (doc->isDeepLocked())
return;
doc->timer()->getLock(DocTimer::id_autoLockTimer);
unsigned int curEntryIndex;
if (index) {
curEntryIndex = *index;
} else {
if (!(view->getCurEntryIndex(&curEntryIndex))) {
+ qDebug("couldn't get index. Maybe we have a binary entry here. ");
printDebug("couldn't get index. Maybe we have a binary entry here.");
doc->timer()->putLock(DocTimer::id_autoLockTimer);
return;
}
}
QString curCategory;
if (category) {
curCategory = *category;
} else {
curCategory = view->getCurrentCategory();
}
PwMDataItem currItem;
if (!doc->getEntry(curCategory, curEntryIndex, &currItem, true)) {
doc->timer()->putLock(DocTimer::id_autoLockTimer);
return;
}
BUG_ON(currItem.binary);
-
AddEntryWndImpl w(doc);
w.setCaption( i18n ("Edit password") );
vector<string> catList;
doc->getCategoryList(&catList);
unsigned i, size = catList.size();
for (i = 0; i < size; ++i) {
w.addCategory(catList[i].c_str());
}
w.setCurrCategory(curCategory);
w.setDescription(currItem.desc.c_str());
w.setUsername(currItem.name.c_str());
w.setPassword(currItem.pw.c_str());
w.setUrl(currItem.url.c_str());
w.setLauncher(currItem.launcher.c_str());
w.setComment(currItem.comment.c_str());
w.descLineEdit->setFocus();
if (w.exec() == 1) {
currItem.desc = w.getDescription().latin1();
currItem.name = w.getUsername().latin1();
currItem.pw = w.getPassword().latin1();
currItem.comment = w.getComment().latin1();
currItem.url = w.getUrl().latin1();
currItem.launcher = w.getLauncher().latin1();
if (!doc->editEntry(curCategory, w.getCategory(),
curEntryIndex, &currItem)) {
KMessageBox::error(this,
i18n("Couldn't edit the entry.\n"
"Maybe you changed the category and\n"
"this entry is already present\nin the new "
"category?"),
i18n("couldn't edit entry."));
doc->timer()->putLock(DocTimer::id_autoLockTimer);
return;
}
}
doc->timer()->putLock(DocTimer::id_autoLockTimer);
}
void PwM::deletePwd_slot()
{
PWM_ASSERT(curDoc());
if (curDoc()->isDocEmpty())
return;
if (curDoc()->isDeepLocked())
return;
curDoc()->timer()->getLock(DocTimer::id_autoLockTimer);
unsigned int curEntryIndex = 0;
if (!(view->getCurEntryIndex(&curEntryIndex))) {
printDebug("couldn't get index");
curDoc()->timer()->putLock(DocTimer::id_autoLockTimer);
return;
}
PwMDataItem currItem;
QString curCategory = view->getCurrentCategory();
if (!curDoc()->getEntry(curCategory, curEntryIndex, &currItem)) {
printDebug("couldn't get entry");
curDoc()->timer()->putLock(DocTimer::id_autoLockTimer);
return;
}
if (KMessageBox::
questionYesNo(this,
i18n
("Do you really want to delete\nthe selected entry") +
" \n\"" + QString(currItem.desc.c_str())
+ "\" ?", i18n("delete?"))
== KMessageBox::Yes) {
curDoc()->delEntry(curCategory, curEntryIndex);
}
curDoc()->timer()->putLock(DocTimer::id_autoLockTimer);
}
void PwM::changeMasterPwd_slot()
{
PWM_ASSERT(curDoc());
curDoc()->changeCurrentPw();
}
void PwM::lockWnd_slot()
{
PWM_ASSERT(curDoc());
curDoc()->lockAll(true);
}
void PwM::deepLockWnd_slot()
{
PWM_ASSERT(curDoc());
curDoc()->deepLock();
}
void PwM::unlockWnd_slot()
{
PWM_ASSERT(curDoc());
curDoc()->lockAll(false);
}
void PwM::config_slot()
{
int oldStyle = conf()->confWndMainViewStyle();
#ifdef PWM_EMBEDDED
KCMultiDialog* ConfigureDialog = new KCMultiDialog( "PIM", this ,"pwmconfigdialog", true );
KCMPwmConfig* pwmcfg = new KCMPwmConfig( ConfigureDialog->getNewVBoxPage(i18n( "PwManager")) , "KCMPwmConfig" );
ConfigureDialog->addModule(pwmcfg );
KCMKdePimConfig* kdelibcfg = new KCMKdePimConfig( ConfigureDialog->getNewVBoxPage(i18n( "Global")) , "KCMKdeLibConfig" );
ConfigureDialog->addModule(kdelibcfg );
#ifndef DESKTOP_VERSION
ConfigureDialog->showMaximized();
#endif
if ( ConfigureDialog->exec() )
KMessageBox::information( this, i18n("Some changes are only\neffective after a restart!\n") );
delete ConfigureDialog;
#else //PWM_EMBEDDED
// display the configuration window (modal mode)
if (!conf()->showConfWnd(this))
return;
#endif
int newStyle = conf()->confWndMainViewStyle();
// reinitialize tray
init->initTray();
// reinitialize KWallet emulation
init->initKWalletEmu();
PwMDocList *_dl = PwMDoc::getOpenDocList();
const vector<PwMDocList::listItem> *dl = _dl->getList();
vector<PwMDocList::listItem>::const_iterator i = dl->begin(),
end = dl->end();
PwMDoc *doc;
while (i != end) {
doc = (*i).doc;
// unlock-without-mpw timeout
doc->timer()->start(DocTimer::id_mpwTimer);
// auto-lock timeout
doc->timer()->start(DocTimer::id_autoLockTimer);
++i;
}
const QValueList<PwM *> *ml = init->mainWndList();
#ifndef PWM_EMBEDDED
QValueList<PwM *>::const_iterator i2 = ml->begin(),
end2 = ml->end();
#else
QValueList<PwM *>::ConstIterator i2 = ml->begin(),
end2 = ml->end();
#endif
PwM *pwm;
while (i2 != end2) {
pwm = *i2;
// reinitialize the window style.
if (oldStyle != newStyle)
pwm->curView()->initStyle(newStyle);
// set the new font
pwm->curView()->setFont(conf()->confGlobEntryFont());
++i2;
}
}
void PwM::activateMpButton(bool activate)
{
managePopup->setItemEnabled(BUTTON_POPUP_MANAGE_CHANGEMP, activate);
}
void PwM::closeEvent(QCloseEvent *e)
{
//qDebug("PwM::closeEvent ");
emit closed( this );
return;
e->accept();
}
void PwM::docClosed(PwMDoc *doc)
{
//qDebug("PwM::docClosed ");
PARAM_UNUSED(doc);
PWM_ASSERT(doc == curDoc());
close();
}
void PwM::find_slot()
{
PWM_ASSERT(curDoc());
if (curDoc()->isDocEmpty())
return;
if (curDoc()->isDeepLocked())
return;
curDoc()->timer()->getLock(DocTimer::id_autoLockTimer);
FindWndImpl findWnd(view);
findWnd.exec();
curDoc()->timer()->putLock(DocTimer::id_autoLockTimer);
}
void PwM::exportToText()
{
PWM_ASSERT(curDoc());
if (curDoc()->isDocEmpty()) {
KMessageBox::information(this,
i18n
("Sorry, there's nothing to export.\n"
"Please first add some passwords."),
i18n("nothing to do"));
return;
}
curDoc()->timer()->getLock(DocTimer::id_autoLockTimer);
QString fn(KFileDialog::getSaveFileName(QString::null,
i18n("*|plain-text file"),
this));
if (fn == "") {
curDoc()->timer()->putLock(DocTimer::id_autoLockTimer);
return;
}
PwMerror ret = curDoc()->exportToText(&fn);
if (ret != e_success) {
KMessageBox::error(this,
i18n("Error: Couldn't write to file.\n"
"Please check if you have permission to write\n"
"to the file in that directory."),
i18n("error while writing"));
} else
showStatMsg(i18n("Successfully exported data."));
curDoc()->timer()->putLock(DocTimer::id_autoLockTimer);
}
bool PwM::importFromText()
{
if (!isVirgin()) {
if (KMessageBox::questionYesNo(this,
i18n("Do you want to import the data\n"
"into the current document? (If you\n"
"select \"no\", a new document will be\n"
"opened.)"),
i18n("import into this document?"))
== KMessageBox::No) {
// import the data to a new window.
PwM *newInstance = init->createMainWnd();
bool ok = newInstance->importFromText();
if (!ok) {
newInstance->setForceQuit(true);
delete_and_null(newInstance);
}
return ok;
}
}
curDoc()->timer()->getLock(DocTimer::id_autoLockTimer);
PwMerror ret;
QString path(KFileDialog::getOpenFileName(QString::null,
i18n("*|PWM-exported text file"),
this));
if (path == "")
goto cancelImport;
ret = curDoc()->importFromText(&path, 0);
if (ret == e_fileFormat) {
KMessageBox::error(this,
i18n("Could not read file-format.\n"
"This seems to be _not_ a valid file\n"
"exported by PwM."),
i18n("invalid file-format"));
goto cancelImport;
} else if (ret == e_invalidArg) {
BUG();
goto cancelImport;
} else if (ret != e_success) {
KMessageBox::error(this,
i18n("Could not import file!\n"
"Do you have permission to read this file?\n"
"Do you have enough free memory?"),
i18n("import failed"));
goto cancelImport;
}
setVirgin(false);
curDoc()->timer()->putLock(DocTimer::id_autoLockTimer);
return true;
cancelImport:
curDoc()->timer()->putLock(DocTimer::id_autoLockTimer);
return false;
}
void PwM::exportToGpasman()
{
PWM_ASSERT(curDoc());
if (curDoc()->isDocEmpty()) {
KMessageBox::information(this,
i18n
("Sorry, there's nothing to export.\n"
"Please first add some passwords."),
i18n("nothing to do"));
return;
}
curDoc()->timer()->getLock(DocTimer::id_autoLockTimer);
QString fn(KFileDialog::getSaveFileName(QString::null,
i18n("*|Gpasman or Kpasman file"),
this));
if (fn == "") {
curDoc()->timer()->putLock(DocTimer::id_autoLockTimer);
return;
}
PwMerror ret = curDoc()->exportToGpasman(&fn);
if (ret != e_success) {
if (ret == e_noPw) {
curDoc()->timer()->putLock(DocTimer::id_autoLockTimer);
return;
}
KMessageBox::error(this,
i18n("Error: Couldn't write to file.\n"
"Please check if you have permission to write "
"to the file in that directory."),
i18n("error while writing"));
} else
showStatMsg(i18n("Successfully exported data."));
curDoc()->timer()->putLock(DocTimer::id_autoLockTimer);
}
void PwM::exportToCsv()
{
PWM_ASSERT(curDoc());
if (curDoc()->isDocEmpty()) {
KMessageBox::information(this,
i18n
("Sorry, there is nothing to export;\n"
"please add some passwords first."),
i18n("Nothing to Do"));
return;
}
curDoc()->timer()->getLock(DocTimer::id_autoLockTimer);
QString fn(KFileDialog::getSaveFileName("*.csv", i18n("*|CSV Text File"), this));
if (fn.isEmpty()) {
curDoc()->timer()->putLock(DocTimer::id_autoLockTimer);
return;
}
Csv csv(this);
if (!csv.exportData(fn, curDoc())) {
curDoc()->timer()->putLock(DocTimer::id_autoLockTimer);
showStatMsg(i18n("CSV file export failed."));
return;
}
showStatMsg(i18n("Successfully exported data."));
curDoc()->timer()->putLock(DocTimer::id_autoLockTimer);
}
bool PwM::importCsv()
{
Csv csv(this);
if (!isVirgin()) {
if (KMessageBox::questionYesNo(this,
i18n("Do you want to import the data\n"
"into the current document? (If you\n"
"select \"no\", a new document will be\n"
"opened.)"),
i18n("Import into This Document?"))
== KMessageBox::No) {
// import the data to a new window.
PwM *newInstance = init->createMainWnd();
bool ok = newInstance->importCsv();
if (!ok) {
newInstance->setForceQuit(true);
delete_and_null(newInstance);
}
return ok;
}
}
QString filename = KFileDialog::getOpenFileName("*.csv", i18n("*|CSV Text File"), this);
if (filename.isEmpty())
return false;
curDoc()->timer()->getLock(DocTimer::id_autoLockTimer);
if (!csv.importData(filename, curDoc())) {
curDoc()->timer()->putLock(DocTimer::id_autoLockTimer);
showStatMsg(i18n("CSV file import failed."));
return false;
}
curDoc()->timer()->putLock(DocTimer::id_autoLockTimer);
KMessageBox::information(this,
i18n("Successfully imported the CSV data\n"
"into the current document."), i18n("Successfully Imported"));
showStatMsg(i18n("Successfully imported"));
setVirgin(false);
return true;
}
void PwM::exportToKWallet()
{
#ifdef CONFIG_KWALLETIF
if (!checkAndAskForKWalletEmu())
return;
PWM_ASSERT(curDoc());
if (curDoc()->isDocEmpty()) {
KMessageBox::information(this,
i18n
("Sorry, there's nothing to export.\n"
"Please first add some passwords."),
i18n("nothing to do"));
init->initKWalletEmu();
return;
}
curDoc()->timer()->getLock(DocTimer::id_autoLockTimer);
KWalletIf walletIf(this);
if (walletIf.kwalletExport(curDoc())) {
KMessageBox::information(this,
i18n("Successfully exported the data of the current "
"document to KWallet."),
i18n("Successfully exported data."));
showStatMsg(i18n("Successfully exported data."));
}
init->initKWalletEmu();
curDoc()->timer()->putLock(DocTimer::id_autoLockTimer);
#endif // CONFIG_KWALLETIF
}
bool PwM::importFromGpasman()
{
if (!isVirgin()) {
if (KMessageBox::questionYesNo(this,
i18n("Do you want to import the data\n"
"into the current document? (If you\n"
"select \"no\", a new document will be\n"
"opened.)"),
i18n("import into this document?"))
== KMessageBox::No) {
// import the data to a new window.
PwM *newInstance = init->createMainWnd();
bool ok = newInstance->importFromGpasman();
if (!ok) {
newInstance->setForceQuit(true);
delete_and_null(newInstance);
}
return ok;
}
}
curDoc()->timer()->getLock(DocTimer::id_autoLockTimer);
PwMerror ret;
QString path(KFileDialog::getOpenFileName(QString::null,
i18n("*|Gpasman or Kpasman file"), this));
if (path == "")
goto cancelImport;
ret = curDoc()->importFromGpasman(&path);
if (ret == e_wrongPw) {
if (KMessageBox::questionYesNo(this,
i18n
("This is probably the wrong master-password\n"
"you have typed in.\n"
"There is no real way to determine the\n"
"correctness of the password in the Gpasman\n"
"file-format. But I think this\n"
"password ist wrong.\n"
"Do you want to continue nevertheless?"),
i18n("password error"))
== KMessageBox::No) {
goto cancelImport;
}
} else if (ret != e_success) {
KMessageBox::error(this,
i18n("Could not import file!\n"
"Do you have permission to read this file?"),
i18n("import failed"));
goto cancelImport;
}
setVirgin(false);
curDoc()->timer()->putLock(DocTimer::id_autoLockTimer);
return true;
cancelImport:
curDoc()->timer()->putLock(DocTimer::id_autoLockTimer);
return false;
}
#ifdef CONFIG_KWALLETIF
bool PwM::checkAndAskForKWalletEmu()
{
if (init->kwalletEmu()) {
/* KWallet emulation is enabled. We can't import/export
* data from/to it, while emulation is active.
*/
if (KMessageBox::questionYesNo(this,
i18n("KWallet emulation is enabled.\n"
"You can't import or export data from/to "
"the original KWallet, while the emulation "
"is active.\n"
"Do you want to tempoarly disable the KWallet emulation?"),
i18n("Tempoarly disable KWallet emulation?"))
== KMessageBox::Yes) {
init->initKWalletEmu(true);
PWM_ASSERT(!init->kwalletEmu());
return true;
}
return false;
}
return true;
}
#endif // CONFIG_KWALLETIF
bool PwM::importKWallet()
{
#ifdef CONFIG_KWALLETIF
if (!checkAndAskForKWalletEmu())
return false;
KWalletIf walletIf(this);
if (!isVirgin()) {
if (KMessageBox::questionYesNo(this,
i18n("Do you want to import the data "
"into the current document? (If you "
"select \"no\", a new document will be "
"opened.)"),
i18n("import into this document?"))
== KMessageBox::No) {
// import the data to a new window.
PwM *newInstance = init->createMainWnd();
bool ok = newInstance->importKWallet();
if (!ok) {
newInstance->setForceQuit(true);
delete_and_null(newInstance);
goto exit_fail;
} else {
goto exit_ok;
}
}
}
curDoc()->timer()->getLock(DocTimer::id_autoLockTimer);
if (!walletIf.kwalletImport(curDoc())) {
curDoc()->timer()->putLock(DocTimer::id_autoLockTimer);
showStatMsg(i18n("KWallet import failed"));
goto exit_fail;
}
KMessageBox::information(this,
i18n("Successfully imported the KWallet data "
"into the current document."),
i18n("successfully imported"));
showStatMsg(i18n("successfully imported"));
setVirgin(false);
curDoc()->timer()->putLock(DocTimer::id_autoLockTimer);
exit_ok:
init->initKWalletEmu();
return true;
exit_fail:
init->initKWalletEmu();
#endif // CONFIG_KWALLETIF
return false;
}
void PwM::print_slot()
{
curDoc()->timer()->getLock(DocTimer::id_autoLockTimer);
#ifndef PWM_EMBEDDED
PwMPrint p(curDoc(), this);
p.printNow();
#else
qDebug("PwM::print_slot , PRINTING IS NOT IMPLEMENTED");
#endif
curDoc()->timer()->putLock(DocTimer::id_autoLockTimer);
}
void PwM::genNewCard_slot()
{
#ifdef CONFIG_KEYCARD
init->keycard()->genNewCard();
#endif
}
void PwM::eraseCard_slot()
{
#ifdef CONFIG_KEYCARD
init->keycard()->eraseCard();
#endif
}
void PwM::readCardId_slot()
{
#ifdef CONFIG_KEYCARD
init->keycard()->displayKey();
#endif
}
void PwM::makeCardBackup_slot()
{
#ifdef CONFIG_KEYCARD
init->keycard()->makeBackupImage();
#endif
}
void PwM::replayCardBackup_slot()
{
#ifdef CONFIG_KEYCARD
init->keycard()->replayBackupImage();
#endif
}
void PwM::execLauncher_slot()
{
PWM_ASSERT(curDoc());
if (curDoc()->isDeepLocked())
return;
unsigned int curEntryIndex;
if (!view->getCurEntryIndex(&curEntryIndex))
return;
bool ret = curDoc()->execLauncher(view->getCurrentCategory(),
curEntryIndex);
if (ret)
showStatMsg(i18n("Executed the \"Launcher\"."));
else
showStatMsg(i18n("ERROR: Couldn't execute the \"Launcher\"!"));
}
void PwM::goToURL_slot()
{
PWM_ASSERT(curDoc());
if (curDoc()->isDeepLocked())
return;
unsigned int curEntryIndex;
if (!view->getCurEntryIndex(&curEntryIndex))
return;
bool ret = curDoc()->goToURL(view->getCurrentCategory(),
curEntryIndex);
if (ret)
showStatMsg(i18n("started browser with current URL."));
else
showStatMsg(i18n("ERROR: Couldn't start browser! Maybe invalid URL?"));
}
void PwM::copyToClipboard(const QString &s)
{
QClipboard *cb = QApplication::clipboard();
#ifndef PWM_EMBEDDED
if (cb->supportsSelection())
cb->setText(s, QClipboard::Selection);
cb->setText(s, QClipboard::Clipboard);
#else
cb->setText(s);
#endif
}
void PwM::showStatMsg(const QString &msg)
{
#ifdef DESKTOP_VERSION
statusBar()->message(msg, STATUSBAR_MSG_TIMEOUT * 1000);
#else
//qDebug("Statusbar : %s",msg.latin1());
Global::statusMessage(msg);
#endif
}
void PwM::focusInEvent(QFocusEvent *e)
{
if (e->gotFocus()) {
emit gotFocus(this);
} else if (e->lostFocus()) {
emit lostFocus(this);
}
}
#ifdef PWM_EMBEDDED
void PwM::category_slot()
{
PwMDoc *doc = curDoc();
PWM_ASSERT(doc);
doc->timer()->getLock(DocTimer::id_autoLockTimer);
editCategoryWnd w(doc, this, "editcategory");
/*
vector<string> catList;
doc->getCategoryList(&catList);
unsigned i, size = catList.size();
for (i = 0; i < size; ++i) {
w.addCategory(catList[i].c_str());
}
w.setCurrCategory(view->getCurrentCategory());
if (pw)
w.pwLineEdit->setText(*pw);
*/
w.setCurrCategory(view->getCurrentCategory());
tryAgain:
if (w.exec() == 1)
{
PwMDataItem d;
//US BUG: to initialize all values of curEntr with meaningfulldata,
// we call clear on it. Reason: Metadata will be uninitialized otherwise.
// another option would be to create a constructor for PwMDataItem
d.clear(true);
/*
d.desc = w.getDescription().latin1();
d.name = w.getUsername().latin1();
d.pw = w.getPassword().latin1();
d.comment = w.getComment().latin1();
d.url = w.getUrl().latin1();
d.launcher = w.getLauncher().latin1();
PwMerror ret = doc->addEntry(w.getCategory(), &d);
if (ret == e_entryExists) {
KMessageBox::error(this,
i18n
("An entry with this \"Description\",\n"
"does already exist.\n"
"Please select another description."),
i18n("entry already exists."));
goto tryAgain;
} else if (ret == e_maxAllowedEntr) {
KMessageBox::error(this, i18n("The maximum possible number of\nentries"
"has been reached.\nYou can't add more entries."),
i18n("maximum number of entries"));
doc->timer()->putLock(DocTimer::id_autoLockTimer);
return;
}
*/
}
setVirgin(false);
doc->timer()->putLock(DocTimer::id_autoLockTimer);
}
void PwM::whatsnew_slot()
{
KApplication::showFile( "KDE-Pim/Pi Version Info", "kdepim/WhatsNew.txt" );
}
void PwM::showLicense_slot()
{
KApplication::showLicence();
}
void PwM::faq_slot()
{
KApplication::showFile( "PWM/Pi FAQ", "kdepim/pwmanager/pwmanagerFAQ.txt" );
}
void PwM::syncHowTo_slot()
{
KApplication::showFile( "KDE-Pim/Pi Synchronization HowTo", "kdepim/SyncHowto.txt" );
}
void PwM::createAboutData_slot()
{
QString version;
#include <../version>
;
QMessageBox::about( this, "About PwManager/Pi",
"PwManager/Platform-independent\n"
"(PWM/Pi) " +version + " - " +
#ifdef DESKTOP_VERSION
"Desktop Edition\n"
#else
"PDA-Edition\n"
"for: Zaurus 5500 / 7x0 / 8x0\n"
#endif
"(c) 2004 Ulf Schenk\n"
"(c) 2004 Lutz Rogowski\n"
diff --git a/pwmanager/pwmanager/pwmdoc.cpp b/pwmanager/pwmanager/pwmdoc.cpp
index 1f15ffd..6fbe110 100644
--- a/pwmanager/pwmanager/pwmdoc.cpp
+++ b/pwmanager/pwmanager/pwmdoc.cpp
@@ -476,1559 +476,1615 @@ PwMerror PwMDoc::saveDoc(char compress, const QString *file)
f.close();
ret = e_hashNotImpl;
goto out_moveback;
} else if (e != e_success) {
printDebug("PwMDoc::saveDoc(): writeDataHash() failed");
f.close();
ret = e_writeHeader;
goto out_moveback;
}
if (!compressDta(&serialized, compress)) {
printDebug("PwMDoc::saveDoc(): compressDta() failed");
f.close();
ret = e_enc;
goto out_moveback;
}
e = encrypt(&serialized, &currentPw, &f, cryptAlgo, hashAlgo);
if (e == e_weakPw) {
printDebug("PwMDoc::saveDoc(): encrypt() failed: e_weakPw");
f.close();
ret = e_weakPw;
goto out_moveback;
} else if (e == e_cryptNotImpl) {
printDebug("PwMDoc::saveDoc(): encrypt() failed: e_cryptNotImpl");
f.close();
ret = e_cryptNotImpl;
goto out_moveback;
} else if (e != e_success) {
printDebug("PwMDoc::saveDoc(): encrypt() failed");
f.close();
ret = e_enc;
goto out_moveback;
}
unsetDocStatFlag(DOC_STAT_DISK_DIRTY);
f.close();
#ifndef _WIN32_
if (chmod(filename.latin1(),
conf()->confGlobFilePermissions())) {
printWarn(string("chmod failed: ") + strerror(errno));
}
#endif
openDocList.edit(this, getTitle().latin1());
if (wasDeepLocked) {
/* Do _not_ save the data with the deepLock()
* call, because this will recurse
* into saveDoc()
*/
deepLock(true, false);
/* We don't check return value here, because
* it won't fail. See NOTE in deepLock()
*/
}
if (tmpFileMoved != QString::null) {
// now remove the moved file.
if (!QFile::remove(tmpFileMoved)) {
printWarn(string("removing file ")
+ tmpFileMoved.latin1()
+ " failed!");
}
}
ret = e_success;
printDebug(string("writing file { name: ")
+ filename.latin1() + " compress: "
+ tostr(static_cast<int>(compress)) + " cryptAlgo: "
+ tostr(static_cast<int>(cryptAlgo)) + " hashAlgo: "
+ tostr(static_cast<int>(hashAlgo))
+ " }");
goto out;
out_moveback:
if (tmpFileMoved != QString::null) {
if (copyFile(tmpFileMoved, filename)) {
if (!QFile::remove(tmpFileMoved)) {
printWarn(string("removing tmp file ")
+ filename.latin1()
+ " failed!");
}
} else {
printWarn(string("couldn't copy file ")
+ tmpFileMoved.latin1()
+ " back to "
+ filename.latin1());
}
}
out:
return ret;
}
PwMerror PwMDoc::openDoc(const QString *file, int openLocked)
{
PWM_ASSERT(file);
PWM_ASSERT(openLocked == 0 || openLocked == 1 || openLocked == 2);
string decrypted, dataHash;
PwMerror ret;
char cryptAlgo, dataHashType, compress;
unsigned int headerLen;
if (*file == "")
return e_readFile;
filename = *file;
/* check if this file is already open.
* This does not catch symlinks!
*/
if (!isDeepLocked()) {
if (getOpenDocList()->find(filename.latin1()))
return e_alreadyOpen;
}
QFile f(filename);
if (openLocked == 2) {
// open deep-locked
if (!QFile::exists(filename))
return e_openFile;
if (deepLock(true, false) != e_success)
return e_openFile;
goto out_success;
}
if (!f.open(IO_ReadOnly))
return e_openFile;
ret = checkHeader(&cryptAlgo, &currentPw, &compress, &headerLen,
&dataHashType, &dataHash, &f);
if (ret != e_success) {
printDebug("PwMDoc::openDoc(): checkHeader() failed");
f.close();
if (ret == e_wrongPw) {
wrongMpwMsgBox(getDocStatFlag(DOC_STAT_USE_CHIPCARD));
return ret;
} else if (ret == e_noPw ||
ret == e_fileVer ||
ret == e_fileFormat ||
ret == e_hashNotImpl) {
return ret;
} else
return e_readFile;
}
ret = decrypt(&decrypted, headerLen, &currentPw, cryptAlgo, dataHashType, &f);
if (ret == e_cryptNotImpl) {
printDebug("PwMDoc::openDoc(): decrypt() failed: e_cryptNotImpl");
f.close();
return e_cryptNotImpl;
} else if (ret != e_success) {
printDebug("PwMDoc::openDoc(): decrypt() failed");
f.close();
return e_readFile;
}
if (!decompressDta(&decrypted, compress)) {
printDebug("PwMDoc::openDoc(): decompressDta() failed");
f.close();
return e_fileCorrupt;
}
ret = checkDataHash(dataHashType, &dataHash, &decrypted);
if (ret == e_hashNotImpl) {
printDebug("PwMDoc::openDoc(): checkDataHash() failed: e_hashNotImpl");
f.close();
return e_hashNotImpl;
} else if (ret != e_success) {
printDebug("PwMDoc::openDoc(): checkDataHash() failed");
f.close();
return e_fileCorrupt;
}
if (!deSerializeDta(&decrypted, openLocked == 1)) {
printDebug("PwMDoc::openDoc(): deSerializeDta() failed");
f.close();
return e_readFile;
}
f.close();
timer()->start(DocTimer::id_mpwTimer);
timer()->start(DocTimer::id_autoLockTimer);
out_success:
openDocList.edit(this, getTitle().latin1());
emit docOpened(this);
return e_success;
}
PwMerror PwMDoc::writeFileHeader(char keyHash, char dataHash, char crypt, char compress,
QString *pw, QFile *f)
{
PWM_ASSERT(pw);
PWM_ASSERT(f);
//US ENH: or maybe a bug: checking here for listView does not make sense because we do not check anywhere else
//Wenn I sync, I open a doc without a view => listView is 0 => Assertion
//US PWM_ASSERT(listView);
if (f->writeBlock(FILE_ID_HEADER, strlen(FILE_ID_HEADER)) !=
static_cast<Q_LONG>(strlen(FILE_ID_HEADER))) {
return e_writeFile;
}
if (f->putch(PWM_FILE_VER) == -1 ||
f->putch(keyHash) == -1 ||
f->putch(dataHash) == -1 ||
f->putch(crypt) == -1 ||
f->putch(compress) == -1 ||
f->putch((getDocStatFlag(DOC_STAT_USE_CHIPCARD)) ?
(static_cast<char>(0x01)) : (static_cast<char>(0x00))) == -1) {
return e_writeFile;
}
// write bytes of NUL-data. These bytes are reserved for future-use.
const int bufSize = 64;
char tmp_buf[bufSize];
memset(tmp_buf, 0x00, bufSize);
if (f->writeBlock(tmp_buf, bufSize) != bufSize)
return e_writeFile;
switch (keyHash) {
case PWM_HASH_SHA1: {
const int hashlen = SHA1_HASH_LEN_BYTE;
Sha1 hash;
hash.sha1_write(reinterpret_cast<const byte *>(pw->latin1()), pw->length());
string ret = hash.sha1_read();
if (f->writeBlock(ret.c_str(), hashlen) != hashlen)
return e_writeFile;
break;
}
case PWM_HASH_SHA256:
/*... fall through */
case PWM_HASH_SHA384:
case PWM_HASH_SHA512:
case PWM_HASH_MD5:
case PWM_HASH_RMD160:
case PWM_HASH_TIGER:
{
if (!LibGCryptIf::available())
return e_hashNotImpl;
LibGCryptIf gc;
PwMerror err;
unsigned char *buf;
size_t hashLen;
err = gc.hash(&buf,
&hashLen,
reinterpret_cast<const unsigned char *>(pw->latin1()),
pw->length(),
keyHash);
if (err != e_success)
return e_hashNotImpl;
if (f->writeBlock(reinterpret_cast<const char *>(buf), hashLen)
!= static_cast<Q_LONG>(hashLen)) {
delete [] buf;
return e_hashNotImpl;
}
delete [] buf;
break;
}
default: {
return e_hashNotImpl;
} }
return e_success;
}
PwMerror PwMDoc::checkHeader(char *cryptAlgo, QString *pw, char *compress,
unsigned int *headerLength, char *dataHashType,
string *dataHash, QFile *f)
{
PWM_ASSERT(cryptAlgo);
PWM_ASSERT(pw);
PWM_ASSERT(headerLength);
PWM_ASSERT(dataHashType);
PWM_ASSERT(dataHash);
PWM_ASSERT(f);
int tmpRet;
// check "magic" header
const char magicHdr[] = FILE_ID_HEADER;
const int hdrLen = array_size(magicHdr) - 1;
char tmp[hdrLen];
if (f->readBlock(tmp, hdrLen) != hdrLen)
return e_readFile;
if (memcmp(tmp, magicHdr, hdrLen) != 0)
return e_fileFormat;
// read and check file ver
int fileV = f->getch();
if (fileV == -1)
return e_fileFormat;
if (fileV != PWM_FILE_VER)
return e_fileVer;
// read hash hash type
int keyHash = f->getch();
if (keyHash == -1)
return e_fileFormat;
// read data hash type
tmpRet = f->getch();
if (tmpRet == -1)
return e_fileFormat;
*dataHashType = tmpRet;
// read crypt algo
tmpRet = f->getch();
if (tmpRet == -1)
return e_fileFormat;
*cryptAlgo = tmpRet;
// get compression-algo
tmpRet = f->getch();
if (tmpRet == -1)
return e_fileFormat;
*compress = tmpRet;
// get the MPW-flag
int mpw_flag = f->getch();
if (mpw_flag == -1)
return e_fileFormat;
if (mpw_flag == 0x01)
setDocStatFlag(DOC_STAT_USE_CHIPCARD);
else
unsetDocStatFlag(DOC_STAT_USE_CHIPCARD);
// skip the "RESERVED"-bytes
if (!(f->at(f->at() + 64)))
return e_fileFormat;
*pw = requestMpw(getDocStatFlag(DOC_STAT_USE_CHIPCARD));
if (*pw == "") {
/* the user didn't give a master-password
* or didn't insert a chipcard
*/
return e_noPw;
}
// verify key-hash
switch (keyHash) {
case PWM_HASH_SHA1: {
// read hash from header
const int hashLen = SHA1_HASH_LEN_BYTE;
string readHash;
int i;
for (i = 0; i < hashLen; ++i)
readHash.push_back(f->getch());
Sha1 hash;
hash.sha1_write(reinterpret_cast<const byte *>(pw->latin1()), pw->length());
string ret = hash.sha1_read();
if (ret != readHash)
return e_wrongPw; // hash doesn't match (wrong key)
break;
}
case PWM_HASH_SHA256:
/*... fall through */
case PWM_HASH_SHA384:
case PWM_HASH_SHA512:
case PWM_HASH_MD5:
case PWM_HASH_RMD160:
case PWM_HASH_TIGER: {
if (!LibGCryptIf::available())
return e_hashNotImpl;
LibGCryptIf gc;
PwMerror err;
unsigned char *buf;
size_t hashLen;
err = gc.hash(&buf,
&hashLen,
reinterpret_cast<const unsigned char *>(pw->latin1()),
pw->length(),
keyHash);
if (err != e_success)
return e_hashNotImpl;
string calcHash(reinterpret_cast<const char *>(buf),
static_cast<string::size_type>(hashLen));
delete [] buf;
// read hash from header
string readHash;
size_t i;
for (i = 0; i < hashLen; ++i)
readHash.push_back(f->getch());
if (calcHash != readHash)
return e_wrongPw; // hash doesn't match (wrong key)
break;
}
default: {
return e_hashNotImpl;
} }
// read the data-hash from the file
unsigned int hashLen, i;
switch (*dataHashType) {
case PWM_HASH_SHA1:
hashLen = SHA1_HASH_LEN_BYTE;
break;
case PWM_HASH_SHA256:
/*... fall through */
case PWM_HASH_SHA384:
case PWM_HASH_SHA512:
case PWM_HASH_MD5:
case PWM_HASH_RMD160:
case PWM_HASH_TIGER: {
if (!LibGCryptIf::available())
return e_hashNotImpl;
LibGCryptIf gc;
hashLen = gc.hashLength(*dataHashType);
if (hashLen == 0)
return e_hashNotImpl;
break;
}
default:
return e_hashNotImpl;
}
*dataHash = "";
for (i = 0; i < hashLen; ++i) {
tmpRet = f->getch();
if (tmpRet == -1)
return e_fileFormat;
dataHash->push_back(static_cast<char>(tmpRet));
}
*headerLength = f->at();
#ifndef PWM_EMBEDDED
printDebug(string("opening file { compress: ")
+ tostr(static_cast<int>(*compress)) + " cryptAlgo: "
+ tostr(static_cast<int>(*cryptAlgo)) + " keyHashAlgo: "
+ tostr(static_cast<int>(keyHash))
+ " }");
#else
printDebug(string("opening file { compress: ")
+ tostr((int)(*compress)) + " cryptAlgo: "
+ tostr((int)(*cryptAlgo)) + " keyHashAlgo: "
+ tostr((int)(keyHash))
+ " }");
#endif
return e_success;
}
PwMerror PwMDoc::writeDataHash(char dataHash, string *d, QFile *f)
{
PWM_ASSERT(d);
PWM_ASSERT(f);
switch (dataHash) {
case PWM_HASH_SHA1: {
const int hashLen = SHA1_HASH_LEN_BYTE;
Sha1 h;
h.sha1_write(reinterpret_cast<const byte *>(d->c_str()), d->size());
string hRet = h.sha1_read();
if (f->writeBlock(hRet.c_str(), hashLen) != hashLen)
return e_writeFile;
break;
}
case PWM_HASH_SHA256:
/*... fall through */
case PWM_HASH_SHA384:
case PWM_HASH_SHA512:
case PWM_HASH_MD5:
case PWM_HASH_RMD160:
case PWM_HASH_TIGER: {
if (!LibGCryptIf::available())
return e_hashNotImpl;
LibGCryptIf gc;
PwMerror err;
unsigned char *buf;
size_t hashLen;
err = gc.hash(&buf,
&hashLen,
reinterpret_cast<const unsigned char *>(d->c_str()),
d->size(),
dataHash);
if (err != e_success)
return e_hashNotImpl;
if (f->writeBlock(reinterpret_cast<const char *>(buf), hashLen)
!= static_cast<Q_LONG>(hashLen)) {
delete [] buf;
return e_hashNotImpl;
}
delete [] buf;
break;
}
default: {
return e_hashNotImpl;
} }
return e_success;
}
bool PwMDoc::backupFile(const QString &filePath)
{
QFileInfo fi(filePath);
if (!fi.exists())
return true; // Yes, true is correct.
QString pathOnly(fi.dirPath(true));
QString nameOnly(fi.fileName());
QString backupPath = pathOnly
+ "/~"
+ nameOnly
+ ".backup";
return copyFile(filePath, backupPath);
}
bool PwMDoc::copyFile(const QString &src, const QString &dst)
{
QFileInfo fi(src);
if (!fi.exists())
return false;
if (QFile::exists(dst)) {
if (!QFile::remove(dst))
return false;
}
QFile srcFd(src);
if (!srcFd.open(IO_ReadOnly))
return false;
QFile dstFd(dst);
if (!dstFd.open(IO_ReadWrite)) {
srcFd.close();
return false;
}
const int tmpBuf_size = 512;
char tmpBuf[tmpBuf_size];
Q_LONG bytesRead, bytesWritten;
while (!srcFd.atEnd()) {
bytesRead = srcFd.readBlock(tmpBuf,
static_cast<Q_ULONG>(tmpBuf_size));
if (bytesRead == -1) {
srcFd.close();
dstFd.close();
return false;
}
bytesWritten = dstFd.writeBlock(tmpBuf,
static_cast<Q_ULONG>(bytesRead));
if (bytesWritten != bytesRead) {
srcFd.close();
dstFd.close();
return false;
}
}
srcFd.close();
dstFd.close();
return true;
}
PwMerror PwMDoc::addEntry(const QString &category, PwMDataItem *d,
bool dontFlagDirty, bool updateMeta)
{
PWM_ASSERT(d);
unsigned int cat = 0;
if (isDeepLocked()) {
PwMerror ret;
ret = deepLock(false);
if (ret != e_success)
return e_lock;
}
addCategory(category, &cat);
if (numEntries(category) >= maxEntries)
return e_maxAllowedEntr;
vector<unsigned int> foundPositions;
/* historically this was:
* const int searchIn = SEARCH_IN_DESC | SEARCH_IN_NAME |
* SEARCH_IN_URL | SEARCH_IN_LAUNCHER;
* But for now we only search in desc.
* That's a tweak to be KWallet compatible. But it should not add
* usability-drop onto PwManager, does it?
* (And yes, "int" was a bug. Correct is "unsigned int")
*/
const unsigned int searchIn = SEARCH_IN_DESC;
findEntry(cat, *d, searchIn, &foundPositions, true);
if (foundPositions.size()) {
// DOH! We found this entry.
return e_entryExists;
}
d->listViewPos = -1;
d->lockStat = conf()->confGlobNewEntrLockStat();
if (updateMeta) {
d->meta.create = QDateTime::currentDateTime();
d->meta.update = d->meta.create;
}
dti.dta[cat].d.push_back(*d);
delAllEmptyCat(true);
if (!dontFlagDirty)
flagDirty();
return e_success;
}
PwMerror PwMDoc::addCategory(const QString &category, unsigned int *categoryIndex,
bool checkIfExist)
{
if (isDeepLocked()) {
PwMerror ret;
ret = deepLock(false);
if (ret != e_success)
return e_lock;
}
if (checkIfExist) {
if (findCategory(category, categoryIndex))
return e_categoryExists;
}
PwMCategoryItem item;
//US ENH: clear item to initialize with default values, or create a constructor
item.clear();
item.name = category.latin1();
dti.dta.push_back(item);
if (categoryIndex)
*categoryIndex = dti.dta.size() - 1;
return e_success;
}
bool PwMDoc::delEntry(const QString &category, unsigned int index, bool dontFlagDirty)
{
unsigned int cat = 0;
if (!findCategory(category, &cat)) {
BUG();
return false;
}
return delEntry(cat, index, dontFlagDirty);
}
bool PwMDoc::delEntry(unsigned int category, unsigned int index, bool dontFlagDirty)
{
if (isDeepLocked())
return false;
if (index > dti.dta[category].d.size() - 1)
return false;
getDataChangedLock();
if (!lockAt(category, index, false)) {
putDataChangedLock();
return false;
}
putDataChangedLock();
int lvPos = dti.dta[category].d[index].listViewPos;
// delete entry
dti.dta[category].d.erase(dti.dta[category].d.begin() + index);
unsigned int i, entries = numEntries(category);
if (!entries) {
// no more entries in this category, so
// we can delete it, too.
BUG_ON(!delCategory(category));
// delCategory() flags it dirty, so we need not to do so.
return true;
}
for (i = 0; i < entries; ++i) {
// decrement all listViewPositions that are greater than the deleted.
if (dti.dta[category].d[i].listViewPos > lvPos)
--dti.dta[category].d[i].listViewPos;
}
if (!dontFlagDirty)
flagDirty();
return true;
}
bool PwMDoc::editEntry(const QString &oldCategory, const QString &newCategory,
unsigned int index, PwMDataItem *d, bool updateMeta)
{
PWM_ASSERT(d);
unsigned int oldCat = 0;
if (!findCategory(oldCategory, &oldCat)) {
BUG();
return false;
}
return editEntry(oldCat, newCategory, index, d, updateMeta);
}
bool PwMDoc::editEntry(unsigned int oldCategory, const QString &newCategory,
unsigned int index, PwMDataItem *d, bool updateMeta)
{
if (isDeepLocked())
return false;
if (updateMeta) {
d->meta.update = QDateTime::currentDateTime();
if (d->meta.create.isNull()) {
d->meta.create = d->meta.update;
}
}
if (dti.dta[oldCategory].name != newCategory.latin1()) {
// the user changed the category.
PwMerror ret;
d->rev = 0;
ret = addEntry(newCategory, d, true, false);
if (ret != e_success)
return false;
if (!delEntry(oldCategory, index, true))
return false;
} else {
d->rev = dti.dta[oldCategory].d[index].rev + 1; // increment revision counter.
dti.dta[oldCategory].d[index] = *d;
}
flagDirty();
return true;
}
unsigned int PwMDoc::numEntries(const QString &category)
{
unsigned int cat = 0;
if (!findCategory(category, &cat)) {
BUG();
return 0;
}
return numEntries(cat);
}
bool PwMDoc::serializeDta(string *d)
{
PWM_ASSERT(d);
Serializer ser;
if (!ser.serialize(dti))
return false;
d->assign(ser.getXml());
if (!d->size())
return false;
return true;
}
bool PwMDoc::deSerializeDta(const string *d, bool entriesLocked)
{
PWM_ASSERT(d);
#ifndef PWM_EMBEDDED
try {
Serializer ser(d->c_str());
ser.setDefaultLockStat(entriesLocked);
if (!ser.deSerialize(&dti))
return false;
} catch (PwMException) {
return false;
}
#else
Serializer ser(d->c_str());
ser.setDefaultLockStat(entriesLocked);
if (!ser.deSerialize(&dti))
return false;
#endif
emitDataChanged(this);
return true;
}
bool PwMDoc::getEntry(const QString &category, unsigned int index,
PwMDataItem * d, bool unlockIfLocked)
{
PWM_ASSERT(d);
unsigned int cat = 0;
if (!findCategory(category, &cat)) {
BUG();
return false;
}
return getEntry(cat, index, d, unlockIfLocked);
}
bool PwMDoc::getEntry(unsigned int category, unsigned int index,
PwMDataItem *d, bool unlockIfLocked)
{
if (index > dti.dta[category].d.size() - 1)
return false;
bool locked = isLocked(category, index);
if (locked) {
/* this entry is locked. We don't return a password,
* until it's unlocked by the user by inserting
* chipcard or entering the mpw
*/
if (unlockIfLocked) {
if (!lockAt(category, index, false)) {
return false;
}
locked = false;
}
}
*d = dti.dta[category].d[index];
if (locked)
d->pw = LOCKED_STRING.latin1();
return true;
}
-
PwMerror PwMDoc::getCommentByLvp(const QString &category, int listViewPos,
string *foundComment)
{
PWM_ASSERT(foundComment);
unsigned int cat = 0;
if (!findCategory(category, &cat))
return e_invalidArg;
unsigned int i, entries = numEntries(cat);
for (i = 0; i < entries; ++i) {
if (dti.dta[cat].d[i].listViewPos == listViewPos) {
*foundComment = dti.dta[cat].d[i].comment;
if (dti.dta[cat].d[i].binary)
return e_binEntry;
return e_normalEntry;
}
}
BUG();
return e_generic;
}
+PwMerror PwMDoc::getCommentByLvp_long(const QString &category, int listViewPos,
+ string *foundComment)
+{
+ PWM_ASSERT(foundComment);
+ unsigned int cat = 0;
+
+ if (!findCategory(category, &cat))
+ return e_invalidArg;
+
+ unsigned int i, entries = numEntries(cat);
+ for (i = 0; i < entries; ++i) {
+ if (dti.dta[cat].d[i].listViewPos == listViewPos) {
+ if (dti.dta[cat].d[i].binary)
+ return e_binEntry;
+ PwMCategoryItem* catItem = getCategoryEntry(cat);
+ QString retval;
+ QString tempval = QString (dti.dta[cat].d[i].desc.c_str());
+ if ( !tempval.isEmpty() ) {
+ retval += "<b>" +QString ( catItem->desc_text.c_str() )+ ":</b> "+ tempval+"<br>" ;
+ }
+ tempval = QString (dti.dta[cat].d[i].name.c_str());
+ if ( !tempval.isEmpty() ) {
+ retval += "<b>" +QString ( catItem->name_text.c_str() ) + ":</b> "+ tempval+"<br>" ;
+ }
+ tempval = QString (dti.dta[cat].d[i].pw.c_str());
+ if ( !tempval.isEmpty() ) {
+ if ( dti.dta[cat].d[i].lockStat )
+ retval += "<b>" +QString ( catItem->pw_text.c_str() )+ ":</b> " + i18n("<LOCKED>") +"<br>" ;
+ else
+ retval += "<b>" +QString ( catItem->pw_text.c_str() )+ ":</b> " + tempval+"<br>" ;
+ }
+ tempval = QString (dti.dta[cat].d[i].url.c_str());
+ if ( !tempval.isEmpty() ) {
+ retval += "<b>" +i18n("URL:")+ "</b> " + tempval+"<br>" ;
+ }
+ tempval = QString (dti.dta[cat].d[i].launcher.c_str());
+ if ( !tempval.isEmpty() ) {
+ retval += "<b>" +i18n("Launcher:")+ "</b> " + tempval+"<br>" ;
+ }
+ tempval = QString (dti.dta[cat].d[i].comment.c_str());
+ if ( !tempval.isEmpty() ) {
+ tempval.replace(QRegExp ( "\n" ), "<br>" );
+ retval += "<b>" +i18n("Comment:")+ "</b><br>" + tempval+"<br>" ;
+ }
+
+ string ret ( retval.latin1() );
+
+
+ // *foundComment = dti.dta[cat].d[i].comment;
+ *foundComment = ret;
+ return e_normalEntry;
+ }
+ }
+ BUG();
+ return e_generic;
+}
+
bool PwMDoc::compressDta(string *d, char algo)
{
PWM_ASSERT(d);
switch (algo) {
case PWM_COMPRESS_GZIP: {
CompressGzip comp;
return comp.compress(d);
}
#ifndef PWM_EMBEDDED
case PWM_COMPRESS_BZIP2: {
CompressBzip2 comp;
return comp.compress(d);
}
#endif
case PWM_COMPRESS_NONE: {
return true;
} default: {
BUG();
}
}
return false;
}
bool PwMDoc::decompressDta(string *d, char algo)
{
PWM_ASSERT(d);
switch (algo) {
case PWM_COMPRESS_GZIP: {
CompressGzip comp;
return comp.decompress(d);
}
#ifndef PWM_EMBEDDED
case PWM_COMPRESS_BZIP2: {
CompressBzip2 comp;
return comp.decompress(d);
}
#endif
case PWM_COMPRESS_NONE: {
return true;
}
}
return false;
}
PwMerror PwMDoc::encrypt(string *d, const QString *pw, QFile *f, char algo,
char hashalgo //US BUG: pass _hashalgo because we need it in hashPassphrase
)
{
PWM_ASSERT(d);
PWM_ASSERT(pw);
PWM_ASSERT(f);
size_t encSize;
byte *encrypted = 0;
switch (algo) {
case PWM_CRYPT_BLOWFISH: {
Blowfish::padNull(d);
encSize = d->length();
encrypted = new byte[encSize];
Blowfish bf;
if (bf.bf_setkey((byte *) pw->latin1(), pw->length())) {
delete [] encrypted;
return e_weakPw;
}
bf.bf_encrypt((byte *) encrypted, (byte *) d->c_str(), encSize);
break;
}
case PWM_CRYPT_AES128:
/*... fall through */
case PWM_CRYPT_AES192:
case PWM_CRYPT_AES256:
case PWM_CRYPT_3DES:
case PWM_CRYPT_TWOFISH:
case PWM_CRYPT_TWOFISH128: {
if (!LibGCryptIf::available())
return e_cryptNotImpl;
LibGCryptIf gc;
PwMerror err;
unsigned char *plain = new unsigned char[d->length() + 1024];
memcpy(plain, d->c_str(), d->length());
err = gc.encrypt(&encrypted,
&encSize,
plain,
d->length(),
reinterpret_cast<const unsigned char *>(pw->latin1()),
pw->length(),
algo,
hashalgo //US BUG: pass _hashalgo because we need it in hashPassphrase
);
delete [] plain;
if (err != e_success)
return e_cryptNotImpl;
break;
}
default: {
delete_ifnot_null_array(encrypted);
return e_cryptNotImpl;
} }
// write encrypted data to file
if (f->writeBlock(reinterpret_cast<const char *>(encrypted),
static_cast<Q_ULONG>(encSize))
!= static_cast<Q_LONG>(encSize)) {
delete_ifnot_null_array(encrypted);
return e_writeFile;
}
delete_ifnot_null_array(encrypted);
return e_success;
}
PwMerror PwMDoc::decrypt(string *d, unsigned int pos, const QString *pw,
char algo,
char hashalgo, //US BUG: pass _hashalgo because we need it in hashPassphrase
QFile *f)
{
PWM_ASSERT(d);
PWM_ASSERT(pw);
PWM_ASSERT(f);
unsigned int cryptLen = f->size() - pos;
byte *encrypted = new byte[cryptLen];
byte *decrypted = new byte[cryptLen];
f->at(pos);
#ifndef PWM_EMBEDDED
if (f->readBlock(reinterpret_cast<char *>(encrypted),
static_cast<Q_ULONG>(cryptLen))
!= static_cast<Q_LONG>(cryptLen)) {
delete [] encrypted;
delete [] decrypted;
return e_readFile;
}
#else
if (f->readBlock((char *)(encrypted),
(unsigned long)(cryptLen))
!= (long)(cryptLen)) {
delete [] encrypted;
delete [] decrypted;
return e_readFile;
}
#endif
switch (algo) {
case PWM_CRYPT_BLOWFISH: {
Blowfish bf;
bf.bf_setkey((byte *) pw->latin1(), pw->length());
bf.bf_decrypt(decrypted, encrypted, cryptLen);
break;
}
case PWM_CRYPT_AES128:
/*... fall through */
case PWM_CRYPT_AES192:
case PWM_CRYPT_AES256:
case PWM_CRYPT_3DES:
case PWM_CRYPT_TWOFISH:
case PWM_CRYPT_TWOFISH128: {
if (!LibGCryptIf::available())
return e_cryptNotImpl;
LibGCryptIf gc;
PwMerror err;
err = gc.decrypt(&decrypted,
&cryptLen,
encrypted,
cryptLen,
reinterpret_cast<const unsigned char *>(pw->latin1()),
pw->length(),
algo,
hashalgo //US BUG: pass _hashalgo because we need it in hashPassphrase
);
if (err != e_success) {
delete [] encrypted;
delete [] decrypted;
return e_cryptNotImpl;
}
break;
}
default: {
delete [] encrypted;
delete [] decrypted;
return e_cryptNotImpl;
} }
delete [] encrypted;
#ifndef PWM_EMBEDDED
d->assign(reinterpret_cast<const char *>(decrypted),
static_cast<string::size_type>(cryptLen));
#else
d->assign((const char *)(decrypted),
(string::size_type)(cryptLen));
#endif
delete [] decrypted;
if (algo == PWM_CRYPT_BLOWFISH) {
if (!Blowfish::unpadNull(d)) {
BUG();
return e_readFile;
}
}
return e_success;
}
PwMerror PwMDoc::checkDataHash(char dataHashType, const string *dataHash,
const string *dataStream)
{
PWM_ASSERT(dataHash);
PWM_ASSERT(dataStream);
switch(dataHashType) {
case PWM_HASH_SHA1: {
Sha1 hash;
hash.sha1_write((byte*)dataStream->c_str(), dataStream->length());
string ret = hash.sha1_read();
if (ret != *dataHash)
return e_fileCorrupt;
break;
}
case PWM_HASH_SHA256:
/*... fall through */
case PWM_HASH_SHA384:
case PWM_HASH_SHA512:
case PWM_HASH_MD5:
case PWM_HASH_RMD160:
case PWM_HASH_TIGER: {
if (!LibGCryptIf::available())
return e_hashNotImpl;
LibGCryptIf gc;
PwMerror err;
unsigned char *buf;
size_t hashLen;
err = gc.hash(&buf,
&hashLen,
reinterpret_cast<const unsigned char *>(dataStream->c_str()),
dataStream->length(),
dataHashType);
if (err != e_success)
return e_hashNotImpl;
string calcHash(reinterpret_cast<const char *>(buf),
static_cast<string::size_type>(hashLen));
delete [] buf;
if (calcHash != *dataHash)
return e_fileCorrupt;
break;
}
default:
return e_hashNotImpl;
}
return e_success;
}
bool PwMDoc::lockAt(unsigned int category, unsigned int index,
bool lock)
{
if (index >= numEntries(category)) {
BUG();
return false;
}
if (lock == dti.dta[category].d[index].lockStat)
return true;
if (!lock && currentPw != "") {
// "unlocking" and "password is already set"
if (!getDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW)) {
// unlocking without pw not allowed
QString pw;
pw = requestMpw(getDocStatFlag(DOC_STAT_USE_CHIPCARD));
if (pw != "") {
if (pw != currentPw) {
wrongMpwMsgBox(getDocStatFlag(DOC_STAT_USE_CHIPCARD));
return false;
} else {
timer()->start(DocTimer::id_mpwTimer);
}
} else {
return false;
}
} else {
timer()->start(DocTimer::id_mpwTimer);
}
}
dti.dta[category].d[index].lockStat = lock;
dti.dta[category].d[index].rev++; // increment revision counter.
emitDataChanged(this);
if (!lock)
timer()->start(DocTimer::id_autoLockTimer);
return true;
}
bool PwMDoc::lockAt(const QString &category,unsigned int index,
bool lock)
{
unsigned int cat = 0;
if (!findCategory(category, &cat)) {
BUG();
return false;
}
return lockAt(cat, index, lock);
}
bool PwMDoc::lockAll(bool lock)
{
if (!lock && isDeepLocked()) {
PwMerror ret;
ret = deepLock(false);
if (ret != e_success)
return false;
return true;
}
if (isDocEmpty()) {
return true;
}
if (!lock && currentPw != "") {
// unlocking and password is already set
if (!getDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW)) {
// unlocking without pw not allowed
QString pw;
pw = requestMpw(getDocStatFlag(DOC_STAT_USE_CHIPCARD));
if (pw != "") {
if (pw != currentPw) {
wrongMpwMsgBox(getDocStatFlag(DOC_STAT_USE_CHIPCARD));
return false;
} else {
timer()->start(DocTimer::id_mpwTimer);
}
} else {
return false;
}
} else {
timer()->start(DocTimer::id_mpwTimer);
}
}
vector<PwMCategoryItem>::iterator catBegin = dti.dta.begin(),
catEnd = dti.dta.end(),
catI = catBegin;
vector<PwMDataItem>::iterator entrBegin, entrEnd, entrI;
while (catI != catEnd) {
entrBegin = catI->d.begin();
entrEnd = catI->d.end();
entrI = entrBegin;
while (entrI != entrEnd) {
entrI->lockStat = lock;
entrI->rev++; // increment revision counter.
++entrI;
}
++catI;
}
emitDataChanged(this);
if (lock)
timer()->stop(DocTimer::id_autoLockTimer);
else
timer()->start(DocTimer::id_autoLockTimer);
return true;
}
bool PwMDoc::isLocked(const QString &category, unsigned int index)
{
unsigned int cat = 0;
if (!findCategory(category, &cat)) {
BUG();
return false;
}
return isLocked(cat, index);
}
bool PwMDoc::unlockAll_tempoary(bool revert)
{
static vector< vector<bool> > *oldLockStates = 0;
static bool wasDeepLocked;
if (revert) { // revert the unlocking
if (oldLockStates) {
/* we actually _have_ unlocked something, because
* we have allocated space for the oldLockStates.
* So, go on and revert them!
*/
if (wasDeepLocked) {
PwMerror ret = deepLock(true);
if (ret == e_success) {
/* deep-lock succeed. We are save.
* (but if it failed, just go on
* lock them normally)
*/
delete_and_null(oldLockStates);
timer()->start(DocTimer::id_autoLockTimer);
printDebug("tempoary unlocking of dta "
"reverted by deep-locking.");
return true;
}
printDebug("deep-lock failed while reverting! "
"Falling back to normal-lock.");
}
if (unlikely(!wasDeepLocked &&
numCategories() != oldLockStates->size())) {
/* DOH! We have modified "dta" while
* it was unlocked tempoary. DON'T DO THIS!
*/
BUG();
delete_and_null(oldLockStates);
timer()->start(DocTimer::id_autoLockTimer);
return false;
}
vector<PwMCategoryItem>::iterator catBegin = dti.dta.begin(),
catEnd = dti.dta.end(),
catI = catBegin;
vector<PwMDataItem>::iterator entrBegin, entrEnd, entrI;
vector< vector<bool> >::iterator oldCatStatI = oldLockStates->begin();
vector<bool>::iterator oldEntrStatBegin,
oldEntrStatEnd,
oldEntrStatI;
while (catI != catEnd) {
entrBegin = catI->d.begin();
entrEnd = catI->d.end();
entrI = entrBegin;
if (likely(!wasDeepLocked)) {
oldEntrStatBegin = oldCatStatI->begin();
oldEntrStatEnd = oldCatStatI->end();
oldEntrStatI = oldEntrStatBegin;
if (unlikely(catI->d.size() != oldCatStatI->size())) {
/* DOH! We have modified "dta" while
* it was unlocked tempoary. DON'T DO THIS!
*/
BUG();
delete_and_null(oldLockStates);
timer()->start(DocTimer::id_autoLockTimer);
return false;
}
}
while (entrI != entrEnd) {
if (wasDeepLocked) {
/* this is an error-fallback if
* deeplock didn't succeed
*/
entrI->lockStat = true;
} else {
entrI->lockStat = *oldEntrStatI;
}
++entrI;
if (likely(!wasDeepLocked))
++oldEntrStatI;
}
++catI;
if (likely(!wasDeepLocked))
++oldCatStatI;
}
delete_and_null(oldLockStates);
if (unlikely(wasDeepLocked)) {
/* error fallback... */
unsetDocStatFlag(DOC_STAT_DEEPLOCKED);
emitDataChanged(this);
printDebug("WARNING: unlockAll_tempoary(true) "
"deeplock fallback!");
}
printDebug("tempoary unlocking of dta reverted.");
} else {
printDebug("unlockAll_tempoary(true): nothing to do.");
}
timer()->start(DocTimer::id_autoLockTimer);
} else { // unlock all data tempoary
if (unlikely(oldLockStates != 0)) {
/* DOH! We have already unlocked the data tempoarly.
* No need to do it twice. ;)
*/
BUG();
return false;
}
wasDeepLocked = false;
bool mustUnlock = false;
if (isDeepLocked()) {
PwMerror ret;
while (1) {
ret = deepLock(false);
if (ret == e_success) {
break;
} else if (ret == e_wrongPw) {
wrongMpwMsgBox(getDocStatFlag(DOC_STAT_USE_CHIPCARD));
} else {
printDebug("deep-unlocking failed while "
"tempoary unlocking!");
return false;
}
}
wasDeepLocked = true;
mustUnlock = true;
} else {
// first check if it's needed to unlock some entries
vector<PwMCategoryItem>::iterator catBegin = dti.dta.begin(),
catEnd = dti.dta.end(),
catI = catBegin;
vector<PwMDataItem>::iterator entrBegin, entrEnd, entrI;
while (catI != catEnd) {
entrBegin = catI->d.begin();
entrEnd = catI->d.end();
entrI = entrBegin;
while (entrI != entrEnd) {
if (entrI->lockStat == true) {
mustUnlock = true;
break;
}
++entrI;
}
if (mustUnlock)
break;
++catI;
}
}
if (!mustUnlock) {
// nothing to do.
timer()->stop(DocTimer::id_autoLockTimer);
printDebug("unlockAll_tempoary(): nothing to do.");
return true;
} else if (!wasDeepLocked) {
if (!getDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW) &&
currentPw != "") {
/* we can't unlock without mpw, so
* we need to ask for it.
*/
QString pw;
while (1) {
pw = requestMpw(getDocStatFlag(DOC_STAT_USE_CHIPCARD));
if (pw == "") {
return false;
} else if (pw == currentPw) {
break;
}
wrongMpwMsgBox(getDocStatFlag(DOC_STAT_USE_CHIPCARD));
}
}
}
timer()->stop(DocTimer::id_autoLockTimer);
oldLockStates = new vector< vector<bool> >;
vector<bool> tmp_vec;
vector<PwMCategoryItem>::iterator catBegin = dti.dta.begin(),
catEnd = dti.dta.end(),
catI = catBegin;
vector<PwMDataItem>::iterator entrBegin, entrEnd, entrI;
while (catI != catEnd) {
entrBegin = catI->d.begin();
entrEnd = catI->d.end();
entrI = entrBegin;
while (entrI != entrEnd) {
if (!wasDeepLocked) {
tmp_vec.push_back(entrI->lockStat);
}
entrI->lockStat = false;
++entrI;
}
if (!wasDeepLocked) {
oldLockStates->push_back(tmp_vec);
tmp_vec.clear();
}
++catI;
}
printDebug("tempoary unlocked dta.");
}
return true;
}
PwMerror PwMDoc::deepLock(bool lock, bool saveToFile)
{
PwMerror ret;
/* NOTE: saveDoc() depends on this function to return
* e_success if saveToFile == false
*/
if (lock) {
if (isDeepLocked())
return e_lock;
if (saveToFile) {
if (isDocEmpty())
return e_docIsEmpty;
ret = saveDoc(conf()->confGlobCompression());
if (ret == e_filename) {
/* the doc wasn't saved to a file
* by the user, yet.
*/
cantDeeplock_notSavedMsgBox();
return e_docNotSaved;
} else if (ret != e_success) {
return e_lock;
}
}
timer()->stop(DocTimer::id_autoLockTimer);
clearDoc();
PwMDataItem d;
d.desc = IS_DEEPLOCKED_SHORTMSG.latin1();
d.comment = IS_DEEPLOCKED_MSG.latin1();
d.listViewPos = 0;
addEntry(DEFAULT_CATEGORY, &d, true);
lockAt(DEFAULT_CATEGORY, 0, true);
unsetDocStatFlag(DOC_STAT_DISK_DIRTY);
setDocStatFlag(DOC_STAT_DEEPLOCKED);
} else {
if (!isDeepLocked())
return e_lock;
ret = openDoc(&filename, (conf()->confGlobUnlockOnOpen())
? 0 : 1);
if (ret == e_wrongPw) {
return e_wrongPw;
} else if (ret != e_success) {
printDebug(string("PwMDoc::deepLock(false): ERR! openDoc() == ")
+ tostr(static_cast<int>(ret)));
return e_lock;
}
unsetDocStatFlag(DOC_STAT_DEEPLOCKED);
timer()->start(DocTimer::id_autoLockTimer);
}
emitDataChanged(this);
return e_success;
}
void PwMDoc::_deepUnlock()
{
deepLock(false);
}
void PwMDoc::clearDoc()
{
dti.clear();
PwMCategoryItem d;
//US ENH: to initialize all members with meaningfull data.
d.clear();
d.name = DEFAULT_CATEGORY.latin1();
dti.dta.push_back(d);
currentPw = "";
unsetDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW);
}
void PwMDoc::changeCurrentPw()
{
if (currentPw == "")
return; // doc hasn't been saved. No mpw available.
bool useChipcard = getDocStatFlag(DOC_STAT_USE_CHIPCARD);
QString pw = requestMpwChange(&currentPw, &useChipcard);
if (pw == "")
return;
if (useChipcard)
setDocStatFlag(DOC_STAT_USE_CHIPCARD);
else
unsetDocStatFlag(DOC_STAT_USE_CHIPCARD);
setCurrentPw(pw);
}
void PwMDoc::setListViewPos(const QString &category, unsigned int index,
int pos)
{
unsigned int cat = 0;
if (!findCategory(category, &cat)) {
BUG();
return;
}
setListViewPos(cat, index, pos);
}
void PwMDoc::setListViewPos(unsigned int category, unsigned int index,
int pos)
{
dti.dta[category].d[index].listViewPos = pos;
/* FIXME workaround: don't flag dirty, because this function sometimes
* get's called when it shouldn't. It's because PwMView assumes
* the user resorted the UI on behalf of signal layoutChanged().
* This is somewhat broken and incorrect, but I've no other
* solution for now.
*/
// setDocStatFlag(DOC_STAT_DISK_DIRTY);
}
int PwMDoc::getListViewPos(const QString &category, unsigned int index)
{
unsigned int cat = 0;
if (!findCategory(category, &cat)) {
BUG();
return -1;
}
return dti.dta[cat].d[index].listViewPos;
}
void PwMDoc::findEntry(unsigned int category, PwMDataItem find, unsigned int searchIn,
vector<unsigned int> *foundPositions, bool breakAfterFound,
bool caseSensitive, bool exactWordMatch, bool sortByLvp)
{
PWM_ASSERT(foundPositions);
PWM_ASSERT(searchIn);
foundPositions->clear();
unsigned int i, entries = numEntries(category);
for (i = 0; i < entries; ++i) {
if (searchIn & SEARCH_IN_DESC) {
if (!compareString(find.desc, dti.dta[category].d[i].desc,
caseSensitive, exactWordMatch)) {
continue;
}
}
if (searchIn & SEARCH_IN_NAME) {
if (!compareString(find.name, dti.dta[category].d[i].name,
caseSensitive, exactWordMatch)) {
continue;
}
}
if (searchIn & SEARCH_IN_PW) {
bool wasLocked = isLocked(category, i);
getDataChangedLock();
lockAt(category, i, false);
if (!compareString(find.pw, dti.dta[category].d[i].pw,
caseSensitive, exactWordMatch)) {
lockAt(category, i, wasLocked);
putDataChangedLock();
continue;
}
lockAt(category, i, wasLocked);
putDataChangedLock();
}
if (searchIn & SEARCH_IN_COMMENT) {
if (!compareString(find.comment, dti.dta[category].d[i].comment,
caseSensitive, exactWordMatch)) {
continue;
}
}
if (searchIn & SEARCH_IN_URL) {
if (!compareString(find.url, dti.dta[category].d[i].url,
caseSensitive, exactWordMatch)) {
continue;
}
}
if (searchIn & SEARCH_IN_LAUNCHER) {
if (!compareString(find.launcher, dti.dta[category].d[i].launcher,
caseSensitive, exactWordMatch)) {
continue;
}
}
// all selected "searchIn" matched.
foundPositions->push_back(i);
if (breakAfterFound)
break;
}
if (sortByLvp && foundPositions->size() > 1) {
vector< pair<unsigned int /* foundPosition (real doc pos) */,
unsigned int /* lvp-pos */> > tmp_vec;
unsigned int i, items = foundPositions->size();
pair<unsigned int, unsigned int> tmp_pair;
for (i = 0; i < items; ++i) {
tmp_pair.first = (*foundPositions)[i];
tmp_pair.second = dti.dta[category].d[(*foundPositions)[i]].listViewPos;
tmp_vec.push_back(tmp_pair);
}
sort(tmp_vec.begin(), tmp_vec.end(), dta_lvp_greater());
foundPositions->clear();
for (i = 0; i < items; ++i) {
foundPositions->push_back(tmp_vec[i].first);
}
}
}
diff --git a/pwmanager/pwmanager/pwmdoc.h b/pwmanager/pwmanager/pwmdoc.h
index 9fcdda7..45dd729 100644
--- a/pwmanager/pwmanager/pwmdoc.h
+++ b/pwmanager/pwmanager/pwmdoc.h
@@ -1,831 +1,833 @@
/***************************************************************************
* *
* copyright (C) 2003, 2004 by Michael Buesch *
* email: mbuesch@freenet.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 *
* as published by the Free Software Foundation. *
* *
***************************************************************************/
/***************************************************************************
* copyright (C) 2004 by Ulf Schenk
* This file is originaly based on version 1.1 of pwmanager
* and was modified to run on embedded devices that run microkde
*
* $Id$
**************************************************************************/
#ifndef __PWMDOC_H
#define __PWMDOC_H
#ifdef _WIN32_
#define ssize_t unsigned int
#endif
#define PWM_FILE_VER (static_cast<char>(0x05))
#define PWM_HASH_SHA1 (static_cast<char>(0x01))
#define PWM_HASH_SHA256 (static_cast<char>(0x02))
#define PWM_HASH_SHA384 (static_cast<char>(0x03))
#define PWM_HASH_SHA512 (static_cast<char>(0x04))
#define PWM_HASH_MD5 (static_cast<char>(0x05))
#define PWM_HASH_RMD160 (static_cast<char>(0x06))
#define PWM_HASH_TIGER (static_cast<char>(0x07))
#define PWM_CRYPT_BLOWFISH (static_cast<char>(0x01))
#define PWM_CRYPT_AES128 (static_cast<char>(0x02))
#define PWM_CRYPT_AES192 (static_cast<char>(0x03))
#define PWM_CRYPT_AES256 (static_cast<char>(0x04))
#define PWM_CRYPT_3DES (static_cast<char>(0x05))
#define PWM_CRYPT_TWOFISH (static_cast<char>(0x06))
#define PWM_CRYPT_TWOFISH128 (static_cast<char>(0x07))
#define PWM_COMPRESS_NONE (static_cast<char>(0x00))
#define PWM_COMPRESS_GZIP (static_cast<char>(0x01))
#define PWM_COMPRESS_BZIP2 (static_cast<char>(0x02))
#define DEFAULT_MAX_ENTRIES (~(static_cast<unsigned int>(0)))
#define FILE_ID_HEADER "PWM_PASSWORD_FILE"
#include "pwmexception.h"
#include "pwmdocui.h"
#include <qobject.h>
#include <qtimer.h>
#include <qdatetime.h>
#include <kprocess.h>
#ifndef PWM_EMBEDDED
#include "configuration.h"
#else
#include <kapplication.h>
#include <ksyncmanager.h>
#endif
#include <string>
#include <vector>
#include <utility>
using std::vector;
using std::string;
using std::pair;
/* used in findEntry() function */
#define SEARCH_IN_DESC (1)
#define SEARCH_IN_NAME (1 << 1)
#define SEARCH_IN_PW (1 << 2)
#define SEARCH_IN_COMMENT (1 << 3)
#define SEARCH_IN_URL (1 << 4)
#define SEARCH_IN_LAUNCHER (1 << 5)
#define SEARCH_IN_ALL (SEARCH_IN_DESC | SEARCH_IN_NAME | \
SEARCH_IN_PW | SEARCH_IN_COMMENT | \
SEARCH_IN_URL | SEARCH_IN_LAUNCHER)
/** document deeplocked. Data is out for lunch to disk */
#define DOC_STAT_DEEPLOCKED (1)
/** encrypted document on disk is dirty. data has to go to disk. */
#define DOC_STAT_DISK_DIRTY (1 << 1)
/** we are using a chipcard to encrypt the data */
#define DOC_STAT_USE_CHIPCARD (1 << 2)
/** use "currentPw" to unlock. (This flag is set/unset by a timer) */
#define DOC_STAT_UNLOCK_WITHOUT_PW (1 << 3)
class PwMDoc;
class PwMView;
class QFile;
/* meta data for a PwMDataItem */
struct PwMMetaData
{
PwMMetaData()
: updateInt (0)
{ }
/** creation date of the PwMDataItem to which
* this meta data belongs.
*/
QDateTime create;
/** becomes valid on this date */
QDateTime valid;
/** expire date */
QDateTime expire;
/** update date (last updated at this date) */
QDateTime update;
/** update interval (in minutes). Time since the
* last update to remind the user to update the item.
* 0 disables.
*/
unsigned long updateInt;
//US ENH: enhancements of the filestructure
/* each entry gets a unique id assigned */
string uniqueid;
void clear()
{
create = QDateTime();
expire = QDateTime();
update = QDateTime();
updateInt = 0;
uniqueid = KApplication::randomString(8).latin1();
}
inline bool isValid() const
{
if (valid.isNull())
return true;
return (valid < QDateTime::currentDateTime());
}
inline bool isExpired() const
{
if (expire.isNull())
return false;
return (expire < QDateTime::currentDateTime());
}
inline bool isUpdateIntOver() const
{
if (updateInt == 0 ||
update.isNull())
return false;
QDateTime d(update);
return (d.addSecs(updateInt * 60) < QDateTime::currentDateTime());
}
};
struct PwMDataItem
{
PwMDataItem()
: lockStat (true)
, listViewPos (-1)
, binary (false)
, rev (0)
{ }
/** password description */
string desc;
/** user-name */
string name;
/** the password itself */
string pw;
/** some comment */
string comment;
/** an URL string */
string url;
/** launcher. Can be executed as a system() command */
string launcher;
/** locking status. If locked (true), pw is not emitted through getEntry() */
bool lockStat;
/** position of this item in main "list-view"
* If -1, the position is not yet specified and should be appended to the list
*/
int listViewPos;
/** does this entry contain binary data? */
bool binary;
/** meta data for this data item. */
PwMMetaData meta;
/** data revision counter. This counter can be used
* to easily, efficiently determine if this data item
* has changed since some time.
* This counter is incremented on every update.
*/
unsigned int rev;
void clear(bool clearMeta = true)
{
/* NOTE: Don't use .clear() here to be
* backward compatible with gcc-2 (Debian Woody)
*/
desc = "";
name = "";
pw = "";
comment = "";
url = "";
launcher = "";
lockStat = true;
listViewPos = -1;
binary = false;
if (clearMeta)
meta.clear();
}
//US ENH: we need this operator to compare two items if we have no unique ids
//available. Generaly this happens before the first sync
bool PwMDataItem::operator==( const PwMDataItem &a ) const
{
//qDebug("oper==%s", a.desc.c_str());
if ( desc != a.desc ) return false;
if ( name != a.name ) return false;
if ( pw != a.pw ) return false;
if ( comment != a.comment ) return false;
if ( url != a.url ) return false;
if ( launcher != a.launcher ) return false;
//all other field will not be checked.
return true;
}
//US ENH: this sync method actually copies all values from the parameter like the =operator
//does with two exceptions: listViewPos will not be changed, and the launcher only if required.
bool PwMDataItem::syncItem(const PwMDataItem &a, bool syncLauncher=true )
{
desc = a.desc;
name = a.name;
pw = a.pw;
comment = a.comment;
url = a.url;
if (syncLauncher == true)
launcher = a.launcher;
meta = a.meta;
binary = a.binary;
lockStat = a.lockStat;
rev = a.rev;
return true;
}
};
struct PwMCategoryItem
{
/** all PwMDataItems (all passwords) within this category */
vector<PwMDataItem> d;
/** category name/description */
string name;
//US ENH: enhancements of the filestructure
/* each category stores the text for description,name and password */
string desc_text;
string name_text;
string pw_text;
void clear()
{
d.clear();
name = "";
desc_text = "Description";
name_text = "Username";
pw_text = "Password";
}
};
struct PwMSyncItem
{
string syncName;
QDateTime lastSyncDate;
void clear()
{
lastSyncDate = QDateTime();
syncName = "";
}
};
struct PwMItem
{
vector<PwMCategoryItem> dta;
vector<PwMSyncItem> syncDta;
void clear()
{
dta.clear();
syncDta.clear();
}
};
/** "Function Object" for sort()ing PwMDataItem::listViewPos */
class dta_lvp_greater
{
public:
bool operator() (const pair<unsigned int, unsigned int> &d1,
const pair<unsigned int, unsigned int> &d2)
{
return d1.second > d2.second;
}
};
/** list of PwMDoc documents and it's IDs */
class PwMDocList
{
public:
struct listItem
{
/** document filename (known as ID, here) */
string docId;
/** pointer to the document class */
PwMDoc *doc;
};
PwMDocList() {}
/** add a new item to the list */
void add(PwMDoc *doc, const string &id);
/** changes the contents of an existing item */
void edit(PwMDoc *doc, const string &newId);
/** remove the given item */
void del(PwMDoc *doc);
/** get the item at index */
listItem getAt(int index)
{ return docList[index]; }
/** find an entry with this id */
bool find(const string &id, listItem *ret = 0);
/** returns a copy of the list */
const vector<listItem>* getList() const
{ return &docList; }
/** returns a new unique number to extend the name of
* an unnamed document.
*/
static unsigned int getNewUnnamedNumber()
{ return unnamedDocCnt++; }
protected:
/* Hm, I think we shouldn't really use a "list" here, should we?
* So I decided to actually use a vector.
*/
vector<listItem> docList;
/** This value is used to get a new number for yet unnamed
* documents. It is incremented on every request. So it's
* theoretically possible to overflow it, but... :)
*/
static unsigned int unnamedDocCnt;
};
/** implements timers for the document */
class DocTimer : public QObject
{
Q_OBJECT
public:
enum TimerIDs
{
id_mpwTimer,
id_autoLockTimer,
id_metaCheckTimer
};
public:
DocTimer(PwMDoc *_doc);
~DocTimer();
/** start the timer */
void start(TimerIDs timer);
/** stop the timer */
void stop(TimerIDs timer);
/** get the lock for a timer.
* This lock is a recursive lock. When a lock is
* held, the timer will be stopped and timeout is
* guaranteed to not happen
*/
void getLock(TimerIDs timer);
/** put a recursive timer lock */
void putLock(TimerIDs timer);
protected slots:
/** timeout slot for the mpw timer */
void mpwTimeout();
/** timeout slot for the autoLock timer */
void autoLockTimeout();
/** timeout slot for the metaCheck timer */
void metaCheckTimeout();
protected:
/** pointer to the document associated with this timer. */
PwMDoc *doc;
/** timer object for mpw timer */
QTimer *mpwTimer;
/** timer object for the autoLock timer */
QTimer *autoLockTimer;
/** timer object for the metaCheck timer */
QTimer *metaCheckTimer;
/** lock counter for the mpw timer */
unsigned int mpwLock;
/** lock counter for the autoLock timer */
unsigned int autoLockLock;
/** lock counter for the metaCheck timer */
unsigned int metaCheckLock;
};
/** Document class for PwM */
//US ENH: derived from KSyncInterfaces, to get called by PwM when a sync is required.
// But PwMDoc is handling the sync by itself.
class PwMDoc : public PwMDocUi, public KSyncInterface
{
Q_OBJECT
friend class DocTimer;
public:
/** construtor */
PwMDoc(QObject* parent = 0, const char *name = 0);
/** destructor */
~PwMDoc();
/** returns a pointer to a list of all open documents */
static PwMDocList* getOpenDocList()
{ return &openDocList; }
/** flag document dirty. dta changed */
void flagDirty()
{
setDocStatFlag(DOC_STAT_DISK_DIRTY);
emitDataChanged(this);
}
/** modified? */
bool isDirty()
{ return getDocStatFlag(DOC_STAT_DISK_DIRTY); }
/** save document to disk */
PwMerror saveDoc(char compress, const QString *file = 0);
/** read document from file.
* "openLocked is must be set to either of these values:
* 0 == open with all entries unlocked
* 1 == open with all entries locked
* 2 == open deep-locked
*/
PwMerror openDoc(const QString *file, int openLocked);
/** export document to ascii-textfile */
PwMerror exportToText(const QString *file);
/** export document to gpasman / kpasman file */
PwMerror exportToGpasman(const QString *file);
/** import document from ascii-textfile */
PwMerror importFromText(const QString *file, int format = -1);
/** import document from gpasman / kpasman file */
PwMerror importFromGpasman(const QString *file);
/** add new entry */
PwMerror addEntry(const QString &category, PwMDataItem *d,
bool dontFlagDirty = false, bool updateMeta = true);
/** add new category. This function doesn't flag the document dirty! */
PwMerror addCategory(const QString &category, unsigned int *categoryIndex,
bool checkIfExist = true);
/** rename an existing category */
bool renameCategory(const QString &category, const QString &newName);
/** rename an existing category */
bool renameCategory(unsigned int category, const QString &newName,
bool dontFlagDirty = false);
/** delete an existing category */
bool delCategory(const QString &category);
/** delete an existing category */
bool delCategory(unsigned int category, bool dontFlagDirty = false);
/** returns a list of all category-names */
void getCategoryList(vector<string> *list);
/** returns a list of all category-names */
void getCategoryList(QStringList *list);
/** returns a list of all entry-descs in the given category */
void getEntryList(const QString &category, QStringList *list);
/** returns a list of all entry-descs in the given category */
void getEntryList(const QString &category, vector<string> *list);
/** returns a list of all entry-descs in the given category */
void getEntryList(unsigned int category, vector<string> *list);
/** returns a list of all entry-descs in the given category */
void getEntryList(unsigned int category, QStringList *list);
/** delete entry */
bool delEntry(const QString &category, unsigned int index, bool dontFlagDirty = false);
/** delete entry */
bool delEntry(unsigned int category, unsigned int index, bool dontFlagDirty = false);
/** edit entry */
bool editEntry(const QString &oldCategory, const QString &newCategory,
unsigned int index, PwMDataItem *d, bool updateMeta = true);
/** edit entry */
bool editEntry(unsigned int oldCategory, const QString &newCategory,
unsigned int index, PwMDataItem *d, bool updateMeta = true);
/** finds the category with the "name" and return it's index */
bool findCategory(const QString &name, unsigned int *index);
/** search for an entry "find" and check while searching only for
* the data-fields specified by "searchIn". To set the "searchIn"
* value, we may use one or more of the SEARCH_IN_* defines at
* the top of this header-file. It returns the positions of all
* matched entries in "foundPositions". If "breakAfterFound" is true,
* the function terminates after the first occurence of the entry
* and doesn't go on searching. So foundPositions->size() is never
* > 1 if breakAfterFound is true.
*/
void findEntry(unsigned int category, PwMDataItem find, unsigned int searchIn,
vector<unsigned int> *foundPositions, bool breakAfterFound = false,
bool caseSensitive = true, bool exactWordMatch = true,
bool sortByLvp = false);
/** see the above funtion. This function allows to set the category by name. */
void findEntry(const QString &category, PwMDataItem find, unsigned int searchIn,
vector<unsigned int> *foundPositions, bool breakAfterFound = false,
bool caseSensitive = true, bool exactWordMatch = true,
bool sortByLvp = false);
/** returns number of entries */
unsigned int numEntries(const QString &category);
unsigned int numEntries(unsigned int category)
{ return dti.dta[category].d.size(); }
/** returns number of categories */
unsigned int numCategories()
{ return dti.dta.size(); }
/** returns the name of the category at "index" */
const string* getCategory(unsigned int index)
{ return (&(dti.dta[index].name)); }
/** returns the data of item at "index".
* It unlocks the entry if it's locked and unlockIfLocked is true.
* If the entry is locked, but unlockIfLocked is false, it'll not return
* the pw.
*/
bool getEntry(const QString &category, unsigned int index,
PwMDataItem *d, bool unlockIfLocked = false);
bool getEntry(unsigned int category, unsigned int index,
PwMDataItem *d, bool unlockIfLocked = false);
/** returns the comment-string by looking at the category
* and the listViewPos
*/
PwMerror getCommentByLvp(const QString &category, int listViewPos,
string *foundComment);
+ PwMerror getCommentByLvp_long(const QString &category, int listViewPos,
+ string *foundComment);
/** checks if a password is already available. (currentPw) */
bool isPwAvailable()
{ return (currentPw != ""); }
/** un/lock entry at "index". If needed, ask for password. */
bool lockAt(const QString &category, unsigned int index,
bool lock = true);
bool lockAt(unsigned int category, unsigned int index,
bool lock = true);
/** returns the lock-status at "index" */
bool isLocked(const QString &category, unsigned int index);
bool isLocked(unsigned int category, unsigned int index)
{ return dti.dta[category].d[index].lockStat; }
/** returns the deeplock status */
bool isDeepLocked()
{ return getDocStatFlag(DOC_STAT_DEEPLOCKED); }
/** (un)lock all entries */
bool lockAll(bool lock);
/** unlocks all entries tempoarly.
* 1st NOTE: Be very careful with this function! :)
* 2nd NOTE: After you have called unlockAll_Tempoary(); ,
* please DON'T forget to call unlockAll_Tempoary(true);
* _before_ the user (or someone else) is able to change
* the document!
* 3rd NOTE: Please DON'T change "dta" while the data is tempoary
* unlocked! This will cause corruption.
*/
bool unlockAll_tempoary(bool revert = false);
/** deep-(un)locks the document.
* deep-locking writes all data to the file, deletes all data
* in memory, but doesn't close the document.
* deep-locking is only available, if the user previously saved
* the doc to a file (with a password).
* If "saveToFile" is false, it does NOT write the data to the file!
*/
PwMerror deepLock(bool lock = true, bool saveToFile = true);
/** is unlockable without pw? */
bool unlockWoPw()
{ return getDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW); }
/** get the "currentPassword" */
const QString& getCurrentPw()
{ return currentPw; }
/** open a window and request the user to change the mpw */
void changeCurrentPw();
/** set the "listViewPos" variable of "dta" */
void setListViewPos(const QString &category, unsigned int index,
int pos);
/** set the "listViewPos" variable of "dta" */
void setListViewPos(unsigned int category, unsigned int index,
int pos);
/** get the "listViewPos" variable of "dta" */
int getListViewPos(const QString &category, unsigned int index);
/** set the maximum number of entries allowed */
void setMaxNumEntries(unsigned int num = DEFAULT_MAX_ENTRIES)
{ maxEntries = num; }
/** get the maximum number of entries allowed */
unsigned int getMaxNumEntries()
{ return maxEntries; }
/** ensure all listViewPos of all dta items are set. (are ! -1).
* If there are some undefined entries, add them to the end of
* the listViewPos(itions). */
void ensureLvp();
/** execute the "launcher" of this entry */
bool execLauncher(const QString &category, unsigned int entryIndex);
/** see above */
bool execLauncher(unsigned int category, unsigned int entryIndex);
/** open a browser with the URL-section of the given entry */
bool goToURL(const QString &category, unsigned int entryIndex);
/** see above */
bool goToURL(unsigned int category, unsigned int entryIndex);
/** returns true if there is no entry present in the document.
* Note: The "default" Category is present everytime, so
* it's checked for it's entries.
*/
bool isDocEmpty()
{
if (numCategories() > 1)
return false;
if (numEntries(0))
return false;
return true;
}
/** returns the filename of this doc */
const QString& getFilename()
{ return filename; }
/** returns the title of the doc */
QString getTitle();
/** sets the list-view-pointer hold in the doc */
void setListViewPointer(PwMView *_listView)
{ listView = _listView; }
/** returns the list-view-pointer */
PwMView * getListViewPointer()
{ return listView; }
/** try to delete the doc. The user may be asked to save
* the data. The user may cancel the whole operation.
* false is returned, then.
*/
bool tryDelete();
/** is the doc deleted? (with tryDelete() ) */
bool isDeleted()
{ return deleted; }
/** returns the document timer object */
DocTimer * timer()
{ return _timer; }
/** get a lock on the dataChanged signal.
* If someone is holding a lock, the signal is not emitted.
*/
void getDataChangedLock()
{ ++dataChangedLock; }
/** put the dataChanged lock */
void putDataChangedLock()
{ --dataChangedLock; }
/** returns the revision count of the item at cat/index */
unsigned int getEntryRevCnt(unsigned int category, unsigned int index)
{ return dti.dta[category].d[index].rev; }
/** returns a const pointer to the entries meta */
const PwMMetaData * getEntryMeta(unsigned int category, unsigned int index)
{ return &(dti.dta[category].d[index].meta); }
/** is the entry at "category" "index" a binary entry? */
bool isBinEntry(unsigned int category, unsigned int index)
{ return dti.dta[category].d[index].binary; }
public slots:
/** wrapper for PwMTray */
void _deepUnlock();
signals:
/** the data of the document has changed and must be updated
* in all views.
* NOTE: use emitDataChanged(PwMDoc *document) to emit this signal!
*/
void dataChanged(PwMDoc *document);
/** the document class is going to close. This signal may be
* used to nofify all views, that the user closed the document,
* so the views can go down, too.
*/
void docClosed(PwMDoc *document);
/** somebody just opened the document */
void docOpened(PwMDoc *document);
/** this document object just got created */
void docCreated(PwMDoc *document);
public:
/** emit the dataChanged signal after checking for a lock */
void emitDataChanged(PwMDoc *document)
{
if (!dataChangedLock)
emit dataChanged(document);
}
protected:
/** current file for this doc */
QString filename;
//US ENH: we need a place where we keep the syncentries. So I invented
// struct PwMItem, that has a vector of PwMCategoryItem and vector of PwMSyncItem
/** holds all data */
PwMItem dti;
/** maximum number of entries */
unsigned int maxEntries;
/** currently used password to encrypt data */
QString currentPw;
/** current global document status flags */
unsigned int curDocStat;
/** browser process for goToURL() */
KProcess browserProc;
/** pointer to the list-view, using this document.
* As there can only be one list-view per doc, we
* don't need a list here.
*/
PwMView *listView;
/** unnamedNum is used to store the "unnamed counter"
* for this document, while it's unnamed. If it's 0,
* we have to get a new unique one.
*/
unsigned int unnamedNum;
/** is this doc going to be deleted (executing in destructor context) */
bool deleted;
/** document timer */
DocTimer *_timer;
/** lock counter for the "dataChanged" signal */
unsigned int dataChangedLock;
/** list of all open documents */
static PwMDocList openDocList;
protected:
/** serialize "dta" and return it in "d". */
bool serializeDta(string *d);
/** de-serialize "d" and overwrite "dta" */
bool deSerializeDta(const string *d, bool entriesLocked);
/** write header to file */
PwMerror writeFileHeader(char keyHash, char dataHash, char crypt, char compress,
QString *pw, QFile *f);
/** write data-hash to file */
PwMerror writeDataHash(char dataHash, string *d, QFile *f);
/** check header. Read header info and verify key-hash and filever.
* returns length of header in "headerLength" */
PwMerror checkHeader(char *cryptAlgo, QString *pw, char *compress,
unsigned int *headerLength, char *dataHashType,
string *dataHash, QFile *f);
/** check the data-hash */
PwMerror checkDataHash(char dataHashType, const string *dataHash, const string *dataStream);
/** encrypt data "d" and write to "filename" */
PwMerror encrypt(string *d, const QString *pw, QFile *f, char algo,
char _hashalgo //US BUG: pass _hashalgo because we need it in hashPassphrase
);
/** read data from file beginning at "pos", decrypt and return it */
PwMerror decrypt(string *d, unsigned int pos, const QString *pw, char algo,
char _hashalgo, //US BUG: pass _hashalgo because we need it in hashPassphrase
QFile *f);
/** compress the data */
bool compressDta(string *d, char algo);
/** uncompress the data */
bool decompressDta(string *d, char algo);
/** internal import function for a text-file generated by PwM.
* If this is not a valid PwM-exported file, it returns e_fileFormat */
PwMerror importText_PwM(const QString *file);
/** PwM-text-import helper function to extract the name/pw/comment out
* of one entry-line */
bool textExtractEntry_PwM(const char *in, ssize_t in_size, string *out);
/** compare two strings */
bool compareString(const string &s1, const string &s2, bool caseSensitive,
bool exactWordMatch);
/** clears all document-data */
void clearDoc();
/** delete all empty categories */
void delAllEmptyCat(bool dontFlagDirty);
/** set a document status flag */
void setDocStatFlag(unsigned int statFlag)
{ curDocStat |= statFlag; }
/** unset a document status flag */
void unsetDocStatFlag(unsigned int statFlag)
{ curDocStat &= ~statFlag; }
/** get a document status flag */
bool getDocStatFlag(unsigned int statFlag) const
{ return (curDocStat & statFlag); }
/** set the "currentPassword" */
void setCurrentPw(const QString &pw)
{
currentPw = pw;
setDocStatFlag(DOC_STAT_DISK_DIRTY);
}
/** make a backup-copy of the given file */
bool backupFile(const QString &filePath);
/** copy a file from src to dst */
bool copyFile(const QString &src, const QString &dst);
public:
#ifdef PWM_EMBEDDED
//US ENH: this is the magic function that syncronizes the local doc with the remote doc.
PwMerror syncronize(KSyncManager* manager, PwMDoc* syncLocal, PwMDoc* syncRemote, int mode );
//takePwMDataItem returns the following values
// 0 equal
// 1 take local
// 2 take remote
// 3 cancel
int takePwMDataItem( PwMDataItem* local, PwMDataItem* remote, QDateTime lastSync, int mode , bool full );
//the following methods are the overwritten callbackmethods from the syncinterface
virtual bool sync(KSyncManager* manager, QString filename, int mode);
virtual void removeSyncInfo( QString syncProfile);
#endif
//US ENH: helpermethods to return a whole category entry
/** returns a pointer to the categoryitem */
PwMCategoryItem* getCategoryEntry(unsigned int index)
{ return &(dti.dta[index]); }
private:
//US ENH: helpermethods to access the sync data for a certain syncname.
// It returns the syncdatas index
bool findSyncData(const QString &syncname, unsigned int *index);
/** add new syncdataentry */
PwMerror addSyncDataEntry(PwMSyncItem *d, bool dontFlagDirty = false);
/** returns a pointer to the syncdata */
PwMSyncItem* getSyncDataEntry(unsigned int index)
{ return &(dti.syncDta[index]); }
/** delete entry */
bool delSyncDataEntry(unsigned int index, bool dontFlagDirty = false);
/** returns number of categories */
unsigned int numSyncDataEntries()
{ return dti.syncDta.size(); }
PwMDataItem* findEntryByID(const QString &uid, unsigned int *category, unsigned int *index);
QStringList getIDEntryList();
};
#endif
diff --git a/pwmanager/pwmanager/pwmview.cpp b/pwmanager/pwmanager/pwmview.cpp
index 7f7dd6f..0092692 100644
--- a/pwmanager/pwmanager/pwmview.cpp
+++ b/pwmanager/pwmanager/pwmview.cpp
@@ -1,621 +1,621 @@
/***************************************************************************
* *
* copyright (C) 2003, 2004 by Michael Buesch *
* email: mbuesch@freenet.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 *
* as published by the Free Software Foundation. *
* *
***************************************************************************/
/***************************************************************************
* copyright (C) 2004 by Ulf Schenk
* This file is originaly based on version 1.0.1 of pwmanager
* and was modified to run on embedded devices that run microkde
*
* $Id$
**************************************************************************/
#include "pwmview.h"
#include "pwmexception.h"
#include "globalstuff.h"
#include "pwm.h"
#include "rencatwnd.h"
#ifndef PWM_EMBEDDED
#include "configuration.h"
#else
#include "pwmprefs.h"
#endif
#include "commentbox.h"
#include <kmessagebox.h>
#include <klocale.h>
#include <qlineedit.h>
#include <qpoint.h>
#include <qapplication.h>
#include <qlayout.h>
//US ENH: wouldn't it be a good idea if we could use this consts everywhere else.
//US ENH: for examle in listviewpwm.cpp
//US ENH: Because of that I transfer them into the headerfile.
/*
#define COLUMN_DESC 0
#define COLUMN_NAME 1
#define COLUMN_PW 2
#define COLUMN_URL 3
#define COLUMN_LAUNCHER 4
*/
PwMView::PwMView(PwM *_mainClass,
QWidget *parent, PwMDoc *_doc,
const char *name)
: PwMViewStyle(parent, name)
{
PWM_ASSERT(_mainClass);
PWM_ASSERT(parent);
PWM_ASSERT(_doc);
setView(this);
doc = _doc;
doc->setListViewPointer(this);
mainClass = _mainClass;
resize(_mainClass->size());
initStyle(conf()->confWndMainViewStyle());
initCtxMenu();
doc->setCurrentView(this);
connect(doc, SIGNAL(dataChanged(PwMDoc *)), this, SLOT(updateView()));
connect(this, SIGNAL(editPW()), mainClass, SLOT(editPwd_slot()));
}
PwMView::~PwMView()
{
}
void PwMView::initCtxMenu()
{
ctxMenu = new QPopupMenu(this);
ctxMenu->insertItem(i18n("&Add password"), mainClass, SLOT(addPwd_slot()));
ctxMenu->insertSeparator();
ctxMenu->insertItem(i18n("&Edit"), mainClass, SLOT(editPwd_slot()));
ctxMenu->insertItem(i18n("&Delete"), mainClass, SLOT(deletePwd_slot()));
ctxMenu->insertSeparator();
ctxMenu->insertItem(i18n("copy password to clipboard"),
this, SLOT(copyPwToClip()));
ctxMenu->insertItem(i18n("copy username to clipboard"),
this, SLOT(copyNameToClip()));
ctxMenu->insertItem(i18n("copy description to clipboard"),
this, SLOT(copyDescToClip()));
ctxMenu->insertItem(i18n("copy url to clipboard"),
this, SLOT(copyUrlToClip()));
ctxMenu->insertItem(i18n("copy launcher to clipboard"),
this, SLOT(copyLauncherToClip()));
ctxMenu->insertItem(i18n("copy comment to clipboard"),
this, SLOT(copyCommentToClip()));
ctxMenu->insertSeparator();
ctxMenu->insertItem(i18n("Execute \"Launcher\""), mainClass,
SLOT(execLauncher_slot()));
ctxMenu->insertItem(i18n("Go to \"URL\""), mainClass,
SLOT(goToURL_slot()));
}
void PwMView::resizeEvent(QResizeEvent *)
{
resizeView(size());
}
void PwMView::refreshCommentTextEdit(QListViewItem *curItem)
{
PWM_ASSERT(commentBox);
if (!curItem)
return;
string comment;
PwMerror ret;
- ret = document()->getCommentByLvp(getCurrentCategory(),
+ ret = document()->getCommentByLvp_long(getCurrentCategory(),
lv->childCount() - lv->itemIndex(curItem) - 1,
&comment);
if (ret == e_binEntry) {
commentBox->setContent(i18n("This is a binary entry.\n"
"It is not a normal password-entry, as it contains "
"binary data, which PwManager can't display here."));
} else if (ret == e_normalEntry) {
commentBox->setContent(comment.c_str());
} else {
BUG();
return;
}
lv->ensureItemVisible(curItem);
}
void PwMView::keyReleaseEvent(QKeyEvent * /*e*/)
{
refreshCommentTextEdit(lv->currentItem());
}
bool PwMView::getCurEntryIndex(unsigned int *index)
{
QListViewItem *current = lv->currentItem();
if (!current)
return false;
return getDocEntryIndex(index, current);
}
bool PwMView::getDocEntryIndex(unsigned int *index,
const QListViewItem *item)
{
vector<unsigned int> foundPositions;
PwMDataItem curItem;
curItem.desc = item->text(COLUMN_DESC).latin1();
curItem.name = item->text(COLUMN_NAME).latin1();
document()->getCommentByLvp(getCurrentCategory(),
lv->childCount() - lv->itemIndex(item) - 1,
&curItem.comment);
curItem.url = item->text(COLUMN_URL).latin1();
curItem.launcher = item->text(COLUMN_LAUNCHER).latin1();
document()->findEntry(getCurrentCategory(), curItem, SEARCH_IN_DESC |
SEARCH_IN_NAME | SEARCH_IN_COMMENT | SEARCH_IN_URL |
SEARCH_IN_LAUNCHER,
&foundPositions, true);
if (foundPositions.size()) {
*index = foundPositions[0];
return true;
}
return false;
}
void PwMView::handleToggle(QListViewItem *item)
{
PWM_ASSERT(doc);
if (!item)
return;
QCheckListItem *clItem = (QCheckListItem *)item;
QString curCat(getCurrentCategory());
// find document position of this entry.
unsigned int curEntryDocIndex;
if (!getDocEntryIndex(&curEntryDocIndex, item))
return;
// hack to refresh the comment, if only one item is present
if (lv->childCount() == 1)
refreshCommentTextEdit(lv->currentItem());
if (doc->isLocked(curCat, curEntryDocIndex) != clItem->isOn())
return; // this is just a click somewhere on the entry
if (doc->isDeepLocked()) {
PwMerror ret;
ret = doc->deepLock(false);
if (ret != e_success)
clItem->setOn(false);
return;
}
doc->lockAt(curCat, curEntryDocIndex, !clItem->isOn());
}
void PwMView::handleRightClick(QListViewItem *item, const QPoint &point, int)
{
if (!item)
return;
ctxMenu->move(point);
/* don't use ctxMenu->exec() here, as it generates race conditions
* with the card interface code. Believe it or not. :)
*/
ctxMenu->show();
}
void PwMView::updateCategories()
{
//qDebug("PwMView::updateCategories() ");
QString oldSel(getCurrentCategory());
delAllCategories();
QStringList catList;
document()->getCategoryList(&catList);
catList.sort();
#ifndef PWM_EMBEDDED
QStringList::iterator i = catList.begin(),
end = catList.end();
#else
QStringList::Iterator i = catList.begin(),
end = catList.end();
#endif
while (i != end) {
addCategory(*i);
++i;
}
selectCategory(oldSel);
}
void PwMView::shiftToView()
{
int cX = lv->contentsX();
int cY = lv->contentsY();
commentBox->clear();
unsigned int catDocIndex;
if (unlikely(
!(document()->findCategory(getCurrentCategory(),
&catDocIndex)))) {
BUG();
}
// ensure all listViewPos are set
doc->ensureLvp();
// clear all tmp-data vectors
unsigned int i, entries = doc->numEntries(catDocIndex);
if (entries) {
mainClass->setVirgin(false);
}
vector<PwMDataItem> tmpSorted;
PwMDataItem currItem;
currItem.clear();
tmpSorted.insert(tmpSorted.begin(), entries, currItem);
// Sort items and store them in tempoary tmpSorted.
for (i = 0; i < entries; ++i) {
doc->getEntry(catDocIndex, i, &currItem);
//qDebug("PwMView::shiftToView: %s, %i", currItem.desc.c_str(), currItem.listViewPos);
tmpSorted[currItem.listViewPos] = currItem;
}
// shift tempoary data to ListView.
tmpDisableSort();
lv->clear();
//US ENH: adjust the headers of the table according the category texts
{
PwMCategoryItem* catItem = doc->getCategoryEntry(catDocIndex);
// qDebug("PwMView::ShiftToView CAT: %i, %s", catDocIndex, catItem->name.c_str());
lv->setColumnText(COLUMN_DESC, catItem->desc_text.c_str());
lv->setColumnText(COLUMN_NAME, catItem->name_text.c_str());
lv->setColumnText(COLUMN_PW, catItem->pw_text.c_str());
}
QCheckListItem *newItem;
vector<PwMDataItem>::iterator it = tmpSorted.begin(),
end = tmpSorted.end();
while (it != end) {
newItem = new ListViewItemPwM(lv);
newItem->setText(COLUMN_DESC, (*it).desc.c_str());
if ((*it).binary) {
newItem->setText(COLUMN_NAME, "");
newItem->setText(COLUMN_PW, i18n("<BINARY ENTRY>"));
newItem->setText(COLUMN_URL, "");
newItem->setText(COLUMN_LAUNCHER, (*it).launcher.c_str());
} else {
newItem->setText(COLUMN_NAME, (*it).name.c_str());
if ((*it).lockStat) {
newItem->setText(COLUMN_PW, QString((*it).pw.c_str())
+ " "
+ i18n("To unlock click the icon on the left."));
} else {
newItem->setText(COLUMN_PW, (*it).pw.c_str());
}
newItem->setText(COLUMN_URL, (*it).url.c_str());
newItem->setText(COLUMN_LAUNCHER, (*it).launcher.c_str());
}
newItem->setOn(!((*it).lockStat));
lv->insertItem(newItem);
++it;
}
tmpReEnableSort();
if (cY || cX)
lv->setContentsPos(cX, cY);
}
void PwMView::reorgLp()
{
if (!lv->childCount())
return;
PWM_ASSERT(doc);
PWM_ASSERT(!doc->isDocEmpty());
QListViewItem *currItem;
vector<unsigned int> foundPos;
/* This searchIn _should_ be:
* const unsigned int searchIn = SEARCH_IN_DESC;
* But we want backward compatibility (see comment in PwMDoc::addEntry()).
* So we need to search again, if we don't find the entry. (see below)
*/
const unsigned int searchIn = SEARCH_IN_DESC | SEARCH_IN_NAME |
SEARCH_IN_URL | SEARCH_IN_LAUNCHER;
QString curCat(getCurrentCategory());
PwMDataItem findThis;
unsigned int i, cnt = lv->childCount();
for (i = 0; i < cnt; ++i) {
currItem = lv->itemAtIndex(i);
findThis.desc = currItem->text(COLUMN_DESC).latin1();
findThis.name = currItem->text(COLUMN_NAME).latin1();
findThis.url = currItem->text(COLUMN_URL).latin1();
findThis.launcher = currItem->text(COLUMN_LAUNCHER).latin1();
doc->findEntry(curCat, findThis, searchIn,
&foundPos, true);
if (!foundPos.size()) {
/* Did not find the entry. We seem to have a binary
* entry here (pray for it!). So search again with
* the "correct" searchIn flags.
*/
const unsigned int searchIn2 = SEARCH_IN_DESC;
doc->findEntry(curCat, findThis, searchIn2,
&foundPos, true);
if (unlikely(!foundPos.size())) {
BUG();
continue;
}
/* We assert that it's a binary entry, now.
* No chance to efficiently verify it here.
*/
}
doc->setListViewPos(curCat, foundPos[0], cnt - i - 1);
}
}
void PwMView::selAt(int index)
{
QListViewItem *item = lv->itemAtIndex(index);
if (!item)
return;
lv->setCurrentItem(item);
lv->ensureItemVisible(item);
}
void PwMView::renCatButton_slot()
{
if (doc->isDeepLocked())
return;
RenCatWnd wnd(this);
if (wnd.exec() == 1) {
QString newName(wnd.getNewName());
if (newName == "")
return;
document()->renameCategory(getCurrentCategory(),
newName);
}
}
void PwMView::delCatButton_slot()
{
if (doc->isDeepLocked())
return;
if (numCategories() <= 1) {
mainClass->showStatMsg(i18n("Can't remove the last category."));
return;
}
if (KMessageBox::questionYesNo(this,
i18n("Do you really want to\n"
"delete the selected\n"
"category? All password-\n"
"entries will be lost in\n"
"this category!\n"),
i18n("Delete category?"))
== KMessageBox::No) {
return;
}
document()->delCategory(getCurrentCategory());
}
void PwMView::copyPwToClip()
{
if (doc->isDeepLocked())
return;
unsigned int curIndex = 0;
if (!getCurEntryIndex(&curIndex))
return;
PwMDataItem d;
document()->getDataChangedLock();
document()->getEntry(getCurrentCategory(), curIndex, &d, true);
document()->putDataChangedLock();
PwM::copyToClipboard(d.pw.c_str());
}
void PwMView::copyNameToClip()
{
if (doc->isDeepLocked())
return;
unsigned int curIndex = 0;
if (!getCurEntryIndex(&curIndex))
return;
PwMDataItem d;
document()->getEntry(getCurrentCategory(), curIndex, &d);
PwM::copyToClipboard(d.name.c_str());
}
void PwMView::copyDescToClip()
{
if (doc->isDeepLocked())
return;
unsigned int curIndex = 0;
if (!getCurEntryIndex(&curIndex))
return;
PwMDataItem d;
document()->getEntry(getCurrentCategory(), curIndex, &d);
PwM::copyToClipboard(d.desc.c_str());
}
void PwMView::copyUrlToClip()
{
if (doc->isDeepLocked())
return;
unsigned int curIndex = 0;
if (!getCurEntryIndex(&curIndex))
return;
PwMDataItem d;
document()->getEntry(getCurrentCategory(), curIndex, &d);
PwM::copyToClipboard(d.url.c_str());
}
void PwMView::copyLauncherToClip()
{
if (doc->isDeepLocked())
return;
unsigned int curIndex = 0;
if (!getCurEntryIndex(&curIndex))
return;
PwMDataItem d;
document()->getEntry(getCurrentCategory(), curIndex, &d);
PwM::copyToClipboard(d.launcher.c_str());
}
void PwMView::copyCommentToClip()
{
if (doc->isDeepLocked())
return;
unsigned int curIndex = 0;
if (!getCurEntryIndex(&curIndex))
return;
PwMDataItem d;
document()->getEntry(getCurrentCategory(), curIndex, &d);
PwM::copyToClipboard(d.comment.c_str());
}
/************************************************************************
*
*
*
************************************************************************/
PwMDataItemView::PwMDataItemView( QWidget *parent, const char *name )
: QTextBrowser( parent, name )
{
//US setWrapPolicy( QTextEdit::AtWordBoundary );
setLinkUnderline( false );
// setVScrollBarMode( QScrollView::AlwaysOff );
//setHScrollBarMode( QScrollView::AlwaysOff );
//US QStyleSheet *sheet = styleSheet();
//US QStyleSheetItem *link = sheet->item( "a" );
//US link->setColor( KGlobalSettings::linkColor() );
}
void PwMDataItemView::setPwMDataItem( const PwMDataItem& a )
{
mItem = a;
// clear view
setText( QString::null );
QString dynamicPart;
QString format = "<tr><td align=\"right\"><b>%1</b></td>"
"<td align=\"left\">%2</td></tr>";
dynamicPart += format
.arg( i18n("LastUpdate") )
.arg( mItem.meta.update.toString().latin1() );
dynamicPart += format
.arg( i18n("Description") )
.arg( mItem.desc.c_str() );
dynamicPart += format
.arg( i18n("Name") )
.arg( mItem.name.c_str() );
dynamicPart += format
.arg( i18n("Password") )
.arg( mItem.pw.c_str() );
QString comment(mItem.pw.c_str());
dynamicPart += format
.arg( i18n("Comment") )
.arg( comment.replace( QRegExp("\n"), "<br>" ) );
dynamicPart += format
.arg( i18n("URL") )
.arg( mItem.url.c_str() );
dynamicPart += format
.arg( i18n("Launcher") )
.arg( mItem.launcher.c_str() );
QString mText = "<table><td colspan=\"2\">&nbsp;</td>";
mText += dynamicPart;
mText += "</table>";
// at last display it...
setText( mText );
}
PwMDataItem PwMDataItemView::pwmdataitem() const
{
return mItem;
}
/************************************************************************
*
*
*
************************************************************************/
PwMDataItemChooser::PwMDataItemChooser( PwMDataItem loc, PwMDataItem rem, bool takeloc, QWidget *parent, const char *name )
: KDialogBase(parent, name, true ,
i18n("Conflict! Please choose Entry!"),Ok|User1|Close,Close, false)
{
findButton( Close )->setText( i18n("Cancel Sync"));
findButton( Ok )->setText( i18n("Remote"));
findButton( User1 )->setText( i18n("Local"));
QWidget* topframe = new QWidget( this );
setMainWidget( topframe );
QBoxLayout* bl;
if ( QApplication::desktop()->width() < 640 ) {
bl = new QVBoxLayout( topframe );
} else {
bl = new QHBoxLayout( topframe );
}
QVBox* subframe = new QVBox( topframe );
bl->addWidget(subframe );
QLabel* lab = new QLabel( i18n("Local Entry"), subframe );
if ( takeloc )
lab->setBackgroundColor(Qt::green.light() );
PwMDataItemView * av = new PwMDataItemView( subframe );
av->setPwMDataItem( loc );
subframe = new QVBox( topframe );
bl->addWidget(subframe );
lab = new QLabel( i18n("Remote Entry"), subframe );
if ( !takeloc )
lab->setBackgroundColor(Qt::green.light() );
av = new PwMDataItemView( subframe );
av->setPwMDataItem( rem );
QObject::connect(findButton( Ok ),SIGNAL(clicked()),this, SLOT(slot_remote()));
QObject::connect(this,SIGNAL(user1Clicked()),this, SLOT(slot_local()));
#ifndef DESKTOP_VERSION
showMaximized();
#else
resize ( 640, 400 );
#endif
}
int PwMDataItemChooser::executeD( bool local )
{
mSyncResult = 3;
if ( local )
findButton( User1 )->setFocus();
else
findButton( Ok )->setFocus();
exec();
return mSyncResult;
}
void PwMDataItemChooser::slot_remote()
{
mSyncResult = 2;
accept();
}
void PwMDataItemChooser::slot_local()
{
mSyncResult = 1;
accept();
}
#ifndef PWM_EMBEDDED
#include "pwmview.moc"
#endif
diff --git a/pwmanager/pwmanager/pwmviewstyle_0.cpp b/pwmanager/pwmanager/pwmviewstyle_0.cpp
index 1fc8a34..d82eb15 100644
--- a/pwmanager/pwmanager/pwmviewstyle_0.cpp
+++ b/pwmanager/pwmanager/pwmviewstyle_0.cpp
@@ -1,112 +1,132 @@
/***************************************************************************
* *
* copyright (C) 2004 by Michael Buesch *
* email: mbuesch@freenet.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 *
* as published by the Free Software Foundation. *
* *
***************************************************************************/
/***************************************************************************
* copyright (C) 2004 by Ulf Schenk
* This file is originaly based on version 1.0.1 of pwmanager
* and was modified to run on embedded devices that run microkde
*
* $Id$
**************************************************************************/
#include "pwmviewstyle_0.h"
#include "pwmview.h"
#include "listviewpwm.h"
#include "commentbox.h"
#include <klocale.h>
#include "pwmprefs.h"
PwMViewStyle_0::PwMViewStyle_0(PwMView *view)
: QObject()
{
vbox1 = new QVBox(view);
vbox1->setSpacing(3);
hbox1 = new QHBox(vbox1);
hbox1->setSpacing(3);
categoriesTitle = new QLabel(hbox1);
categoriesTitle->setText(i18n("Categories:"));
categoriesCombo = new QComboBox(hbox1);
renCatButton = new QPushButton(i18n("&Rename"), hbox1);
delCatButton = new QPushButton(i18n("&Delete"), hbox1);
#ifndef PWM_EMBEDDED
splitter1 = new QSplitter(vbox1);
splitter1->setOrientation(Qt::Vertical);
#else
splitter1 = new KDGanttMinimizeSplitter( Qt::Vertical, vbox1);
splitter1->setMinimizeDirection ( KDGanttMinimizeSplitter::Down );
//US topLayout->addWidget(mMiniSplitter );
#endif
lv = new ListViewPwM(splitter1);
commentBox = new CommentBox(splitter1);
// set sizes and styles
commentBox->resize(commentBox->size().width(), 60);
categoriesTitle->setAlignment(Qt::AlignVCenter | Qt::AlignRight);
// connections
connect(categoriesCombo, SIGNAL(activated(int)),
view, SLOT(shiftToView()));
connect(renCatButton, SIGNAL(clicked()),
view, SLOT(renCatButton_slot()));
connect(delCatButton, SIGNAL(clicked()),
view, SLOT(delCatButton_slot()));
+ connect(lv, SIGNAL(toggleOverview()),
+ this, SLOT(toggleSplitter()));
}
PwMViewStyle_0::~PwMViewStyle_0()
{
delete vbox1;
}
+void PwMViewStyle_0::toggleSplitter()
+{
+
+ QValueList<int> si = splitter1->sizes();
+ splitter1->toggle();
+ QValueList<int> si2 = splitter1->sizes();
+ //qDebug("PwMViewStyle_0::toggleSplitter() %d %d %d %d", si[0],si[1],si2[0],si2[1] );
+ if ( si[0] == si2[0] && si[1] == si2[1] && si2[1] == 1 ) {
+ int diff = si[0]/2;
+ if ( diff > 200 )
+ diff = 200;
+ si[0] -= diff;
+ si[1] += diff;
+ splitter1->toggle();
+ splitter1->setSizes( si );
+ }
+
+}
void PwMViewStyle_0::delCategory(const QString &cat)
{
PWM_ASSERT(categoriesCombo);
int i, count = categoriesCombo->count();
for (i = 0; i < count; ++i) {
if (categoriesCombo->text(i) == cat) {
categoriesCombo->removeItem(i);
return;
}
}
BUG();
}
void PwMViewStyle_0::selectCategory(const QString &cat)
{
PWM_ASSERT(categoriesCombo);
int i, count = categoriesCombo->count();
for (i = 0; i < count; ++i) {
if (categoriesCombo->text(i) == cat) {
categoriesCombo->setCurrentItem(i);
return;
}
}
// fall back to 0
categoriesCombo->setCurrentItem(0);
}
//US ENH: I need a place to load the view dependend settings. Eg. splittersize
void PwMViewStyle_0::restoreSettings(PWMPrefs* prefs)
{
//load and store the size of the listviewcolumns
lv->restoreLayout(prefs->getConfig(), "listview");
splitter1->setSizes( prefs->mCommentSplitter );
commentBox->setFont( prefs->mViewFont );
}
//US ENH: I need a place to load the view dependend settings. Eg. splittersize
void PwMViewStyle_0::saveSettings(PWMPrefs* prefs)
{
//store the size of the listviewcolumns
lv->saveLayout(prefs->getConfig(), "listview");
prefs->mCommentSplitter = splitter1->sizes();
}
diff --git a/pwmanager/pwmanager/pwmviewstyle_0.h b/pwmanager/pwmanager/pwmviewstyle_0.h
index bd93c06..6d3c1d1 100644
--- a/pwmanager/pwmanager/pwmviewstyle_0.h
+++ b/pwmanager/pwmanager/pwmviewstyle_0.h
@@ -1,105 +1,107 @@
/***************************************************************************
* *
* copyright (C) 2004 by Michael Buesch *
* email: mbuesch@freenet.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 *
* as published by the Free Software Foundation. *
* *
***************************************************************************/
/***************************************************************************
* copyright (C) 2004 by Ulf Schenk
* This file is originaly based on version 1.0.1 of pwmanager
* and was modified to run on embedded devices that run microkde
*
* $Id$
**************************************************************************/
#ifndef PWMVIEWSTYLE_0_H
#define PWMVIEWSTYLE_0_H
#include <qhbox.h>
#include <qvbox.h>
#include <qpushbutton.h>
#ifndef PWM_EMBEDDED
#include <qtextedit.h>
#include <qsplitter.h>
#else
#include <qmultilineedit.h>
#include <KDGanttMinimizeSplitter.h>
#endif
#include <qlabel.h>
#include <qcombobox.h>
class PwMView;
class ListViewPwM;
class CommentBox;
class PWMPrefs;
class PwMViewStyle_0 : public QObject
{
+ Q_OBJECT
public:
PwMViewStyle_0(PwMView *view);
~PwMViewStyle_0();
ListViewPwM * getLv()
{ return lv; }
CommentBox * getCommentBox()
{ return commentBox; }
/** returns the currently selected category */
QString getCurrentCategory()
{ return categoriesCombo->currentText(); }
/** add Category to the view */
void addCategory(const QString &cat)
{ categoriesCombo->insertItem(cat); }
/** delete Category from view */
void delCategory(const QString &cat);
/** delete all categories from view */
void delAllCategories()
{ categoriesCombo->clear(); }
/** select the specified category */
void selectCategory(const QString &cat);
/** returns the number of categories in this view.
* This value dosn't say anything about the number of
* categories in the document.
*/
int numCategories()
{ return categoriesCombo->count(); }
/** resize the view */
void resize(const QSize &size)
{ vbox1->resize(size); }
//US ENH: I need a place to load the view dependend settings. Eg. splittersize
void restoreSettings(PWMPrefs* prefs);
void saveSettings(PWMPrefs* prefs);
-
+public slots:
+ void toggleSplitter();
protected:
/** main list view */
ListViewPwM *lv;
/** categories combo-box */
QComboBox *categoriesCombo;
/** title string for the categories combo or list box */
QLabel *categoriesTitle;
/** hbox1 for widget style */
QHBox *hbox1;
/** vbox1 for widget style */
QVBox *vbox1;
/** splitter for commentTextEdit */
#ifndef PWM_EMBEDDED
QSplitter *splitter1;
#else
KDGanttMinimizeSplitter * splitter1;
#endif
/** push button to change the category name */
QPushButton *renCatButton;
/** push button to delete the category */
QPushButton *delCatButton;
/** comment box */
CommentBox *commentBox;
};
#endif
diff --git a/pwmanager/pwmanager/pwmviewstyle_1.cpp b/pwmanager/pwmanager/pwmviewstyle_1.cpp
index 4a7ffd7..7294f34 100644
--- a/pwmanager/pwmanager/pwmviewstyle_1.cpp
+++ b/pwmanager/pwmanager/pwmviewstyle_1.cpp
@@ -1,173 +1,192 @@
/***************************************************************************
* *
* copyright (C) 2004 by Michael Buesch *
* email: mbuesch@freenet.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 *
* as published by the Free Software Foundation. *
* *
***************************************************************************/
/***************************************************************************
* copyright (C) 2004 by Ulf Schenk
* This file is originaly based on version 1.0.1 of pwmanager
* and was modified to run on embedded devices that run microkde
*
* $Id$
**************************************************************************/
#include "pwmviewstyle_1.h"
#include "pwmview.h"
#include "listviewpwm.h"
#include "commentbox.h"
#include <klocale.h>
#include "pwmprefs.h"
#ifndef DESKTOP_VERSION
#include <qpe/qpeapplication.h>
#else
#include <qapplication.h>
#endif
#define INITIAL_CATEGORIES_WIDTH 100
PwMViewStyle_1::PwMViewStyle_1(PwMView *view)
: QObject()
{
#ifndef PWM_EMBEDDED
splitter = new QSplitter(view);
#else
if ( QApplication::desktop()->width() > 240 ) {
splitter = new KDGanttMinimizeSplitter( Qt::Horizontal, view);
splitter->setMinimizeDirection ( KDGanttMinimizeSplitter::Left );
// topLayout = new QHBoxLayout( this );
// mMiniSplitter = new KDGanttMinimizeSplitter( Qt::Horizontal, this);
// mMiniSplitter->setMinimizeDirection ( KDGanttMinimizeSplitter::Right );
} else {
splitter = new KDGanttMinimizeSplitter( Qt::Vertical, view);
splitter->setMinimizeDirection ( KDGanttMinimizeSplitter::Up );
// topLayout = new QHBoxLayout( this );
// mMiniSplitter = new KDGanttMinimizeSplitter( Qt::Vertical, this);
// mMiniSplitter->setMinimizeDirection ( KDGanttMinimizeSplitter::Down );
}
//US topLayout->addWidget(mMiniSplitter );
#endif
vbox1 = new QVBox(splitter);
categoriesTitle = new QLabel(vbox1);
categoriesList = new QListBox(vbox1);
#ifndef PWM_EMBEDDED
splitter2 = new QSplitter(splitter);
splitter2->setOrientation(Qt::Vertical);
#else
splitter2 = new KDGanttMinimizeSplitter( Qt::Vertical, splitter);
splitter2->setMinimizeDirection ( KDGanttMinimizeSplitter::Down );
//US topLayout->addWidget(mMiniSplitter );
#endif
lv = new ListViewPwM(splitter2);
commentBox = new CommentBox(splitter2);
// set sizes and styles
//US commentBox->resize(commentBox->size().width(), 60);
QValueList<int> sizes;
#ifndef PWM_EMBEDDED
sizes.push_back(INITIAL_CATEGORIES_WIDTH);
sizes.push_back(view->height() - INITIAL_CATEGORIES_WIDTH);
#else
sizes.append(INITIAL_CATEGORIES_WIDTH);
sizes.append(view->height() - INITIAL_CATEGORIES_WIDTH);
#endif
//US splitter->setSizes(sizes);
categoriesTitle->setAlignment(Qt::AlignHCenter);
#ifndef PWM_EMBEDDED
categoriesTitle->setFrameShape(QFrame::MenuBarPanel);
#else
categoriesTitle->setFrameShape(QFrame::StyledPanel);
#endif
categoriesTitle->setText(i18n("Categories:"));
catCtxMenu = new QPopupMenu(view);
catCtxMenu->insertItem(i18n("&Rename"),
view, SLOT(renCatButton_slot()));
catCtxMenu->insertItem(i18n("&Delete"),
view, SLOT(delCatButton_slot()));
#ifndef DESKTOP_VERSION
QPEApplication::setStylusOperation( categoriesList->viewport(), QPEApplication::RightOnHold );
#endif
// connections
connect(categoriesList, SIGNAL(highlighted(int)),
view, SLOT(shiftToView()));
connect(categoriesList,
SIGNAL(rightButtonClicked(QListBoxItem *, const QPoint &)),
this,
SLOT(catRightClick(QListBoxItem *, const QPoint &)));
+
+ connect(lv, SIGNAL(toggleOverview()),
+ this, SLOT(toggleSplitter()));
}
PwMViewStyle_1::~PwMViewStyle_1()
{
delete catCtxMenu;
delete splitter;
}
+void PwMViewStyle_1::toggleSplitter()
+{
+ QValueList<int> si = splitter2->sizes();
+ splitter2->toggle();
+ QValueList<int> si2 = splitter2->sizes();
+ //qDebug("PwMViewStyle_1::toggleSplitter() %d %d %d %d", si[0],si[1],si2[0],si2[1] );
+ if ( si[0] == si2[0] && si[1] == si2[1] && si2[1] == 1 ) {
+ int diff = si[0]/2;
+ if ( diff > 200 )
+ diff = 200;
+ si[0] -= diff;
+ si[1] += diff;
+ splitter2->toggle();
+ splitter2->setSizes( si );
+ }
+}
void PwMViewStyle_1::catRightClick(QListBoxItem *item, const QPoint &point)
{
if (!item)
return;
catCtxMenu->move(point);
catCtxMenu->show();
}
void PwMViewStyle_1::delCategory(const QString &cat)
{
PWM_ASSERT(categoriesList);
int i, count = categoriesList->count();
for (i = 0; i < count; ++i) {
if (categoriesList->text(i) == cat) {
categoriesList->removeItem(i);
return;
}
}
BUG();
}
void PwMViewStyle_1::selectCategory(const QString &cat)
{
PWM_ASSERT(categoriesList);
int i, count = categoriesList->count();
for (i = 0; i < count; ++i) {
if (categoriesList->text(i) == cat) {
categoriesList->setCurrentItem(i);
return;
}
}
// fall back to 0
categoriesList->setCurrentItem(0);
}
//US ENH: I need a place to load the view dependend settings. Eg. splittersize
void PwMViewStyle_1::restoreSettings(PWMPrefs* prefs)
{
//load and store the size of the listviewcolumns
lv->restoreLayout(prefs->getConfig(), "listview");
splitter->setSizes( prefs->mCategorySplitter );
splitter2->setSizes( prefs->mCommentSplitter );
commentBox->setFont( prefs->mViewFont );
}
//US ENH: I need a place to load the view dependend settings. Eg. splittersize
void PwMViewStyle_1::saveSettings(PWMPrefs* prefs)
{
//store the size of the listviewcolumns
lv->saveLayout(prefs->getConfig(), "listview");
prefs->mCategorySplitter = splitter->sizes();
prefs->mCommentSplitter = splitter2->sizes();
}
#ifndef PWM_EMBEDDED
#include "pwmviewstyle_1.moc"
#endif
diff --git a/pwmanager/pwmanager/pwmviewstyle_1.h b/pwmanager/pwmanager/pwmviewstyle_1.h
index a7f100c..4f7a256 100644
--- a/pwmanager/pwmanager/pwmviewstyle_1.h
+++ b/pwmanager/pwmanager/pwmviewstyle_1.h
@@ -1,112 +1,114 @@
/***************************************************************************
* *
* copyright (C) 2004 by Michael Buesch *
* email: mbuesch@freenet.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 *
* as published by the Free Software Foundation. *
* *
***************************************************************************/
/***************************************************************************
* copyright (C) 2004 by Ulf Schenk
* This file is originaly based on version 1.0.1 of pwmanager
* and was modified to run on embedded devices that run microkde
*
* $Id$
**************************************************************************/
#ifndef PWMVIEWSTYLE_1_H
#define PWMVIEWSTYLE_1_H
#include <qvbox.h>
#ifndef PWM_EMBEDDED
#include <qtextedit.h>
#include <qsplitter.h>
#else
#include <qmultilineedit.h>
#include <KDGanttMinimizeSplitter.h>
#endif
#include <qlabel.h>
#include <qlistbox.h>
#include <qpopupmenu.h>
class PwMView;
class ListViewPwM;
class CommentBox;
class PWMPrefs;
class PwMViewStyle_1 : public QObject
{
Q_OBJECT
public:
PwMViewStyle_1(PwMView *view);
~PwMViewStyle_1();
ListViewPwM * getLv()
{ return lv; }
CommentBox * getCommentBox()
{ return commentBox; }
/** returns the currently selected category */
QString getCurrentCategory()
{ return categoriesList->currentText(); }
/** add Category to the view */
void addCategory(const QString &cat)
{ categoriesList->insertItem(cat); }
/** delete Category from view */
void delCategory(const QString &cat);
/** delete all categories from view */
void delAllCategories()
{ categoriesList->clear(); }
/** select the specified category */
void selectCategory(const QString &cat);
/** returns the number of categories in this view.
* This value dosn't say anything about the number of
* categories in the document.
*/
int numCategories()
{ return categoriesList->count(); }
/** resize the view */
void resize(const QSize &size)
{ splitter->resize(size); }
//US ENH: I need a place to load the view dependend settings. Eg. splittersize
void restoreSettings(PWMPrefs* prefs);
void saveSettings(PWMPrefs* prefs);
+public slots:
+ void toggleSplitter();
protected slots:
/** user clicked right button in category list */
void catRightClick(QListBoxItem *item, const QPoint &point);
protected:
/** main list view */
ListViewPwM *lv;
#ifndef PWM_EMBEDDED
/** main splitter widget */
QSplitter *splitter;
/** commentTextEdit splitter */
QSplitter *splitter2;
#else
/** main splitter widget */
KDGanttMinimizeSplitter *splitter;
/** commentTextEdit splitter */
KDGanttMinimizeSplitter *splitter2;
#endif
/** categories list-box */
QListBox *categoriesList;
/** title string for the categories combo or list box */
QLabel *categoriesTitle;
/** hbox1 for widget style */
QVBox *vbox1;
/** text-edit to display the comment */
CommentBox *commentBox;
/** category list context menu */
QPopupMenu *catCtxMenu;
};
#endif