/*************************************************************************** copyright : (C) 2001-2006 by Robby Stephenson email : robby@periapsis.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of version 2 of the GNU General Public License as * * published by the Free Software Foundation; * * * ***************************************************************************/ #include "configdialog.h" #include "field.h" #include "collection.h" #include "collectionfactory.h" #include "fetch/execexternalfetcher.h" #include "fetch/fetchmanager.h" #include "fetch/configwidget.h" #include "controller.h" #include "fetcherconfigdialog.h" #include "tellico_kernel.h" #include "latin1literal.h" #include "tellico_utils.h" #include "core/tellico_config.h" #include "imagefactory.h" #include "gui/combobox.h" #include "gui/previewdialog.h" #include "newstuff/dialog.h" #include "../tellico_debug.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace { static const int CONFIG_MIN_WIDTH = 640; static const int CONFIG_MIN_HEIGHT = 420; } using Tellico::SourceListViewItem; using Tellico::ConfigDialog; SourceListViewItem::SourceListViewItem(KListView* parent_, const GeneralFetcherInfo& info_, const TQString& groupName_) : KListViewItem(parent_, info_.name), m_info(info_), m_configGroup(groupName_), m_newSource(groupName_.isNull()), m_fetcher(0) { TQPixmap pix = Fetch::Manager::fetcherIcon(info_.type); if(!pix.isNull()) { setPixmap(0, pix); } } SourceListViewItem::SourceListViewItem(KListView* parent_, TQListViewItem* after_, const GeneralFetcherInfo& info_, const TQString& groupName_) : KListViewItem(parent_, after_, info_.name), m_info(info_), m_configGroup(groupName_), m_newSource(groupName_.isNull()), m_fetcher(0) { TQPixmap pix = Fetch::Manager::fetcherIcon(info_.type); if(!pix.isNull()) { setPixmap(0, pix); } } void SourceListViewItem::setFetcher(Fetch::Fetcher::Ptr fetcher) { m_fetcher = fetcher; TQPixmap pix = Fetch::Manager::fetcherIcon(fetcher.data()); if(!pix.isNull()) { setPixmap(0, pix); } } ConfigDialog::ConfigDialog(TQWidget* parent_, const char* name_/*=0*/) : KDialogBase(IconList, i18n("Configure Tellico"), Help|Ok|Apply|Cancel|Default, Ok, parent_, name_, true, false) , m_modifying(false) , m_okClicked(false) { setupGeneralPage(); setupPrintingPage(); setupTemplatePage(); setupFetchPage(); updateGeometry(); TQSize s = tqsizeHint(); resize(TQMAX(s.width(), CONFIG_MIN_WIDTH), TQMAX(s.height(), CONFIG_MIN_HEIGHT)); // purely for asthetics make all widgets line up TQPtrList widgets; widgets.append(m_fontCombo); widgets.append(m_fontSizeInput); widgets.append(m_baseColorCombo); widgets.append(m_textColorCombo); widgets.append(m_highBaseColorCombo); widgets.append(m_highTextColorCombo); int w = 0; for(TQPtrListIterator it(widgets); it.current(); ++it) { it.current()->polish(); w = TQMAX(w, it.current()->tqsizeHint().width()); } for(TQPtrListIterator it(widgets); it.current(); ++it) { it.current()->setMinimumWidth(w); } enableButtonOK(false); enableButtonApply(false); setHelp(TQString::tqfromLatin1("general-options")); connect(this, TQT_SIGNAL(aboutToShowPage(TQWidget*)), TQT_SLOT(slotUpdateHelpLink(TQWidget*))); } ConfigDialog::~ConfigDialog() { for(TQPtrListIterator it(m_newStuffConfigWidgets); it.current(); ++it) { it.current()->removed(); } } void ConfigDialog::slotUpdateHelpLink(TQWidget* w_) { switch(pageIndex(w_)) { case 0: setHelp(TQString::tqfromLatin1("general-options")); break; case 1: setHelp(TQString::tqfromLatin1("printing-options")); break; case 2: setHelp(TQString::tqfromLatin1("template-options")); break; case 3: setHelp(TQString::tqfromLatin1("internet-sources-options")); break; default: break; } } void ConfigDialog::slotOk() { m_okClicked = true; slotApply(); accept(); m_okClicked = false; } void ConfigDialog::slotApply() { emit signalConfigChanged(); enableButtonApply(false); } void ConfigDialog::slotDefault() { // only change the defaults on the active page Config::self()->useDefaults(true); switch(activePageIndex()) { case 0: readGeneralConfig(); break; case 1: readPrintingConfig(); break; case 2: readTemplateConfig(); break; } Config::self()->useDefaults(false); slotModified(); } void ConfigDialog::setupGeneralPage() { TQPixmap pix = DesktopIcon(TQString::tqfromLatin1("tellico"), KIcon::SizeMedium); TQFrame* frame = addPage(i18n("General"), i18n("General Options"), pix); TQVBoxLayout* l = new TQVBoxLayout(frame, KDialog::marginHint(), KDialog::spacingHint()); m_cbOpenLastFile = new TQCheckBox(i18n("&Reopen file at startup"), frame); TQWhatsThis::add(m_cbOpenLastFile, i18n("If checked, the file that was last open " "will be re-opened at program start-up.")); l->addWidget(m_cbOpenLastFile); connect(m_cbOpenLastFile, TQT_SIGNAL(clicked()), TQT_SLOT(slotModified())); m_cbShowTipDay = new TQCheckBox(i18n("&Show \"Tip of the Day\" at startup"), frame); TQWhatsThis::add(m_cbShowTipDay, i18n("If checked, the \"Tip of the Day\" will be " "shown at program start-up.")); l->addWidget(m_cbShowTipDay); connect(m_cbShowTipDay, TQT_SIGNAL(clicked()), TQT_SLOT(slotModified())); TQButtonGroup* imageGroup = new TQVButtonGroup(i18n("Image Storage Options"), frame); m_rbImageInFile = new TQRadioButton(i18n("Store images in data file"), imageGroup); m_rbImageInAppDir = new TQRadioButton(i18n("Store images in common application directory"), imageGroup); m_rbImageInLocalDir = new TQRadioButton(i18n("Store images in directory relative to data file"), imageGroup); TQWhatsThis::add(imageGroup, i18n("Images may be saved in the data file itself, which can " "cause Tellico to run slowly, stored in the Tellico " "application directory, or stored in a directory in the " "same location as the data file.")); l->addWidget(imageGroup); connect(imageGroup, TQT_SIGNAL(clicked(int)), TQT_SLOT(slotModified())); TQVGroupBox* formatGroup = new TQVGroupBox(i18n("Formatting Options"), frame); l->addWidget(formatGroup); m_cbCapitalize = new TQCheckBox(i18n("Auto capitalize &titles and names"), formatGroup); TQWhatsThis::add(m_cbCapitalize, i18n("If checked, titles and names will " "be automatically capitalized.")); connect(m_cbCapitalize, TQT_SIGNAL(clicked()), TQT_SLOT(slotModified())); m_cbFormat = new TQCheckBox(i18n("Auto &format titles and names"), formatGroup); TQWhatsThis::add(m_cbFormat, i18n("If checked, titles and names will " "be automatically formatted.")); connect(m_cbFormat, TQT_SIGNAL(clicked()), TQT_SLOT(slotModified())); TQGrid* g1 = new TQGrid(2, formatGroup); g1->setSpacing(5); TQLabel* lab = new TQLabel(i18n("No capitali&zation:"), g1); m_leCapitals = new KLineEdit(g1); lab->setBuddy(m_leCapitals); TQString whats = i18n("A list of words which should not be capitalized. Multiple values " "should be separated by a semi-colon."); TQWhatsThis::add(lab, whats); TQWhatsThis::add(m_leCapitals, whats); connect(m_leCapitals, TQT_SIGNAL(textChanged(const TQString&)), TQT_SLOT(slotModified())); lab = new TQLabel(i18n("Artic&les:"), g1); m_leArticles = new KLineEdit(g1); lab->setBuddy(m_leArticles); whats = i18n("A list of words which should be considered as articles " "if they are the first word in a title. Multiple values " "should be separated by a semi-colon."); TQWhatsThis::add(lab, whats); TQWhatsThis::add(m_leArticles, whats); connect(m_leArticles, TQT_SIGNAL(textChanged(const TQString&)), TQT_SLOT(slotModified())); lab = new TQLabel(i18n("Personal suffi&xes:"), g1); m_leSuffixes = new KLineEdit(g1); lab->setBuddy(m_leSuffixes); whats = i18n("A list of suffixes which might be used in personal names. Multiple values " "should be separated by a semi-colon."); TQWhatsThis::add(lab, whats); TQWhatsThis::add(m_leSuffixes, whats); connect(m_leSuffixes, TQT_SIGNAL(textChanged(const TQString&)), TQT_SLOT(slotModified())); lab = new TQLabel(i18n("Surname &prefixes:"), g1); m_lePrefixes = new KLineEdit(g1); lab->setBuddy(m_lePrefixes); whats = i18n("A list of prefixes which might be used in surnames. Multiple values " "should be separated by a semi-colon."); TQWhatsThis::add(lab, whats); TQWhatsThis::add(m_lePrefixes, whats); connect(m_lePrefixes, TQT_SIGNAL(textChanged(const TQString&)), TQT_SLOT(slotModified())); // stretch to fill lower area l->addStretch(1); } void ConfigDialog::setupPrintingPage() { // SuSE changed the icon name on me TQPixmap pix; KIconLoader* loader = KGlobal::iconLoader(); if(loader) { pix = loader->loadIcon(TQString::tqfromLatin1("printer1"), KIcon::Desktop, KIcon::SizeMedium, KIcon::DefaultState, 0, true /*canReturnNull */); if(pix.isNull()) { pix = loader->loadIcon(TQString::tqfromLatin1("printer2"), KIcon::Desktop, KIcon::SizeMedium, KIcon::DefaultState, 0, true /*canReturnNull */); } if(pix.isNull()) { pix = loader->loadIcon(TQString::tqfromLatin1("print_printer"), KIcon::Desktop, KIcon::SizeMedium); } } TQFrame* frame = addPage(i18n("Printing"), i18n("Printing Options"), pix); TQVBoxLayout* l = new TQVBoxLayout(frame, KDialog::marginHint(), KDialog::spacingHint()); TQVGroupBox* formatOptions = new TQVGroupBox(i18n("Formatting Options"), frame); l->addWidget(formatOptions); m_cbPrintFormatted = new TQCheckBox(i18n("&Format titles and names"), formatOptions); TQWhatsThis::add(m_cbPrintFormatted, i18n("If checked, titles and names will be automatically formatted.")); connect(m_cbPrintFormatted, TQT_SIGNAL(clicked()), TQT_SLOT(slotModified())); m_cbPrintHeaders = new TQCheckBox(i18n("&Print field headers"), formatOptions); TQWhatsThis::add(m_cbPrintHeaders, i18n("If checked, the field names will be printed as table headers.")); connect(m_cbPrintHeaders, TQT_SIGNAL(clicked()), TQT_SLOT(slotModified())); TQHGroupBox* groupOptions = new TQHGroupBox(i18n("Grouping Options"), frame); l->addWidget(groupOptions); m_cbPrintGrouped = new TQCheckBox(i18n("&Group the entries"), groupOptions); TQWhatsThis::add(m_cbPrintGrouped, i18n("If checked, the entries will be grouped by the selected field.")); connect(m_cbPrintGrouped, TQT_SIGNAL(clicked()), TQT_SLOT(slotModified())); TQVGroupBox* imageOptions = new TQVGroupBox(i18n("Image Options"), frame); l->addWidget(imageOptions); TQGrid* grid = new TQGrid(3, imageOptions); grid->setSpacing(5); TQLabel* lab = new TQLabel(i18n("Maximum image &width:"), grid); m_imageWidthBox = new KIntSpinBox(0, 999, 1, 50, 10, grid); m_imageWidthBox->setSuffix(TQString::tqfromLatin1(" px")); lab->setBuddy(m_imageWidthBox); (void) new TQWidget(grid); TQString whats = i18n("The maximum width of the images in the printout. The aspect ration is preserved."); TQWhatsThis::add(lab, whats); TQWhatsThis::add(m_imageWidthBox, whats); connect(m_imageWidthBox, TQT_SIGNAL(valueChanged(int)), TQT_SLOT(slotModified())); // TQSpinBox doesn't emit valueChanged if you edit the value with // the lineEdit until you change the keyboard focus connect(m_imageWidthBox->child("qt_spinbox_edit"), TQT_SIGNAL(textChanged(const TQString&)), TQT_SLOT(slotModified())); lab = new TQLabel(i18n("&Maximum image height:"), grid); m_imageHeightBox = new KIntSpinBox(0, 999, 1, 50, 10, grid); m_imageHeightBox->setSuffix(TQString::tqfromLatin1(" px")); lab->setBuddy(m_imageHeightBox); (void) new TQWidget(grid); whats = i18n("The maximum height of the images in the printout. The aspect ration is preserved."); TQWhatsThis::add(lab, whats); TQWhatsThis::add(m_imageHeightBox, whats); connect(m_imageHeightBox, TQT_SIGNAL(valueChanged(int)), TQT_SLOT(slotModified())); // TQSpinBox doesn't emit valueChanged if you edit the value with // the lineEdit until you change the keyboard focus connect(m_imageHeightBox->child("qt_spinbox_edit"), TQT_SIGNAL(textChanged(const TQString&)), TQT_SLOT(slotModified())); // stretch to fill lower area l->addStretch(1); } void ConfigDialog::setupTemplatePage() { TQPixmap pix = DesktopIcon(TQString::tqfromLatin1("looknfeel"), KIcon::SizeMedium); TQFrame* frame = addPage(i18n("Templates"), i18n("Template Options"), pix); TQVBoxLayout* l = new TQVBoxLayout(frame, KDialog::marginHint(), KDialog::spacingHint()); TQGridLayout* gridLayout = new TQGridLayout(l); gridLayout->setSpacing(KDialogBase::spacingHint()); int row = -1; // so I can reuse an i18n string, a plain label can't have an '&' TQLabel* lab = new TQLabel(i18n("Collection &type:").remove('&'), frame); gridLayout->addWidget(lab, ++row, 0); const int collType = Kernel::self()->collectionType(); lab = new TQLabel(CollectionFactory::nameMap()[collType], frame); gridLayout->addMultiCellWidget(lab, row, row, 1, 2); lab = new TQLabel(i18n("Template:"), frame); m_templateCombo = new GUI::ComboBox(frame); connect(m_templateCombo, TQT_SIGNAL(activated(int)), TQT_SLOT(slotModified())); lab->setBuddy(m_templateCombo); TQString whats = i18n("Select the template to use for the current type of collections. " "Not all templates will use the font and color settings."); TQWhatsThis::add(lab, whats); TQWhatsThis::add(m_templateCombo, whats); gridLayout->addWidget(lab, ++row, 0); gridLayout->addWidget(m_templateCombo, row, 1); KPushButton* btn = new KPushButton(i18n("&Preview..."), frame); TQWhatsThis::add(btn, i18n("Show a preview of the template")); btn->setIconSet(SmallIconSet(TQString::tqfromLatin1("viewmag"))); gridLayout->addWidget(btn, row, 2); connect(btn, TQT_SIGNAL(clicked()), TQT_SLOT(slotShowTemplatePreview())); // so the button is squeezed small gridLayout->setColStretch(0, 10); gridLayout->setColStretch(1, 10); loadTemplateList(); // TQLabel* l1 = new TQLabel(i18n("The options below will be passed to the template, but not " // "all templates will use them. Some fonts and colors may be " // "specified directly in the template."), frame); // l1->setTextFormat(TQt::RichText); // l->addWidget(l1); TQGroupBox* fontGroup = new TQGroupBox(0, Qt::Vertical, i18n("Font Options"), frame); l->addWidget(fontGroup); row = -1; TQGridLayout* fontLayout = new TQGridLayout(fontGroup->tqlayout()); fontLayout->setSpacing(KDialogBase::spacingHint()); lab = new TQLabel(i18n("Font:"), fontGroup); fontLayout->addWidget(lab, ++row, 0); m_fontCombo = new KFontCombo(fontGroup); fontLayout->addWidget(m_fontCombo, row, 1); connect(m_fontCombo, TQT_SIGNAL(activated(int)), TQT_SLOT(slotModified())); lab->setBuddy(m_fontCombo); whats = i18n("This font is passed to the template used in the Entry View."); TQWhatsThis::add(lab, whats); TQWhatsThis::add(m_fontCombo, whats); fontLayout->addWidget(new TQLabel(i18n("Size:"), fontGroup), ++row, 0); m_fontSizeInput = new KIntNumInput(fontGroup); m_fontSizeInput->setRange(5, 30); // 30 is same max as konq config m_fontSizeInput->setSuffix(TQString::tqfromLatin1("pt")); fontLayout->addWidget(m_fontSizeInput, row, 1); connect(m_fontSizeInput, TQT_SIGNAL(valueChanged(int)), TQT_SLOT(slotModified())); lab->setBuddy(m_fontSizeInput); TQWhatsThis::add(lab, whats); TQWhatsThis::add(m_fontSizeInput, whats); TQGroupBox* colGroup = new TQGroupBox(0, Qt::Vertical, i18n("Color Options"), frame); l->addWidget(colGroup); row = -1; TQGridLayout* colLayout = new TQGridLayout(colGroup->tqlayout()); colLayout->setSpacing(KDialogBase::spacingHint()); lab = new TQLabel(i18n("Background color:"), colGroup); colLayout->addWidget(lab, ++row, 0); m_baseColorCombo = new KColorCombo(colGroup); colLayout->addWidget(m_baseColorCombo, row, 1); connect(m_baseColorCombo, TQT_SIGNAL(activated(int)), TQT_SLOT(slotModified())); lab->setBuddy(m_baseColorCombo); whats = i18n("This color is passed to the template used in the Entry View."); TQWhatsThis::add(lab, whats); TQWhatsThis::add(m_baseColorCombo, whats); lab = new TQLabel(i18n("Text color:"), colGroup); colLayout->addWidget(lab, ++row, 0); m_textColorCombo = new KColorCombo(colGroup); colLayout->addWidget(m_textColorCombo, row, 1); connect(m_textColorCombo, TQT_SIGNAL(activated(int)), TQT_SLOT(slotModified())); lab->setBuddy(m_textColorCombo); TQWhatsThis::add(lab, whats); TQWhatsThis::add(m_textColorCombo, whats); lab = new TQLabel(i18n("Highlight color:"), colGroup); colLayout->addWidget(lab, ++row, 0); m_highBaseColorCombo = new KColorCombo(colGroup); colLayout->addWidget(m_highBaseColorCombo, row, 1); connect(m_highBaseColorCombo, TQT_SIGNAL(activated(int)), TQT_SLOT(slotModified())); lab->setBuddy(m_highBaseColorCombo); TQWhatsThis::add(lab, whats); TQWhatsThis::add(m_highBaseColorCombo, whats); lab = new TQLabel(i18n("Highlighted text color:"), colGroup); colLayout->addWidget(lab, ++row, 0); m_highTextColorCombo = new KColorCombo(colGroup); colLayout->addWidget(m_highTextColorCombo, row, 1); connect(m_highTextColorCombo, TQT_SIGNAL(activated(int)), TQT_SLOT(slotModified())); lab->setBuddy(m_highTextColorCombo); TQWhatsThis::add(lab, whats); TQWhatsThis::add(m_highTextColorCombo, whats); TQVGroupBox* groupBox = new TQVGroupBox(i18n("Manage Templates"), frame); l->addWidget(groupBox); TQHBox* box1 = new TQHBox(groupBox); box1->setSpacing(KDialog::spacingHint()); KPushButton* b1 = new KPushButton(i18n("Install..."), box1); b1->setIconSet(SmallIconSet(TQString::tqfromLatin1("add"))); connect(b1, TQT_SIGNAL(clicked()), TQT_SLOT(slotInstallTemplate())); whats = i18n("Click to install a new template directly."); TQWhatsThis::add(b1, whats); KPushButton* b2 = new KPushButton(i18n("Download..."), box1); b2->setIconSet(SmallIconSet(TQString::tqfromLatin1("knewstuff"))); connect(b2, TQT_SIGNAL(clicked()), TQT_SLOT(slotDownloadTemplate())); whats = i18n("Click to download additional templates via the Internet."); TQWhatsThis::add(b2, whats); KPushButton* b3 = new KPushButton(i18n("Delete..."), box1); b3->setIconSet(SmallIconSet(TQString::tqfromLatin1("remove"))); connect(b3, TQT_SIGNAL(clicked()), TQT_SLOT(slotDeleteTemplate())); whats = i18n("Click to select and remove installed templates."); TQWhatsThis::add(b3, whats); // stretch to fill lower area l->addStretch(1); KAcceleratorManager::manage(frame); } void ConfigDialog::setupFetchPage() { TQPixmap pix = DesktopIcon(TQString::tqfromLatin1("network"), KIcon::SizeMedium); TQFrame* frame = addPage(i18n("Data Sources"), i18n("Data Source Options"), pix); TQHBoxLayout* l = new TQHBoxLayout(frame, KDialog::marginHint(), KDialog::spacingHint()); TQVBoxLayout* leftLayout = new TQVBoxLayout(l); m_sourceListView = new KListView(frame); m_sourceListView->addColumn(i18n("Source")); m_sourceListView->setResizeMode(TQListView::LastColumn); m_sourceListView->setSorting(-1); // no sorting m_sourceListView->setSelectionMode(TQListView::Single); leftLayout->addWidget(m_sourceListView, 1); connect(m_sourceListView, TQT_SIGNAL(selectionChanged(TQListViewItem*)), TQT_SLOT(slotSelectedSourceChanged(TQListViewItem*))); connect(m_sourceListView, TQT_SIGNAL(doubleClicked(TQListViewItem*, const TQPoint&, int)), TQT_SLOT(slotModifySourceClicked())); TQHBox* hb = new TQHBox(frame); leftLayout->addWidget(hb); hb->setSpacing(KDialog::spacingHint()); m_moveUpSourceBtn = new KPushButton(i18n("Move &Up"), hb); m_moveUpSourceBtn->setIconSet(SmallIconSet(TQString::tqfromLatin1("up"))); TQWhatsThis::add(m_moveUpSourceBtn, i18n("The order of the data sources sets the order " "that Tellico uses when entries are automatically updated.")); m_moveDownSourceBtn = new KPushButton(i18n("Move &Down"), hb); m_moveDownSourceBtn->setIconSet(SmallIconSet(TQString::tqfromLatin1("down"))); TQWhatsThis::add(m_moveDownSourceBtn, i18n("The order of the data sources sets the order " "that Tellico uses when entries are automatically updated.")); // these icons are rather arbitrary, but seem to vaguely fit TQVBoxLayout* vlay = new TQVBoxLayout(l); KPushButton* newSourceBtn = new KPushButton(i18n("&New..."), frame); newSourceBtn->setIconSet(SmallIconSet(TQString::tqfromLatin1("filenew"))); TQWhatsThis::add(newSourceBtn, i18n("Click to add a new data source.")); m_modifySourceBtn = new KPushButton(i18n("&Modify..."), frame); m_modifySourceBtn->setIconSet(SmallIconSet(TQString::tqfromLatin1("network"))); TQWhatsThis::add(m_modifySourceBtn, i18n("Click to modify the selected data source.")); m_removeSourceBtn = new KPushButton(i18n("&Delete"), frame); m_removeSourceBtn->setIconSet(SmallIconSet(TQString::tqfromLatin1("remove"))); TQWhatsThis::add(m_removeSourceBtn, i18n("Click to delete the selected data source.")); m_newStuffBtn = new KPushButton(i18n("Download..."), frame); m_newStuffBtn->setIconSet(SmallIconSet(TQString::tqfromLatin1("knewstuff"))); TQWhatsThis::add(m_newStuffBtn, i18n("Click to download additional data sources via the Internet.")); #if !KDE_IS_VERSION(3,3,90) // only available in KDE 3.4 and up m_newStuffBtn->setEnabled(false); #endif vlay->addWidget(newSourceBtn); vlay->addWidget(m_modifySourceBtn); vlay->addWidget(m_removeSourceBtn); // separate newstuff button from the rest vlay->addSpacing(2 * KDialog::spacingHint()); vlay->addWidget(m_newStuffBtn); vlay->addStretch(1); connect(newSourceBtn, TQT_SIGNAL(clicked()), TQT_SLOT(slotNewSourceClicked())); connect(m_modifySourceBtn, TQT_SIGNAL(clicked()), TQT_SLOT(slotModifySourceClicked())); connect(m_moveUpSourceBtn, TQT_SIGNAL(clicked()), TQT_SLOT(slotMoveUpSourceClicked())); connect(m_moveDownSourceBtn, TQT_SIGNAL(clicked()), TQT_SLOT(slotMoveDownSourceClicked())); connect(m_removeSourceBtn, TQT_SIGNAL(clicked()), TQT_SLOT(slotRemoveSourceClicked())); connect(m_newStuffBtn, TQT_SIGNAL(clicked()), TQT_SLOT(slotNewStuffClicked())); KAcceleratorManager::manage(frame); } void ConfigDialog::readConfiguration() { m_modifying = true; readGeneralConfig(); readPrintingConfig(); readTemplateConfig(); readFetchConfig(); m_modifying = false; } void ConfigDialog::readGeneralConfig() { m_cbShowTipDay->setChecked(Config::showTipOfDay()); m_cbOpenLastFile->setChecked(Config::reopenLastFile()); switch(Config::imageLocation()) { case Config::ImagesInFile: m_rbImageInFile->setChecked(true); break; case Config::ImagesInAppDir: m_rbImageInAppDir->setChecked(true); break; case Config::ImagesInLocalDir: m_rbImageInLocalDir->setChecked(true); break; } bool autoCapitals = Config::autoCapitalization(); m_cbCapitalize->setChecked(autoCapitals); bool autoFormat = Config::autoFormat(); m_cbFormat->setChecked(autoFormat); const TQRegExp comma(TQString::tqfromLatin1("\\s*,\\s*")); const TQString semicolon = TQString::tqfromLatin1("; "); m_leCapitals->setText(Config::noCapitalizationString().replace(comma, semicolon)); m_leArticles->setText(Config::articlesString().replace(comma, semicolon)); m_leSuffixes->setText(Config::nameSuffixesString().replace(comma, semicolon)); m_lePrefixes->setText(Config::surnamePrefixesString().replace(comma, semicolon)); } void ConfigDialog::readPrintingConfig() { m_cbPrintHeaders->setChecked(Config::printFieldHeaders()); m_cbPrintFormatted->setChecked(Config::printFormatted()); m_cbPrintGrouped->setChecked(Config::printGrouped()); m_imageWidthBox->setValue(Config::maxImageWidth()); m_imageHeightBox->setValue(Config::maxImageHeight()); } void ConfigDialog::readTemplateConfig() { // entry template selection const int collType = Kernel::self()->collectionType(); TQString file = Config::templateName(collType); file.replace('_', ' '); TQString fileContext = file + TQString::tqfromLatin1(" XSL Template"); m_templateCombo->setCurrentItem(i18n(fileContext.utf8(), file.utf8())); m_fontCombo->setCurrentFont(Config::templateFont(collType).family()); m_fontSizeInput->setValue(Config::templateFont(collType).pointSize()); m_baseColorCombo->setColor(Config::templateBaseColor(collType)); m_textColorCombo->setColor(Config::templateTextColor(collType)); m_highBaseColorCombo->setColor(Config::templateHighlightedBaseColor(collType)); m_highTextColorCombo->setColor(Config::templateHighlightedTextColor(collType)); } void ConfigDialog::readFetchConfig() { m_sourceListView->clear(); m_configWidgets.clear(); Fetch::FetcherVec fetchers = Fetch::Manager::self()->fetchers(); for(Fetch::FetcherVec::Iterator it = fetchers.begin(); it != fetchers.end(); ++it) { GeneralFetcherInfo info(it->type(), it->source(), it->updateOverwrite()); SourceListViewItem* item = new SourceListViewItem(m_sourceListView, m_sourceListView->lastItem(), info); item->setFetcher(it.data()); // grab the config widget, taking ownership Fetch::ConfigWidget* cw = it->configWidget(this); if(cw) { // might return 0 when no widget available for fetcher type m_configWidgets.insert(item, cw); // there's weird tqlayout bug if it's not hidden cw->hide(); } kapp->processEvents(); } if(m_sourceListView->childCount() == 0) { m_modifySourceBtn->setEnabled(false); m_removeSourceBtn->setEnabled(false); } else { // go ahead and select the first one m_sourceListView->setSelected(m_sourceListView->firstChild(), true); } } void ConfigDialog::saveConfiguration() { Config::setShowTipOfDay(m_cbShowTipDay->isChecked()); int imageLocation; if(m_rbImageInFile->isChecked()) { imageLocation = Config::ImagesInFile; } else if(m_rbImageInAppDir->isChecked()) { imageLocation = Config::ImagesInAppDir; } else { imageLocation = Config::ImagesInLocalDir; } Config::setImageLocation(imageLocation); Config::setReopenLastFile(m_cbOpenLastFile->isChecked()); Config::setAutoCapitalization(m_cbCapitalize->isChecked()); Config::setAutoFormat(m_cbFormat->isChecked()); const TQRegExp semicolon(TQString::tqfromLatin1("\\s*;\\s*")); const TQChar comma = ','; Config::setNoCapitalizationString(m_leCapitals->text().replace(semicolon, comma)); Config::setArticlesString(m_leArticles->text().replace(semicolon, comma)); Data::Field::articlesUpdated(); Config::setNameSuffixesString(m_leSuffixes->text().replace(semicolon, comma)); Config::setSurnamePrefixesString(m_lePrefixes->text().replace(semicolon, comma)); Config::setPrintFieldHeaders(m_cbPrintHeaders->isChecked()); Config::setPrintFormatted(m_cbPrintFormatted->isChecked()); Config::setPrintGrouped(m_cbPrintGrouped->isChecked()); Config::setMaxImageWidth(m_imageWidthBox->value()); Config::setMaxImageHeight(m_imageHeightBox->value()); // entry template selection const int collType = Kernel::self()->collectionType(); Config::setTemplateName(collType, m_templateCombo->currentData().toString()); TQFont font(m_fontCombo->currentFont(), m_fontSizeInput->value()); Config::setTemplateFont(collType, font); Config::setTemplateBaseColor(collType, m_baseColorCombo->color()); Config::setTemplateTextColor(collType, m_textColorCombo->color()); Config::setTemplateHighlightedBaseColor(collType, m_highBaseColorCombo->color()); Config::setTemplateHighlightedTextColor(collType, m_highTextColorCombo->color()); // first, tell config widgets they got deleted for(TQPtrListIterator it(m_removedConfigWidgets); it.current(); ++it) { it.current()->removed(); } m_removedConfigWidgets.clear(); KConfig* masterConfig = KGlobal::config(); bool reloadFetchers = false; int count = 0; // start group numbering at 0 for(TQListViewItemIterator it(m_sourceListView); it.current(); ++it, ++count) { SourceListViewItem* item = static_cast(it.current()); Fetch::ConfigWidget* cw = m_configWidgets[item]; if(!cw || (!cw->shouldSave() && !item->isNewSource())) { continue; } m_newStuffConfigWidgets.removeRef(cw); TQString group = TQString::tqfromLatin1("Data Source %1").tqarg(count); // in case we later change the order, clear the group now masterConfig->deleteGroup(group); KConfigGroup configGroup(masterConfig, group); configGroup.writeEntry("Name", item->text(0)); configGroup.writeEntry("Type", item->fetchType()); configGroup.writeEntry("UpdateOverwrite", item->updateOverwrite()); cw->saveConfig(configGroup); item->setNewSource(false); // in case the ordering changed item->setConfigGroup(group); reloadFetchers = true; } // now update total number of sources KConfigGroup sourceGroup(masterConfig, "Data Sources"); sourceGroup.writeEntry("Sources Count", count); // and purge old config groups TQString group = TQString::tqfromLatin1("Data Source %1").tqarg(count); while(masterConfig->hasGroup(group)) { masterConfig->deleteGroup(group); ++count; group = TQString::tqfromLatin1("Data Source %1").tqarg(count); } masterConfig->sync(); Config::writeConfig(); TQString s = m_sourceListView->selectedItem() ? m_sourceListView->selectedItem()->text(0) : TQString(); if(reloadFetchers) { Fetch::Manager::self()->loadFetchers(); Controller::self()->updatedFetchers(); // reload fetcher items if OK was not clicked // meaning apply was clicked if(!m_okClicked) { readFetchConfig(); if(!s.isEmpty()) { for(TQListViewItemIterator it(m_sourceListView); it.current(); ++it) { if(it.current()->text(0) == s) { m_sourceListView->setSelected(it.current(), true); m_sourceListView->ensureItemVisible(it.current()); break; } } } } } } void ConfigDialog::slotModified() { if(m_modifying) { return; } enableButtonOK(true); enableButtonApply(true); } void ConfigDialog::slotNewSourceClicked() { FetcherConfigDialog dlg(this); if(dlg.exec() != TQDialog::Accepted) { return; } Fetch::Type type = dlg.sourceType(); if(type == Fetch::Unknown) { return; } GeneralFetcherInfo info(type, dlg.sourceName(), dlg.updateOverwrite()); SourceListViewItem* item = new SourceListViewItem(m_sourceListView, m_sourceListView->lastItem(), info); m_sourceListView->ensureItemVisible(item); m_sourceListView->setSelected(item, true); Fetch::ConfigWidget* cw = dlg.configWidget(); if(cw) { cw->setAccepted(true); cw->slotSetModified(); cw->reparent(this, TQPoint()); // keep the config widget around m_configWidgets.insert(item, cw); } m_modifySourceBtn->setEnabled(true); m_removeSourceBtn->setEnabled(true); slotModified(); // toggle apply button } void ConfigDialog::slotModifySourceClicked() { SourceListViewItem* item = static_cast(m_sourceListView->selectedItem()); if(!item) { return; } Fetch::ConfigWidget* cw = 0; if(m_configWidgets.contains(item)) { cw = m_configWidgets[item]; } if(!cw) { // no config widget for this one // might be because support was compiled out myDebug() << "ConfigDialog::slotModifySourceClicked() - no config widget for source " << item->text(0) << endl; return; } FetcherConfigDialog dlg(item->text(0), item->fetchType(), item->updateOverwrite(), cw, this); if(dlg.exec() == TQDialog::Accepted) { cw->setAccepted(true); // mark to save TQString newName = dlg.sourceName(); if(newName != item->text(0)) { item->setText(0, newName); cw->slotSetModified(); } item->setUpdateOverwrite(dlg.updateOverwrite()); slotModified(); // toggle apply button } cw->reparent(this, TQPoint()); // keep the config widget around } void ConfigDialog::slotRemoveSourceClicked() { SourceListViewItem* item = static_cast(m_sourceListView->selectedItem()); if(!item) { return; } Fetch::ConfigWidget* cw = m_configWidgets[item]; if(cw) { m_removedConfigWidgets.append(cw); // it gets deleted by the parent } m_configWidgets.remove(item); delete item; m_sourceListView->setSelected(m_sourceListView->currentItem(), true); slotModified(); // toggle apply button } void ConfigDialog::slotMoveUpSourceClicked() { TQListViewItem* item = m_sourceListView->selectedItem(); if(!item) { return; } SourceListViewItem* prev = static_cast(item->itemAbove()); // could be 0 if(prev) { GeneralFetcherInfo info(prev->fetchType(), prev->text(0), prev->updateOverwrite()); SourceListViewItem* newItem = new SourceListViewItem(m_sourceListView, item, info, prev->configGroup()); newItem->setFetcher(prev->fetcher()); Fetch::ConfigWidget* cw = m_configWidgets[prev]; m_configWidgets.remove(prev); m_configWidgets.insert(newItem, cw); delete prev; slotModified(); // toggle apply button slotSelectedSourceChanged(item); } } void ConfigDialog::slotMoveDownSourceClicked() { SourceListViewItem* item = static_cast(m_sourceListView->selectedItem()); if(!item) { return; } TQListViewItem* next = item->nextSibling(); // could be 0 if(next) { GeneralFetcherInfo info(item->fetchType(), item->text(0), item->updateOverwrite()); SourceListViewItem* newItem = new SourceListViewItem(m_sourceListView, next, info, item->configGroup()); newItem->setFetcher(item->fetcher()); Fetch::ConfigWidget* cw = m_configWidgets[item]; m_configWidgets.remove(item); m_configWidgets.insert(newItem, cw); delete item; slotModified(); // toggle apply button m_sourceListView->setSelected(newItem, true); } } void ConfigDialog::slotSelectedSourceChanged(TQListViewItem* item_) { m_moveUpSourceBtn->setEnabled(item_ && item_->itemAbove()); m_moveDownSourceBtn->setEnabled(item_ && item_->nextSibling()); } void ConfigDialog::slotNewStuffClicked() { NewStuff::Dialog dlg(NewStuff::DataScript, this); dlg.exec(); TQPtrList infoList = dlg.dataSourceInfo(); for(TQPtrListIterator it(infoList); it.current(); ++it) { const NewStuff::DataSourceInfo& info = *it.current(); Fetch::ExecExternalFetcher::ConfigWidget* cw = 0; SourceListViewItem* item = 0; // yes, this is checking if item exists if(info.isUpdate && (item = findItem(info.sourceExec))) { m_sourceListView->setSelected(item, true); cw = dynamic_cast(m_configWidgets[item]); } else { cw = new Fetch::ExecExternalFetcher::ConfigWidget(this); m_newStuffConfigWidgets.append(cw); GeneralFetcherInfo fetchInfo(Fetch::ExecExternal, info.sourceName, false); item = new SourceListViewItem(m_sourceListView, m_sourceListView->lastItem(), fetchInfo); m_configWidgets.insert(item, cw); } if(!cw) { continue; } KConfig spec(info.specFile, false, false); cw->readConfig(&spec); cw->slotSetModified(); cw->setAccepted(true); if(item) { m_sourceListView->setSelected(item, true); m_sourceListView->ensureItemVisible(item); } } if(infoList.count() > 0) { m_modifySourceBtn->setEnabled(true); m_removeSourceBtn->setEnabled(true); slotModified(); // toggle apply button } } Tellico::SourceListViewItem* ConfigDialog::findItem(const TQString& path_) const { if(path_.isEmpty()) { kdWarning() << "ConfigDialog::findItem() - empty path" << endl; return 0; } // this is a bit ugly, loop over all items, find the execexternal one // that matches the path for(TQListViewItemIterator it(m_sourceListView); it.current(); ++it) { SourceListViewItem* item = static_cast(it.current()); if(item->fetchType() != Fetch::ExecExternal) { continue; } Fetch::ExecExternalFetcher* f = dynamic_cast(item->fetcher().data()); if(f && f->execPath() == path_) { return item; } } myDebug() << "ConfigDialog::findItem() - no matching item found" << endl; return 0; } void ConfigDialog::slotShowTemplatePreview() { GUI::PreviewDialog* dlg = new GUI::PreviewDialog(this); const TQString templateName = m_templateCombo->currentData().toString(); dlg->setXSLTFile(templateName + TQString::tqfromLatin1(".xsl")); StyleOptions options; options.fontFamily = m_fontCombo->currentFont(); options.fontSize = m_fontSizeInput->value(); options.baseColor = m_baseColorCombo->color(); options.textColor = m_textColorCombo->color(); options.highlightedTextColor = m_highTextColorCombo->color(); options.highlightedBaseColor = m_highBaseColorCombo->color(); dlg->setXSLTOptions(options); Data::CollPtr c = CollectionFactory::collection(Kernel::self()->collectionType(), true); Data::EntryPtr e = new Data::Entry(c); for(Data::FieldVec::ConstIterator f = c->fields().begin(); f != c->fields().end(); ++f) { if(f->name() == Latin1Literal("title")) { e->setField(f->name(), m_templateCombo->currentText()); } else if(f->type() == Data::Field::Image) { continue; } else if(f->type() == Data::Field::Choice) { e->setField(f->name(), f->allowed().front()); } else if(f->type() == Data::Field::Number) { e->setField(f->name(), TQString::tqfromLatin1("1")); } else if(f->type() == Data::Field::Bool) { e->setField(f->name(), TQString::tqfromLatin1("true")); } else if(f->type() == Data::Field::Rating) { e->setField(f->name(), TQString::tqfromLatin1("5")); } else { e->setField(f->name(), f->title()); } } dlg->showEntry(e); dlg->show(); // dlg gets deleted by itself // the finished() signal is connected in its constructor to delayedDestruct } void ConfigDialog::loadTemplateList() { TQStringList files = KGlobal::dirs()->findAllResources("appdata", TQString::tqfromLatin1("entry-templates/*.xsl"), false, true); KSortableValueList templates; for(TQStringList::ConstIterator it = files.begin(); it != files.end(); ++it) { TQFileInfo fi(*it); TQString file = fi.fileName().section('.', 0, -2); TQString name = file; name.replace('_', ' '); TQString title = i18n((name + TQString::tqfromLatin1(" XSL Template")).utf8(), name.utf8()); templates.insert(title, file); } templates.sort(); TQString s = m_templateCombo->currentText(); m_templateCombo->clear(); for(KSortableValueList::iterator it2 = templates.begin(); it2 != templates.end(); ++it2) { m_templateCombo->insertItem((*it2).index(), (*it2).value()); } m_templateCombo->setCurrentItem(s); } void ConfigDialog::slotInstallTemplate() { TQString filter = i18n("*.xsl|XSL Files (*.xsl)") + '\n'; filter += i18n("*.tar.gz *.tgz|Template Packages (*.tar.gz)") + '\n'; filter += i18n("*|All Files"); KURL u = KFileDialog::getOpenURL(TQString(), filter, this); if(u.isEmpty() || !u.isValid()) { return; } NewStuff::Manager man(TQT_TQOBJECT(this)); if(man.installTemplate(u)) { loadTemplateList(); } } void ConfigDialog::slotDownloadTemplate() { NewStuff::Dialog dlg(NewStuff::EntryTemplate, this); dlg.exec(); loadTemplateList(); } void ConfigDialog::slotDeleteTemplate() { TQDir dir(Tellico::saveLocation(TQString::tqfromLatin1("entry-templates/"))); dir.setNameFilter(TQString::tqfromLatin1("*.xsl")); dir.setFilter(TQDir::Files | TQDir::Writable); TQStringList files = dir.entryList(); TQMap nameFileMap; for(TQStringList::Iterator it = files.begin(); it != files.end(); ++it) { (*it).truncate((*it).length()-4); // remove ".xsl" TQString name = (*it); name.replace('_', ' '); nameFileMap.insert(name, *it); } bool ok; TQString name = KInputDialog::getItem(i18n("Delete Template"), i18n("Select template to delete:"), nameFileMap.keys(), 0, false, &ok, this); if(ok && !name.isEmpty()) { TQString file = nameFileMap[name]; NewStuff::Manager man(TQT_TQOBJECT(this)); man.removeTemplate(file); loadTemplateList(); } } #include "configdialog.moc"