diff options
Diffstat (limited to 'kde2/kpsion/kpsion.cpp')
-rw-r--r-- | kde2/kpsion/kpsion.cpp | 866 |
1 files changed, 726 insertions, 140 deletions
diff --git a/kde2/kpsion/kpsion.cpp b/kde2/kpsion/kpsion.cpp index 808ed1a..2e605d9 100644 --- a/kde2/kpsion/kpsion.cpp +++ b/kde2/kpsion/kpsion.cpp @@ -41,16 +41,15 @@ #include <qtimer.h> #include <qlayout.h> #include <qiodevice.h> +#include <qheader.h> #include <qdir.h> +#include <qmessagebox.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 !!!!! @@ -58,37 +57,88 @@ #define STID_CONNECTION 1 +class KPsionCheckListItem::KPsionCheckListItemMetaData { + friend KPsionCheckListItem; + +private: + KPsionCheckListItemMetaData(); + ~KPsionCheckListItemMetaData() { }; + + bool parentIsKPsionCheckListItem; + bool dontPropagate; + int backupType; + int size; + time_t when; + u_int32_t timeHi; + u_int32_t timeLo; + u_int32_t attr; + QString name; +}; + +KPsionCheckListItem::KPsionCheckListItemMetaData::KPsionCheckListItemMetaData() { + when = 0; + size = 0; + timeHi = 0; + timeLo = 0; + attr = 0; + name = QString::null; + backupType = KPsionBackupListView::UNKNOWN; +} + +KPsionCheckListItem::~KPsionCheckListItem() { + delete meta; +} + +KPsionCheckListItem *KPsionCheckListItem:: +firstChild() const { + return (KPsionCheckListItem *)QListViewItem::firstChild(); +} + +KPsionCheckListItem *KPsionCheckListItem:: +nextSibling() const { + return (KPsionCheckListItem *)QListViewItem::nextSibling(); +} + void KPsionCheckListItem:: init(bool myparent) { setSelectable(false); - dontPropagate = false; - parentIsKPsionCheckListItem = myparent; + meta = new KPsionCheckListItemMetaData(); + meta->dontPropagate = false; + meta->parentIsKPsionCheckListItem = myparent; } void KPsionCheckListItem:: -setMetaData(int bType, time_t bWhen) { - backupType = bType; - when = bWhen; +setMetaData(int type, time_t when, QString name, int size, + u_int32_t tHi, u_int32_t tLo, u_int32_t attr) { + meta->backupType = type; + meta->when = when; + meta->name = name; + meta->size = size; + meta->timeHi = tHi; + meta->timeLo = tLo; + meta->attr = attr; } void KPsionCheckListItem:: stateChange(bool state) { QCheckListItem::stateChange(state); - if (dontPropagate) + if (meta->dontPropagate) return; - if (parentIsKPsionCheckListItem) - ((KPsionCheckListItem *)parent())->propagateUp(state); + if (meta->parentIsKPsionCheckListItem) + ((KPsionCheckListItem *)QListViewItem::parent())->propagateUp(state); + else + emit rootToggled(); propagateDown(state); } void KPsionCheckListItem:: propagateDown(bool state) { setOn(state); - KPsionCheckListItem *child = (KPsionCheckListItem *)firstChild(); + KPsionCheckListItem *child = firstChild(); while (child) { child->propagateDown(state); - child = (KPsionCheckListItem *)child->nextSibling(); + child = child->nextSibling(); } } @@ -96,15 +146,15 @@ void KPsionCheckListItem:: propagateUp(bool state) { bool deactivateThis = false; - KPsionCheckListItem *child = (KPsionCheckListItem *)firstChild(); + KPsionCheckListItem *child = firstChild(); while (child) { if ((child->isOn() != state) || (!child->isEnabled())) { deactivateThis = true; break; } - child = (KPsionCheckListItem *)child->nextSibling(); + child = child->nextSibling(); } - dontPropagate = true; + meta->dontPropagate = true; if (deactivateThis) { setOn(true); setEnabled(false); @@ -116,9 +166,68 @@ propagateUp(bool state) { // enabled/disabled without activating. // -> force it. listView()->repaintItem(this); - dontPropagate = false; - if (parentIsKPsionCheckListItem) - ((KPsionCheckListItem *)parent())->propagateUp(state); + meta->dontPropagate = false; + if (meta->parentIsKPsionCheckListItem) + ((KPsionCheckListItem *)QListViewItem::parent())->propagateUp(state); + else + emit rootToggled(); +} + +QString KPsionCheckListItem:: +key(int column, bool ascending) const { + if (meta->when) { + QString tmp; + tmp.sprintf("%08d", meta->when); + return tmp; + } + return text(); +} + +QString KPsionCheckListItem:: +psionname() { + if (meta->parentIsKPsionCheckListItem) + return meta->name; + else + return QString::null; +} + +QString KPsionCheckListItem:: +unixname() { + if (meta->parentIsKPsionCheckListItem) + return KPsionMainWindow::psion2unix(meta->name); + else + return QString::null; +} + +QString KPsionCheckListItem:: +tarname() { + if (meta->parentIsKPsionCheckListItem) + return ((KPsionCheckListItem *)QListViewItem::parent())->tarname(); + else + return meta->name; +} + +int KPsionCheckListItem:: +backupType() { + if (meta->parentIsKPsionCheckListItem) + return ((KPsionCheckListItem *)QListViewItem::parent())->backupType(); + else + return meta->backupType; +} + +time_t KPsionCheckListItem:: +when() { + if (meta->parentIsKPsionCheckListItem) + return ((KPsionCheckListItem *)QListViewItem::parent())->when(); + else + return meta->when; +} + +PlpDirent KPsionCheckListItem:: +plpdirent() { + assert(meta->parentIsKPsionCheckListItem); + return PlpDirent(meta->size, meta->attr, meta->timeHi, meta->timeLo, + meta->name); } KPsionBackupListView::KPsionBackupListView(QWidget *parent, const char *name) @@ -133,17 +242,25 @@ KPsionBackupListView::KPsionBackupListView(QWidget *parent, const char *name) setRootIsDecorated(true); } +KPsionCheckListItem *KPsionBackupListView:: +firstChild() const { + return (KPsionCheckListItem *)QListView::firstChild(); +} + void KPsionBackupListView:: readBackups(QString uid) { QString bdir(backupDir); bdir += "/"; bdir += uid; QDir d(bdir); + kapp->processEvents(); const QFileInfoList *fil = d.entryInfoList("*.tar.gz", QDir::Files|QDir::Readable, QDir::Name); QFileInfoListIterator it(*fil); QFileInfo *fi; while ((fi = it.current())) { + kapp->processEvents(); + bool isValid = false; KTarGz tgz(fi->absFilePath()); const KTarEntry *te; @@ -169,30 +286,51 @@ readBackups(QString uid) { } if (isValid) { - QString n = i18n("%1 backup, created at %2").arg(bTypeName).arg(date.toString()); + QString n = i18n("%1 backup, created at %2").arg(bTypeName).arg(KGlobal::locale()->formatDateTime(date, false)); + QByteArray a = ((KTarFile *)te)->data(); + QTextIStream indexData(a); + + indexData.readLine(); + indexData.flags(QTextStream::hex); + indexData.fill('0'); + indexData.width(8); KPsionCheckListItem *i = new KPsionCheckListItem(this, n, KPsionCheckListItem::CheckBox); - i->setMetaData(bType, te->date()); - i->setPixmap(0, KGlobal::iconLoader()->loadIcon("mime_empty", KIcon::Small)); + i->setMetaData(bType, te->date(), tgz.fileName(), 0, 0, 0, 0); + i->setPixmap(0, KGlobal::iconLoader()->loadIcon("mime_empty", + KIcon::Small)); + connect(i, SIGNAL(rootToggled()), this, SLOT(slotRootToggled())); + 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); + listTree(i, tgz.directory()->entry(*f), indexData, 0); } tgz.close(); ++it; } + header()->setClickEnabled(false); + header()->setResizeEnabled(false); + header()->setMovingEnabled(false); + setMinimumSize(columnWidth(0) + 4, height()); + QWhatsThis::add(this, i18n( + "<qt>Here, you can select the available backups." + " Select the items you want to restore, the click" + " on <b>Start</b> to start restoring these items." + "</qt>")); } void KPsionBackupListView:: -listTree(KPsionCheckListItem *cli, const KTarEntry *te, int level) { +listTree(KPsionCheckListItem *cli, const KTarEntry *te, QTextIStream &idx, + int level) { KPsionCheckListItem *i = new KPsionCheckListItem(cli, te->name(), KPsionCheckListItem::CheckBox); + kapp->processEvents(); if (te->isDirectory()) { if (level) i->setPixmap(0, KGlobal::iconLoader()->loadIcon("folder", @@ -200,17 +338,118 @@ listTree(KPsionCheckListItem *cli, const KTarEntry *te, int level) { else i->setPixmap(0, KGlobal::iconLoader()->loadIcon("hdd_unmount", KIcon::Small)); + i->setMetaData(0, 0, QString::null, 0, 0, 0, 0); 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 + listTree(i, td->entry(*f), idx, level + 1); + } else { + uint32_t timeHi; + uint32_t timeLo; + uint32_t size; + uint32_t attr; + QString name; + i->setPixmap(0, KGlobal::iconLoader()->loadIcon("mime_empty", KIcon::Small)); + idx >> timeHi >> timeLo >> size >> attr >> name; + i->setMetaData(0, 0, name, size, timeHi, timeLo, attr); + } +} + +void KPsionBackupListView:: +slotRootToggled() { + bool anyOn = false; + KPsionCheckListItem *i = firstChild(); + while (i != 0L) { + if (i->isOn()) { + anyOn = true; + break; + } + i = i->nextSibling(); + } + emit itemsEnabled(anyOn); +} + +QStringList KPsionBackupListView:: +getSelectedTars() { + QStringList l; + + KPsionCheckListItem *i = firstChild(); + while (i != 0L) { + if (i->isOn()) + l += i->tarname(); + i = i->nextSibling(); + } + return l; +} + +bool KPsionBackupListView:: +autoSelect(QString drive) { + KPsionCheckListItem *latest = NULL; + time_t stamp = 0; + + drive += ":"; + // Find latest full backup for given drive + KPsionCheckListItem *i = firstChild(); + while (i != 0L) { + if ((i->backupType() == FULL) && (i->when() > stamp)) { + KPsionCheckListItem *c = i->firstChild(); + while (c != 0L) { + if (c->text() == drive) { + latest = c; + stamp = i->when(); + break; + } + c = c->nextSibling(); + } + } + i = i->nextSibling(); + } + // Now find all incremental backups for given drive which are newer than + // selected backup + if (latest != 0) { + latest->setOn(true); + i = firstChild(); + while (i != 0L) { + if ((i->backupType() == INCREMENTAL) && (i->when() >= stamp)) { + KPsionCheckListItem *c = i->firstChild(); + while (c != 0L) { + if (c->text() == drive) + c->setOn(true); + c = c->nextSibling(); + } + } + i = i->nextSibling(); + } + } + return (latest != 0L); +} + +void KPsionBackupListView:: +collectEntries(KPsionCheckListItem *i) { + while (i != 0L) { + KPsionCheckListItem *c = i->firstChild(); + if (c == 0L) { + if (i->isOn()) + toRestore.push_back(i->plpdirent()); + } else + collectEntries(c); + i = i->nextSibling(); + } } PlpDir &KPsionBackupListView:: -getRestoreList() { +getRestoreList(QString tarname) { + toRestore.clear(); + KPsionCheckListItem *i = firstChild(); + while (i != 0L) { + if ((i->tarname() == tarname) && (i->isOn())) { + collectEntries(i->firstChild()); + break; + } + i = i->nextSibling(); + } return toRestore; } @@ -222,6 +461,18 @@ KPsionMainWindow::KPsionMainWindow() statusBar()->setItemAlignment(STID_CONNECTION, QLabel::AlignLeft|QLabel::AlignVCenter); + progress = new KPsionStatusBarProgress(statusBar(), "progressBar"); + statusBar()->addWidget(progress, 10); + + connect(progress, SIGNAL(pressed()), this, SLOT(slotProgressBarPressed())); + connect(this, SIGNAL(setProgress(int)), progress, SLOT(setValue(int))); + connect(this, SIGNAL(setProgress(int, int)), progress, + SLOT(setValue(int, int))); + connect(this, SIGNAL(setProgressText(const QString &)), progress, + SLOT(setText(const QString &))); + connect(this, SIGNAL(enableProgressText(bool)), progress, + SLOT(setTextEnabled(bool))); + backupRunning = false; restoreRunning = false; formatRunning = false; @@ -267,6 +518,11 @@ KPsionMainWindow::KPsionMainWindow() connected = false; shuttingDown = false; + args = KCmdLineArgs::parsedArgs(); + if (args->isSet("autobackup")) { + firstTry = false; + reconnectTime = 0; + } tryConnect(); } @@ -282,6 +538,24 @@ KPsionMainWindow::~KPsionMainWindow() { delete rpcsSocket; } +QString KPsionMainWindow:: +unix2psion(const char * const path) { + QString tmp = path; + tmp.replace(QRegExp("/"), "\\"); + tmp.replace(QRegExp("%2f"), "/"); + tmp.replace(QRegExp("%25"), "%"); + return tmp; +} + +QString KPsionMainWindow:: +psion2unix(const char * const path) { + QString tmp = path; + tmp.replace(QRegExp("%"), "%25"); + tmp.replace(QRegExp("/"), "%2f"); + tmp.replace(QRegExp("\\"), "/"); + return tmp; +} + void KPsionMainWindow:: setupActions() { @@ -447,6 +721,18 @@ queryPsion() { } #endif if (!machineFound) { + if (args->isSet("autobackup")) { + connected = false; + if (plpRfsv) + delete plpRfsv; + if (plpRpcs) + delete plpRpcs; + if (rfsvSocket) + delete rfsvSocket; + if (rfsvSocket) + delete rpcsSocket; + return; + } NewPsionWizard *wiz = new NewPsionWizard(this, "newpsionwiz"); wiz->exec(); } @@ -457,11 +743,9 @@ queryPsion() { 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; + char tmp[20]; + sprintf(tmp, "%16llx", machineUID); + return QString(tmp); } bool KPsionMainWindow:: @@ -506,28 +790,37 @@ tryConnect() { 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)); + } else { + statusBar()->changeItem(statusMsg, STID_CONNECTION); + if (showMB) + KMessageBox::error(this, statusMsg); } - 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()); + statusMsg = i18n("RFSV could not establish link: %1.").arg(KGlobal::locale()->translate(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)); + } else { + statusBar()->changeItem(statusMsg, STID_CONNECTION); + if (showMB) + KMessageBox::error(this, statusMsg); } - statusBar()->changeItem(statusMsg.arg(reconnectTime), - STID_CONNECTION); - if (showMB) - KMessageBox::error(this, statusMsg.arg(reconnectTime)); return; } @@ -542,17 +835,21 @@ tryConnect() { 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)); + } else { + statusBar()->changeItem(statusMsg, STID_CONNECTION); + if (showMB) + KMessageBox::error(this, statusMsg); } - 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()); + statusMsg = i18n("RPCS could not establish link: %1.").arg(KGlobal::locale()->translate(factory2.getError())); delete plpRfsv; plpRfsv = 0L; delete rfsvSocket; @@ -563,11 +860,15 @@ tryConnect() { 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)); + } else { + statusBar()->changeItem(statusMsg, STID_CONNECTION); + if (showMB) + KMessageBox::error(this, statusMsg); } - statusBar()->changeItem(statusMsg.arg(reconnectTime), - STID_CONNECTION); - if (showMB) - KMessageBox::error(this, statusMsg.arg(reconnectTime)); return; } #endif @@ -587,6 +888,10 @@ slotUpdateTimer() { } void KPsionMainWindow:: +slotProgressBarPressed() { +} + +void KPsionMainWindow:: slotStartFullBackup() { fullBackup = true; doBackup(); @@ -598,33 +903,40 @@ slotStartIncBackup() { doBackup(); } +const KTarEntry *KPsionMainWindow:: +findTarEntry(const KTarEntry *te, QString path, QString rpath) { + const KTarEntry *fte = NULL; + if (te->isDirectory() && (path.left(rpath.length()) == rpath)) { + KTarDirectory *td = (KTarDirectory *)te; + QStringList files = td->entries(); + for (QStringList::Iterator f = files.begin(); f != files.end(); f++) { + QString tmp = rpath; + if (tmp.length()) + tmp += "/"; + tmp += *f; + fte = findTarEntry(td->entry(*f), path, tmp); + if (fte != 0L) + break; + } + } else { + if (path == rpath) + fte = te; + } + return fte; +} + 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; + emit enableProgressText(true); + emit setProgress(0); for (QIconViewItem *i = view->firstItem(); i; i = i->nextItem()) { if (i->isSelected()) { QString drv = i->key(); @@ -632,14 +944,16 @@ doBackup() { int drvNum = *(drv.data()) - 'A'; PlpDrive drive; if (plpRfsv->devinfo(drvNum, drive) != rfsv::E_PSI_GEN_NONE) { + statusBar()->changeItem(i18n("Connected to %1").arg(machineName), + STID_CONNECTION); + emit enableProgressText(false); + emit setProgress(0); 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)); + emit setProgressText(i18n("Scanning drive %1").arg(drv)); progressLocal = drive.getSize() - drive.getSpace(); progressLocalCount = 0; @@ -648,17 +962,19 @@ doBackup() { collectFiles(drv); } } - progressLabel->setText(i18n("%1 files need backup").arg(backupSize)); + emit setProgressText(i18n("%1 files need backup").arg(backupSize)); if (backupCount == 0) { + emit enableProgressText(false); + emit setProgress(0); + statusBar()->changeItem(i18n("Connected to %1").arg(machineName), + STID_CONNECTION); KMessageBox::information(this, i18n("No files need backup")); - d->hide(); - delete d; backupRunning = false; switchActions(); return; } - statusBar()->message(i18n("Backup")); + // statusBar()->message(i18n("Backup")); progressCount = 0; progressTotal = backupSize; progressPercent = -1; @@ -671,10 +987,12 @@ doBackup() { QDir archiveDir(archiveName); if (!archiveDir.exists()) if (!archiveDir.mkdir(archiveName)) { + emit enableProgressText(false); + emit setProgress(0); + statusBar()->changeItem(i18n("Connected to %1").arg(machineName), + STID_CONNECTION); KMessageBox::error(this, i18n("Could not create backup folder %1").arg(archiveName)); - d->hide(); - delete d; - statusBar()->clear(); + // statusBar()->clear(); backupRunning = false; switchActions(); return; @@ -697,40 +1015,19 @@ doBackup() { bool badBackup = false; Enum<rfsv::errs> res; // Now the real backup + progressTotalText = i18n("Backup %1% done"); 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'; + QString unixname = psion2unix(fn); + QByteArray ba; + QDataStream os(ba, IO_WriteOnly); - ostrstream os; - - progressLabel->setText(i18n("Backing up %1").arg(fn)); + emit setProgressText(QString("%1").arg(fn)); progressLocal = e.getSize(); progressLocalCount = 0; progressLocalPercent = -1; - progress->setValue(0); + emit setProgress(0); u_int32_t handle; @@ -751,10 +1048,9 @@ doBackup() { do { if ((res = plpRfsv->fread(handle, buff, RFSV_SENDLEN, len)) == rfsv::E_PSI_GEN_NONE) { - os.write(buff, len); + os.writeRawBytes((char *)buff, len); updateProgress(len); } - kapp->processEvents(); } while ((len > 0) && (res == rfsv::E_PSI_GEN_NONE)); delete[]buff; plpRfsv->fclose(handle); @@ -767,17 +1063,16 @@ doBackup() { continue; } } - backupTgz->writeFile(unixname, "root", "root", os.pcount(), - os.str()); + backupTgz->writeFile(unixname, "root", "root", ba.size(), ba.data()); } if (!badBackup) { // Reset archive attributes of all backuped files. - progressLabel->setText(i18n("Resetting archive attributes ...")); + emit setProgressText(i18n("Resetting archive attributes")); progressLocal = backupSize; progressLocalCount = 0; progressLocalPercent = -1; - progress->setValue(0); + emit setProgress(0); for (int i = 0; i < toBackup.size(); i++) { PlpDirent e = toBackup[i]; const char *fn = e.getName(); @@ -802,41 +1097,327 @@ doBackup() { delete backupTgz; if (badBackup) unlink(archiveName.data()); - d->hide(); - delete d; backupRunning = false; switchActions(); + statusBar()->changeItem(i18n("Connected to %1").arg(machineName), + STID_CONNECTION); + emit enableProgressText(false); + emit setProgress(0); statusBar()->message(i18n("Backup done"), 2000); } +KPsionRestoreDialog::KPsionRestoreDialog(QWidget *parent, QString uid) + : KDialogBase(parent, "restoreDialog", true, i18n("Restore"), + KDialogBase::Cancel | KDialogBase::Ok, + KDialogBase::Ok, true) { + + setButtonOKText(i18n("Start")); + enableButtonOK(false); + setButtonWhatsThis(KDialogBase::Ok, + i18n("Select items in the list of" + " available backups, then click" + " here to start restore of these" + " items.")); + + QWidget *w = new QWidget(this); + setMainWidget(w); + QGridLayout *gl = new QGridLayout(w, 1, 1, KDialog::marginHint(), + KDialog::marginHint()); + backupView = new KPsionBackupListView(w, "restoreSelector"); + gl->addWidget(backupView, 0, 0); + backupView->readBackups(uid); + connect(backupView, SIGNAL(itemsEnabled(bool)), this, + SLOT(slotBackupsSelected(bool))); +} + +void KPsionRestoreDialog:: +slotBackupsSelected(bool any) { + enableButtonOK(any); +} + +QStringList KPsionRestoreDialog:: +getSelectedTars() { + return backupView->getSelectedTars(); +} + +bool KPsionRestoreDialog:: +autoSelect(QString drive) { + return backupView->autoSelect(drive); +} + +PlpDir &KPsionRestoreDialog:: +getRestoreList(QString tarname) { + return backupView->getRestoreList(tarname); +} + +bool KPsionMainWindow:: +askOverwrite(PlpDirent e) { + if (overWriteAll) + return true; + const char *fn = e.getName(); + if (overWriteList.contains(QString(fn))) + return true; + PlpDirent old; + Enum<rfsv::errs> res = plpRfsv->fgeteattr(fn, old); + if (res != rfsv::E_PSI_GEN_NONE) { + KMessageBox::error(this, i18n( + "<QT>Could not get attributes of<BR/>" + "<B>%1</B><BR/>Reason: %2</QT>").arg(fn).arg(KGlobal::locale()->translate(res))); + return false; + } + + // Don't ask if size and attribs are same + if ((old.getSize() == e.getSize()) && + ((old.getAttr() & ~rfsv::PSI_A_ARCHIVE) == + (e.getAttr() & ~rfsv::PSI_A_ARCHIVE))) + return true; + + QDateTime odate; + QDateTime ndate; + + odate.setTime_t(old.getPsiTime().getTime()); + ndate.setTime_t(e.getPsiTime().getTime()); + + // Dates + QString od = KGlobal::locale()->formatDateTime(odate, false); + QString nd = KGlobal::locale()->formatDateTime(ndate, false); + + // Sizes + QString os = QString("%1 (%2)").arg(KIO::convertSize(old.getSize())).arg(KGlobal::locale()->formatNumber(old.getSize(), 0)); + QString ns = QString("%1 (%2)").arg(KIO::convertSize(e.getSize())).arg(KGlobal::locale()->formatNumber(e.getSize(), 0)); + + // Attributes + QString oa(plpRfsv->attr2String(old.getAttr()).c_str()); + QString na(plpRfsv->attr2String(e.getAttr()).c_str()); + + KDialogBase dialog(i18n("Overwrite"), KDialogBase::Yes | KDialogBase::No | + KDialogBase::Cancel, KDialogBase::No, + KDialogBase::Cancel, this, "overwriteDialog", true, true, + QString::null, QString::null, i18n("Overwrite &All")); + + QWidget *contents = new QWidget(&dialog); + QHBoxLayout * lay = new QHBoxLayout(contents); + lay->setSpacing(KDialog::spacingHint()*2); + lay->setMargin(KDialog::marginHint()*2); + + lay->addStretch(1); + QLabel *label1 = new QLabel(contents); + label1->setPixmap(QMessageBox::standardIcon(QMessageBox::Warning, + kapp->style().guiStyle())); + lay->add(label1); + lay->add(new QLabel(i18n( + "<QT>The file <B>%1</B> exists already on the Psion with " + "different size and/or attributes." + "<P><B>On the Psion:</B><BR/>" + " Size: %2<BR/>" + " Date: %3<BR/>" + " Attributes: %4</P>" + "<P><B>In backup:</B><BR/>" + " Size: %5<BR/>" + " Date: %6<BR/>" + " Attributes: %7</P>" + "Do you want to overwrite it?</QT>").arg(fn).arg(os).arg(od).arg(oa).arg(ns).arg(nd).arg(na), contents)); + lay->addStretch(1); + + dialog.setMainWidget(contents); + dialog.enableButtonSeparator(false); + + int result = dialog.exec(); + switch (result) { + case KDialogBase::Yes: + return true; + case KDialogBase::No: + return false; + case KDialogBase::Cancel: + overWriteAll = true; + return true; + default: // Huh? + break; + } + + return false; // Default +} + 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; + kapp->setOverrideCursor(Qt::waitCursor); + statusBar()->changeItem(i18n("Reading backups ..."), STID_CONNECTION); + update(); + kapp->processEvents(); + KPsionRestoreDialog restoreDialog(this, getMachineUID()); + kapp->restoreOverrideCursor(); + statusBar()->changeItem(i18n("Selecting backups ..."), STID_CONNECTION); + + for (QIconViewItem *i = view->firstItem(); i; i = i->nextItem()) { + if (i->isSelected() && (i->key() != "Z")) + restoreDialog.autoSelect(i->key()); + } + + overWriteList.clear(); + overWriteAll = false; + + if (restoreDialog.exec() == KDialogBase::Accepted) { + QStringList tars = restoreDialog.getSelectedTars(); + QStringList::Iterator t; + + backupSize = 0; + backupCount = 0; + for (t = tars.begin(); t != tars.end(); t++) { + PlpDir toRestore = restoreDialog.getRestoreList(*t); + for (int r = 0; r < toRestore.size(); r++) { + PlpDirent e = toRestore[r]; + backupSize += e.getSize(); + backupCount++; + } + } + if (backupCount == 0) { + restoreRunning = false; + switchActions(); + statusBar()->changeItem(i18n("Connected to %1").arg(machineName), + STID_CONNECTION); + return; + } + + progressTotalText = i18n("Restore %1% done"); + progressTotal = backupSize; + progressCount = 0; + progressPercent = -1; + emit setProgressText(""); + emit enableProgressText(true); + emit setProgress(0); + + // Kill all running applications on the Psion + // and save their state. + killSave(); + + for (t = tars.begin(); t != tars.end(); t++) { + PlpDir toRestore = restoreDialog.getRestoreList(*t); + if (toRestore.size() > 0) { + KTarGz tgz(*t); + const KTarEntry *te; + QString pDir(""); + + tgz.open(IO_ReadOnly); + for (int r = 0; r < toRestore.size(); r++) { + PlpDirent e = toRestore[r]; + PlpDirent olde; + + const char *fn = e.getName(); + QString unixname = psion2unix(fn); + Enum<rfsv::errs> res; + + progressLocal = e.getSize(); + progressLocalCount = 0; + progressLocalPercent = -1; + emit setProgressText(QString("%1").arg(fn)); + emit setProgress(0); + + te = findTarEntry(tgz.directory(), unixname); + if (te != 0L) { + u_int32_t handle; + QString cpDir(fn); + QByteArray ba = ((KTarFile *)te)->data(); + int bslash = cpDir.findRev('\\'); + if (bslash > 0) + cpDir = cpDir.left(bslash); + if (pDir != cpDir) { + pDir = cpDir; + res = plpRfsv->mkdir(pDir); + if ((res != rfsv::E_PSI_GEN_NONE) && + (res != rfsv::E_PSI_FILE_EXIST)) { + KMessageBox::error(this, i18n( + "<QT>Could not create directory<BR/>" + "<B>%1</B><BR/>Reason: %2</QT>").arg(pDir).arg(KGlobal::locale()->translate(res))); + continue; + } + } + res = plpRfsv->fcreatefile( + plpRfsv->opMode(rfsv::PSI_O_RDWR), fn, handle); + if (res == rfsv::E_PSI_FILE_EXIST) { + if (!askOverwrite(e)) + continue; + res = plpRfsv->freplacefile( + plpRfsv->opMode(rfsv::PSI_O_RDWR), fn, handle); + } + if (res != rfsv::E_PSI_GEN_NONE) { + KMessageBox::error(this, i18n( + "<QT>Could not create<BR/>" + "<B>%1</B><BR/>Reason: %2</QT>").arg(fn).arg(KGlobal::locale()->translate(res))); + continue; + } + const unsigned char *data = + (const unsigned char *)(ba.data()); + long len = ba.size(); + + do { + u_int32_t written; + u_int32_t count = + (len > RFSV_SENDLEN) ? RFSV_SENDLEN : len; + res = plpRfsv->fwrite(handle, data, count, written); + if (res != rfsv::E_PSI_GEN_NONE) + break; + len -= written; + data += written; + updateProgress(written); + } while (len > 0); + plpRfsv->fclose(handle); + if (res != rfsv::E_PSI_GEN_NONE) { + KMessageBox::error(this, i18n( + "<QT>Could not write to<BR/>" + "<B>%1</B><BR/>Reason: %2</QT>").arg(fn).arg(KGlobal::locale()->translate(res))); + continue; + } + u_int32_t oldattr; + res = plpRfsv->fgetattr(fn, oldattr); + if (res != rfsv::E_PSI_GEN_NONE) { + KMessageBox::error(this, i18n( + "<QT>Could not get attributes of<BR/>" + "<B>%1</B><BR/>Reason: %2</QT>").arg(fn).arg(KGlobal::locale()->translate(res))); + continue; + } + u_int32_t mask = e.getAttr() ^ oldattr; + u_int32_t sattr = e.getAttr() & mask; + u_int32_t dattr = ~sattr & mask; + res = plpRfsv->fsetattr(fn, sattr, dattr); + if (res != rfsv::E_PSI_GEN_NONE) { + KMessageBox::error(this, i18n( + "<QT>Could not set attributes of<BR/>" + "<B>%1</B><BR/>Reason: %2</QT>").arg(fn).arg(KGlobal::locale()->translate(res))); + continue; + } + res = plpRfsv->fsetmtime(fn, e.getPsiTime()); + if (res != rfsv::E_PSI_GEN_NONE) { + KMessageBox::error(this, i18n( + "<QT>Could not set modification time of<BR/>" + "<B>%1</B><BR/>Reason: %2</QT>").arg(fn).arg(KGlobal::locale()->translate(res))); + continue; + } + overWriteList += QString(fn); + } + } + tgz.close(); + } + } + // Restart previously running applications on the Psion + // from saved state info. + runRestore(); + } else { + restoreRunning = false; + switchActions(); + statusBar()->changeItem(i18n("Connected to %1").arg(machineName), + STID_CONNECTION); + return; + } + restoreRunning = false; switchActions(); + emit setProgress(0); + emit enableProgressText(false); + statusBar()->changeItem(i18n("Connected to %1").arg(machineName), + STID_CONNECTION); statusBar()->message(i18n("Restore done"), 2000); } @@ -885,7 +1466,7 @@ updateProgress(unsigned long amount) { else progressLocalPercent = 100; if (progressLocalPercent != lastPercent) - progress->setValue(progressLocalPercent); + emit setProgress(progressLocalPercent); if (progressTotal > 0) { progressCount += amount; lastPercent = progressPercent; @@ -894,8 +1475,10 @@ updateProgress(unsigned long amount) { else progressPercent = 100; if (progressPercent != lastPercent) - statusBar()->message(i18n("Backup %1% complete").arg(progressPercent)); + statusBar()->changeItem(progressTotalText.arg(progressPercent), + STID_CONNECTION); } + kapp->processEvents(); } void KPsionMainWindow:: @@ -920,7 +1503,6 @@ collectFiles(QString dir) { if (attr & rfsv::PSI_A_DIR) { collectFiles(tmp); } else { - kapp->processEvents(); updateProgress(e.getSize()); if ((attr & rfsv::PSI_A_ARCHIVE) || fullBackup) { backupCount++; @@ -959,7 +1541,7 @@ killSave() { cmdline += bs.getString(0); savedCommands += cmdline; } - progressLabel->setText(i18n("Stopping %1").arg(cmdargs.getString(0))); + emit setProgressText(i18n("Stopping %1").arg(cmdargs.getString(0))); kapp->processEvents(); plpRpcs->stopProgram(pbuf); } @@ -981,7 +1563,7 @@ runRestore() { // 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)); + emit setProgressText(i18n("Starting %1").arg(cmd)); kapp->processEvents(); if ((arg.length() > 2) && (arg[1] == ':') && (arg[0] >= 'A') && (arg[0] <= 'Z')) @@ -1016,7 +1598,8 @@ runRestore() { void KPsionMainWindow:: createIndex() { - ostrstream os; + QByteArray ba; + QTextOStream os(ba); os << "#plpbackup index " << (fullBackup ? "F" : "I") << endl; for (int i = 0; i < toBackup.size(); i++) { @@ -1036,7 +1619,10 @@ createIndex() { << setw(0) << e.getName() << endl; kapp->processEvents(); } - backupTgz->writeFile("Index", "root", "root", os.pcount(), os.str()); + QString idxName = + QString::fromLatin1("KPsion%1Index").arg(fullBackup ? + "Full" : "Incremental"); + backupTgz->writeFile(idxName, "root", "root", ba.size(), ba.data()); } /* |