aboutsummaryrefslogtreecommitdiffstats
path: root/kde2/kpsion
diff options
context:
space:
mode:
Diffstat (limited to 'kde2/kpsion')
-rw-r--r--kde2/kpsion/Makefile.am31
-rw-r--r--kde2/kpsion/kpsion.cpp1046
-rw-r--r--kde2/kpsion/kpsion.desktop10
-rw-r--r--kde2/kpsion/kpsion.h165
-rw-r--r--kde2/kpsion/kpsionui.rc15
-rw-r--r--kde2/kpsion/lo16-action-psion_backup.pngbin0 -> 268 bytes
-rw-r--r--kde2/kpsion/lo16-action-psion_restore.pngbin0 -> 274 bytes
-rw-r--r--kde2/kpsion/lo16-app-kpsion.pngbin0 -> 250 bytes
-rw-r--r--kde2/kpsion/lo22-action-psion_backup.pngbin0 -> 318 bytes
-rw-r--r--kde2/kpsion/lo22-action-psion_restore.pngbin0 -> 318 bytes
-rw-r--r--kde2/kpsion/lo32-action-psion_backup.pngbin0 -> 366 bytes
-rw-r--r--kde2/kpsion/lo32-action-psion_restore.pngbin0 -> 368 bytes
-rw-r--r--kde2/kpsion/lo32-app-kpsion.pngbin0 -> 309 bytes
-rw-r--r--kde2/kpsion/main.cpp55
-rw-r--r--kde2/kpsion/setupdialog.cpp62
-rw-r--r--kde2/kpsion/setupdialog.h17
-rw-r--r--kde2/kpsion/wizards.cpp586
-rw-r--r--kde2/kpsion/wizards.h78
18 files changed, 2065 insertions, 0 deletions
diff --git a/kde2/kpsion/Makefile.am b/kde2/kpsion/Makefile.am
new file mode 100644
index 0000000..85f70fa
--- /dev/null
+++ b/kde2/kpsion/Makefile.am
@@ -0,0 +1,31 @@
+# $Id$
+
+METASOURCES = AUTO
+
+KDE_ICON = AUTO
+
+INCLUDES = $(all_includes) -I$(top_srcdir)/lib
+
+DISTCLEANFILES = $(kpsion_METASOURCES) ./.deps/* ./.deps/.P
+
+lib_LTLIBRARIES = libkpsion.la
+bin_PROGRAMS = kpsion
+
+libkpsion_la_LDFLAGS = $(LIBDEBUG) $(all_libraries) -module -version-info $(LIBVERSION)
+libkpsion_la_SOURCES = kpsion.cpp setupdialog.cpp wizards.cpp
+libkpsion_la_LIBADD = -L$(top_srcdir)/lib -lplp $(LIB_KFILE)
+
+kpsion_SOURCES = main.cpp
+kpsion_LDFLAGS = $(KDE_RPATH)
+kpsion_LDADD = libkpsion.la $(top_srcdir)/lib/libplp.la
+
+applnk_DATA = kpsion.desktop
+applnkdir = $(kde_appsdir)/Utilities
+
+rcdir = $(kde_datadir)/kpsion
+rc_DATA = kpsionui.rc
+
+noinst_HEADERS = kpsion.h setupdialog.h wizards.h
+
+messages:
+ $(XGETTEXT) -C -ki18n -kI18N_NOOP -ktranslate -kaliasLocale *.cpp *.h && mv messages.po ../po/kpsion.pot
diff --git a/kde2/kpsion/kpsion.cpp b/kde2/kpsion/kpsion.cpp
new file mode 100644
index 0000000..808ed1a
--- /dev/null
+++ b/kde2/kpsion/kpsion.cpp
@@ -0,0 +1,1046 @@
+/*-*-c++-*-
+ * $Id$
+ *
+ * This file is part of plptools.
+ *
+ * Copyright (C) 1999 Philip Proudman <philip.proudman@btinternet.com>
+ * Copyright (C) 2000, 2001 Fritz Elfert <felfert@to.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "kpsion.h"
+#include "wizards.h"
+
+#include <kapp.h>
+#include <klocale.h>
+#include <kaction.h>
+#include <kstdaction.h>
+#include <kconfig.h>
+#include <kiconview.h>
+#include <kmessagebox.h>
+#include <kfileitem.h>
+
+#include <qwhatsthis.h>
+#include <qtimer.h>
+#include <qlayout.h>
+#include <qiodevice.h>
+#include <qdir.h>
+
+#include <ppsocket.h>
+#include <rfsvfactory.h>
+#include <rpcsfactory.h>
+#include <bufferarray.h>
+
+#include <iomanip>
+#include <strstream>
+
+// internal use for developing offline without
+// having a Psion connected.
+// !!!!! set to 0 for production code !!!!!
+#define OFFLINE 0
+
+#define STID_CONNECTION 1
+
+void KPsionCheckListItem::
+init(bool myparent) {
+ setSelectable(false);
+ dontPropagate = false;
+ parentIsKPsionCheckListItem = myparent;
+}
+
+void KPsionCheckListItem::
+setMetaData(int bType, time_t bWhen) {
+ backupType = bType;
+ when = bWhen;
+}
+
+void KPsionCheckListItem::
+stateChange(bool state) {
+ QCheckListItem::stateChange(state);
+
+ if (dontPropagate)
+ return;
+ if (parentIsKPsionCheckListItem)
+ ((KPsionCheckListItem *)parent())->propagateUp(state);
+ propagateDown(state);
+}
+
+void KPsionCheckListItem::
+propagateDown(bool state) {
+ setOn(state);
+ KPsionCheckListItem *child = (KPsionCheckListItem *)firstChild();
+ while (child) {
+ child->propagateDown(state);
+ child = (KPsionCheckListItem *)child->nextSibling();
+ }
+}
+
+void KPsionCheckListItem::
+propagateUp(bool state) {
+ bool deactivateThis = false;
+
+ KPsionCheckListItem *child = (KPsionCheckListItem *)firstChild();
+ while (child) {
+ if ((child->isOn() != state) || (!child->isEnabled())) {
+ deactivateThis = true;
+ break;
+ }
+ child = (KPsionCheckListItem *)child->nextSibling();
+ }
+ dontPropagate = true;
+ if (deactivateThis) {
+ setOn(true);
+ setEnabled(false);
+ } else {
+ setEnabled(true);
+ setOn(state);
+ }
+ // Bug in QListView? It doesn't update, when
+ // enabled/disabled without activating.
+ // -> force it.
+ listView()->repaintItem(this);
+ dontPropagate = false;
+ if (parentIsKPsionCheckListItem)
+ ((KPsionCheckListItem *)parent())->propagateUp(state);
+}
+
+KPsionBackupListView::KPsionBackupListView(QWidget *parent, const char *name)
+ : KListView(parent, name) {
+
+ toRestore.clear();
+ uid = QString::null;
+ KConfig *config = kapp->config();
+ config->setGroup("Settings");
+ backupDir = config->readEntry("BackupDir");
+ addColumn(i18n("Available backups"));
+ setRootIsDecorated(true);
+}
+
+void KPsionBackupListView::
+readBackups(QString uid) {
+ QString bdir(backupDir);
+ bdir += "/";
+ bdir += uid;
+ QDir d(bdir);
+ const QFileInfoList *fil =
+ d.entryInfoList("*.tar.gz", QDir::Files|QDir::Readable, QDir::Name);
+ QFileInfoListIterator it(*fil);
+ QFileInfo *fi;
+ while ((fi = it.current())) {
+ bool isValid = false;
+ KTarGz tgz(fi->absFilePath());
+ const KTarEntry *te;
+ QString bTypeName;
+ int bType;
+ QDateTime date;
+
+ tgz.open(IO_ReadOnly);
+ te = tgz.directory()->entry("KPsionFullIndex");
+ if (te && (!te->isDirectory())) {
+ date.setTime_t(te->date());
+ bTypeName = i18n("Full");
+ bType = FULL;
+ isValid = true;
+ } else {
+ te = tgz.directory()->entry("KPsionIncrementalIndex");
+ if (te && (!te->isDirectory())) {
+ date.setTime_t(te->date());
+ bTypeName = i18n("Incremental");
+ bType = INCREMENTAL;
+ isValid = true;
+ }
+ }
+
+ if (isValid) {
+ QString n = i18n("%1 backup, created at %2").arg(bTypeName).arg(date.toString());
+
+ KPsionCheckListItem *i =
+ new KPsionCheckListItem(this, n,
+ KPsionCheckListItem::CheckBox);
+ i->setMetaData(bType, te->date());
+ i->setPixmap(0, KGlobal::iconLoader()->loadIcon("mime_empty", KIcon::Small));
+ QStringList files = tgz.directory()->entries();
+ for (QStringList::Iterator f = files.begin();
+ f != files.end(); f++)
+ if ((*f != "KPsionFullIndex") &&
+ (*f != "KPsionIncrementalIndex"))
+ listTree(i, tgz.directory()->entry(*f), 0);
+ }
+ tgz.close();
+ ++it;
+ }
+}
+
+void KPsionBackupListView::
+listTree(KPsionCheckListItem *cli, const KTarEntry *te, int level) {
+ KPsionCheckListItem *i =
+ new KPsionCheckListItem(cli, te->name(),
+ KPsionCheckListItem::CheckBox);
+ if (te->isDirectory()) {
+ if (level)
+ i->setPixmap(0, KGlobal::iconLoader()->loadIcon("folder",
+ KIcon::Small));
+ else
+ i->setPixmap(0, KGlobal::iconLoader()->loadIcon("hdd_unmount",
+ KIcon::Small));
+ KTarDirectory *td = (KTarDirectory *)te;
+ QStringList files = td->entries();
+ for (QStringList::Iterator f = files.begin(); f != files.end(); f++)
+ listTree(i, td->entry(*f), level + 1);
+ } else
+ i->setPixmap(0, KGlobal::iconLoader()->loadIcon("mime_empty",
+ KIcon::Small));
+}
+
+PlpDir &KPsionBackupListView::
+getRestoreList() {
+ return toRestore;
+}
+
+KPsionMainWindow::KPsionMainWindow()
+ : KMainWindow() {
+ setupActions();
+
+ statusBar()->insertItem(i18n("Idle"), STID_CONNECTION, 1);
+ statusBar()->setItemAlignment(STID_CONNECTION,
+ QLabel::AlignLeft|QLabel::AlignVCenter);
+
+ backupRunning = false;
+ restoreRunning = false;
+ formatRunning = false;
+
+ view = new KIconView(this, "iconview");
+ view->setSelectionMode(KIconView::Multi);
+ view->setResizeMode(KIconView::Adjust);
+ view->setItemsMovable(false);
+ connect(view, SIGNAL(clicked(QIconViewItem *)),
+ SLOT(iconClicked(QIconViewItem *)));
+ connect(view, SIGNAL(onItem(QIconViewItem *)),
+ SLOT(iconOver(QIconViewItem *)));
+ KConfig *config = kapp->config();
+ config->setGroup("Psion");
+ QStringList uids = config->readListEntry("MachineUIDs");
+ for (QStringList::Iterator it = uids.begin(); it != uids.end(); it++) {
+ QString tmp = QString::fromLatin1("Name_%1").arg(*it);
+ machines.insert(*it, config->readEntry(tmp));
+ }
+ config->setGroup("Settings");
+ backupDir = config->readEntry("BackupDir");
+ config->setGroup("Connection");
+ reconnectTime = config->readNumEntry("Retry");
+ ncpdDevice = config->readEntry("Device", i18n("off"));
+ ncpdSpeed = config->readNumEntry("Speed", 115200);
+
+ QWhatsThis::add(view, i18n(
+ "<qt>Here, you see your Psion's drives.<br/>"
+ "Every drive is represented by an Icon. If you "
+ "click on it, it gets selected for the next "
+ "operation. E.g.: backup, restore or format.<br/>"
+ "To unselect it, simply click on it again.<br/>"
+ "Select as many drives a you want, then choose "
+ "an operation.</qt>"));
+ setCentralWidget(view);
+
+ rfsvSocket = 0L;
+ rpcsSocket = 0L;
+ plpRfsv = 0L;
+ plpRpcs = 0L;
+
+ firstTry = true;
+ connected = false;
+ shuttingDown = false;
+
+ tryConnect();
+}
+
+KPsionMainWindow::~KPsionMainWindow() {
+ shuttingDown = true;
+ if (plpRfsv)
+ delete plpRfsv;
+ if (plpRpcs)
+ delete plpRpcs;
+ if (rfsvSocket)
+ delete rfsvSocket;
+ if (rfsvSocket)
+ delete rpcsSocket;
+}
+
+void KPsionMainWindow::
+setupActions() {
+
+ KStdAction::quit(this, SLOT(close()), actionCollection());
+ KStdAction::showToolbar(this, SLOT(slotToggleToolbar()),
+ actionCollection());
+ KStdAction::showStatusbar(this, SLOT(slotToggleStatusbar()),
+ actionCollection());
+ KStdAction::saveOptions(this, SLOT(slotSaveOptions()),
+ actionCollection());
+ KStdAction::preferences(this, SLOT(slotPreferences()),
+ actionCollection());
+ new KAction(i18n("Start &Format"), 0L, 0, this,
+ SLOT(slotStartFormat()), actionCollection(), "format");
+ new KAction(i18n("Start Full &Backup"), "psion_backup", 0, this,
+ SLOT(slotStartFullBackup()), actionCollection(),
+ "fullbackup");
+ new KAction(i18n("Start &Incremental Backup"), "psion_backup", 0, this,
+ SLOT(slotStartIncBackup()), actionCollection(), "incbackup");
+ new KAction(i18n("Start &Restore"), "psion_restore", 0, this,
+ SLOT(slotStartRestore()), actionCollection(), "restore");
+ createGUI();
+
+ actionCollection()->action("fullbackup")->setEnabled(false);
+ actionCollection()->action("incbackup")->setEnabled(false);
+#if OFFLINE
+ actionCollection()->action("restore")->setEnabled(true);
+#else
+ actionCollection()->action("restore")->setEnabled(false);
+#endif
+ actionCollection()->action("format")->setEnabled(false);
+
+ actionCollection()->action("fullbackup")->
+ setToolTip(i18n("Full backup of selected drive(s)"));
+ actionCollection()->action("incbackup")->
+ setToolTip(i18n("Incremental backup of selected drive(s)"));
+ actionCollection()->action("restore")->
+ setToolTip(i18n("Restore selected drive(s)"));
+ actionCollection()->action("format")->
+ setToolTip(i18n("Format selected drive(s)"));
+}
+
+void KPsionMainWindow::
+iconOver(QIconViewItem *i) {
+ lastSelected = i->isSelected();
+}
+
+void KPsionMainWindow::
+switchActions() {
+ QIconViewItem *i;
+ bool rwSelected = false;
+ bool anySelected = false;
+
+ if (backupRunning | restoreRunning | formatRunning)
+ view->setEnabled(false);
+ else {
+ for (i = view->firstItem(); i; i = i->nextItem()) {
+ if (i->isSelected()) {
+ anySelected = true;
+ if (i->key() != "Z") {
+ rwSelected = true;
+ break;
+ }
+ }
+ }
+ view->setEnabled(true);
+ }
+#if OFFLINE
+ actionCollection()->action("restore")->setEnabled(true);
+#else
+ actionCollection()->action("restore")->setEnabled(rwSelected);
+#endif
+ actionCollection()->action("format")->setEnabled(rwSelected);
+ actionCollection()->action("fullbackup")->setEnabled(anySelected);
+ actionCollection()->action("incbackup")->setEnabled(anySelected);
+}
+
+void KPsionMainWindow::
+iconClicked(QIconViewItem *i) {
+ if (i == 0L)
+ return;
+ lastSelected = !lastSelected;
+ i->setSelected(lastSelected);
+ switchActions();
+}
+
+void KPsionMainWindow::
+insertDrive(char letter, const char * const name) {
+ QString tmp;
+
+ if (name && strlen(name))
+ tmp = QString::fromLatin1("%1 (%2:)").arg(name).arg(letter);
+ else
+ tmp = QString::fromLatin1("%1:").arg(letter);
+ drives.insert(letter,tmp);
+ QIconViewItem *it =
+ new QIconViewItem(view, tmp,
+ KFileItem(KURL(), "inode/x-psion-drive", 0).pixmap(0));
+ tmp = QString::fromLatin1("%1").arg(letter);
+ it->setKey(tmp);
+ it->setDropEnabled(false);
+ it->setDragEnabled(false);
+ it->setRenameEnabled(false);
+}
+
+void KPsionMainWindow::
+queryPsion() {
+ u_int32_t devbits;
+ Enum <rfsv::errs> res;
+
+ statusBar()->changeItem(i18n("Retrieving machine info ..."),
+ STID_CONNECTION);
+#if OFFLINE
+ machineUID = 0x1000118a0c428fa3ULL;
+ S5mx = true;
+ insertDrive('C', "Intern");
+ insertDrive('D', "Flash");
+ insertDrive('Z', "RomDrive");
+#else
+ rpcs::machineInfo mi;
+ if ((res = plpRpcs->getMachineInfo(mi)) != rfsv::E_PSI_GEN_NONE) {
+ QString msg = i18n("Could not get Psion machine info");
+ statusBar()->changeItem(msg, STID_CONNECTION);
+ KMessageBox::error(this, msg);
+ return;
+ }
+ machineUID = mi.machineUID;
+ S5mx = (strcmp(mi.machineName, "SERIES5mx") == 0);
+#endif
+
+ QString uid = getMachineUID();
+ bool machineFound = false;
+ KConfig *config = kapp->config();
+ config->setGroup("Psion");
+ machineName = i18n("an unknown machine");
+ psionMap::Iterator it;
+ for (it = machines.begin(); it != machines.end(); it++) {
+ if (uid == it.key()) {
+ machineName = it.data();
+ QString tmp =
+ QString::fromLatin1("BackupDrives_%1").arg(it.key());
+ backupDrives = config->readListEntry(tmp);
+ machineFound = true;
+ }
+ }
+#if (!(OFFLINE))
+ drives.clear();
+ statusBar()->changeItem(i18n("Retrieving drive list ..."),
+ STID_CONNECTION);
+ if ((res = plpRfsv->devlist(devbits)) != rfsv::E_PSI_GEN_NONE) {
+ QString msg = i18n("Could not get list of drives");
+ statusBar()->changeItem(msg, STID_CONNECTION);
+ KMessageBox::error(this, msg);
+ return;
+ }
+ for (int i = 0; i < 26; i++) {
+ if ((devbits & 1) != 0) {
+ PlpDrive drive;
+ if (plpRfsv->devinfo(i, drive) == rfsv::E_PSI_GEN_NONE)
+ insertDrive('A' + i, drive.getName().c_str());
+ }
+ devbits >>= 1;
+ }
+#endif
+ if (!machineFound) {
+ NewPsionWizard *wiz = new NewPsionWizard(this, "newpsionwiz");
+ wiz->exec();
+ }
+ statusBar()->changeItem(i18n("Connected to %1").arg(machineName),
+ STID_CONNECTION);
+}
+
+QString KPsionMainWindow::
+getMachineUID() {
+ // ??! None of QString's formatting methods knows about long long.
+ ostrstream s;
+ s << hex << setw(16) << machineUID;
+ QString ret = s.str();
+ ret = ret.left(16);
+ return ret;
+}
+
+bool KPsionMainWindow::
+queryClose() {
+ QString msg = 0L;
+
+ if (backupRunning)
+ msg = i18n("A backup is running.\nDo you really want to quit?");
+ if (restoreRunning)
+ msg = i18n("A restore is running.\nDo you really want to quit?");
+ if (formatRunning)
+ msg = i18n("A format is running.\nDo you really want to quit?");
+
+ if ((!msg.isNull()) &&
+ (KMessageBox::warningYesNo(this, msg) == KMessageBox::No))
+ return false;
+ return true;
+}
+
+void KPsionMainWindow::
+tryConnect() {
+#if (!(OFFLINE))
+ if (shuttingDown || connected)
+ return;
+ bool showMB = firstTry;
+ firstTry = false;
+
+ if (plpRfsv)
+ delete plpRfsv;
+ if (plpRpcs)
+ delete plpRpcs;
+ if (rfsvSocket)
+ delete rfsvSocket;
+ if (rfsvSocket)
+ delete rpcsSocket;
+
+ rfsvSocket = new ppsocket();
+ statusBar()->changeItem(i18n("Connecting ..."), STID_CONNECTION);
+ if (!rfsvSocket->connect(NULL, 7501)) {
+ statusMsg = i18n("RFSV could not connect to ncpd at %1:%2. ").arg("localhost").arg(7501);
+ if (reconnectTime) {
+ nextTry = reconnectTime;
+ statusMsg += i18n(" (Retry in %1 seconds.)");
+ QTimer::singleShot(1000, this, SLOT(slotUpdateTimer()));
+ }
+ statusBar()->changeItem(statusMsg.arg(reconnectTime),
+ STID_CONNECTION);
+ if (showMB)
+ KMessageBox::error(this, statusMsg.arg(reconnectTime));
+ return;
+ }
+ rfsvfactory factory(rfsvSocket);
+ plpRfsv = factory.create(false);
+ if (plpRfsv == 0L) {
+ statusMsg = i18n("RFSV could not establish link: %1.").arg(factory.getError());
+ delete rfsvSocket;
+ rfsvSocket = 0L;
+ if (reconnectTime) {
+ nextTry = reconnectTime;
+ statusMsg += i18n(" (Retry in %1 seconds.)");
+ QTimer::singleShot(1000, this, SLOT(slotUpdateTimer()));
+ }
+ statusBar()->changeItem(statusMsg.arg(reconnectTime),
+ STID_CONNECTION);
+ if (showMB)
+ KMessageBox::error(this, statusMsg.arg(reconnectTime));
+ return;
+ }
+
+ rpcsSocket = new ppsocket();
+ if (!rpcsSocket->connect(NULL, 7501)) {
+ statusMsg = i18n("RPCS could not connect to ncpd at %1:%2.").arg("localhost").arg(7501);
+ delete plpRfsv;
+ plpRfsv = 0L;
+ delete rfsvSocket;
+ rfsvSocket = 0L;
+ if (reconnectTime) {
+ nextTry = reconnectTime;
+ statusMsg += i18n(" (Retry in %1 seconds.)");
+ QTimer::singleShot(1000, this, SLOT(slotUpdateTimer()));
+ }
+ statusBar()->changeItem(statusMsg.arg(reconnectTime),
+ STID_CONNECTION);
+ if (showMB)
+ KMessageBox::error(this, statusMsg.arg(reconnectTime));
+ return;
+ }
+ rpcsfactory factory2(rpcsSocket);
+ plpRpcs = factory2.create(false);
+ if (plpRpcs == 0L) {
+ statusMsg = i18n("RPCS could not establish link: %1.").arg(factory.getError());
+ delete plpRfsv;
+ plpRfsv = 0L;
+ delete rfsvSocket;
+ rfsvSocket = 0L;
+ delete rpcsSocket;
+ rpcsSocket = 0L;
+ if (reconnectTime) {
+ nextTry = reconnectTime;
+ statusMsg += i18n(" (Retry in %1 seconds.)");
+ QTimer::singleShot(1000, this, SLOT(slotUpdateTimer()));
+ }
+ statusBar()->changeItem(statusMsg.arg(reconnectTime),
+ STID_CONNECTION);
+ if (showMB)
+ KMessageBox::error(this, statusMsg.arg(reconnectTime));
+ return;
+ }
+#endif
+ connected = true;
+ queryPsion();
+}
+
+void KPsionMainWindow::
+slotUpdateTimer() {
+ nextTry--;
+ if (nextTry <= 0)
+ tryConnect();
+ else {
+ statusBar()->changeItem(statusMsg.arg(nextTry), STID_CONNECTION);
+ QTimer::singleShot(1000, this, SLOT(slotUpdateTimer()));
+ }
+}
+
+void KPsionMainWindow::
+slotStartFullBackup() {
+ fullBackup = true;
+ doBackup();
+}
+
+void KPsionMainWindow::
+slotStartIncBackup() {
+ fullBackup = false;
+ doBackup();
+}
+
+void KPsionMainWindow::
+doBackup() {
+ backupRunning = true;
+ switchActions();
+ toBackup.clear();
+ KDialog *d = new KDialog(this, "backupDialog", false);
+ d->setCaption(i18n("Backup"));
+ QGridLayout *gl = new QGridLayout(d);
+ progressLabel = new KSqueezedTextLabel(d);
+ gl->addWidget(progressLabel, 1, 1);
+ progress = new KProgress(0, 100, 0, KProgress::Horizontal, d,
+ "backupProgress");
+
+ gl->addWidget(progress, 2, 1);
+ gl->addRowSpacing(0, KDialog::marginHint());
+ gl->addRowSpacing(3, KDialog::marginHint());
+ gl->addColSpacing(0, KDialog::marginHint());
+ gl->addColSpacing(2, KDialog::marginHint());
+ gl->setColStretch(1, 1);
+ gl->setRowStretch(1, 1);
+ d->setMinimumSize(250, 80);
+ d->show();
+
+ // Collect list of files to backup
+ backupSize = 0;
+ backupCount = 0;
+ progressTotal = 0;
+ for (QIconViewItem *i = view->firstItem(); i; i = i->nextItem()) {
+ if (i->isSelected()) {
+ QString drv = i->key();
+ drv += ":";
+ int drvNum = *(drv.data()) - 'A';
+ PlpDrive drive;
+ if (plpRfsv->devinfo(drvNum, drive) != rfsv::E_PSI_GEN_NONE) {
+ KMessageBox::error(this, i18n("Could not retrieve drive details for drive %1").arg(drv));
+ d->hide();
+ delete d;
+ backupRunning = false;
+ switchActions();
+ return;
+ }
+ progressLabel->setText(i18n("Scanning drive %1").arg(drv));
+
+ progressLocal = drive.getSize() - drive.getSpace();
+ progressLocalCount = 0;
+ progressLocalPercent = -1;
+ progress->setValue(0);
+ collectFiles(drv);
+ }
+ }
+ progressLabel->setText(i18n("%1 files need backup").arg(backupSize));
+ if (backupCount == 0) {
+ KMessageBox::information(this, i18n("No files need backup"));
+ d->hide();
+ delete d;
+ backupRunning = false;
+ switchActions();
+ return;
+ }
+
+ statusBar()->message(i18n("Backup"));
+ progressCount = 0;
+ progressTotal = backupSize;
+ progressPercent = -1;
+
+ // Create tgz with index file.
+ QString archiveName = backupDir;
+ if (archiveName.right(1) != "/")
+ archiveName += "/";
+ archiveName += getMachineUID();
+ QDir archiveDir(archiveName);
+ if (!archiveDir.exists())
+ if (!archiveDir.mkdir(archiveName)) {
+ KMessageBox::error(this, i18n("Could not create backup folder %1").arg(archiveName));
+ d->hide();
+ delete d;
+ statusBar()->clear();
+ backupRunning = false;
+ switchActions();
+ return;
+ }
+
+ archiveName += (fullBackup) ? "/F-" : "/I-";
+ time_t now = time(0);
+ char tstr[30];
+ strftime(tstr, sizeof(tstr), "%Y-%m-%d-%H-%M-%S.tar.gz",
+ localtime(&now));
+ archiveName += tstr;
+ backupTgz = new KTarGz(archiveName);
+ backupTgz->open(IO_WriteOnly);
+ createIndex();
+
+ // Kill all running applications on the Psion
+ // and save their state.
+ killSave();
+
+ bool badBackup = false;
+ Enum<rfsv::errs> res;
+ // Now the real backup
+ for (int i = 0; i < toBackup.size(); i++) {
+ PlpDirent e = toBackup[i];
+ const char *fn = e.getName();
+ const char *p;
+ char *q;
+ char unixname[1024];
+
+ for (p = fn, q = unixname; *p; p++, q++)
+ switch (*p) {
+ case '%':
+ *q++ = '%';
+ *q++ = '2';
+ *q = '5';
+ break;
+ case '/':
+ *q++ = '%';
+ *q++ = '2';
+ *q= 'f';
+ break;
+ case '\\':
+ *q = '/';
+ break;
+ default:
+ *q = *p;
+ }
+ *q = '\0';
+
+ ostrstream os;
+
+ progressLabel->setText(i18n("Backing up %1").arg(fn));
+ progressLocal = e.getSize();
+ progressLocalCount = 0;
+ progressLocalPercent = -1;
+ progress->setValue(0);
+
+ u_int32_t handle;
+
+ kapp->processEvents();
+ res = plpRfsv->fopen(plpRfsv->opMode(rfsv::PSI_O_RDONLY), fn,
+ handle);
+ if (res != rfsv::E_PSI_GEN_NONE) {
+ if (KMessageBox::warningYesNo(this, i18n("<QT>Could not open<BR/><B>%1</B></QT>").arg(fn)) == KMessageBox::No) {
+ badBackup = true;
+ break;
+ } else {
+ e.setName("!");
+ continue;
+ }
+ }
+ unsigned char *buff = new unsigned char[RFSV_SENDLEN];
+ u_int32_t len;
+ do {
+ if ((res = plpRfsv->fread(handle, buff, RFSV_SENDLEN, len)) ==
+ rfsv::E_PSI_GEN_NONE) {
+ os.write(buff, len);
+ updateProgress(len);
+ }
+ kapp->processEvents();
+ } while ((len > 0) && (res == rfsv::E_PSI_GEN_NONE));
+ delete[]buff;
+ plpRfsv->fclose(handle);
+ if (res != rfsv::E_PSI_GEN_NONE) {
+ if (KMessageBox::warningYesNo(this, i18n("<QT>Could not read<BR/><B>%1</B></QT>").arg(fn)) == KMessageBox::No) {
+ badBackup = true;
+ break;
+ } else {
+ e.setName("!");
+ continue;
+ }
+ }
+ backupTgz->writeFile(unixname, "root", "root", os.pcount(),
+ os.str());
+ }
+
+ if (!badBackup) {
+ // Reset archive attributes of all backuped files.
+ progressLabel->setText(i18n("Resetting archive attributes ..."));
+ progressLocal = backupSize;
+ progressLocalCount = 0;
+ progressLocalPercent = -1;
+ progress->setValue(0);
+ for (int i = 0; i < toBackup.size(); i++) {
+ PlpDirent e = toBackup[i];
+ const char *fn = e.getName();
+ if ((e.getAttr() & rfsv::PSI_A_ARCHIVE) &&
+ (strcmp(fn, "!") != 0)) {
+ kapp->processEvents();
+ res = plpRfsv->fsetattr(fn, 0, rfsv::PSI_A_ARCHIVE);
+ if (res != rfsv::E_PSI_GEN_NONE) {
+ if (KMessageBox::warningYesNo(this, i18n("<QT>Could not set attributes of<BR/><B>%1</B></QT>").arg(fn)) == KMessageBox::No) {
+ break;
+ }
+ }
+ }
+ updateProgress(e.getSize());
+ }
+ }
+ // Restart previously running applications on the Psion
+ // from saved state info.
+ runRestore();
+
+ backupTgz->close();
+ delete backupTgz;
+ if (badBackup)
+ unlink(archiveName.data());
+ d->hide();
+ delete d;
+ backupRunning = false;
+ switchActions();
+ statusBar()->message(i18n("Backup done"), 2000);
+}
+
+void KPsionMainWindow::
+slotStartRestore() {
+ restoreRunning = true;
+ switchActions();
+
+ KDialog *d = new KDialog(this, "restoreDialog", true);
+ d->setCaption(i18n("Restore"));
+ QGridLayout *gl = new QGridLayout(d);
+ //progressLabel = new KSqueezedTextLabel(d);
+ KPsionBackupListView *v = new KPsionBackupListView(d, "restoreSelector");
+ gl->addWidget(v, 1, 1);
+ //progress = new KProgress(0, 100, 0, KProgress::Horizontal, d, "restoreProgress");
+
+ //gl->addWidget(progress, 2, 1);
+ gl->addRowSpacing(0, KDialog::marginHint());
+ gl->addRowSpacing(3, KDialog::marginHint());
+ gl->addColSpacing(0, KDialog::marginHint());
+ gl->addColSpacing(2, KDialog::marginHint());
+ gl->setColStretch(1, 1);
+ gl->setRowStretch(1, 1);
+ d->setMinimumSize(250, 80);
+ v->readBackups(getMachineUID());
+ d->exec();
+
+ d->hide();
+ delete d;
+ restoreRunning = false;
+ switchActions();
+ statusBar()->message(i18n("Restore done"), 2000);
+}
+
+void KPsionMainWindow::
+slotStartFormat() {
+ if (KMessageBox::warningYesNo(this, i18n(
+ "<QT>This erases <B>ALL</B> data "
+ "on the drive(s).<BR/>Do you really "
+ "want to proceed?"
+ )) == KMessageBox::No)
+ return;
+ formatRunning = true;
+ switchActions();
+}
+
+void KPsionMainWindow::
+slotToggleToolbar() {
+ if (toolBar()->isVisible())
+ toolBar()->hide();
+ else
+ toolBar()->show();
+}
+
+void KPsionMainWindow::
+slotToggleStatusbar() {
+ if (statusBar()->isVisible())
+ statusBar()->hide();
+ else
+ statusBar()->show();
+}
+
+void KPsionMainWindow::
+slotSaveOptions() {
+}
+
+void KPsionMainWindow::
+slotPreferences() {
+}
+
+void KPsionMainWindow::
+updateProgress(unsigned long amount) {
+ progressLocalCount += amount;
+ int lastPercent = progressLocalPercent;
+ if (progressLocal)
+ progressLocalPercent = progressLocalCount * 100 / progressLocal;
+ else
+ progressLocalPercent = 100;
+ if (progressLocalPercent != lastPercent)
+ progress->setValue(progressLocalPercent);
+ if (progressTotal > 0) {
+ progressCount += amount;
+ lastPercent = progressPercent;
+ if (progressTotal)
+ progressPercent = progressCount * 100 / progressTotal;
+ else
+ progressPercent = 100;
+ if (progressPercent != lastPercent)
+ statusBar()->message(i18n("Backup %1% complete").arg(progressPercent));
+ }
+}
+
+void KPsionMainWindow::
+collectFiles(QString dir) {
+ Enum<rfsv::errs> res;
+ PlpDir files;
+ QString tmp = dir;
+
+ kapp->processEvents();
+ tmp += "\\";
+ if ((res = plpRfsv->dir(tmp.data(), files)) != rfsv::E_PSI_GEN_NONE) {
+ // messagebox "Couldn't get directory ...."
+ } else
+ for (int i = 0; i < files.size(); i++) {
+ PlpDirent e = files[i];
+
+
+ long attr = e.getAttr();
+ tmp = dir;
+ tmp += "\\";
+ tmp += e.getName();
+ if (attr & rfsv::PSI_A_DIR) {
+ collectFiles(tmp);
+ } else {
+ kapp->processEvents();
+ updateProgress(e.getSize());
+ if ((attr & rfsv::PSI_A_ARCHIVE) || fullBackup) {
+ backupCount++;
+ backupSize += e.getSize();
+ e.setName(tmp.data());
+ toBackup.push_back(e);
+ }
+ }
+ }
+}
+
+void KPsionMainWindow::
+killSave() {
+ Enum<rfsv::errs> res;
+ bufferArray tmp;
+
+ savedCommands.clear();
+ if ((res = plpRpcs->queryDrive('C', tmp)) != rfsv::E_PSI_GEN_NONE) {
+ cerr << "Could not get process list, Error: " << res << endl;
+ return;
+ } else {
+ while (!tmp.empty()) {
+ QString pbuf;
+ bufferStore cmdargs;
+ bufferStore bs = tmp.pop();
+ int pid = bs.getWord(0);
+ const char *proc = bs.getString(2);
+ if (S5mx)
+ pbuf.sprintf("%s.$%02d", proc, pid);
+ else
+ pbuf.sprintf("%s.$%d", proc, pid);
+ bs = tmp.pop();
+ if (plpRpcs->getCmdLine(pbuf.data(), cmdargs) == 0) {
+ QString cmdline(cmdargs.getString(0));
+ cmdline += " ";
+ cmdline += bs.getString(0);
+ savedCommands += cmdline;
+ }
+ progressLabel->setText(i18n("Stopping %1").arg(cmdargs.getString(0)));
+ kapp->processEvents();
+ plpRpcs->stopProgram(pbuf);
+ }
+ }
+ return;
+}
+
+void KPsionMainWindow::
+runRestore() {
+ Enum<rfsv::errs> res;
+
+ for (QStringList::Iterator it = savedCommands.begin(); it != savedCommands.end(); it++) {
+ int firstBlank = (*it).find(' ');
+ QString cmd = (*it).left(firstBlank);
+ QString arg = (*it).mid(firstBlank + 1);
+
+ if (!cmd.isEmpty()) {
+ // Workaround for broken programs like Backlite.
+ // These do not storethe full program path.
+ // In that case we try running the arg1 which
+ // results in starting the program via recog. facility.
+ progressLabel->setText(i18n("Starting %1").arg(cmd));
+ kapp->processEvents();
+ if ((arg.length() > 2) && (arg[1] == ':') && (arg[0] >= 'A') &&
+ (arg[0] <= 'Z'))
+ res = plpRpcs->execProgram(arg.data(), "");
+ else
+ res = plpRpcs->execProgram(cmd.data(), arg.data());
+ if (res != rfsv::E_PSI_GEN_NONE) {
+ // If we got an error here, that happened probably because
+ // we have no path at all (e.g. Macro5) and the program is
+ // not registered in the Psion's path properly. Now try
+ // the ususal \System\Apps\<AppName>\<AppName>.app
+ // on all drives.
+ if (cmd.find('\\') == -1) {
+ driveMap::Iterator it;
+ for (it = drives.begin(); it != drives.end(); it++) {
+ QString newcmd = QString::fromLatin1("%1:\\System\\Apps\\%2\\%3").arg(it.key()).arg(cmd).arg(cmd);
+ res = plpRpcs->execProgram(newcmd.data(), "");
+ if (res == rfsv::E_PSI_GEN_NONE)
+ break;
+ newcmd += ".app";
+ res = plpRpcs->execProgram(newcmd.data(), "");
+ if (res == rfsv::E_PSI_GEN_NONE)
+ break;
+
+ }
+ }
+ }
+ }
+ }
+ return;
+}
+
+void KPsionMainWindow::
+createIndex() {
+ ostrstream os;
+ os << "#plpbackup index " <<
+ (fullBackup ? "F" : "I") << endl;
+ for (int i = 0; i < toBackup.size(); i++) {
+ PlpDirent e = toBackup[i];
+ PsiTime t = e.getPsiTime();
+ long attr = e.getAttr() &
+ ~rfsv::PSI_A_ARCHIVE;
+ os << hex
+ << setw(8) << setfill('0') <<
+ t.getPsiTimeHi() << " "
+ << setw(8) << setfill('0') <<
+ t.getPsiTimeLo() << " "
+ << setw(8) << setfill('0') <<
+ e.getSize() << " "
+ << setw(8) << setfill('0') <<
+ attr << " "
+ << setw(0) << e.getName() << endl;
+ kapp->processEvents();
+ }
+ backupTgz->writeFile("Index", "root", "root", os.pcount(), os.str());
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/kde2/kpsion/kpsion.desktop b/kde2/kpsion/kpsion.desktop
new file mode 100644
index 0000000..e29bb73
--- /dev/null
+++ b/kde2/kpsion/kpsion.desktop
@@ -0,0 +1,10 @@
+[Desktop Entry]
+DocPath=kpsion/index.html
+Exec=kpsion
+Terminal=0
+Type=Application
+Icon=psion_desktop
+Comment=My Psion PDA
+Comment[de]=Mein Psion
+Name=KPsion
+Name[de]=KPsion
diff --git a/kde2/kpsion/kpsion.h b/kde2/kpsion/kpsion.h
new file mode 100644
index 0000000..86aeff4
--- /dev/null
+++ b/kde2/kpsion/kpsion.h
@@ -0,0 +1,165 @@
+#ifndef _KPSION_H_
+#define _KPSION_H_
+
+#include "setupdialog.h"
+
+#include <kmainwindow.h>
+#include <kiconview.h>
+#include <kprogress.h>
+#include <ksqueezedtextlabel.h>
+#include <klistview.h>
+#include <ktar.h>
+
+#include <rfsv.h>
+#include <rpcs.h>
+#include <ppsocket.h>
+
+typedef QMap<char,QString> driveMap;
+typedef QMap<QString,QString> psionMap;
+
+class KPsionCheckListItem : public QCheckListItem {
+ public:
+ KPsionCheckListItem(KPsionCheckListItem *parent, const QString &text,
+ Type tt)
+ : QCheckListItem(parent, text, tt) { init(true); }
+ KPsionCheckListItem(QCheckListItem *parent, const QString &text, Type tt)
+ : QCheckListItem(parent, text, tt) { init(false); }
+ KPsionCheckListItem(QListViewItem *parent, const QString &text, Type tt)
+ : QCheckListItem(parent, text, tt) { init(false); }
+ KPsionCheckListItem(QListView *parent, const QString &text, Type tt)
+ : QCheckListItem(parent, text, tt) { init(false); }
+ KPsionCheckListItem(QListViewItem *parent, const QString &text,
+ const QPixmap &p)
+ : QCheckListItem(parent, text, p) { init(false); }
+ KPsionCheckListItem(QListView *parent, const QString &text,
+ const QPixmap &p)
+ : QCheckListItem(parent, text, p) { init(false); }
+ void setMetaData(int, time_t);
+
+ protected:
+ virtual void stateChange(bool);
+ void propagateUp(bool);
+ void propagateDown(bool);
+
+ private:
+ void init(bool);
+
+ bool parentIsKPsionCheckListItem;
+ bool dontPropagate;
+ int backupType;
+ time_t when;
+};
+
+class KPsionBackupListView : public KListView {
+ Q_OBJECT
+ public:
+ enum backupTypes {
+ UNKNOWN = 0,
+ FULL = 1,
+ INCREMENTAL = 2,
+ };
+
+ KPsionBackupListView(QWidget *parent = 0, const char *name = 0);
+ void readBackups(QString uid);
+ PlpDir &getRestoreList();
+
+ private:
+ void listTree(KPsionCheckListItem *cli, const KTarEntry *te, int level);
+
+ QString uid;
+ QString backupDir;
+ PlpDir toRestore;
+};
+
+class KPsionMainWindow : public KMainWindow {
+ Q_OBJECT
+
+ public:
+ KPsionMainWindow();
+ ~KPsionMainWindow();
+ void setMachineName(QString &_name) { machineName = _name; }
+ QString getMachineUID();
+ driveMap &getDrives() { return drives; }
+ psionMap &getMachines() { return machines; }
+ QString &getMachineName() { return machineName; }
+ QString &getBackupDir() { return backupDir; }
+
+ public slots:
+ void slotStartRestore();
+ void slotStartFullBackup();
+ void slotStartIncBackup();
+ void slotStartFormat();
+ void slotToggleToolbar();
+ void slotToggleStatusbar();
+ void slotSaveOptions();
+ void slotPreferences();
+
+ protected:
+ virtual bool queryClose();
+ void setupActions();
+ void switchActions();
+ void queryPsion();
+ void insertDrive(char letter, const char * const name);
+
+ private slots:
+ void iconClicked(QIconViewItem *i);
+ void iconOver(QIconViewItem *i);
+ void slotUpdateTimer();
+
+ private:
+ void doBackup();
+ void tryConnect();
+ void updateProgress(unsigned long);
+ void collectFiles(QString dir);
+ void killSave();
+ void runRestore();
+ void createIndex();
+
+ rfsv *plpRfsv;
+ rpcs *plpRpcs;
+ ppsocket *rfsvSocket;
+ ppsocket *rpcsSocket;
+ SetupDialog *setupDialog;
+ KIconView *view;
+ KProgress *progress;
+ KSqueezedTextLabel *progressLabel;
+ KTarGz *backupTgz;
+
+ driveMap drives;
+ psionMap machines;
+ QStringList backupDrives;
+ QStringList savedCommands;
+ QString backupDir;
+ QString machineName;
+ QString statusMsg;
+ QString ncpdDevice;
+ bool S5mx;
+ bool backupRunning;
+ bool restoreRunning;
+ bool formatRunning;
+ bool lastSelected;
+ bool connected;
+ bool firstTry;
+ bool shuttingDown;
+ bool fullBackup;
+ int reconnectTime;
+ int nextTry;
+ int ncpdSpeed;
+ unsigned long long machineUID;
+ PlpDir toBackup;
+ unsigned long backupSize;
+ unsigned long backupCount;
+ unsigned long progressTotal;
+ unsigned long progressLocal;
+ unsigned long progressCount;
+ unsigned long progressLocalCount;
+ int progressPercent;
+ int progressLocalPercent;
+};
+
+#endif
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/kde2/kpsion/kpsionui.rc b/kde2/kpsion/kpsionui.rc
new file mode 100644
index 0000000..17302c5
--- /dev/null
+++ b/kde2/kpsion/kpsionui.rc
@@ -0,0 +1,15 @@
+<!DOCTYPE kpartgui>
+<kpartgui name="kpsion">
+ <MenuBar>
+ <Menu name="file"><text>&amp;File</text>
+ <Action name="fullbackup"/>
+ <Action name="incbackup"/>
+ <Action name="restore"/>
+ <Action name="format"/>
+ </Menu>
+ </MenuBar>
+ <ToolBar fullWidth="true" name="mainToolBar">
+ <Action name="fullbackup"/>
+ <Action name="restore"/>
+ </ToolBar>
+</kpartgui>
diff --git a/kde2/kpsion/lo16-action-psion_backup.png b/kde2/kpsion/lo16-action-psion_backup.png
new file mode 100644
index 0000000..4d0f815
--- /dev/null
+++ b/kde2/kpsion/lo16-action-psion_backup.png
Binary files differ
diff --git a/kde2/kpsion/lo16-action-psion_restore.png b/kde2/kpsion/lo16-action-psion_restore.png
new file mode 100644
index 0000000..8f3103b
--- /dev/null
+++ b/kde2/kpsion/lo16-action-psion_restore.png
Binary files differ
diff --git a/kde2/kpsion/lo16-app-kpsion.png b/kde2/kpsion/lo16-app-kpsion.png
new file mode 100644
index 0000000..2382c76
--- /dev/null
+++ b/kde2/kpsion/lo16-app-kpsion.png
Binary files differ
diff --git a/kde2/kpsion/lo22-action-psion_backup.png b/kde2/kpsion/lo22-action-psion_backup.png
new file mode 100644
index 0000000..b5ebd45
--- /dev/null
+++ b/kde2/kpsion/lo22-action-psion_backup.png
Binary files differ
diff --git a/kde2/kpsion/lo22-action-psion_restore.png b/kde2/kpsion/lo22-action-psion_restore.png
new file mode 100644
index 0000000..47780b8
--- /dev/null
+++ b/kde2/kpsion/lo22-action-psion_restore.png
Binary files differ
diff --git a/kde2/kpsion/lo32-action-psion_backup.png b/kde2/kpsion/lo32-action-psion_backup.png
new file mode 100644
index 0000000..4a99260
--- /dev/null
+++ b/kde2/kpsion/lo32-action-psion_backup.png
Binary files differ
diff --git a/kde2/kpsion/lo32-action-psion_restore.png b/kde2/kpsion/lo32-action-psion_restore.png
new file mode 100644
index 0000000..782e2d9
--- /dev/null
+++ b/kde2/kpsion/lo32-action-psion_restore.png
Binary files differ
diff --git a/kde2/kpsion/lo32-app-kpsion.png b/kde2/kpsion/lo32-app-kpsion.png
new file mode 100644
index 0000000..7285992
--- /dev/null
+++ b/kde2/kpsion/lo32-app-kpsion.png
Binary files differ
diff --git a/kde2/kpsion/main.cpp b/kde2/kpsion/main.cpp
new file mode 100644
index 0000000..df909ef
--- /dev/null
+++ b/kde2/kpsion/main.cpp
@@ -0,0 +1,55 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "kpsion.h"
+#include "wizards.h"
+#include <kapp.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <kcmdlineargs.h>
+#include <kaboutdata.h>
+
+static KCmdLineOptions options[] = {
+ {"b", 0, 0},
+ {"backup", I18N_NOOP("perform backup"), 0},
+ {"r", 0, 0},
+ {"restore", I18N_NOOP("perform restore"), 0},
+ {"f", 0, 0},
+ {"format", I18N_NOOP("format drive"), 0},
+ {"+[DriveLetter]", I18N_NOOP("The drive letter to backup/restore or format."), 0},
+ { 0, 0, 0},
+};
+
+int main(int argc, char **argv) {
+ KAboutData *about = new KAboutData("kpsion", I18N_NOOP("KPsion"),
+ VERSION, I18N_NOOP("Psion connectivity utility"),
+ KAboutData::License_GPL,
+ "(C) 2001, Fritz Elfert", 0L,
+ "http://plptools.sourceforge.net",
+ "plptools-developers@sourceforge.net");
+ about->addAuthor("Fritz Elfert", I18N_NOOP("Original Developer/Maintainer"),
+ "felfert@users.sourceforge.net",
+ "http://plptools.sourceforge.net");
+ KCmdLineArgs::init(argc, argv, about);
+ KCmdLineArgs::addCmdLineOptions(options);
+
+ KApplication a;
+
+ KConfig *config = kapp->config();
+ config->setGroup("Settings");
+ QString backupDir = config->readEntry("BackupDir");
+
+ if (backupDir.isEmpty()) {
+ FirstTimeWizard *wiz = new FirstTimeWizard(0L, "firsttimewizard");
+ wiz->exec();
+ }
+
+ KPsionMainWindow *w = new KPsionMainWindow();
+ w->resize(300, 150);
+ a.setMainWidget(w);
+ w->show();
+ return a.exec();
+}
+
+
diff --git a/kde2/kpsion/setupdialog.cpp b/kde2/kpsion/setupdialog.cpp
new file mode 100644
index 0000000..370bb30
--- /dev/null
+++ b/kde2/kpsion/setupdialog.cpp
@@ -0,0 +1,62 @@
+#include "setupdialog.h"
+
+#include <kapp.h>
+#include <kconfig.h>
+#include <klocale.h>
+#include <knuminput.h>
+#include <klineedit.h>
+#include <kcombobox.h>
+
+#include <qlayout.h>
+#include <qlabel.h>
+
+SetupDialog::SetupDialog(QWidget *parent, rfsv *plpRfsv, rpcs *plpRpcs)
+ : KDialogBase(Tabbed, "Settings", Ok|Apply|Default|Cancel, Ok, parent,
+ "settingsDialog", true, true) {
+
+ enableLinkedHelp(true);
+
+ KConfig *config = kapp->config();
+ QFrame *page = addPage(i18n("&General"));
+ QGridLayout *gl = new QGridLayout(page, 4, 2, 15);
+ gl->addRowSpacing(0, 10);
+ QLabel *l;
+
+ l = new QLabel(i18n("Backup &directory"), page, "backupDirLabel");
+ gl->addWidget(l, 1, 0);
+ KLineEdit *bdiredit = new KLineEdit(page, "backupDirEdit");
+ gl->addWidget(bdiredit, 1 , 1);
+ l->setBuddy(bdiredit);
+ QPushButton *bdirbutton = new QPushButton(i18n("Browse"), page, "backupDirButton");
+ gl->addWidget(bdirbutton, 1 , 2);
+
+ l = new QLabel(i18n("Backup &generations"), page, "backupGenLabel");
+ gl->addMultiCellWidget(l, 2, 2, 0, 1);
+ KIntSpinBox *genspin = new KIntSpinBox(0, 10, 1, 3, 10, page, "backupGenSpin");
+ gl->addWidget(genspin, 2, 2);
+ l->setBuddy(genspin);
+
+ page = addPage(i18n("&Machines"));
+ gl = new QGridLayout(page, 4, 2, 15);
+ gl->addRowSpacing(0, 10);
+
+ l = new QLabel(i18n("Machine &Name"), page, "NameLabel");
+ gl->addWidget(l, 1, 0);
+ KLineEdit *nedit = new KLineEdit(page, "NameEdit");
+ gl->addWidget(nedit, 1, 1);
+ l->setBuddy(nedit);
+ l = new QLabel(i18n("Machine &UID"), page, "UIDLabel");
+ gl->addWidget(l, 2, 0);
+ KComboBox *uidcombo = new KComboBox(true, page, "UIDCombo");
+ config->setGroup("Psion");
+ uidcombo->insertStringList(config->readListEntry("MachineUIDs"));
+ gl->addWidget(uidcombo, 1, 1);
+ l->setBuddy(uidcombo);
+
+ connect(this, SIGNAL(defaultClicked()), SLOT(slotDefaultClicked()));
+}
+
+void SetupDialog::
+slotDefaultClicked() {
+ enableLinkedHelp(false);
+}
diff --git a/kde2/kpsion/setupdialog.h b/kde2/kpsion/setupdialog.h
new file mode 100644
index 0000000..b385dce
--- /dev/null
+++ b/kde2/kpsion/setupdialog.h
@@ -0,0 +1,17 @@
+#ifndef _SETUPDIALOGS_H_
+#define _SETUPDIALOGS_H_
+
+#include <rfsv.h>
+#include <rpcs.h>
+
+#include <kdialogbase.h>
+
+class SetupDialog : public KDialogBase {
+ public:
+ SetupDialog(QWidget *parent, rfsv *plpRfsv, rpcs *plpRpcs);
+
+ private slots:
+ void slotDefaultClicked();
+};
+
+#endif
diff --git a/kde2/kpsion/wizards.cpp b/kde2/kpsion/wizards.cpp
new file mode 100644
index 0000000..24cd121
--- /dev/null
+++ b/kde2/kpsion/wizards.cpp
@@ -0,0 +1,586 @@
+/*-*-c++-*-
+ * $Id$
+ *
+ * This file is part of plptools.
+ *
+ * Copyright (C) 2001 Fritz Elfert <felfert@to.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <pwd.h>
+
+#include "wizards.h"
+
+#include <kapp.h>
+#include <kdebug.h>
+#include <kdialog.h>
+#include <klocale.h>
+#include <kfiledialog.h>
+#include <kmessagebox.h>
+
+#include <qlayout.h>
+#include <qwhatsthis.h>
+#include <qheader.h>
+
+FirstTimeWizard::FirstTimeWizard(QWidget *parent, const char *name)
+ : KWizard(parent, name, true) {
+
+ setCaption(i18n("KPsion Setup"));
+ QWhatsThis::add(nextButton(),
+ i18n("Click this button to continue with the next page."));
+ QWhatsThis::add(backButton(),
+ i18n("Click this button, to go to a previous page."));
+ QWhatsThis::add(cancelButton(),
+ i18n("<QT>If you click this button, the setup of <B>KPSion</B> will be aborted and next time you start <B>KPsion</B>, it will run this setup again.</QT>"));
+
+ // Getting the users home directory from the passwd-entry is MUCH safer
+ // than getting it from $HOME !!! (Environments can be tweaked)
+ struct passwd *pw = getpwuid(getuid());
+ bdirDefault = QString((pw) ? pw->pw_dir : 0L);
+ if (bdirDefault.isEmpty())
+ bdirDefault = QDir::homeDirPath();
+ bdirDefault += "/KPsionBackup";
+ bdirCreated = "";
+
+ // Page 1
+ page1 = new QWidget(this, "welcome");
+ QGridLayout *grid = new QGridLayout(page1);
+
+ QLabel *l = new QLabel(page1, "welcome message");
+ l->setText(i18n(
+ "<QT>"
+ "<H2>Welcome to KPsion!</H2>"
+ "It looks like you started <B>KPsion</B> the first time. "
+ "At least, i could not find any valid configuration.</BR>"
+ "On the following pages, we will gather some information, "
+ "which is needed for working with <B>KPsion</B>.</BR>"
+ " </BR>"
+ "Have fun."
+ "</QT>"
+ ));
+ grid->addWidget(l, 1, 1, Qt::AlignTop);
+ grid->setColStretch(1, 1);
+ grid->setRowStretch(1, 1);
+ grid->addRowSpacing(0, KDialog::marginHint());
+ grid->addRowSpacing(2, KDialog::marginHint());
+ grid->addColSpacing(0, KDialog::marginHint());
+ grid->addColSpacing(2, KDialog::marginHint());
+ addPage(page1, i18n("<QT><BIG><B>Welcome<B></BIG></QT>"));
+
+ // Page 2
+ page2 = new QWidget(this, "step1");
+ grid = new QGridLayout(page2);
+
+ l = new QLabel(page2, "step1");
+ l->setText(i18n(
+ "<QT>"
+ "First, we need a folder for storing backups of "
+ "your Psion. You probably don't want others to "
+ "have access to it, so it's best to choose a "
+ "location somewhere in your home directory. "
+ "Please browse through existing folders and select a suitable "
+ "location or simply accept the default shown below."
+ "</QT>"
+ ));
+ grid->addMultiCellWidget(l, 1, 1, 1, 2, Qt::AlignTop);
+
+ bdirLabel = new QLabel(page2, "bdirLabel");
+ bdirLabel->setText(bdirDefault);
+ bdirButton = new QPushButton(i18n("Browse"), page2);
+
+ QWhatsThis::add(bdirLabel,
+ i18n("This is the name of the backup folder."));
+ QWhatsThis::add(bdirButton,
+ i18n("Click here, for opening a dialog which lets you easily select the backup folder."));
+ grid->addWidget(bdirLabel, 3, 1);
+ grid->addWidget(bdirButton, 3, 2);
+
+ grid->setRowStretch(1, 1);
+ grid->setColStretch(1, 1);
+
+ grid->addRowSpacing(2, KDialog::spacingHint());
+
+ grid->addRowSpacing(0, KDialog::marginHint());
+ grid->addRowSpacing(4, KDialog::marginHint());
+ grid->addColSpacing(0, KDialog::marginHint());
+ grid->addColSpacing(3, KDialog::marginHint());
+
+ connect(bdirButton, SIGNAL(clicked()), SLOT(slotBdirBrowse()));
+ addPage(page2, i18n("<QT><BIG><B>Step 1</B></BIG> - Specify backup directory</QT>"));
+ // Page 3
+ page3 = new QWidget(this, "step2");
+ grid = new QGridLayout(page3);
+
+ l = new QLabel(page3, "step2");
+ l->setText(i18n(
+ "<QT>"
+ "Next, please specify some information regarding "
+ "backup policy:<UL><LI>How many generations of backups "
+ "do you want to keep?</LI><LI>Shall i remind you about "
+ "backups?</LI><LI>If yes, in what intervals do you want "
+ "to happen backups?</LI></UL>"
+ "</QT>"
+ ));
+ grid->addMultiCellWidget(l, 1, 1, 1, 2, Qt::AlignTop);
+
+ l = new QLabel(i18n("&Incremental backup reminder"), page3, "iBackupIntLabel");
+ grid->addWidget(l, 3, 1);
+ iIntCombo = new KComboBox(false, page3, "iIntCombo");
+ iIntCombo->insertItem(i18n("none"));
+ iIntCombo->insertItem(i18n("daily"));
+ iIntCombo->insertItem(i18n("every 2 days"));
+ iIntCombo->insertItem(i18n("every 3 days"));
+ iIntCombo->insertItem(i18n("every 4 days"));
+ iIntCombo->insertItem(i18n("every 5 days"));
+ iIntCombo->insertItem(i18n("every 6 days"));
+ iIntCombo->insertItem(i18n("weekly"));
+ iIntCombo->insertItem(i18n("every 2 weeks"));
+ iIntCombo->insertItem(i18n("every 3 weeks"));
+ iIntCombo->insertItem(i18n("monthly"));
+ iIntCombo->setCurrentItem(1);
+ grid->addWidget(iIntCombo, 3, 2);
+ l->setBuddy(iIntCombo);
+
+ l = new QLabel(i18n("&Full backup reminder"), page3, "fBackupIntLabel");
+ grid->addWidget(l, 5, 1);
+ fIntCombo = new KComboBox(false, page3, "fIntCombo");
+ fIntCombo->insertItem(i18n("none"));
+ fIntCombo->insertItem(i18n("daily"));
+ fIntCombo->insertItem(i18n("every 2 days"));
+ fIntCombo->insertItem(i18n("every 3 days"));
+ fIntCombo->insertItem(i18n("every 4 days"));
+ fIntCombo->insertItem(i18n("every 5 days"));
+ fIntCombo->insertItem(i18n("every 6 days"));
+ fIntCombo->insertItem(i18n("weekly"));
+ fIntCombo->insertItem(i18n("every 2 weeks"));
+ fIntCombo->insertItem(i18n("every 3 weeks"));
+ fIntCombo->insertItem(i18n("monthly"));
+ fIntCombo->setCurrentItem(7);
+ grid->addWidget(fIntCombo, 5, 2);
+ l->setBuddy(fIntCombo);
+
+ l = new QLabel(i18n("Backup &generations"), page3, "backupGenLabel");
+ grid->addWidget(l, 7, 1);
+ genSpin = new KIntSpinBox(0, 10, 1, 3, 10, page3, "backupGenSpin");
+ grid->addWidget(genSpin, 7, 2);
+ l->setBuddy(genSpin);
+
+ grid->setRowStretch(1, 1);
+ grid->setColStretch(1, 1);
+
+ grid->addRowSpacing(2, KDialog::spacingHint());
+ grid->addRowSpacing(4, KDialog::spacingHint());
+ grid->addRowSpacing(6, KDialog::spacingHint());
+
+ grid->addRowSpacing(0, KDialog::marginHint());
+ grid->addRowSpacing(8, KDialog::marginHint());
+ grid->addColSpacing(0, KDialog::marginHint());
+ grid->addColSpacing(3, KDialog::marginHint());
+
+ addPage(page3, i18n("<QT><BIG><B>Step 2</B></BIG> - Backup policy</QT>"));
+
+ // Page 4
+ page4 = new QWidget(this, "step3");
+ grid = new QGridLayout(page4);
+
+ l = new QLabel(page4, "step2");
+ l->setText(i18n(
+ "<QT>"
+ "If no connection could be established on startup, "
+ "<B>KPsion</B> will attempt to connect in regular "
+ "intervals. Please specify the interval after which "
+ "a connection attempt should happen. If you don't want "
+ "automatic retry, set the interval to zero. Furthermore, "
+ "<B>KPsion</B> can try to start ncpd if it is not already "
+ "running. For that to work correctly, you need to"
+ "<UL><LI>specify the serial port to use.</LI>"
+ "<LI>specify the baud rate</LI>"
+ "<LI>have permission to use the specified port</LI></UL>"
+ "</QT>"
+ ));
+ grid->addMultiCellWidget(l, 1, 1, 1, 2, Qt::AlignTop);
+
+ l = new QLabel(i18n("&Connection retry interval (sec.)"), page4, "rconLabel");
+ grid->addWidget(l, 3, 1);
+ rconSpin = new KIntSpinBox(0, 600, 1, 30, 10, page4, "rconSpin");
+ grid->addWidget(rconSpin, 3, 2);
+ l->setBuddy(rconSpin);
+
+ l = new QLabel(i18n("Serial &device"), page4, "devLabel");
+ grid->addWidget(l, 5, 1);
+ devCombo = new KComboBox(false, page4, "devCombo");
+ devCombo->insertItem(i18n("off"));
+ devCombo->insertItem(i18n("/dev/ttyS0"));
+ devCombo->insertItem(i18n("/dev/ttyS1"));
+ devCombo->insertItem(i18n("/dev/ttyS2"));
+ devCombo->insertItem(i18n("/dev/ttyS3"));
+ devCombo->insertItem(i18n("/dev/ircomm0"));
+ devCombo->insertItem(i18n("/dev/ircomm1"));
+ devCombo->insertItem(i18n("/dev/ircomm2"));
+ devCombo->insertItem(i18n("/dev/ircomm3"));
+ devCombo->setCurrentItem(0);
+ grid->addWidget(devCombo, 5, 2);
+ l->setBuddy(devCombo);
+
+ l = new QLabel(i18n("Serial &speed"), page4, "speedLabel");
+ grid->addWidget(l, 7, 1);
+ speedCombo = new KComboBox(false, page4, "speedCombo");
+ speedCombo->insertItem("9600");
+ speedCombo->insertItem("19200");
+ speedCombo->insertItem("38400");
+ speedCombo->insertItem("57600");
+ speedCombo->insertItem("115200");
+ speedCombo->setCurrentItem(4);
+ grid->addWidget(speedCombo, 7, 2);
+ l->setBuddy(speedCombo);
+
+ grid->setRowStretch(1, 1);
+ grid->setColStretch(1, 1);
+
+ grid->addRowSpacing(2, KDialog::spacingHint());
+ grid->addRowSpacing(4, KDialog::spacingHint());
+ grid->addRowSpacing(6, KDialog::spacingHint());
+
+ grid->addRowSpacing(0, KDialog::marginHint());
+ grid->addRowSpacing(8, KDialog::marginHint());
+ grid->addColSpacing(0, KDialog::marginHint());
+ grid->addColSpacing(3, KDialog::marginHint());
+
+ addPage(page4, i18n("<QT><BIG><B>Step 3</B></BIG> - Connection parameters</QT>"));
+
+ // Page 5
+ page5 = new QWidget(this, "step3");
+ grid = new QGridLayout(page5);
+
+ l = new QLabel(page5, "step2");
+ l->setText(i18n(
+ "<QT>"
+ "That's it!<BR/>"
+ "Next, i will start <B>KPsion</B> and if your Psion is already "
+ "connected and it's communication turned on (use "
+ "<B>Ctrl-T</B> at system level), then <B>KPsion</B> will "
+ "bring up a similar Dialog like this which lets you assing a "
+ "Name for it. After that, i suggest performing a full "
+ "Backup.<BR/>Please click <B>Finish</B> now.</QT>"
+ ));
+ grid->addWidget(l, 1, 1, Qt::AlignTop);
+
+ grid->setRowStretch(1, 1);
+ grid->setColStretch(1, 1);
+
+ grid->addRowSpacing(0, KDialog::marginHint());
+ grid->addRowSpacing(2, KDialog::marginHint());
+ grid->addColSpacing(0, KDialog::marginHint());
+ grid->addColSpacing(2, KDialog::marginHint());
+
+ addPage(page5, i18n("<QT><BIG><B>Finished</B></BIG></QT>"));
+
+ setFinishEnabled(page5, true);
+}
+
+void FirstTimeWizard::
+slotBdirBrowse() {
+ QString dir = KFileDialog::getExistingDirectory(bdirLabel->text(), this,
+ i18n("Backup folder"));
+ checkBackupDir(dir);
+}
+
+void FirstTimeWizard::
+reject() {
+ // kapp->quit() and [QK]Application::exit(0) don't work here?!
+ // probably because we didn't call kapp->exec() yet?
+ // -> brute force
+ if (KMessageBox::questionYesNo(this,
+ i18n("<QT>You are about to abort the initial setup of <B>KPsion</B>. No configuration will be stored and you will have to repeat this procedure when you start <B>KPsion</B> next time.<BR/>Do you really want to exit now?</QT>")) == KMessageBox::Yes) {
+ if (!bdirCreated.isEmpty())
+ ::rmdir(bdirCreated.data());
+ ::exit(0);
+ }
+}
+
+void FirstTimeWizard::
+accept() {
+ KConfig *config = kapp->config();
+ config->setGroup("Settings");
+ config->writeEntry("BackupDir", bdirLabel->text());
+ config->writeEntry("BackupGenerations", genSpin->value());
+ config->writeEntry("IncrementalInterval", iIntCombo->currentItem());
+ config->writeEntry("FullInterval", fIntCombo->currentItem());
+ config->setGroup("Connection");
+ config->writeEntry("Retry", rconSpin->value());
+ config->writeEntry("Device", devCombo->currentText());
+ config->writeEntry("Speed", speedCombo->currentText());
+ hide();
+ setResult(Accepted);
+}
+
+void FirstTimeWizard::
+next() {
+ for (int i = 0; i < pageCount(); i++)
+ if (currentPage() == page(i)) {
+ switch (i) {
+ case 1:
+ QString dir(bdirLabel->text());
+ if (!checkBackupDir(dir))
+ return;
+ }
+ break;
+ }
+ KWizard::next();
+}
+
+void FirstTimeWizard::
+closeEvent(QCloseEvent *e) {
+ reject();
+}
+
+bool FirstTimeWizard::
+checkBackupDir(QString &dir) {
+ if (!bdirCreated.isEmpty()) {
+ if (bdirCreated != dir) {
+ ::rmdir(bdirCreated.data());
+ bdirCreated = "";
+ }
+ }
+ if (!dir.isEmpty()) {
+ QDir d(dir);
+ if (!d.exists()) {
+ if (KMessageBox::questionYesNo(this,
+ i18n("<QT>The folder <B>%1</B> does <B>not</B> exist.<BR/>Shall it be created?</QT>").arg(dir)) == KMessageBox::No) {
+ bdirLabel->setText(bdirDefault);
+ return false;
+ }
+ if (mkdir(dir.data(), 0700) != 0) {
+ QString msg = i18n("<QT>The specified folder<BR/><B>%1</B><BR/>could <B>not</B> be created");
+ switch (errno) {
+ case EACCES:
+ case EPERM:
+ case EROFS:
+ msg += i18n(", because you either don't have sufficient rights to do that, or the filesystem is readonly.");
+ // Insufficient permissions/ readonly FS
+ break;
+ case ENOSPC:
+ msg += i18n(", because the filesystem has not enough space.");
+ // No space
+ break;
+ case EEXIST:
+ // shouldn't happen, we checked already
+ // for existence.
+ msg += i18n(", because there already exists another object with the same name.");
+ break;
+ case EFAULT:
+ case ENOMEM:
+ case ENAMETOOLONG:
+ // shouldn't happen.
+ msg += ".";
+ break;
+ case ENOENT:
+ // propably dangling symlink
+ msg += i18n(", because you specified a path which probably contains a dangling symbolic link.");
+ break;
+ case ENOTDIR:
+ msg += i18n(", because you specified a path which contains an element which is not a folder.");
+ // path element not dir.
+ break;
+ case ELOOP:
+ msg += i18n(", because you specified a path which contains too many symbolic links.");
+ // Too many symlinks
+ break;
+
+
+ }
+ bdirLabel->setText(bdirDefault);
+ msg += i18n("<BR/>Please select another folder.</QT>");
+ KMessageBox::error(this, msg.arg(dir));
+ return false;
+ }
+ bdirCreated = dir;
+ }
+ bdirLabel->setText(dir);
+ return true;
+ }
+ bdirLabel->setText(bdirDefault);
+ return false;
+}
+
+NewPsionWizard::NewPsionWizard(QWidget *parent, const char *name)
+ : KWizard(parent, name, true) {
+
+ setCaption(i18n("New Psion detected"));
+ psion = (KPsionMainWindow *)parent;
+
+ QWhatsThis::add(nextButton(),
+ i18n("Click this button to continue with the next page."));
+ QWhatsThis::add(backButton(),
+ i18n("Click this button, to go to a previous page."));
+ QWhatsThis::add(cancelButton(),
+ i18n("<QT>If you click this button, the setup for the new connected Psion will be aborted and next time you connect this Psion again, <B>KPsion</B> will run this setup again.</QT>"));
+
+ // Page 1
+ page1 = new QWidget(this, "newmachine");
+ QGridLayout *grid = new QGridLayout(page1);
+
+ QLabel *l = new QLabel(page1, "newmachmessage");
+ uid = psion->getMachineUID();
+ l->setText(i18n(
+ "<QT>"
+ "The Psion with the unique ID <B>%1</B> "
+ "is connected the first time. Please assign a name to it."
+ "</QT>").arg(uid));
+ grid->addMultiCellWidget(l, 1, 1, 1, 2, Qt::AlignTop);
+
+ l = new QLabel(page1, "nameLabel");
+ l->setText(i18n("&Name of new Psion"));
+ nameEdit = new KLineEdit(page1, "nameEdit");
+ nameEdit->setText(i18n("My new Psion"));
+ nameEdit->selectAll();
+ nameEdit->setFocus();
+ l->setBuddy(nameEdit);
+ grid->addWidget(l, 3, 1);
+ grid->addWidget(nameEdit, 3, 2);
+
+ grid->setColStretch(1, 1);
+ grid->setRowStretch(1, 1);
+
+ grid->addRowSpacing(2, KDialog::spacingHint());
+
+ grid->addRowSpacing(0, KDialog::marginHint());
+ grid->addRowSpacing(4, KDialog::marginHint());
+ grid->addColSpacing(0, KDialog::marginHint());
+ grid->addColSpacing(2, KDialog::marginHint());
+
+ addPage(page1, i18n("<QT><BIG><B>New Psion detected<B></BIG></QT>"));
+
+ // Page 2
+ page2 = new QWidget(this, "bdrives");
+ grid = new QGridLayout(page2);
+
+ l = new QLabel(page2, "bdrivemessage");
+ l->setText(i18n(
+ "<QT>"
+ "Please select the Drive(s), you want to be backed up when "
+ "running in unattended backup mode."
+ "</QT>"
+ ));
+ grid->addMultiCellWidget(l, 1, 1, 1, 3, Qt::AlignTop);
+
+ backupListView = new KListView(page2, "bdriveListView");
+ backupListView->addColumn(i18n("Available drives"));
+ driveMap dlist = psion->getDrives();
+ driveMap::Iterator it;
+ int height = backupListView->header()->height();
+ for (it = dlist.begin(); it != dlist.end(); it++) {
+ QCheckListItem *i = new QCheckListItem(backupListView, it.data(),
+ QCheckListItem::CheckBox);
+ height += i->height();
+ i->setSelectable(false);
+ }
+ backupListView->setMaximumSize(backupListView->columnWidth(0) + 5, height + 5);
+ grid->addWidget(backupListView, 3, 2);
+
+ grid->setColStretch(1, 1);
+ grid->setRowStretch(1, 1);
+ grid->setColStretch(3, 1);
+
+ grid->addRowSpacing(2, KDialog::spacingHint());
+
+ grid->addRowSpacing(0, KDialog::marginHint());
+ grid->addRowSpacing(4, KDialog::marginHint());
+ grid->addColSpacing(0, KDialog::marginHint());
+ grid->addColSpacing(4, KDialog::marginHint());
+
+ addPage(page2, i18n("<QT><BIG><B>Specify drives to backup<B></BIG></QT>"));
+
+ setFinishEnabled(page2, true);
+}
+
+void NewPsionWizard::
+next() {
+ for (int i = 0; i < pageCount(); i++)
+ if (currentPage() == page(i)) {
+ switch (i) {
+ case 0:
+ QString tmp(nameEdit->text());
+ if (!checkPsionName(tmp))
+ return;
+ }
+ break;
+ }
+ KWizard::next();
+}
+
+bool NewPsionWizard::
+checkPsionName(QString &name) {
+ KConfig *config = kapp->config();
+ if (name.isEmpty()) {
+ KMessageBox::sorry(this, i18n("The name cannot be empty."));
+ return false;
+ }
+ psionMap l = psion->getMachines();
+ psionMap::Iterator it;
+ for (it = l.begin(); it != l.end(); it++) {
+ if (name == it.data()) {
+ KMessageBox::sorry(this, i18n("<QT>The name <B>%1</B> is already assigned to another machine.<BR/>Please choose a different name.</QT>"));
+ return false;
+ }
+ }
+ return true;
+}
+
+void NewPsionWizard::
+accept() {
+ KConfig *config = kapp->config();
+ config->setGroup("Psion");
+ QStringList machines = config->readListEntry("MachineUIDs");
+ machines += uid;
+ config->writeEntry("MachineUIDs", machines);
+ QString tmp = QString::fromLatin1("Name_%1").arg(uid);
+ config->writeEntry(tmp, nameEdit->text());
+ tmp = nameEdit->text();
+ psion->setMachineName(tmp);
+ QListViewItemIterator li(backupListView);
+ driveMap dlist = psion->getDrives();
+ driveMap::Iterator di;
+ QStringList bdrives;
+ for (; li.current(); li++) {
+ QCheckListItem *qcli = (QCheckListItem *)(li.current());
+ if (qcli->isOn()) {
+ tmp = qcli->text();
+ for (di = dlist.begin(); di != dlist.end(); di++)
+ if (di.data() == tmp) {
+ QString drv = "";
+ drv += di.key();
+ bdrives += drv;
+ }
+ }
+ }
+ config->writeEntry("BackupDrives", bdrives);
+ hide();
+ setResult(Accepted);
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/kde2/kpsion/wizards.h b/kde2/kpsion/wizards.h
new file mode 100644
index 0000000..6edd8d9
--- /dev/null
+++ b/kde2/kpsion/wizards.h
@@ -0,0 +1,78 @@
+#ifndef _WIZARDS_H_
+#define _WIZARDS_H_
+
+#include "kpsion.h"
+
+#include <kwizard.h>
+#include <knuminput.h>
+#include <kcombobox.h>
+#include <klineedit.h>
+#include <klistview.h>
+
+#include <qpushbutton.h>
+#include <qcheckbox.h>
+#include <qlabel.h>
+
+class FirstTimeWizard : public KWizard {
+ Q_OBJECT
+ public:
+ FirstTimeWizard(QWidget *parent = 0, const char *name = 0);
+
+ protected:
+ virtual void closeEvent(QCloseEvent *e);
+ virtual void reject();
+ virtual void accept();
+
+ protected slots:
+ virtual void next();
+
+ private slots:
+ void slotBdirBrowse();
+
+ private:
+ bool checkBackupDir(QString &);
+
+ QWidget *page1;
+ QWidget *page2;
+ QWidget *page3;
+ QWidget *page4;
+ QWidget *page5;
+ QLabel *bdirLabel;
+ KIntSpinBox *genSpin;
+ KIntSpinBox *rconSpin;
+ QPushButton *bdirButton;
+ QCheckBox *remCheck;
+ KComboBox *iIntCombo;
+ KComboBox *fIntCombo;
+ KComboBox *devCombo;
+ KComboBox *speedCombo;
+
+ QString bdirDefault;
+ QString bdirCreated;
+};
+
+class NewPsionWizard : public KWizard {
+ Q_OBJECT
+
+ public:
+ NewPsionWizard(QWidget *parent = 0, const char *name = 0);
+
+ protected:
+ virtual void accept();
+
+ protected slots:
+ virtual void next();
+
+ private:
+ bool checkPsionName(QString &);
+
+ QWidget *page1;
+ QWidget *page2;
+ KPsionMainWindow *psion;
+ KLineEdit *nameEdit;
+ KListView *backupListView;
+
+ QString uid;
+ QString machineName;
+};
+#endif