// Copyright (c) 2003 Charles Samuels // See the file COPYING for redistribution terms. #include "cmodule.h" #include "oblique.h" #include "file.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include SchemaConfig::SchemaConfig(TQWidget *parent, Oblique *oblique) : TQWidget(parent) { mOblique = oblique; mIgnore = true; mRegexpEditor=0; { TQVBoxLayout *layout = new TQVBoxLayout(this, 11, 7); layout->setAutoAdd(true); layout->setSpacing(7); } { TQHBox *box = new TQHBox(this); box->setSpacing(7); mSchemaList = new TQComboBox(box); connect( mSchemaList, TQT_SIGNAL(activated(const TQString&)), TQT_SLOT(selectSchema(const TQString&)) ); mAdd = new TQPushButton(BarIconSet("filenew"), 0, box); mAdd->setFixedWidth(mAdd->height()); TQToolTip::add(mAdd, i18n("Create new schema")); connect(mAdd, TQT_SIGNAL(clicked()), TQT_SLOT(newSchema())); mRemove = new TQPushButton(BarIconSet("editdelete"), 0, box); mRemove->setFixedWidth(mRemove->height()); TQToolTip::add(mRemove, i18n("Remove this schema")); connect(mRemove, TQT_SIGNAL(clicked()), TQT_SLOT(removeSchema())); mCopy = new TQPushButton(BarIconSet("editcopy"), 0, box); mCopy->setFixedWidth(mCopy->height()); TQToolTip::add(mCopy, i18n("Copy this schema")); connect(mCopy, TQT_SIGNAL(clicked()), TQT_SLOT(copySchema())); } { TQHBox *middle = new TQHBox(this); middle->setSpacing(7); mSchemaTree = new KListView(middle); connect( mSchemaTree, TQT_SIGNAL(currentChanged(TQListViewItem*)), TQT_SLOT(setCurrent(TQListViewItem*)) ); connect( mSchemaTree, TQT_SIGNAL(moved(TQListViewItem *, TQListViewItem *, TQListViewItem *)), TQT_SLOT(move(TQListViewItem *, TQListViewItem *, TQListViewItem *)) ); mSchemaTree->setAcceptDrops(true); mSchemaTree->setSorting(-1); mSchemaTree->setDropVisualizer(true); mSchemaTree->setDragEnabled(true); mSchemaTree->setItemsMovable(true); mSchemaTree->addColumn(i18n("Property")); mSchemaTree->addColumn(i18n("Value")); mSchemaTree->addColumn(i18n("Presentation")); TQVBox *buttons = new TQVBox(middle); mAddSibling = new TQPushButton(BarIconSet("1rightarrow", KIcon::SizeSmall), "",buttons); mAddSibling->setFixedWidth(mAddSibling->height()); connect(mAddSibling, TQT_SIGNAL(clicked()), TQT_SLOT(addSibling())); TQToolTip::add(mAddSibling, i18n("Create a new item after the selected one")); mAddChild = new TQPushButton(BarIconSet("2rightarrow", KIcon::SizeSmall), "", buttons); mAddChild->setFixedWidth(mAddChild->height()); connect(mAddChild, TQT_SIGNAL(clicked()), TQT_SLOT(addChild())); TQToolTip::add(mAddChild, i18n("Create a new child item under the selected one")); mRemoveSelf = new TQPushButton(BarIconSet("filenew", KIcon::SizeSmall), "", buttons); mRemoveSelf->setFixedWidth(mRemoveSelf->height()); connect(mRemoveSelf, TQT_SIGNAL(clicked()), TQT_SLOT(removeSelf())); TQToolTip::add(mRemoveSelf, i18n("Remove the selected item")); new TQWidget(buttons); } { TQVBox *side = new TQVBox(this); side->setSpacing(7); // the controllers { TQWidget *topSide = new TQWidget(side); TQGridLayout *grid = new TQGridLayout(topSide); TQLabel *label; label = new TQLabel(i18n("&Property:"), topSide); mPropertyEdit = new KLineEdit(topSide); label->setBuddy(mPropertyEdit); grid->addWidget(label, 0, 0); grid->addMultiCellWidget(mPropertyEdit, 0, 0, 1, 2); connect(mPropertyEdit, TQT_SIGNAL(textChanged(const TQString&)), TQT_SLOT(updateCurrent())); label = new TQLabel(i18n("&Value:"), topSide); mValueEdit = new KLineEdit(topSide); label->setBuddy(mPropertyEdit); grid->addWidget(label, 1, 0); grid->addMultiCellWidget(mValueEdit, 1, 1, 1, 1); connect(mValueEdit, TQT_SIGNAL(textChanged(const TQString&)), TQT_SLOT(updateCurrent())); TQPushButton *editRe = new TQPushButton(i18n("&Edit..."), topSide); grid->addWidget(editRe, 1, 2); connect(editRe, TQT_SIGNAL(clicked()), TQT_SLOT(editValueRegexp())); label = new TQLabel(i18n("Pre&sentation:"), topSide); mPresentationEdit = new KLineEdit(topSide); label->setBuddy(mPropertyEdit); grid->addWidget(label, 2, 0); grid->addMultiCellWidget(mPresentationEdit, 2, 2, 1, 2); connect(mPresentationEdit, TQT_SIGNAL(textChanged(const TQString&)), TQT_SLOT(updateCurrent())); } { TQGroupBox *groupbox = new TQGroupBox( 3, Qt::Horizontal, i18n("Options"), side ); mOptionPlayable = new TQCheckBox(i18n("Play&able"), groupbox); TQWhatsThis::add(mOptionPlayable, i18n("This branch represents an individual file. If two items' presentation match, two items are created.")); connect(mOptionPlayable, TQT_SIGNAL(toggled(bool)), TQT_SLOT(updateCurrent())); mOptionChildrenVisible = new TQCheckBox(i18n("&Children visible"), groupbox); TQWhatsThis::add(mOptionChildrenVisible, i18n("Don't create this node, this nodes children become direct children of this node's parent")); connect(mOptionChildrenVisible, TQT_SIGNAL(toggled(bool)), TQT_SLOT(updateCurrent())); mOptionAutoOpen = new TQCheckBox(i18n("Auto &open"), groupbox); TQWhatsThis::add(mOptionAutoOpen, i18n("This branch is marked as open immediately.")); connect(mOptionAutoOpen, TQT_SIGNAL(toggled(bool)), TQT_SLOT(updateCurrent())); } } } class QueryGroupItem : public KListViewItem { QueryGroup *mItem; public: QueryGroupItem(QueryGroupItem *parent, QueryGroup *group, QueryGroupItem *after=0) : KListViewItem(parent, after) { init(group); } QueryGroupItem(KListView *parent, QueryGroup *group, QueryGroupItem *after=0) : KListViewItem(parent, after) { init(group); } QueryGroup *item() { return mItem; } const QueryGroup *item() const { return mItem; } void redisplay() { setText(0, item()->propertyName()); setText(1, item()->value().pattern()); setText(2, item()->presentation()); } QueryGroupItem *parent() { return static_cast(KListViewItem::parent()); } KListView *listView() { return static_cast(KListViewItem::listView()); } private: void init(QueryGroup *group) { mItem = group; redisplay(); if (group->firstChild()) new QueryGroupItem(this, group->firstChild(), this); // do siblings now iff I don't already have them if (!nextSibling()) { if (QueryGroup *after = group->nextSibling()) { if (parent()) new QueryGroupItem(parent(), after, this); else new QueryGroupItem(listView(), after, this); } } setOpen(true); } }; void SchemaConfig::reopen() { mSchemaList->clear(); mQueries.clear(); mSchemaTree->clear(); TQStringList names = oblique()->schemaNames(); TQString firstTitle; for (TQStringList::Iterator i(names.begin()); i != names.end(); ++i) { QueryItem qi; qi.title = oblique()->loadSchema(qi.query, *i); qi.changed = false; mQueries.insert(*i, qi); if (!mSchemaList->count()) firstTitle = qi.title; mSchemaList->insertItem(qi.title); } selectSchema(firstTitle); } void SchemaConfig::save() { for (TQMap::Iterator i(mQueries.begin()); i != mQueries.end(); ++i) { TQString name = i.key(); name = TQFileInfo(name).fileName(); if (i.data().changed) { oblique()->saveSchema(i.data().query, name, i.data().title); // TODO update the trees. } } } TQString SchemaConfig::nameToFilename(const TQString &_name) { TQString name = _name; name = name.replace(TQRegExp("[^a-zA-Z0-9]"), "_"); return name; } void SchemaConfig::newSchema() { bool ok; TQString str=KInputDialog::getText( i18n("Name of Schema"), i18n("Please enter the name of the new schema:"), "", &ok, this ); if (!ok) return; TQString filename = nameToFilename(str); if (mQueries.contains(nameToFilename(filename))) return; QueryItem queryitem; queryitem.query = Query(); queryitem.title = str; queryitem.changed=true; mSchemaList->insertItem(str); mQueries.insert(filename, queryitem); selectSchema(str); } void SchemaConfig::copySchema() { bool ok; TQString str=KInputDialog::getText( i18n("Name of Schema"), i18n("Please enter the name of the new schema:"), "", &ok, this ); if (!ok) return; TQString filename = nameToFilename(str); if (mQueries.contains(nameToFilename(filename))) return; QueryItem queryitem; queryitem.query = currentQuery()->query; queryitem.title = str; queryitem.changed=true; mSchemaList->insertItem(str); mQueries.insert(filename, queryitem); selectSchema(str); } void SchemaConfig::removeSchema() { QueryItem *item = currentQuery(); mSchemaList->removeItem(mSchemaList->currentItem()); oblique()->removeSchema(nameToFilename(item->title)); selectSchema(mSchemaList->currentText()); } void SchemaConfig::selectSchema(const TQString &title) { mSchemaTree->clear(); mSchemaList->setCurrentText(title); mIgnore = true; if (QueryItem *grp = currentQuery()) { if (QueryGroup *g = grp->query.firstChild()) new QueryGroupItem(mSchemaTree, g); } mSchemaTree->setCurrentItem(mSchemaTree->firstChild()); setCurrent(mSchemaTree->firstChild()); mSchemaTree->setSelected(mSchemaTree->firstChild(), true); mIgnore=false; } void SchemaConfig::editValueRegexp() { unless (mRegexpEditor) { mRegexpEditor = KParts::ComponentFactory::createInstanceFromQuery( "KRegExpEditor/KRegExpEditor", TQString(), TQT_TQOBJECT(this) ); } if ( mRegexpEditor ) { KRegExpEditorInterface *iface = static_cast( mRegexpEditor->tqt_cast( "KRegExpEditorInterface") ); iface->setRegExp(mValueEdit->text()); if (mRegexpEditor->exec() == TQDialog::Accepted) mValueEdit->setText(iface->regExp()); } } void SchemaConfig::setCurrent(TQListViewItem *_item) { if (!_item) return; QueryGroupItem *item = static_cast(_item); mIgnore = true; mPropertyEdit->setText(item->item()->propertyName()); mValueEdit->setText(item->item()->value().pattern()); mPresentationEdit->setText(item->item()->presentation()); mOptionPlayable->setChecked(item->item()->option(QueryGroup::Playable)); mOptionAutoOpen->setChecked(item->item()->option(QueryGroup::AutoOpen)); mOptionChildrenVisible->setChecked(item->item()->option(QueryGroup::ChildrenVisible)); mIgnore = false; } void SchemaConfig::updateCurrent() { QueryGroupItem *item = static_cast(mSchemaTree->currentItem()); if (mIgnore || !item) return; setCurrentModified(); QueryGroup *mod = item->item(); mod->setPropertyName(mPropertyEdit->text()); mod->setPresentation(mPresentationEdit->text()); mod->setValue(TQRegExp(mValueEdit->text())); mod->setOption(QueryGroup::AutoOpen, mOptionAutoOpen->isChecked()); mod->setOption(QueryGroup::Playable, mOptionPlayable->isChecked()); mod->setOption(QueryGroup::ChildrenVisible, mOptionChildrenVisible->isChecked()); item->redisplay(); } void SchemaConfig::move(TQListViewItem *_item, TQListViewItem *, TQListViewItem *_afterNow) { setCurrentModified(); QueryGroupItem *item = static_cast(_item); QueryGroupItem *afterNow = static_cast(_afterNow); QueryGroup *after, *under; under = item->parent() ? item->parent()->item() : 0; after = afterNow ? afterNow->item() : 0; item->item()->move(¤tQuery()->query, under, after); } void SchemaConfig::addSibling() { QueryGroupItem *item = static_cast(mSchemaTree->currentItem()); unless (item) { addChild(); return; } setCurrentModified(); // add it QueryGroup * g = new QueryGroup; item->item()->insertAfter(g); // now match the action in the tree QueryGroupItem *created; if (item->parent()) created = new QueryGroupItem(item->parent(), g, item); else created = new QueryGroupItem(item->listView(), g, item); // select it so the user can edit it now item->listView()->setCurrentItem(created); item->listView()->setSelected(created, true); } void SchemaConfig::addChild() { QueryGroupItem *item = static_cast(mSchemaTree->currentItem()); setCurrentModified(); // add it QueryGroup * g = new QueryGroup; if (item) item->item()->insertUnder(g); else currentQuery()->query.setFirstChild(g); // now match the action in the tree QueryGroupItem *created; if (item) created = new QueryGroupItem(item, g); else created = new QueryGroupItem(mSchemaTree, g); // select it so the user can edit it now mSchemaTree->setCurrentItem(created); mSchemaTree->setSelected(created, true); } void SchemaConfig::removeSelf() { setCurrentModified(); QueryGroupItem *item = static_cast(mSchemaTree->currentItem()); unless (item) return; QueryGroup *grp = item->item(); delete item; currentQuery()->query.take(grp); delete grp; } void SchemaConfig::setCurrentModified() { if (QueryItem *grp = currentQuery()) grp->changed = true; } SchemaConfig::QueryItem *SchemaConfig::currentQuery() { TQString title = mSchemaList->currentText(); for (TQMap::Iterator i(mQueries.begin()); i != mQueries.end(); ++i) { if (i.data().title != title) continue; return &i.data(); } return 0; } SliceConfig::SliceConfig(TQWidget *parent, Oblique *oblique) : TQWidget(parent) { mOblique = oblique; (new TQVBoxLayout(this, 11, 7))->setAutoAdd(true); { TQHBox *middle = new TQHBox(this); middle->setSpacing(7); mSliceList = new KListView(middle); TQWhatsThis::add(mSliceList, i18n("The list of slices. A Slice is part of the full collection. This allows you to categorize your playlist. You can add an item to the list by right clicking on it and selecting the Slice you want it in.")); mSliceList->addColumn(""); mSliceList->header()->hide(); mSliceList->setSorting(0); mSliceList->setItemsRenameable(true); TQVBox *buttons = new TQVBox(middle); mAdd = new TQPushButton(BarIconSet("1rightarrow", KIcon::SizeSmall), "",buttons); mAdd->setFixedWidth(mAdd->height()); connect(mAdd, TQT_SIGNAL(clicked()), TQT_SLOT(addSibling())); TQToolTip::add(mAdd, i18n("Create a new item")); mRemove = new TQPushButton(BarIconSet("filenew", KIcon::SizeSmall), "", buttons); mRemove->setFixedWidth(mRemove->height()); connect(mRemove, TQT_SIGNAL(clicked()), TQT_SLOT(removeSelf())); TQToolTip::add(mRemove, i18n("Remove the selected item")); new TQWidget(buttons); } } class SliceListItem : public KListViewItem { Slice *mSlice; public: SliceListItem(KListView *parent, Slice *slice) : KListViewItem(parent, slice->name()), mSlice(slice) { } /** * new item **/ SliceListItem(KListView *parent) : KListViewItem(parent, i18n("New Slice")), mSlice(0) { } Slice *slice() { return mSlice; } }; SliceListItem *SliceConfig::currentItem() { TQListViewItem *c = mSliceList->currentItem(); return static_cast(c); } void SliceConfig::reopen() { mSliceList->clear(); mRemovedItems.clear(); mAddedItems.clear(); TQPtrList slices = oblique()->base()->slices(); for (TQPtrListIterator i(slices); *i; ++i) { Slice *slice = *i; new SliceListItem(mSliceList, slice); } } void SliceConfig::save() { for ( TQValueList::Iterator i(mRemovedItems.begin()); i != mRemovedItems.end(); ++i ) { (*i)->remove(); delete *i; } for ( TQValueList::Iterator i(mAddedItems.begin()); i != mAddedItems.end(); ++i ) { oblique()->base()->addSlice((*i)->text(0)); } for (TQListViewItem *i = mSliceList->firstChild(); i; i = i->nextSibling()) { SliceListItem *si = static_cast(i); if (si->slice()) { si->slice()->setName(si->text(0)); } } reopen(); } void SliceConfig::addSibling() { SliceListItem *si = new SliceListItem(mSliceList); mAddedItems.append(si); } void SliceConfig::removeSelf() { SliceListItem *r = currentItem(); if (mAddedItems.contains(r)) { mAddedItems.remove(r); } else { Q_ASSERT(r->slice()); mRemovedItems.append(r->slice()); } delete r; } Configure::Configure(Oblique *oblique) : CModule(i18n("Oblique"), i18n("Configure Oblique Playlist"), "", oblique) { (new TQVBoxLayout(this))->setAutoAdd(true); tabs = new TQTabWidget(this); tabs->addTab(slice = new SliceConfig(tabs, oblique), i18n("Slices")); tabs->addTab(schema = new SchemaConfig(tabs, oblique), i18n("Schemas")); } void Configure::reopen() { schema->reopen(); slice->reopen(); } void Configure::save() { schema->save(); slice->save(); } #include "cmodule.moc"