/*-*-c++-*- * $Id$ * * This file is part of plptools. * * Copyright (C) 2001 Fritz Elfert <felfert@to.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifdef HAVE_CONFIG_H #include <config.h> #endif #include <errno.h> #include <sys/types.h> #include <unistd.h> #include <pwd.h> #include "kpsionconfig.h" #include "wizards.h" #include <kapp.h> #include <kdebug.h> #include <kdialog.h> #include <klocale.h> #include <kfiledialog.h> #include <kmessagebox.h> #include <qlayout.h> #include <qwhatsthis.h> #include <qheader.h> FirstTimeWizard::FirstTimeWizard(QWidget *parent, const char *name) : KWizard(parent, name, true) { QStringList sl; KPsionConfig pcfg; setCaption(i18n("KPsion Configuration")); QWhatsThis::add(nextButton(), i18n("Click this button to continue with the next page.")); QWhatsThis::add(backButton(), i18n("Click this button, to go to a previous page.")); QWhatsThis::add(cancelButton(), i18n("<QT>If you click this button, the setup of <B>KPSion</B> will be aborted and next time you start <B>KPsion</B>, it will run this setup again.</QT>")); bdirDefault = pcfg.getStrDefault(KPsionConfig::DEF_BACKUPDIR); bdirCreated = ""; // Page 1 page1 = new QWidget(this, "welcome"); QGridLayout *grid = new QGridLayout(page1); QLabel *l = new QLabel(page1, "welcome message"); l->setText(i18n( "<QT>" "<H2>Welcome to KPsion!</H2>" "It looks like you started <B>KPsion</B> the first time. " "At least, i could not find any valid configuration.</BR>" "On the following pages, we will gather some information, " "which is needed for working with <B>KPsion</B>.</BR>" " </BR>" "Have fun." "</QT>" )); grid->addWidget(l, 1, 1, Qt::AlignTop); grid->setColStretch(1, 1); grid->setRowStretch(1, 1); grid->addRowSpacing(0, KDialog::marginHint()); grid->addRowSpacing(2, KDialog::marginHint()); grid->addColSpacing(0, KDialog::marginHint()); grid->addColSpacing(2, KDialog::marginHint()); addPage(page1, i18n("<QT><BIG><B>Welcome<B></BIG></QT>")); // Page 2 page2 = new QWidget(this, "step1"); grid = new QGridLayout(page2); l = new QLabel(page2, "step1"); l->setText(i18n( "<QT>" "First, we need a folder for storing backups of " "your Psion. You probably don't want others to " "have access to it, so it's best to choose a " "location somewhere in your home directory. " "Please browse through existing folders and select a suitable " "location or simply accept the default shown below." "</QT>" )); grid->addMultiCellWidget(l, 1, 1, 1, 2, Qt::AlignTop); bdirLabel = new QLabel(page2, "bdirLabel"); bdirLabel->setText(bdirDefault); bdirButton = new QPushButton(i18n("Browse"), page2); QWhatsThis::add(bdirLabel, i18n("This is the name of the backup folder.")); QWhatsThis::add(bdirButton, i18n("Click here, for opening a dialog which lets you easily select the backup folder.")); grid->addWidget(bdirLabel, 3, 1); grid->addWidget(bdirButton, 3, 2); grid->setRowStretch(1, 1); grid->setColStretch(1, 1); grid->addRowSpacing(2, KDialog::spacingHint()); grid->addRowSpacing(0, KDialog::marginHint()); grid->addRowSpacing(4, KDialog::marginHint()); grid->addColSpacing(0, KDialog::marginHint()); grid->addColSpacing(3, KDialog::marginHint()); connect(bdirButton, SIGNAL(clicked()), SLOT(slotBdirBrowse())); addPage(page2, i18n("<QT><BIG><B>Step 1</B></BIG> - Specify backup directory</QT>")); // Page 3 page3 = new QWidget(this, "step2"); grid = new QGridLayout(page3); l = new QLabel(page3, "step2"); l->setText(i18n( "<QT>" "Next, please specify some information regarding " "backup policy:<UL><LI>How many generations of backups " "do you want to keep?</LI><LI>Shall i perform automatic " "backups?</LI><LI>If yes, in what intervals do you want " "to happen backups?</LI></UL>" "</QT>" )); grid->addMultiCellWidget(l, 1, 1, 1, 2, Qt::AlignTop); l = new QLabel( i18n("&Incremental backup interval"), page3, "iBackupIntLabel"); grid->addWidget(l, 3, 1); iIntCombo = new KComboBox(false, page3, "iIntCombo"); iIntCombo->insertStringList(pcfg.getConfigBackupInterval()); iIntCombo->setCurrentItem(pcfg.getIntDefault(KPsionConfig::DEF_INCINTERVAL)); grid->addWidget(iIntCombo, 3, 2); l->setBuddy(iIntCombo); l = new QLabel(i18n("&Full backup interval"), page3, "fBackupIntLabel"); grid->addWidget(l, 5, 1); fIntCombo = new KComboBox(false, page3, "fIntCombo"); fIntCombo->insertStringList(pcfg.getConfigBackupInterval()); fIntCombo->setCurrentItem(pcfg.getIntDefault(KPsionConfig::DEF_FULLINTERVAL)); grid->addWidget(fIntCombo, 5, 2); l->setBuddy(fIntCombo); l = new QLabel(i18n("Backup &generations"), page3, "backupGenLabel"); grid->addWidget(l, 7, 1); genSpin = new KIntSpinBox(0, 10, 1, pcfg.getIntDefault(KPsionConfig::DEF_BACKUPGEN), 10, page3, "backupGenSpin"); grid->addWidget(genSpin, 7, 2); l->setBuddy(genSpin); grid->setRowStretch(1, 1); grid->setColStretch(1, 1); grid->addRowSpacing(2, KDialog::spacingHint()); grid->addRowSpacing(4, KDialog::spacingHint()); grid->addRowSpacing(6, KDialog::spacingHint()); grid->addRowSpacing(0, KDialog::marginHint()); grid->addRowSpacing(8, KDialog::marginHint()); grid->addColSpacing(0, KDialog::marginHint()); grid->addColSpacing(3, KDialog::marginHint()); addPage(page3, i18n("<QT><BIG><B>Step 2</B></BIG> - Backup policy</QT>")); // Page 4 page4 = new QWidget(this, "step3"); grid = new QGridLayout(page4); l = new QLabel(page4, "step2"); l->setText(i18n( "<QT>" "If no connection could be established on startup, " "<B>KPsion</B> will attempt to connect in regular " "intervals. Please specify the interval after which " "a connection attempt should happen. If you don't want " "automatic retry, set the interval to zero. Furthermore, " "<B>KPsion</B> can try to start ncpd if it is not already " "running. For that to work correctly, you need to" "<UL><LI>specify the serial port to use.</LI>" "<LI>specify the baud rate</LI>" "<LI>have permission to use the specified port</LI></UL>" "</QT>" )); grid->addMultiCellWidget(l, 1, 1, 1, 2, Qt::AlignTop); l = new QLabel( i18n("&Connection retry interval (sec.)"), page4, "rconLabel"); grid->addWidget(l, 3, 1); rconSpin = new KIntSpinBox(0, 600, 1, pcfg.getIntDefault(KPsionConfig::DEF_CONNRETRY), 10, page4, "rconSpin"); grid->addWidget(rconSpin, 3, 2); l->setBuddy(rconSpin); l = new QLabel(i18n("Serial &device"), page4, "devLabel"); grid->addWidget(l, 5, 1); devCombo = new KComboBox(false, page4, "devCombo"); sl = pcfg.getConfigDevices(); devCombo->insertStringList(sl); devCombo->setCurrentItem(pcfg.getIntDefault(KPsionConfig::DEF_SERIALDEV)); grid->addWidget(devCombo, 5, 2); l->setBuddy(devCombo); l = new QLabel(i18n("Serial &speed"), page4, "speedLabel"); grid->addWidget(l, 7, 1); speedCombo = new KComboBox(false, page4, "speedCombo"); sl = pcfg.getConfigSpeeds(); speedCombo->insertStringList(sl); speedCombo->setCurrentItem(pcfg.getIntDefault(KPsionConfig::DEF_SERIALSPEED)); grid->addWidget(speedCombo, 7, 2); l->setBuddy(speedCombo); grid->setRowStretch(1, 1); grid->setColStretch(1, 1); grid->addRowSpacing(2, KDialog::spacingHint()); grid->addRowSpacing(4, KDialog::spacingHint()); grid->addRowSpacing(6, KDialog::spacingHint()); grid->addRowSpacing(0, KDialog::marginHint()); grid->addRowSpacing(8, KDialog::marginHint()); grid->addColSpacing(0, KDialog::marginHint()); grid->addColSpacing(3, KDialog::marginHint()); addPage(page4, i18n("<QT><BIG><B>Step 3</B></BIG> - Connection parameters</QT>")); // Page 5 page5 = new QWidget(this, "step3"); grid = new QGridLayout(page5); l = new QLabel(page5, "step2"); l->setText(i18n( "<QT>" "That's it!<BR/>" "Next, i will start <B>KPsion</B> and if your Psion is already " "connected and it's communication turned on (use " "<B>Ctrl-T</B> at system level), then <B>KPsion</B> will " "bring up a similar Dialog like this which lets you assing a " "Name for it. After that, i suggest performing a full " "Backup.<BR/>Please click <B>Finish</B> now.</QT>" )); grid->addWidget(l, 1, 1, Qt::AlignTop); grid->setRowStretch(1, 1); grid->setColStretch(1, 1); grid->addRowSpacing(0, KDialog::marginHint()); grid->addRowSpacing(2, KDialog::marginHint()); grid->addColSpacing(0, KDialog::marginHint()); grid->addColSpacing(2, KDialog::marginHint()); addPage(page5, i18n("<QT><BIG><B>Finished</B></BIG></QT>")); setFinishEnabled(page5, true); } void FirstTimeWizard:: slotBdirBrowse() { QString dir = KFileDialog::getExistingDirectory(bdirLabel->text(), this, i18n("Backup folder")); checkBackupDir(dir); } void FirstTimeWizard:: reject() { // kapp->quit() and [QK]Application::exit(0) don't work here?! // probably because we didn't call kapp->exec() yet? // -> brute force if (KMessageBox::questionYesNo(this, i18n("<QT>You are about to abort the initial setup of <B>KPsion</B>. No configuration will be stored and you will have to repeat this procedure when you start <B>KPsion</B> next time.<BR/>Do you really want to exit now?</QT>")) == KMessageBox::Yes) { if (!bdirCreated.isEmpty()) ::rmdir(bdirCreated.data()); ::exit(0); } } void FirstTimeWizard:: accept() { KConfig *config = kapp->config(); KPsionConfig pcfg; config->setGroup(pcfg.getSectionName(KPsionConfig::OPT_BACKUPDIR)); config->writeEntry(pcfg.getOptionName(KPsionConfig::OPT_BACKUPDIR), bdirLabel->text()); config->setGroup(pcfg.getSectionName(KPsionConfig::OPT_BACKUPGEN)); config->writeEntry(pcfg.getOptionName(KPsionConfig::OPT_BACKUPGEN), genSpin->value()); config->setGroup(pcfg.getSectionName(KPsionConfig::OPT_INCINTERVAL)); config->writeEntry(pcfg.getOptionName(KPsionConfig::OPT_INCINTERVAL), iIntCombo->currentItem()); config->setGroup(pcfg.getSectionName(KPsionConfig::OPT_FULLINTERVAL)); config->writeEntry(pcfg.getOptionName(KPsionConfig::OPT_FULLINTERVAL), fIntCombo->currentItem()); config->setGroup(pcfg.getSectionName(KPsionConfig::OPT_CONNRETRY)); config->writeEntry(pcfg.getOptionName(KPsionConfig::OPT_CONNRETRY), rconSpin->value()); config->setGroup(pcfg.getSectionName(KPsionConfig::OPT_SERIALDEV)); config->writeEntry(pcfg.getOptionName(KPsionConfig::OPT_SERIALDEV), devCombo->currentText()); config->setGroup(pcfg.getSectionName(KPsionConfig::OPT_SERIALSPEED)); config->writeEntry(pcfg.getOptionName(KPsionConfig::OPT_SERIALSPEED), speedCombo->currentText()); hide(); setResult(Accepted); } void FirstTimeWizard:: next() { for (int i = 0; i < pageCount(); i++) if (currentPage() == page(i)) { switch (i) { case 1: QString dir(bdirLabel->text()); if (!checkBackupDir(dir)) return; } break; } KWizard::next(); } void FirstTimeWizard:: closeEvent(QCloseEvent *e) { reject(); } bool FirstTimeWizard:: checkBackupDir(QString &dir) { if (!bdirCreated.isEmpty()) { if (bdirCreated != dir) { ::rmdir(bdirCreated.data()); bdirCreated = ""; } } if (!dir.isEmpty()) { QDir d(dir); if (!d.exists()) { if (KMessageBox::questionYesNo(this, i18n("<QT>The folder <B>%1</B> does <B>not</B> exist.<BR/>Shall it be created?</QT>").arg(dir)) == KMessageBox::No) { bdirLabel->setText(bdirDefault); return false; } if (mkdir(dir.data(), 0700) != 0) { QString msg = i18n("<QT>The specified folder<BR/><B>%1</B><BR/>could <B>not</B> be created"); switch (errno) { case EACCES: case EPERM: case EROFS: msg += i18n(", because you either don't have sufficient rights to do that, or the filesystem is readonly."); // Insufficient permissions/ readonly FS break; case ENOSPC: msg += i18n(", because the filesystem has not enough space."); // No space break; case EEXIST: // shouldn't happen, we checked already // for existence. msg += i18n(", because there already exists another object with the same name."); break; case EFAULT: case ENOMEM: case ENAMETOOLONG: // shouldn't happen. msg += "."; break; case ENOENT: // propably dangling symlink msg += i18n(", because you specified a path which probably contains a dangling symbolic link."); break; case ENOTDIR: msg += i18n(", because you specified a path which contains an element which is not a folder."); // path element not dir. break; case ELOOP: msg += i18n(", because you specified a path which contains too many symbolic links."); // Too many symlinks break; } bdirLabel->setText(bdirDefault); msg += i18n("<BR/>Please select another folder.</QT>"); KMessageBox::error(this, msg.arg(dir)); return false; } bdirCreated = dir; } bdirLabel->setText(dir); return true; } bdirLabel->setText(bdirDefault); return false; } NewPsionWizard::NewPsionWizard(QWidget *parent, const char *name) : KWizard(parent, name, true) { setCaption(i18n("New Psion detected")); psion = (KPsionMainWindow *)parent; QWhatsThis::add(nextButton(), i18n("Click this button to continue with the next page.")); QWhatsThis::add(backButton(), i18n("Click this button, to go to a previous page.")); QWhatsThis::add(cancelButton(), i18n("<QT>If you click this button, the setup for the new connected Psion will be aborted and next time you connect this Psion again, <B>KPsion</B> will run this setup again.</QT>")); // Page 1 page1 = new QWidget(this, "newmachine"); QGridLayout *grid = new QGridLayout(page1); QLabel *l = new QLabel(page1, "newmachmessage"); uid = psion->getMachineUID(); l->setText(i18n( "<QT>" "The Psion with the unique ID <B>%1</B> " "is connected the first time. Please assign a name to it." "</QT>").arg(uid)); grid->addMultiCellWidget(l, 1, 1, 1, 2, Qt::AlignTop); l = new QLabel(page1, "nameLabel"); l->setText(i18n("&Name of new Psion")); nameEdit = new KLineEdit(page1, "nameEdit"); nameEdit->setText(i18n("My new Psion")); nameEdit->selectAll(); nameEdit->setFocus(); l->setBuddy(nameEdit); grid->addWidget(l, 3, 1); grid->addWidget(nameEdit, 3, 2); grid->setColStretch(1, 1); grid->setRowStretch(1, 1); grid->addRowSpacing(2, KDialog::spacingHint()); grid->addRowSpacing(0, KDialog::marginHint()); grid->addRowSpacing(4, KDialog::marginHint()); grid->addColSpacing(0, KDialog::marginHint()); grid->addColSpacing(2, KDialog::marginHint()); addPage(page1, i18n("<QT><BIG><B>New Psion detected<B></BIG></QT>")); // Page 2 page2 = new QWidget(this, "bdrives"); grid = new QGridLayout(page2); l = new QLabel(page2, "bdrivemessage"); l->setText(i18n( "<QT>" "Please select the Drive(s), you want to be backed up when " "running in unattended backup mode." "</QT>" )); grid->addMultiCellWidget(l, 1, 1, 1, 3, Qt::AlignTop); backupListView = new KListView(page2, "bdriveListView"); backupListView->addColumn(i18n("Available drives")); driveMap dlist = psion->getDrives(); driveMap::Iterator it; int height = backupListView->header()->height(); for (it = dlist.begin(); it != dlist.end(); it++) { QCheckListItem *i = new QCheckListItem(backupListView, it.data(), QCheckListItem::CheckBox); height += i->height(); i->setSelectable(false); } backupListView->setMaximumSize(backupListView->columnWidth(0) + 5, height + 5); grid->addWidget(backupListView, 3, 2); grid->setColStretch(1, 1); grid->setRowStretch(1, 1); grid->setColStretch(3, 1); grid->addRowSpacing(2, KDialog::spacingHint()); grid->addRowSpacing(0, KDialog::marginHint()); grid->addRowSpacing(4, KDialog::marginHint()); grid->addColSpacing(0, KDialog::marginHint()); grid->addColSpacing(4, KDialog::marginHint()); addPage(page2, i18n("<QT><BIG><B>Specify drives to backup<B></BIG></QT>")); setFinishEnabled(page2, true); } void NewPsionWizard:: next() { for (int i = 0; i < pageCount(); i++) if (currentPage() == page(i)) { switch (i) { case 0: QString tmp(nameEdit->text()); if (!checkPsionName(tmp)) return; } break; } KWizard::next(); } bool NewPsionWizard:: checkPsionName(QString &name) { if (name.isEmpty()) { KMessageBox::sorry(this, i18n("The name cannot be empty.")); return false; } psionMap l = psion->getMachines(); psionMap::Iterator it; for (it = l.begin(); it != l.end(); it++) { if (name == it.data()) { KMessageBox::sorry(this, i18n("<QT>The name <B>%1</B> is already assigned to another machine.<BR/>Please choose a different name.</QT>")); return false; } } return true; } void NewPsionWizard:: accept() { KConfig *config = kapp->config(); KPsionConfig pcfg; config->setGroup(pcfg.getSectionName(KPsionConfig::OPT_UIDS)); QStringList machines = config->readListEntry( pcfg.getOptionName(KPsionConfig::OPT_UIDS)); machines += uid; config->writeEntry(pcfg.getOptionName(KPsionConfig::OPT_UIDS), machines); config->setGroup(pcfg.getSectionName(KPsionConfig::OPT_MACHNAME)); QString tmp = pcfg.getOptionName(KPsionConfig::OPT_MACHNAME).arg(uid); config->writeEntry(tmp, nameEdit->text()); tmp = nameEdit->text(); psion->setMachineName(tmp); driveMap dlist = psion->getDrives(); driveMap::Iterator di; QStringList drives; for (di = dlist.begin(); di != dlist.end(); di++) { QString drv = ""; drv += di.key(); drives += drv; } config->setGroup(pcfg.getSectionName(KPsionConfig::OPT_DRIVES)); config->writeEntry( pcfg.getOptionName(KPsionConfig::OPT_DRIVES).arg(uid), drives); QListViewItemIterator li(backupListView); QStringList bdrives; for (; li.current(); li++) { QCheckListItem *qcli = (QCheckListItem *)(li.current()); if (qcli->isOn()) { tmp = qcli->text(); for (di = dlist.begin(); di != dlist.end(); di++) if (di.data() == tmp) { QString drv = ""; drv += di.key(); bdrives += drv; } } } config->setGroup(pcfg.getSectionName(KPsionConfig::OPT_BACKUPDRIVES)); config->writeEntry( pcfg.getOptionName(KPsionConfig::OPT_BACKUPDRIVES).arg(uid), bdrives); hide(); setResult(Accepted); } /* * Local variables: * c-basic-offset: 4 * End: */