diff options
author | Fritz Elfert <felfert@to.com> | 2001-03-05 10:12:26 +0000 |
---|---|---|
committer | Fritz Elfert <felfert@to.com> | 2001-03-05 10:12:26 +0000 |
commit | 3c5877e3f7fcd101a9868e6da86f12b92b6d4896 (patch) | |
tree | fb8ca31738d782bb0d11e55dc2e4794db2d17ae3 /kde2/kpsion | |
parent | 3ebac278eff9f4ba457a5f1ccbce9857ea00dba5 (diff) | |
download | plptools-3c5877e3f7fcd101a9868e6da86f12b92b6d4896.tar.gz plptools-3c5877e3f7fcd101a9868e6da86f12b92b6d4896.tar.bz2 plptools-3c5877e3f7fcd101a9868e6da86f12b92b6d4896.zip |
Fixed some 64bit related stuff in psitime and plpdirent.
More work on restore in kpsion.
Diffstat (limited to 'kde2/kpsion')
-rw-r--r-- | kde2/kpsion/Makefile.am | 3 | ||||
-rw-r--r-- | kde2/kpsion/kpsion.cpp | 866 | ||||
-rw-r--r-- | kde2/kpsion/kpsion.h | 140 | ||||
-rw-r--r-- | kde2/kpsion/main.cpp | 121 | ||||
-rw-r--r-- | kde2/kpsion/statusbarprogress.cpp | 438 | ||||
-rw-r--r-- | kde2/kpsion/statusbarprogress.h | 169 |
6 files changed, 1534 insertions, 203 deletions
diff --git a/kde2/kpsion/Makefile.am b/kde2/kpsion/Makefile.am index 6cbc731..d0b27f4 100644 --- a/kde2/kpsion/Makefile.am +++ b/kde2/kpsion/Makefile.am @@ -12,7 +12,8 @@ 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_SOURCES = kpsion.cpp setupdialog.cpp wizards.cpp \ + statusbarprogress.cpp libkpsion_la_LIBADD = -L$(top_srcdir)/lib -lplp $(LIB_KFILE) kpsion_SOURCES = main.cpp 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()); } /* diff --git a/kde2/kpsion/kpsion.h b/kde2/kpsion/kpsion.h index 86aeff4..2543fa6 100644 --- a/kde2/kpsion/kpsion.h +++ b/kde2/kpsion/kpsion.h @@ -1,15 +1,39 @@ +/*-*-c++-*- + * $Id$ + * + * This file is part of plptools. + * + * Copyright (C) 1999-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 + * + */ #ifndef _KPSION_H_ #define _KPSION_H_ #include "setupdialog.h" +#include "statusbarprogress.h" #include <kmainwindow.h> +#include <kcmdlineargs.h> #include <kiconview.h> -#include <kprogress.h> -#include <ksqueezedtextlabel.h> #include <klistview.h> +#include <kdialogbase.h> #include <ktar.h> +#include <qtextstream.h> #include <rfsv.h> #include <rpcs.h> #include <ppsocket.h> @@ -17,8 +41,10 @@ typedef QMap<char,QString> driveMap; typedef QMap<QString,QString> psionMap; -class KPsionCheckListItem : public QCheckListItem { - public: +class KPsionCheckListItem : public QObject, public QCheckListItem { + Q_OBJECT + +public: KPsionCheckListItem(KPsionCheckListItem *parent, const QString &text, Type tt) : QCheckListItem(parent, text, tt) { init(true); } @@ -34,25 +60,43 @@ class KPsionCheckListItem : public QCheckListItem { KPsionCheckListItem(QListView *parent, const QString &text, const QPixmap &p) : QCheckListItem(parent, text, p) { init(false); } - void setMetaData(int, time_t); - protected: + KPsionCheckListItem *firstChild() const; + KPsionCheckListItem *nextSibling() const; + + ~KPsionCheckListItem(); + + virtual QString key(int column, bool ascending) const; + void setMetaData(int bType, time_t bTime, QString tarName, int size, + u_int32_t tHi, u_int32_t tLo, u_int32_t attr); + + QString unixname(); + QString psionname(); + QString tarname(); + PlpDirent plpdirent(); + int backupType(); + int size(); + time_t when(); + bool isPathChecked(QString path); + +signals: + void rootToggled(void); + +protected: virtual void stateChange(bool); void propagateUp(bool); void propagateDown(bool); - private: +private: void init(bool); - - bool parentIsKPsionCheckListItem; - bool dontPropagate; - int backupType; - time_t when; + class KPsionCheckListItemMetaData; + KPsionCheckListItemMetaData *meta; }; class KPsionBackupListView : public KListView { Q_OBJECT - public: + +public: enum backupTypes { UNKNOWN = 0, FULL = 1, @@ -60,21 +104,50 @@ class KPsionBackupListView : public KListView { }; KPsionBackupListView(QWidget *parent = 0, const char *name = 0); + KPsionCheckListItem *firstChild() const; + void readBackups(QString uid); - PlpDir &getRestoreList(); + PlpDir &getRestoreList(QString tarname); + QStringList getSelectedTars(); + bool autoSelect(QString drive); + +signals: + void itemsEnabled(bool); - private: - void listTree(KPsionCheckListItem *cli, const KTarEntry *te, int level); +private slots: + void slotRootToggled(void); + +private: + void collectEntries(KPsionCheckListItem *i); + void listTree(KPsionCheckListItem *cli, const KTarEntry *te, + QTextIStream &idx, int level); QString uid; QString backupDir; PlpDir toRestore; }; +class KPsionRestoreDialog : public KDialogBase { + Q_OBJECT + +public: + KPsionRestoreDialog(QWidget *parent, QString uid); + + PlpDir &getRestoreList(QString tarname); + QStringList getSelectedTars(); + bool autoSelect(QString drive); + +private slots: + void slotBackupsSelected(bool); + +private: + KPsionBackupListView *backupView; +}; + class KPsionMainWindow : public KMainWindow { Q_OBJECT - - public: + +public: KPsionMainWindow(); ~KPsionMainWindow(); void setMachineName(QString &_name) { machineName = _name; } @@ -83,8 +156,20 @@ class KPsionMainWindow : public KMainWindow { psionMap &getMachines() { return machines; } QString &getMachineName() { return machineName; } QString &getBackupDir() { return backupDir; } + bool isConnected() { return connected; } + const KTarEntry *findTarEntry(const KTarEntry *te, QString path, + QString rpath = ""); - public slots: + static QString unix2psion(const char * const); + static QString psion2unix(const char * const); + +signals: + void setProgress(int); + void setProgress(int, int); + void setProgressText(const QString &); + void enableProgressText(bool); + +public slots: void slotStartRestore(); void slotStartFullBackup(); void slotStartIncBackup(); @@ -93,20 +178,21 @@ class KPsionMainWindow : public KMainWindow { void slotToggleStatusbar(); void slotSaveOptions(); void slotPreferences(); - - protected: + void slotProgressBarPressed(); + +protected: virtual bool queryClose(); void setupActions(); void switchActions(); void queryPsion(); void insertDrive(char letter, const char * const name); - private slots: +private slots: void iconClicked(QIconViewItem *i); void iconOver(QIconViewItem *i); void slotUpdateTimer(); - private: +private: void doBackup(); void tryConnect(); void updateProgress(unsigned long); @@ -114,6 +200,7 @@ class KPsionMainWindow : public KMainWindow { void killSave(); void runRestore(); void createIndex(); + bool askOverwrite(PlpDirent e); rfsv *plpRfsv; rpcs *plpRpcs; @@ -121,18 +208,20 @@ class KPsionMainWindow : public KMainWindow { ppsocket *rpcsSocket; SetupDialog *setupDialog; KIconView *view; - KProgress *progress; - KSqueezedTextLabel *progressLabel; + KPsionStatusBarProgress *progress; KTarGz *backupTgz; + KCmdLineArgs *args; driveMap drives; psionMap machines; + QStringList overWriteList; QStringList backupDrives; QStringList savedCommands; QString backupDir; QString machineName; QString statusMsg; QString ncpdDevice; + QString progressTotalText; bool S5mx; bool backupRunning; bool restoreRunning; @@ -142,6 +231,7 @@ class KPsionMainWindow : public KMainWindow { bool firstTry; bool shuttingDown; bool fullBackup; + bool overWriteAll; int reconnectTime; int nextTry; int ncpdSpeed; diff --git a/kde2/kpsion/main.cpp b/kde2/kpsion/main.cpp index df909ef..c9c0a0f 100644 --- a/kde2/kpsion/main.cpp +++ b/kde2/kpsion/main.cpp @@ -1,3 +1,25 @@ +/*-*-c++-*- + * $Id$ + * + * This file is part of plptools. + * + * Copyright (C) 1999-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 @@ -10,46 +32,71 @@ #include <kcmdlineargs.h> #include <kaboutdata.h> +namespace LIBPLP { +extern "C" { +#include <intl.h> + void init_libplp_i18n() { + bind_textdomain_codeset(PACKAGE, "latin1"); + textdomain(PACKAGE); + } +}; +}; + + 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}, + {"a", 0, 0}, + {"autobackup", I18N_NOOP("perform scheduled backup"), 0}, + {"b <drive>", 0, 0}, + {"backup <drive>", I18N_NOOP("perform backup"), 0}, + {"r <drive>", 0, 0}, + {"restore <drive>", I18N_NOOP("perform restore"), 0}, + {"f <drive>", 0, 0}, + {"format <drive>", I18N_NOOP("format drive"), 0}, + {"+drive", 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(); - } + 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); - KPsionMainWindow *w = new KPsionMainWindow(); - w->resize(300, 150); - a.setMainWidget(w); - w->show(); - return a.exec(); + KApplication a; + + // Install additional translations + LIBPLP::init_libplp_i18n(); + KGlobal::locale()->insertCatalogue(QString::fromLatin1("plptools")); + + 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(); + + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + if (args->isSet("autobackup") && (!w->isConnected())) + return 0; + w->resize(300, 170); + a.setMainWidget(w); + w->show(); + return a.exec(); } - - + +/* + * Local variables: + * c-basic-offset: 4 + * End: + */ diff --git a/kde2/kpsion/statusbarprogress.cpp b/kde2/kpsion/statusbarprogress.cpp new file mode 100644 index 0000000..8449faa --- /dev/null +++ b/kde2/kpsion/statusbarprogress.cpp @@ -0,0 +1,438 @@ +/*-*-c++-*- + * $Id$ + * + * Shamlessly stolen from: + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * This file is based on the work by Martynas Kunigelis (KProgress) + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "statusbarprogress.h" + +#include <qpainter.h> +#include <qstring.h> +#include <qpixmap.h> +#include <qtooltip.h> + +#include <kapp.h> +#include <kglobal.h> +#include <kglobalsettings.h> +#include <klocale.h> + +KPsionStatusBarProgress:: +KPsionStatusBarProgress(QWidget *parent, + const char *name) + : QFrame(parent, name), QRangeControl(0, 100, 1, 10, 0), +mOrientation(Horizontal) { + initialize(); +} + +KPsionStatusBarProgress:: +KPsionStatusBarProgress(Orientation orientation, + QWidget *parent, + const char *name) + : QFrame(parent, name), QRangeControl(0, 100, 1, 10, 0), +mOrientation(orientation) { + initialize(); +} + +KPsionStatusBarProgress:: +KPsionStatusBarProgress(int minValue, int maxValue, + int value, + Orientation orientation, + QWidget *parent, + const char *name) + : QFrame(parent, name), QRangeControl(minValue, maxValue, 1, 10, value), +mOrientation(orientation) { + initialize(); +} + +KPsionStatusBarProgress:: +~KPsionStatusBarProgress() { + delete mBarPixmap; +} + +void KPsionStatusBarProgress:: +advance(int offset) { + setValue(value() + offset); +} + +void KPsionStatusBarProgress:: +initialize(void) { + mBarPixmap = 0; + mBarStyle = Solid; + + mBarColor = palette().normal().highlight(); + mBarTextColor = palette().normal().highlightedText(); + mTextColor = palette().normal().text(); + setBackgroundColor(palette().normal().background()); + + QFont font(KGlobalSettings::generalFont()); + // font.setBold(true); + setFont(font); + + mTextEnabled = false; + adjustStyle(); +} + + +void KPsionStatusBarProgress:: +setBarPixmap(const QPixmap &pixmap) { + if (pixmap.isNull() == true) + return; + if (mBarPixmap != 0) { + delete mBarPixmap; + mBarPixmap = 0; + } + mBarPixmap = new QPixmap(pixmap); +} + +void KPsionStatusBarProgress:: +setBarColor(const QColor &color) { + mBarColor = color; + if (mBarPixmap != 0) { + delete mBarPixmap; + mBarPixmap = 0; + } +} + +void KPsionStatusBarProgress:: +setBarStyle(BarStyle style) { + if (mBarStyle != style) { + mBarStyle = style; + update(); + } +} + +void KPsionStatusBarProgress:: +setOrientation(Orientation orientation) { + if (mOrientation != orientation) { + mOrientation = orientation; + update(); + } +} + +void KPsionStatusBarProgress:: +setValue(int value) { + mCurItem = mMaxItem = -1; + QRangeControl::setValue(value); +} + +void KPsionStatusBarProgress:: +setValue(int curItem, int maxItem) { + if (curItem <= 0 || maxItem <= 0 || curItem > maxItem) { + mCurItem = mMaxItem = -1; + QRangeControl::setValue(0); + } else { + mCurItem = curItem; + mMaxItem = maxItem; + float fraction = (float)curItem/(float)maxItem; + QRangeControl::setValue((int)(fraction * 100.0)); + } +} + + +void KPsionStatusBarProgress:: +setTextEnabled(bool state) { + if (mTextEnabled != state) { + mTextEnabled = state; + update(); + } +} + +void KPsionStatusBarProgress:: +setText(const QString &msg) { + labelMsg = msg; + if (mTextEnabled == true) + update(); +} + + + + +const QColor & KPsionStatusBarProgress:: +barColor(void) const { + return(mBarColor); +} + +const QPixmap * KPsionStatusBarProgress:: +barPixmap(void) const { + return(mBarPixmap); +} + +bool KPsionStatusBarProgress:: +textEnabled(void) const { + return(mTextEnabled); +} + +QSize KPsionStatusBarProgress:: +sizeHint(void) const { + QSize s(size()); + + if (orientation() == KPsionStatusBarProgress::Vertical) + s.setWidth(fontMetrics().lineSpacing()); + else + s.setHeight(fontMetrics().lineSpacing()); + return(s); +} + + +KPsionStatusBarProgress::Orientation KPsionStatusBarProgress:: +orientation(void) const { + return(mOrientation); +} + +KPsionStatusBarProgress::BarStyle KPsionStatusBarProgress:: +barStyle() const { + return(mBarStyle); +} + +int KPsionStatusBarProgress:: +recalcValue(int range) { + int abs_value = value() - minValue(); + int abs_range = maxValue() - minValue(); + if (abs_range == 0) + return range; + return range * abs_value / abs_range; +} + +void KPsionStatusBarProgress:: +valueChange() { + repaint(contentsRect(), FALSE); + emit percentageChanged(recalcValue(100)); +} + +void KPsionStatusBarProgress:: +rangeChange() { + repaint(contentsRect(), FALSE); + emit percentageChanged(recalcValue(100)); +} + +void KPsionStatusBarProgress:: +styleChange(GUIStyle) { + adjustStyle(); +} + +void KPsionStatusBarProgress:: +adjustStyle(void) { + switch(style().guiStyle()) { + case WindowsStyle: + setFrameStyle(QFrame::NoFrame); + break; + + case MotifStyle: + default: + setFrameStyle(QFrame::Panel|QFrame::Sunken); + setLineWidth(1); + break; + } + update(); +} + +void KPsionStatusBarProgress:: +paletteChange(const QPalette &) { + mBarColor = palette().normal().highlight(); + mBarTextColor = palette().normal().highlightedText(); + mTextColor = palette().normal().text(); + setBackgroundColor(palette().normal().background()); +} + +void KPsionStatusBarProgress:: +drawText(QPainter *p) { + QRect r(contentsRect()); + + squeezeTextToLabel(); + p->setPen(mTextColor); + p->drawText(r, AlignCenter, labelText); + p->setClipRegion(fr); + p->setPen(mBarTextColor); + p->drawText(r, AlignCenter, labelText); +} + +void KPsionStatusBarProgress:: +drawContents(QPainter *p) { + QRect cr = contentsRect(), er = cr; + fr = cr; + QBrush fb(mBarColor), eb(backgroundColor()); + + if (mBarPixmap != 0) + fb.setPixmap(*mBarPixmap); + + if (backgroundPixmap()) + eb.setPixmap(*backgroundPixmap()); + + switch(mBarStyle) { + case Solid: + if (mOrientation == Horizontal) { + fr.setWidth(recalcValue(cr.width())); + er.setLeft(fr.right() + 1); + } else { + fr.setTop(cr.bottom() - recalcValue(cr.height())); + er.setBottom(fr.top() - 1); + } + + p->setBrushOrigin(cr.topLeft()); + p->fillRect(fr, fb); + p->fillRect(er, eb); + + if (mTextEnabled == true) + drawText(p); + break; + + case Blocked: + const int margin = 2; + int max, num, dx, dy; + if (mOrientation == Horizontal) { + fr.setHeight(cr.height() - 2 * margin); + fr.setWidth((int)(0.67 * fr.height())); + fr.moveTopLeft(QPoint(cr.left() + margin, cr.top() + margin)); + dx = fr.width() + margin; + dy = 0; + max = (cr.width() - margin) / (fr.width() + margin) + 1; + num = recalcValue(max); + } else { + fr.setWidth(cr.width() - 2 * margin); + fr.setHeight((int)(0.67 * fr.width())); + fr.moveBottomLeft(QPoint(cr.left() + margin, cr.bottom() - margin)); + dx = 0; + dy = - (fr.height() + margin); + max = (cr.height() - margin) / (fr.height() + margin) + 1; + num = recalcValue(max); + } + p->setClipRect(cr.x() + margin, cr.y() + margin, + cr.width() - margin, cr.height() - margin); + for (int i = 0; i < num; i++) { + p->setBrushOrigin(fr.topLeft()); + p->fillRect(fr, fb); + fr.moveBy(dx, dy); + } + + if (num != max) { + if (mOrientation == Horizontal) + er.setLeft(fr.right() + 1); + else + er.setBottom(fr.bottom() + 1); + if (!er.isNull()) { + p->setBrushOrigin(cr.topLeft()); + p->fillRect(er, eb); + } + } + break; + } + +} + +void KPsionStatusBarProgress:: +mousePressEvent(QMouseEvent */*e*/) { + emit pressed(); +} + +void KPsionStatusBarProgress:: +squeezeTextToLabel() { + QFontMetrics fm(fontMetrics()); + int labelWidth = size().width(); + int percent; + QString fullText; + + if (labelMsg.isEmpty() == true) { + labelText = QString("%1%").arg(recalcValue(100)); + return; + } else { + if (mCurItem > 0) + fullText = i18n("%1 %2 of %3").arg(labelMsg).arg(mCurItem).arg(mMaxItem); + else { + percent = recalcValue(100); + fullText = QString("%1 %2%").arg(labelMsg).arg(percent); + } + } + int textWidth = fm.width(fullText); + if (textWidth > labelWidth) { + // start with the dots only + QString squeezedMsg = "..."; + QString squeezedText; + + if (mCurItem > 0) + squeezedText = i18n("%1 %2 of %3").arg(squeezedMsg).arg(mCurItem).arg(mMaxItem); + else + squeezedText = QString("%1 %2%").arg(squeezedMsg).arg(percent); + int squeezedWidth = fm.width(squeezedText); + + // estimate how many letters we can add to the dots on both sides + int letters = fullText.length() * (labelWidth - squeezedWidth) / textWidth / 2; + squeezedMsg = labelMsg.left(letters) + "..." + labelMsg.right(letters); + if (mCurItem > 0) + squeezedText = i18n("%1 %2 of %3").arg(squeezedMsg).arg(mCurItem).arg(mMaxItem); + else + squeezedText = QString("%1 %2%").arg(squeezedMsg).arg(percent); + squeezedWidth = fm.width(squeezedText); + + if (squeezedWidth < labelWidth) { + // we estimated too short + // add letters while text < label + do { + letters++; + squeezedMsg = labelMsg.left(letters) + "..." + + labelMsg.right(letters); + if (mCurItem > 0) + squeezedText = i18n("%1 %2 of %3").arg(squeezedMsg).arg(mCurItem).arg(mMaxItem); + else + squeezedText = QString("%1 %2%").arg(squeezedMsg).arg(percent); + squeezedWidth = fm.width(squeezedText); + } while (squeezedWidth < labelWidth); + letters--; + squeezedMsg = labelMsg.left(letters) + "..." + + labelMsg.right(letters); + if (mCurItem > 0) + squeezedText = i18n("%1 %2 of %3").arg(squeezedMsg).arg(mCurItem).arg(mMaxItem); + else + squeezedText = QString("%1 %2%").arg(squeezedMsg).arg(percent); + } else if (squeezedWidth > labelWidth) { + // we estimated too long + // remove letters while text > label + do { + letters--; + squeezedMsg = labelMsg.left(letters) + "..." + + labelMsg.right(letters); + if (mCurItem > 0) + squeezedText = i18n("%1 %2 of %3").arg(squeezedMsg).arg(mCurItem).arg(mMaxItem); + else + squeezedText = QString("%1 %2%").arg(squeezedMsg).arg(percent); + squeezedWidth = fm.width(squeezedText); + } while (squeezedWidth > labelWidth); + } + + if (letters < 5) { + // too few letters added -> we give up squeezing + labelText = fullText; + } else + labelText = squeezedText; + + QToolTip::remove(this); + QToolTip::add(this, fullText); + } else { + labelText = fullText; + QToolTip::remove( this ); + QToolTip::hide(); + }; +} + +/* + * Local variables: + * c-basic-offset: 4 + * End: + */ diff --git a/kde2/kpsion/statusbarprogress.h b/kde2/kpsion/statusbarprogress.h new file mode 100644 index 0000000..9b1ae4d --- /dev/null +++ b/kde2/kpsion/statusbarprogress.h @@ -0,0 +1,169 @@ +/*-*-c++-*- + * $Id$ + * + * Shamelessly stolen from: + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * This file is based on the work by Martynas Kunigelis (KProgress) + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef _STATUSBAR_PROGRESS_H_ +#define _STATUSBAR_PROGRESS_H_ + +#include <qframe.h> +#include <qrangecontrol.h> + +class KPsionStatusBarProgress : public QFrame, public QRangeControl { + Q_OBJECT + +public: + /** + * Possible values for orientation + */ + enum Orientation { Horizontal, Vertical }; + + /** + * Possible values for bar style. + * + * Solid means one continuous progress bar, Blocked means a + * progress bar made up of several blocks. + */ + enum BarStyle { Solid, Blocked }; + + /** + * Construct a default progress bar. Orientation is horizontal. + */ + KPsionStatusBarProgress(QWidget *parent=0, const char *name=0); + + /** + * Construct a KProgress bar with an orientation. + */ + KPsionStatusBarProgress(Orientation, QWidget *parent=0, const char *name=0); + + /** + * Construct a KProgress bar with minimum, maximum and initial value. + */ + KPsionStatusBarProgress(int minValue, int maxValue, int value, Orientation, + QWidget *parent=0, const char *name=0); + + /** + * Destructor + */ + ~KPsionStatusBarProgress( void ); + + /** + * Set the progress bar style. Allowed values are Solid and Blocked. + */ + void setBarStyle(BarStyle style); + + /** + * Set the color of the progress bar. + */ + void setBarColor(const QColor &); + + /** + * Set a pixmap to be shown in the progress bar. + */ + void setBarPixmap(const QPixmap &); + + /** + * Set the orientation of the progress bar. + * Allowed values are Horizonzal and Vertical. + */ + void setOrientation(Orientation); + + /** + * Retrieve the bar style. + */ + BarStyle barStyle() const; + + /** + * Retrieve the bar color. + */ + const QColor &barColor() const; + + /** + * Retrieve the bar pixmap. + */ + const QPixmap *barPixmap() const; + + /** + * Retrieve the orientation. + */ + Orientation orientation() const; + + /** + * Returns TRUE if progress text will be displayed, FALSE otherwise. + */ + bool textEnabled() const; + + /** + * Returns the recommended width for vertical progress bars or + * the recommended height for vertical progress bars + */ + virtual QSize sizeHint() const; + + +public slots: + void setValue( int ); + void setValue( int, int); + void advance( int ); + void setTextEnabled( bool state ); + void setText( const QString &msg ); + +signals: + void percentageChanged(int); + void pressed( void ); + +protected: + void valueChange(); + void rangeChange(); + void styleChange( GUIStyle ); + void paletteChange( const QPalette & ); + void drawContents( QPainter * ); + void mousePressEvent( QMouseEvent *e ); + +private: + QPixmap *mBarPixmap; + QColor mBarColor; + QColor mBarTextColor; + QColor mTextColor; + QRect fr; + BarStyle mBarStyle; + Orientation mOrientation; + bool mTextEnabled; + QString labelMsg; + QString labelText; + int mCurItem; + int mMaxItem; + + void initialize(void); + int recalcValue(int); + void drawText(QPainter *); + void adjustStyle(void); + void squeezeTextToLabel(void); +}; + + +#endif + +/* + * Local variables: + * c-basic-offset: 4 + * End: + */ |