/* This file is part of the KDE project Copyright (C) 2004 Cedric Pasteur Copyright (C) 2005 Jaroslaw Staniek This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #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 #if TDE_VERSION >= KDE_MAKE_VERSION(3,1,9) && !defined(TQ_WS_WIN) # include #endif #include "widgetpropertyset.h" #include "objecttree.h" #include "widgetlibrary.h" #include "form.h" #include "container.h" #include "formIO.h" #include "objecttreeview.h" #include "commands.h" #include "tabstopdialog.h" #include "connectiondialog.h" #include "pixmapcollection.h" #include "events.h" #include "utils.h" #include "kfdpixmapedit.h" #include #include #include #include "formmanager.h" #define KFD_NO_STYLES //disables; styles support needs improvements namespace KFormDesigner { //! @internal class PropertyFactory : public KoProperty::CustomPropertyFactory { public: PropertyFactory(TQObject *parent) : KoProperty::CustomPropertyFactory(parent) // m_manager(manager) { } virtual ~PropertyFactory() {} KoProperty::CustomProperty* createCustomProperty(KoProperty::Property *) { return 0;} KoProperty::Widget* createCustomWidget(KoProperty::Property *prop) { return new KFDPixmapEdit(prop); } }; } using namespace KFormDesigner; static KStaticDeleter m_managerDeleter; FormManager* FormManager::_self = 0L; FormManager::FormManager(TQObject *parent, int options, const char *name) : TQObject(parent, name) #ifdef KEXI_DEBUG_GUI , m_uiCodeDialog(0) , m_options(options) #endif , m_objectBlockingPropertyEditorUpdating(0) , m_isRedoing(false) { Q_UNUSED(options); #ifdef KEXI_STANDALONE KGlobal::locale()->insertCatalogue("standalone_kformdesigner"); #else KGlobal::locale()->insertCatalogue("kformdesigner"); #endif connect( kapp, TQT_SIGNAL( settingsChanged(int) ), TQT_SLOT( slotSettingsChanged(int) ) ); slotSettingsChanged(KApplication::SETTINGS_SHORTCUTS); //moved to createWidgetLibrary() m_lib = new WidgetLibrary(this, supportedFactoryGroups); m_propSet = new WidgetPropertySet(this); //unused m_editor = 0; m_active = 0; m_inserting = false; m_drawingSlot = false; m_collection = 0; m_connection = 0; m_popup = 0; m_treeview = 0; m_emitSelectionSignalsUpdatesPropertySet = false; m_domDoc.appendChild(m_domDoc.createElement("UI")); m_deleteWidgetLater_list.setAutoDelete(true); connect( &m_deleteWidgetLater_timer, TQT_SIGNAL(timeout()), this, TQT_SLOT(deleteWidgetLaterTimeout())); connect( this, TQT_SIGNAL(connectionCreated(KFormDesigner::Form*, KFormDesigner::Connection&)), this, TQT_SLOT(slotConnectionCreated(KFormDesigner::Form*, KFormDesigner::Connection&))); // register kfd custom editors KoProperty::FactoryManager::self()->registerFactoryForEditor(KoProperty::Pixmap, new PropertyFactory(KoProperty::FactoryManager::self())); } FormManager::~FormManager() { m_managerDeleter.setObject(_self, 0, false); //safe delete m_popup; delete m_connection; #ifdef KEXI_DEBUG_GUI delete m_uiCodeDialog; #endif // delete m_propFactory; } FormManager* FormManager::self() { return _self; } WidgetLibrary* FormManager::createWidgetLibrary(FormManager* m, const TQStringList& supportedFactoryGroups) { if(!_self) m_managerDeleter.setObject( _self, m ); return new WidgetLibrary(_self, supportedFactoryGroups); } void FormManager::setEditor(KoProperty::Editor *editor) { m_editor = editor; if(editor) editor->changeSet(m_propSet->set()); } void FormManager::setObjectTreeView(ObjectTreeView *treeview) { m_treeview = treeview; if (m_treeview) connect(m_propSet, TQT_SIGNAL(widgetNameChanged(const TQCString&, const TQCString&)), m_treeview, TQT_SLOT(renameItem(const TQCString&, const TQCString&))); } ActionList FormManager::createActions(WidgetLibrary *lib, KActionCollection* collection, KXMLGUIClient* client) { m_collection = collection; ActionList actions = lib->createWidgetActions(client, m_collection, this, TQT_SLOT(insertWidget(const TQCString &))); if (m_options & HideSignalSlotConnections) m_dragConnection = 0; else { m_dragConnection = new KToggleAction(i18n("Connect Signals/Slots"), "signalslot", KShortcut(0), this, TQT_SLOT(startCreatingConnection()), m_collection, "drag_connection"); //to be exclusive with any 'widget' action m_dragConnection->setExclusiveGroup("LibActionWidgets"); m_dragConnection->setChecked(false); actions.append(m_dragConnection); } m_pointer = new KToggleAction(i18n("Pointer"), "mouse_pointer", KShortcut(0), this, TQT_SLOT(slotPointerClicked()), m_collection, "pointer"); m_pointer->setExclusiveGroup("LibActionWidgets"); //to be exclusive with any 'widget' action m_pointer->setChecked(true); actions.append(m_pointer); m_snapToGrid = new KToggleAction(i18n("Snap to Grid"), TQString(), KShortcut(0), 0, 0, m_collection, "snap_to_grid"); m_snapToGrid->setChecked(true); actions.append(m_snapToGrid); // Create the Style selection action (with a combo box in toolbar and submenu items) KSelectAction *m_style = new KSelectAction( i18n("Style"), KShortcut(0), this, TQT_SLOT(slotStyle()), m_collection, "change_style"); m_style->setEditable(false); KGlobal::config()->setGroup("General"); TQString currentStyle = TQString::fromLatin1(kapp->style().name()).lower(); const TQStringList styles = TQStyleFactory::keys(); m_style->setItems(styles); m_style->setCurrentItem(0); TQStringList::ConstIterator endIt = styles.constEnd(); int idx = 0; for (TQStringList::ConstIterator it = styles.constBegin(); it != endIt; ++it, ++idx) { if ((*it).lower() == currentStyle) { m_style->setCurrentItem(idx); break; } } m_style->setToolTip(i18n("Set the current view style.")); m_style->setMenuAccelsEnabled(true); actions.append(m_style); lib->addCustomWidgetActions(m_collection); return actions; } bool FormManager::isPasteEnabled() { return m_domDoc.namedItem("UI").hasChildNodes(); } void FormManager::undo() { if(!activeForm() || !activeForm()->objectTree()) return; activeForm()->commandHistory()->undo(); } void FormManager::redo() { if(!activeForm() || !activeForm()->objectTree()) return; m_isRedoing = true; activeForm()->commandHistory()->redo(); m_isRedoing = false; } void FormManager::insertWidget(const TQCString &classname) { if(m_drawingSlot) stopCreatingConnection(); m_inserting = true; Form *form; for(form = m_forms.first(); form; form = m_forms.next()) { // form->d->cursors = new TQMap(); if (form->toplevelContainer()) form->widget()->setCursor(TQCursor(CrossCursor)); TQObjectList *l = form->widget()->queryList( TQWIDGET_OBJECT_NAME_STRING ); for(TQObject *o = l->first(); o; o = l->next()) { if( ((TQWidget*)o)->ownCursor() ) { // form->d->cursors->insert(o->name(), ((TQWidget*)o)->cursor()); form->d->cursors.insert(o, TQT_TQWIDGET(o)->cursor()); TQT_TQWIDGET(o)->setCursor(TQCursor(TQt::CrossCursor)); } } delete l; } m_selectedClass = classname; m_pointer->setChecked(false); } void FormManager::stopInsert() { if(m_drawingSlot) stopCreatingConnection(); if(!m_inserting) return; //#ifndef KEXI_NO_CURSOR_PROPERTY Form *form; for(form = m_forms.first(); form; form = m_forms.next()) { form->widget()->unsetCursor(); TQObjectList *l = form->widget()->queryList( TQWIDGET_OBJECT_NAME_STRING ); for(TQObject *o = l->first(); o; o = l->next()) { TQT_TQWIDGET(o)->unsetCursor(); #if 0 if( ((TQWidget*)o)->ownCursor()) { TQMap::ConstIterator curIt( form->d->cursors.find(o) ); if (curIt!=form->d->cursors.constEnd()) TQT_TQWIDGET(o)->setCursor( *curIt ); // ((TQWidget*)o)->setCursor( (*(form->d->cursors))[o->name()] ) ; } #endif } delete l; // delete (form->d->cursors); // form->d->cursors = 0; } //#endif m_inserting = false; m_pointer->setChecked(true); } void FormManager::slotPointerClicked() { if(m_inserting) stopInsert(); else if(m_dragConnection) stopCreatingConnection(); } void FormManager::startCreatingConnection() { if (m_options & HideSignalSlotConnections) return; if(m_inserting) stopInsert(); // We set a Pointing hand cursor while drawing the connection Form *form; for(form = m_forms.first(); form; form = m_forms.next()) { // form->d->cursors = new TQMap(); form->d->mouseTrackers = new TQStringList(); if (form->toplevelContainer()) { form->widget()->setCursor(TQCursor(PointingHandCursor)); form->widget()->setMouseTracking(true); } TQObjectList *l = form->widget()->queryList( TQWIDGET_OBJECT_NAME_STRING ); for(TQObject *o = l->first(); o; o = l->next()) { TQWidget *w = TQT_TQWIDGET(o); if( w->ownCursor() ) { form->d->cursors.insert(TQT_TQOBJECT(w), w->cursor()); // form->d->cursors->insert(TQT_TQOBJECT(w)->name(), w->cursor()); w->setCursor(TQCursor(PointingHandCursor )); } if(w->hasMouseTracking()) form->d->mouseTrackers->append(w->name()); w->setMouseTracking(true); } delete l; } delete m_connection; m_connection = new Connection(); m_drawingSlot = true; if (m_dragConnection) m_dragConnection->setChecked(true); } void FormManager::resetCreatedConnection() { if (m_options & HideSignalSlotConnections) return; delete m_connection; m_connection = new Connection(); if(m_active && m_active->formWidget()) { Form *ff = (Form*)m_active; FormWidget *fw = 0; if (ff) fw = ff->formWidget(); m_active->formWidget()->clearForm(); } if (m_active && m_active->widget()) m_active->widget()->repaint(); } void FormManager::stopCreatingConnection() { if (m_options & HideSignalSlotConnections) return; if(!m_drawingSlot) return; if(m_active && m_active->formWidget()) m_active->formWidget()->clearForm(); Form *form; for(form = m_forms.first(); form; form = m_forms.next()) { form->widget()->unsetCursor(); form->widget()->setMouseTracking(false); TQObjectList *l = form->widget()->queryList( TQWIDGET_OBJECT_NAME_STRING ); for(TQObject *o = l->first(); o; o = l->next()) { TQWidget *w = (TQWidget*)o; if( w->ownCursor()) { TQMap::ConstIterator curIt( form->d->cursors.find(o) ); if (curIt!=form->d->cursors.constEnd()) TQT_TQWIDGET(o)->setCursor( *curIt ); } // w->setCursor( (*(form->d->cursors))[o->name()] ) ; w->setMouseTracking( !form->d->mouseTrackers->grep(w->name()).isEmpty() ); } delete l; // delete (form->d->cursors); // form->d->cursors = 0; delete (form->d->mouseTrackers); form->d->mouseTrackers = 0; } if(m_connection->slot().isNull()) emit connectionAborted(activeForm()); delete m_connection; m_connection = 0; m_drawingSlot = false; m_pointer->setChecked(true); } bool FormManager::snapWidgetsToGrid() { return m_snapToGrid->isChecked(); } void FormManager::windowChanged(TQWidget *w) { kdDebug() << "FormManager::windowChanged(" << (w ? (TQString(w->className())+" "+w->name()) : TQString("0")) << ")" << endl; if(!w) { m_active = 0; if(m_treeview) m_treeview->setForm(0); emit propertySetSwitched(0); if(isCreatingConnection()) stopCreatingConnection(); emitNoFormSelected(); return; } Form *previousActive = m_active; Form *form; for(form = m_forms.first(); form; form = m_forms.next()) { if(form->toplevelContainer() && form->widget() == w) { if(m_treeview) m_treeview->setForm(form); //if(m_propSet) // m_propList->setCollection(form->pixmapCollection()); kdDebug() << "FormManager::windowChanged() active form is " << form->objectTree()->name() << endl; if(m_collection) { #ifndef KFD_NO_STYLES // update the 'style' action KSelectAction *m_style = (KSelectAction*)m_collection->action("change_style", "KSelectAction"); const TQString currentStyle = form->widget()->style().name(); const TQStringList styles = m_style->items(); int idx = 0; TQStringList::ConstIterator endIt = styles.constEnd(); for (TQStringList::ConstIterator it = styles.constBegin(); it != endIt; ++it, ++idx) { if ((*it).lower() == currentStyle) { kdDebug() << "Updating the style to " << currentStyle << endl; m_style->setCurrentItem(idx); break; } } #endif } if((form != previousActive) && isCreatingConnection()) resetCreatedConnection(); m_active = form; emit dirty(form, form->isModified()); // update actions state m_active->emitActionSignals(); //update the buffer too form->emitSelectionSignals(); if (!m_emitSelectionSignalsUpdatesPropertySet) showPropertySet( propertySet(), true ); return; } } for(form = m_preview.first(); form; form = m_preview.next()) { kdDebug() << (form->widget() ? form->widget()->name() : "") << endl; if(form->toplevelContainer() && form->widget() == w) { kdDebug() << "FormManager::windowChanged() active preview form is " << form->widget()->name() << endl; if(m_collection) { #ifndef KFD_NO_STYLES // update the 'style' action KSelectAction *m_style = (KSelectAction*)m_collection->action("change_style", "KSelectAction"); const TQString currentStyle = form->widget()->style().name(); const TQStringList styles = m_style->items(); int idx = 0; TQStringList::ConstIterator endIt = styles.constEnd(); for (TQStringList::ConstIterator it = styles.constBegin(); it != endIt; ++it, ++idx) { if ((*it).lower() == currentStyle) { kdDebug() << "Updating the style to " << currentStyle << endl; m_style->setCurrentItem(idx); break; } } #endif resetCreatedConnection(); m_active = form; emit dirty(form, false); emitNoFormSelected(); showPropertySet(0); return; } } } //m_active = 0; } Form* FormManager::activeForm() const { return m_active; } Form* FormManager::formForWidget(TQWidget *w) { for(Form *form = m_forms.first(); form; form = m_forms.next()) { if(form->toplevelContainer() && form->widget() == w) return form; } return 0; // not one of toplevel widgets } void FormManager::deleteForm(Form *form) { if (!form) return; if(m_forms.find(form) == -1) m_preview.remove(form); else m_forms.remove(form); if(m_forms.count() == 0) { m_active = 0; emit propertySetSwitched(0); } } void FormManager::importForm(Form *form, bool preview) { if(!preview) initForm(form); else { m_preview.append(form); form->setDesignMode(false); } } void FormManager::initForm(Form *form) { m_forms.append(form); if(m_treeview) m_treeview->setForm(form); m_active = form; connect(form, TQT_SIGNAL(selectionChanged(TQWidget*, bool, bool)), m_propSet, TQT_SLOT(setSelectedWidgetWithoutReload(TQWidget*, bool, bool))); if(m_treeview) { connect(form, TQT_SIGNAL(selectionChanged(TQWidget*, bool, bool)), m_treeview, TQT_SLOT(setSelectedWidget(TQWidget*, bool))); connect(form, TQT_SIGNAL(childAdded(ObjectTreeItem* )), m_treeview, TQT_SLOT(addItem(ObjectTreeItem*))); connect(form, TQT_SIGNAL(childRemoved(ObjectTreeItem* )), m_treeview, TQT_SLOT(removeItem(ObjectTreeItem*))); } connect(m_propSet, TQT_SIGNAL(widgetNameChanged(const TQCString&, const TQCString&)), form, TQT_SLOT(changeName(const TQCString&, const TQCString&))); form->setSelectedWidget(form->widget()); windowChanged(form->widget()); } void FormManager::previewForm(Form *form, TQWidget *container, Form *toForm) { if(!form || !container || !form->objectTree()) return; TQDomDocument domDoc; if (!FormIO::saveFormToDom(form, domDoc)) return; Form *myform; if(!toForm) myform = new Form(form->library(), form->objectTree()->name().latin1(), false/*!designMode, we need to set it early enough*/); else myform = toForm; myform->createToplevel(container); container->setStyle( &(form->widget()->style()) ); if (!FormIO::loadFormFromDom(myform, container, domDoc)) { delete myform; return; } myform->setDesignMode(false); m_preview.append(myform); container->show(); } /* bool FormManager::loadFormFromDomInternal(Form *form, TQWidget *container, TQDomDocument &inBuf) { return FormIO::loadFormFromDom(myform, container, domDoc); } bool FormManager::saveFormToStringInternal(Form *form, TQString &dest, int indent) { return KFormDesigner::FormIO::saveFormToString(form, dest, indent); }*/ bool FormManager::isTopLevel(TQWidget *w) { if(!activeForm() || !activeForm()->objectTree()) return false; // kdDebug() << "FormManager::isTopLevel(): for: " << w->name() << " = " // << activeForm()->objectTree()->lookup(w->name())<< endl; ObjectTreeItem *item = activeForm()->objectTree()->lookup(w->name()); if(!item) return true; return (!item->parent()); } void FormManager::deleteWidget() { if(!activeForm() || !activeForm()->objectTree()) return; TQPtrList *list = activeForm()->selectedWidgets(); if(list->isEmpty()) return; if (activeForm()->widget() == list->first()) { //toplevel form is selected, cannot delete it return; } KCommand *com = new DeleteWidgetCommand(*list, activeForm()); activeForm()->addCommand(com, true); } void FormManager::copyWidget() { if (!activeForm() || !activeForm()->objectTree()) return; TQPtrList *list = activeForm()->selectedWidgets(); if(list->isEmpty()) return; removeChildrenFromList(*list); // We clear the current clipboard m_domDoc.setContent(TQString(), true); TQDomElement parent = m_domDoc.createElement("UI"); m_domDoc.appendChild(parent); TQWidget *w; for(w = list->first(); w; w = list->next()) { ObjectTreeItem *it = activeForm()->objectTree()->lookup(w->name()); if (!it) continue; FormIO::saveWidget(it, parent, m_domDoc); } FormIO::cleanClipboard(parent); activeForm()->emitActionSignals(); // to update 'Paste' item state } void FormManager::cutWidget() { if(!activeForm() || !activeForm()->objectTree()) return; TQPtrList *list = activeForm()->selectedWidgets(); if(list->isEmpty()) return; KCommand *com = new CutWidgetCommand(*list, activeForm()); activeForm()->addCommand(com, true); } void FormManager::pasteWidget() { if(!m_domDoc.namedItem("UI").hasChildNodes()) return; if(!activeForm() || !activeForm()->objectTree()) return; KCommand *com = new PasteWidgetCommand(m_domDoc, activeForm()->activeContainer(), m_insertPoint); activeForm()->addCommand(com, true); } void FormManager::setInsertPoint(const TQPoint &p) { m_insertPoint = p; } void FormManager::createSignalMenu(TQWidget *w) { m_sigSlotMenu = new KPopupMenu(); m_sigSlotMenu->insertTitle(SmallIcon("connection"), i18n("Signals")); TQStrList list = w->metaObject()->signalNames(true); TQStrListIterator it(list); for(; it.current() != 0; ++it) m_sigSlotMenu->insertItem(*it); int result = m_sigSlotMenu->exec(TQCursor::pos()); if(result == -1) resetCreatedConnection(); else menuSignalChosen(result); delete m_sigSlotMenu; m_sigSlotMenu = 0; } void FormManager::createSlotMenu(TQWidget *w) { m_sigSlotMenu = new KPopupMenu(); m_sigSlotMenu->insertTitle(SmallIcon("connection"), i18n("Slots")); TQString signalArg( m_connection->signal().remove( TQRegExp(".*[(]|[)]") ) ); TQStrList list = w->metaObject()->slotNames(true); TQStrListIterator it(list); for(; it.current() != 0; ++it) { // we add the slot only if it is compatible with the signal TQString slotArg(*it); slotArg = slotArg.remove( TQRegExp(".*[(]|[)]") ); if(!signalArg.startsWith(slotArg, true)) // args not compatible continue; m_sigSlotMenu->insertItem(*it); } int result = m_sigSlotMenu->exec(TQCursor::pos()); if(result == -1) resetCreatedConnection(); else menuSignalChosen(result); delete m_sigSlotMenu; m_sigSlotMenu = 0; } void FormManager::createContextMenu(TQWidget *w, Container *container, bool popupAtCursor) { if(!activeForm() || !activeForm()->widget()) return; const bool toplevelWidgetSelected = activeForm()->widget() == w; const uint widgetsCount = container->form()->selectedWidgets()->count(); const bool multiple = widgetsCount > 1; //const bool enableRemove = w != m_active->widget(); // We only enablelayout creation if more than one widget with the same parent are selected const bool enableLayout = multiple || w == container->widget(); m_menuWidget = w; TQString n = container->form()->library()->displayName(w->className()); // TQValueVector menuIds(); if (!m_popup) { m_popup = new KPopupMenu(); } else { m_popup->clear(); } //set title if(!multiple) { if(w == container->form()->widget()) m_popup->insertTitle(SmallIcon("form"), i18n("%1 : Form").arg(w->name()) ); else m_popup->insertTitle( SmallIcon( container->form()->library()->iconName(w->className())), TQString(w->name()) + " : " + n ); } else m_popup->insertTitle(SmallIcon("multiple_obj"), i18n("Multiple Widgets") + TQString(" (%1)").arg(widgetsCount)); KAction *a; #define PLUG_ACTION(_name, forceVisible) \ { a = action(_name); \ if (a && (forceVisible || a->isEnabled())) { \ if (separatorNeeded) \ m_popup->insertSeparator(); \ separatorNeeded = false; \ a->plug(m_popup); \ } \ } bool separatorNeeded = false; PLUG_ACTION("edit_cut", !toplevelWidgetSelected); PLUG_ACTION("edit_copy", !toplevelWidgetSelected); PLUG_ACTION("edit_paste", true); PLUG_ACTION("edit_delete", !toplevelWidgetSelected); separatorNeeded = true; PLUG_ACTION("layout_menu", enableLayout); PLUG_ACTION("break_layout", enableLayout); separatorNeeded = true; PLUG_ACTION("align_menu", !toplevelWidgetSelected); PLUG_ACTION("adjust_size_menu", !toplevelWidgetSelected); separatorNeeded = true; // We create the buddy menu if(!multiple && w->inherits(TQLABEL_OBJECT_NAME_STRING) && ((TQLabel*)w)->text().contains("&") && (((TQLabel*)w)->textFormat() != RichText)) { if (separatorNeeded) m_popup->insertSeparator(); KPopupMenu *sub = new KPopupMenu(w); TQWidget *buddy = ((TQLabel*)w)->buddy(); sub->insertItem(i18n("No Buddy"), MenuNoBuddy); if(!buddy) sub->setItemChecked(MenuNoBuddy, true); sub->insertSeparator(); // add all the widgets that can have focus for(ObjectTreeListIterator it( container->form()->tabStopsIterator() ); it.current(); ++it) { int index = sub->insertItem( SmallIcon(container->form()->library()->iconName(it.current()->className().latin1())), it.current()->name()); if(it.current()->widget() == buddy) sub->setItemChecked(index, true); } /*int id =*/ m_popup->insertItem(i18n("Choose Buddy..."), sub); // menuIds->append(id); connect(sub, TQT_SIGNAL(activated(int)), this, TQT_SLOT(buddyChosen(int))); separatorNeeded = true; } //int sigid=0; #ifdef KEXI_DEBUG_GUI if(!multiple && !(m_options & HideEventsInPopupMenu)) { if (separatorNeeded) m_popup->insertSeparator(); // We create the signals menu KPopupMenu *sigMenu = new KPopupMenu(); TQStrList list = w->metaObject()->signalNames(true); TQStrListIterator it(list); for(; it.current() != 0; ++it) sigMenu->insertItem(*it); int id = m_popup->insertItem(SmallIconSet(""), i18n("Events"), sigMenu); // menuIds->append(id); if(list.isEmpty()) m_popup->setItemEnabled(id, false); connect(sigMenu, TQT_SIGNAL(activated(int)), this, TQT_SLOT(menuSignalChosen(int))); separatorNeeded = true; } #endif // Other items if(!multiple) { int lastID = -1; if (separatorNeeded) { lastID = m_popup->insertSeparator(); } const uint oldIndex = m_popup->count()-1; container->form()->library()->createMenuActions(w->className(), w, m_popup, container); if (oldIndex == (m_popup->count()-1)) { // for (uint i=oldIndex; icount(); i++) { // int id = m_popup->idAt( i ); // if (id!=-1) // menuIds->append( id ); // } //nothing added if (separatorNeeded) { m_popup->removeItem( lastID ); // menuIds->pop_back(); } } } //show the popup at the selected widget TQPoint popupPos; if (popupAtCursor) { popupPos = TQCursor::pos(); } else { WidgetList *lst = container->form()->selectedWidgets(); TQWidget * sel_w = lst ? lst->first() : container->form()->selectedWidget(); popupPos = sel_w ? sel_w->mapToGlobal(TQPoint(sel_w->width()/2, sel_w->height()/2)) : TQCursor::pos(); } m_insertPoint = container->widget()->mapFromGlobal(popupPos); m_popup->exec(popupPos);//TQCursor::pos()); m_insertPoint = TQPoint(); // TQValueVector::iterator it; // for(it = menuIds->begin(); it != menuIds->end(); ++it) // m_popup->removeItem(*it); } void FormManager::buddyChosen(int id) { if(!m_menuWidget) return; TQLabel *label = static_cast((TQWidget*)m_menuWidget); if(id == MenuNoBuddy) { label->setBuddy(0); return; } ObjectTreeItem *item = activeForm()->objectTree()->lookup(m_popup->text(id)); if(!item || !item->widget()) return; label->setBuddy(item->widget()); } void FormManager::menuSignalChosen(int id) { if (m_options & HideSignalSlotConnections) return; //if(!m_menuWidget) // return; if(m_drawingSlot && m_sigSlotMenu) { if( m_connection->receiver().isNull() ) m_connection->setSignal(m_sigSlotMenu->text(id)); else { m_connection->setSlot(m_sigSlotMenu->text(id)); kdDebug() << "Finished creating the connection: sender=" << m_connection->sender() << "; signal=" << m_connection->signal() << "; receiver=" << m_connection->receiver() << "; slot=" << m_connection->slot() << endl; emit connectionCreated(activeForm(), *m_connection); stopCreatingConnection(); } } else if(m_menuWidget) emit createFormSlot(m_active, m_menuWidget->name(), m_popup->text(id)); } void FormManager::slotConnectionCreated(Form *form, Connection &connection) { if (m_options & HideSignalSlotConnections) return; if(!form) return; Connection *c = new Connection(connection); form->connectionBuffer()->append(c); } void FormManager::layoutHBox() { createLayout(Container::HBox); } void FormManager::layoutVBox() { createLayout(Container::VBox); } void FormManager::layoutGrid() { createLayout(Container::Grid); } void FormManager::layoutHSplitter() { createLayout(Container::HSplitter); } void FormManager::layoutVSplitter() { createLayout(Container::VSplitter); } void FormManager::layoutHFlow() { createLayout(Container::HFlow); } void FormManager::layoutVFlow() { createLayout(Container::VFlow); } void FormManager::createLayout(int layoutType) { WidgetList *list = m_active->selectedWidgets(); // if only one widget is selected (a container), we modify its layout if (list->isEmpty()) {//sanity check kdWarning() << "FormManager::createLayout(): list is empty!" << endl; return; } if(list->count() == 1) { ObjectTreeItem *item = m_active->objectTree()->lookup(list->first()->name()); if(!item || !item->container() || !m_propSet->contains("layout")) return; (*m_propSet)["layout"] = Container::layoutTypeToString(layoutType); return; } TQWidget *parent = list->first()->parentWidget(); for(TQWidget *w = list->first(); w; w = list->next()) { kdDebug() << "comparing widget " << w->name() << " whose parent is " << w->parentWidget()->name() << " insteaed of " << parent->name() << endl; if(w->parentWidget() != parent) { KMessageBox::sorry(m_active->widget()->topLevelWidget(), i18n("Cannot create the layout.\n" "All selected widgets must have the same parent.")); kdDebug() << "FormManager::createLayout() widgets don't have the same parent widget" << endl; return; } } KCommand *com = new CreateLayoutCommand(layoutType, *list, m_active); m_active->addCommand(com, true); } void FormManager::breakLayout() { if(!activeForm() || !activeForm()->objectTree()) return; Container *container = activeForm()->activeContainer(); TQCString c( container->widget()->className() ); if((c == "Grid") || (c == "VBox") || (c == "HBox") || (c == "HFlow") || (c == "VFlow")) { KCommand *com = new BreakLayoutCommand(container); m_active->addCommand(com, true); } else // normal container { if(activeForm()->selectedWidgets()->count() == 1) (*m_propSet)["layout"] = "NoLayout"; else container->setLayout(Container::NoLayout); } } void FormManager::showPropertySet(WidgetPropertySet *set, bool forceReload, const TQCString& propertyToSelect) { if (m_objectBlockingPropertyEditorUpdating) return; /*unused if(m_editor) { if (propertyToSelect.isEmpty() && forceReload) m_editor->changeSet(set ? set->set() : 0, propertyToSelect); else m_editor->changeSet(set ? set->set() : 0); }*/ emit propertySetSwitched(set ? set->set(): 0, /*preservePrevSelection*/forceReload, propertyToSelect); } void FormManager::blockPropertyEditorUpdating(void *blockingObject) { if (!blockingObject || m_objectBlockingPropertyEditorUpdating) return; m_objectBlockingPropertyEditorUpdating = blockingObject; } void FormManager::unblockPropertyEditorUpdating(void *blockingObject, WidgetPropertySet *set) { if (!blockingObject || m_objectBlockingPropertyEditorUpdating!=blockingObject) return; m_objectBlockingPropertyEditorUpdating = 0; showPropertySet(set, true/*forceReload*/); } void FormManager::editTabOrder() { if(!activeForm() || !activeForm()->objectTree()) return; TQWidget *topLevel = m_active->widget()->topLevelWidget(); TabStopDialog dlg(topLevel); //const bool oldAutoTabStops = m_active->autoTabStops(); if (dlg.exec(m_active) == TQDialog::Accepted) { //inform about changing "autoTabStop" property // -- this will be received eg. by Kexi, so custom "autoTabStop" property can be updated emit autoTabStopsSet(m_active, dlg.autoTabStops()); //force set dirty emit dirty(m_active, true); } } void FormManager::slotStyle() { if(!activeForm()) return; KSelectAction *m_style = (KSelectAction*)m_collection->action("change_style", "KSelectAction"); TQString style = m_style->currentText(); activeForm()->widget()->setStyle( style ); TQObjectList *l = activeForm()->widget()->queryList( TQWIDGET_OBJECT_NAME_STRING ); for(TQObject *o = l->first(); o; o = l->next()) (TQT_TQWIDGET(o))->setStyle( style ); delete l; } void FormManager::editFormPixmapCollection() { if(!activeForm() || !activeForm()->objectTree()) return; PixmapCollectionEditor dialog(activeForm()->pixmapCollection(), activeForm()->widget()->topLevelWidget()); dialog.exec(); } void FormManager::editConnections() { if (m_options & HideSignalSlotConnections) return; if(!activeForm() || !activeForm()->objectTree()) return; ConnectionDialog dialog(activeForm()->widget()->topLevelWidget()); dialog.exec(activeForm()); } void FormManager::alignWidgets(int type) { if(!activeForm() || !activeForm()->objectTree() || (activeForm()->selectedWidgets()->count() < 2)) return; TQWidget *parentWidget = activeForm()->selectedWidgets()->first()->parentWidget(); for(TQWidget *w = activeForm()->selectedWidgets()->first(); w; w = activeForm()->selectedWidgets()->next()) { if(w->parentWidget() != parentWidget) { kdDebug() << "FormManager::alignWidgets() type ==" << type << " widgets don't have the same parent widget" << endl; return; } } KCommand *com = new AlignWidgetsCommand(type, *(activeForm()->selectedWidgets()), activeForm()); activeForm()->addCommand(com, true); } void FormManager::alignWidgetsToLeft() { alignWidgets(AlignWidgetsCommand::AlignToLeft); } void FormManager::alignWidgetsToRight() { alignWidgets(AlignWidgetsCommand::AlignToRight); } void FormManager::alignWidgetsToTop() { alignWidgets(AlignWidgetsCommand::AlignToTop); } void FormManager::alignWidgetsToBottom() { alignWidgets(AlignWidgetsCommand::AlignToBottom); } void FormManager::adjustWidgetSize() { if(!activeForm() || !activeForm()->objectTree()) return; KCommand *com = new AdjustSizeCommand(AdjustSizeCommand::SizeToFit, *(activeForm()->selectedWidgets()), activeForm()); activeForm()->addCommand(com, true); } void FormManager::alignWidgetsToGrid() { if(!activeForm() || !activeForm()->objectTree()) return; KCommand *com = new AlignWidgetsCommand(AlignWidgetsCommand::AlignToGrid, *(activeForm()->selectedWidgets()), activeForm()); activeForm()->addCommand(com, true); } void FormManager::adjustSizeToGrid() { if(!activeForm() || !activeForm()->objectTree()) return; KCommand *com = new AdjustSizeCommand(AdjustSizeCommand::SizeToGrid, *(activeForm()->selectedWidgets()), activeForm()); activeForm()->addCommand(com, true); } void FormManager::adjustWidthToSmall() { if(!activeForm() || !activeForm()->objectTree()) return; KCommand *com = new AdjustSizeCommand(AdjustSizeCommand::SizeToSmallWidth, *(activeForm()->selectedWidgets()), activeForm()); activeForm()->addCommand(com, true); } void FormManager::adjustWidthToBig() { if(!activeForm() || !activeForm()->objectTree()) return; KCommand *com = new AdjustSizeCommand(AdjustSizeCommand::SizeToBigWidth, *(activeForm()->selectedWidgets()), activeForm()); activeForm()->addCommand(com, true); } void FormManager::adjustHeightToSmall() { if(!activeForm() || !activeForm()->objectTree()) return; KCommand *com = new AdjustSizeCommand(AdjustSizeCommand::SizeToSmallHeight, *(activeForm()->selectedWidgets()), activeForm()); activeForm()->addCommand(com, true); } void FormManager::adjustHeightToBig() { if(!activeForm() || !activeForm()->objectTree()) return; KCommand *com = new AdjustSizeCommand(AdjustSizeCommand::SizeToBigHeight, *(activeForm()->selectedWidgets()), activeForm()); activeForm()->addCommand(com, true); } void FormManager::bringWidgetToFront() { if(!activeForm() || !activeForm()->objectTree()) return; for(TQWidget *w = activeForm()->selectedWidgets()->first(); w; w = activeForm()->selectedWidgets()->next()) w->raise(); } void FormManager::sendWidgetToBack() { if(!activeForm() || !activeForm()->objectTree()) return; for(TQWidget *w = activeForm()->selectedWidgets()->first(); w; w = activeForm()->selectedWidgets()->next()) w->lower(); } void FormManager::selectAll() { if(!activeForm() || !activeForm()->objectTree()) return; activeForm()->selectFormWidget(); uint count = activeForm()->objectTree()->children()->count(); for(ObjectTreeItem *it = activeForm()->objectTree()->children()->first(); it; it = activeForm()->objectTree()->children()->next(), count--) { activeForm()->setSelectedWidget(it->widget(), /*add*/true, /*raise*/false, /*moreWillBeSelected*/count>1); } } void FormManager::clearWidgetContent() { if(!activeForm() || !activeForm()->objectTree()) return; for(TQWidget *w = activeForm()->selectedWidgets()->first(); w; w = activeForm()->selectedWidgets()->next()) activeForm()->library()->clearWidgetContent(w->className(), w); } void FormManager::deleteWidgetLater( TQWidget *w ) { w->hide(); w->reparent(0, WType_TopLevel, TQPoint(0,0)); m_deleteWidgetLater_list.append( w ); m_deleteWidgetLater_timer.start( 100, true ); } void FormManager::deleteWidgetLaterTimeout() { m_deleteWidgetLater_list.clear(); } void FormManager::showFormUICode() { #ifdef KEXI_DEBUG_GUI if(!activeForm()) return; TQString uiCode; if (!FormIO::saveFormToString(activeForm(), uiCode, 3)) { //! @todo show err? return; } if (!m_uiCodeDialog) { m_uiCodeDialog = new KDialogBase(0, "uiwindow", true, i18n("Form's UI Code"), KDialogBase::Close, KDialogBase::Close); m_uiCodeDialog->resize(700, 600); TQVBox *box = m_uiCodeDialog->makeVBoxMainWidget(); KTabWidget* tab = new KTabWidget(box); m_currentUICodeDialogEditor = new KTextEdit(TQString(), TQString(), tab); tab->addTab( m_currentUICodeDialogEditor, i18n("Current")); m_currentUICodeDialogEditor->setReadOnly(true); TQFont f( m_currentUICodeDialogEditor->font() ); f.setFamily("courier"); m_currentUICodeDialogEditor->setFont(f); m_currentUICodeDialogEditor->setTextFormat(TQt::PlainText); m_originalUICodeDialogEditor = new KTextEdit(TQString(), TQString(), tab); tab->addTab( m_originalUICodeDialogEditor, i18n("Original")); m_originalUICodeDialogEditor->setReadOnly(true); m_originalUICodeDialogEditor->setFont(f); m_originalUICodeDialogEditor->setTextFormat(TQt::PlainText); } m_currentUICodeDialogEditor->setText( uiCode ); //indent and set our original doc as well: TQDomDocument doc; doc.setContent( activeForm()->m_recentlyLoadedUICode ); m_originalUICodeDialogEditor->setText( doc.toString( 3 ) ); m_uiCodeDialog->show(); #endif } void FormManager::slotSettingsChanged(int category) { if (category==KApplication::SETTINGS_SHORTCUTS) { m_contextMenuKey = KGlobalSettings::contextMenuKey(); } } void FormManager::emitWidgetSelected( KFormDesigner::Form* form, bool multiple ) { enableFormActions(); // Enable edit actions enableAction("edit_copy", true); enableAction("edit_cut", true); enableAction("edit_delete", true); enableAction("clear_contents", true); // 'Align Widgets' menu enableAction("align_menu", multiple); enableAction("align_to_left", multiple); enableAction("align_to_right", multiple); enableAction("align_to_top", multiple); enableAction("align_to_bottom", multiple); enableAction("adjust_size_menu", true); enableAction("adjust_width_small", multiple); enableAction("adjust_width_big", multiple); enableAction("adjust_height_small", multiple); enableAction("adjust_height_big", multiple); enableAction("format_raise", true); enableAction("format_lower", true); WidgetList *wlist = form->selectedWidgets(); bool fontEnabled = false; for (WidgetListIterator it(*wlist); it.current(); ++it) { if (-1 != it.current()->metaObject()->findProperty("font", true)) { fontEnabled = true; break; } } enableAction("format_font", fontEnabled); // If the widgets selected is a container, we enable layout actions bool containerSelected = false; if(!multiple) { KFormDesigner::ObjectTreeItem *item = 0; if (form->selectedWidgets()->first()) form->objectTree()->lookup( form->selectedWidgets()->first()->name() ); if(item && item->container()) containerSelected = true; } const bool twoSelected = form->selectedWidgets()->count()==2; // Layout actions enableAction("layout_menu", multiple || containerSelected); enableAction("layout_hbox", multiple || containerSelected); enableAction("layout_vbox", multiple || containerSelected); enableAction("layout_grid", multiple || containerSelected); enableAction("layout_hsplitter", twoSelected); enableAction("layout_vsplitter", twoSelected); KFormDesigner::Container *container = activeForm() ? activeForm()->activeContainer() : 0; if (container) enableAction("break_layout", (container->layoutType() != KFormDesigner::Container::NoLayout)); emit widgetSelected(form, true); } void FormManager::emitFormWidgetSelected( KFormDesigner::Form* form ) { // disableWidgetActions(); enableAction("edit_copy", false); enableAction("edit_cut", false); enableAction("edit_delete", false); enableAction("clear_contents", false); // Disable format functions enableAction("align_menu", false); enableAction("align_to_left", false); enableAction("align_to_right", false); enableAction("align_to_top", false); enableAction("align_to_bottom", false); enableAction("adjust_size_menu", false); enableAction("format_raise", false); enableAction("format_lower", false); enableAction("format_font", false); enableFormActions(); const bool twoSelected = form->selectedWidgets()->count()==2; const bool hasChildren = !form->objectTree()->children()->isEmpty(); // Layout actions enableAction("layout_menu", hasChildren); enableAction("layout_hbox", hasChildren); enableAction("layout_vbox", hasChildren); enableAction("layout_grid", hasChildren); enableAction("layout_hsplitter", twoSelected); enableAction("layout_vsplitter", twoSelected); enableAction("break_layout", (form->toplevelContainer()->layoutType() != KFormDesigner::Container::NoLayout)); emit formWidgetSelected( form ); } void FormManager::emitNoFormSelected() { disableWidgetActions(); // Disable edit actions // enableAction("edit_paste", false); // enableAction("edit_undo", false); // enableAction("edit_redo", false); // Disable 'Tools' actions enableAction("pixmap_collection", false); if (!(m_options & HideSignalSlotConnections)) enableAction("form_connections", false); enableAction("taborder", false); enableAction("change_style", activeForm()!=0); // Disable items in 'File' if (!(m_options & SkipFileActions)) { enableAction("file_save", false); enableAction("file_save_as", false); enableAction("preview_form", false); } emit noFormSelected(); } void FormManager::enableFormActions() { // Enable 'Tools' actions enableAction("pixmap_collection", true); if (!(m_options & HideSignalSlotConnections)) enableAction("form_connections", true); enableAction("taborder", true); enableAction("change_style", true); // Enable items in 'File' if (!(m_options & SkipFileActions)) { enableAction("file_save", true); enableAction("file_save_as", true); enableAction("preview_form", true); } enableAction("edit_paste", isPasteEnabled()); enableAction("edit_select_all", true); } void FormManager::disableWidgetActions() { // Disable edit actions enableAction("edit_copy", false); enableAction("edit_cut", false); enableAction("edit_delete", false); enableAction("clear_contents", false); // Disable format functions enableAction("align_menu", false); enableAction("align_to_left", false); enableAction("align_to_right", false); enableAction("align_to_top", false); enableAction("align_to_bottom", false); enableAction("adjust_size_menu", false); enableAction("format_raise", false); enableAction("format_lower", false); enableAction("layout_menu", false); enableAction("layout_hbox", false); enableAction("layout_vbox", false); enableAction("layout_grid", false); enableAction("layout_hsplitter", false); enableAction("layout_vsplitter", false); enableAction("break_layout", false); } void FormManager::emitUndoEnabled(bool enabled, const TQString &text) { enableAction("edit_undo", enabled); emit undoEnabled(enabled, text); } void FormManager::emitRedoEnabled(bool enabled, const TQString &text) { enableAction("edit_redo", enabled); emit redoEnabled(enabled, text); } void FormManager::changeFont() { if (!m_active) return; WidgetList *wlist = m_active->selectedWidgets(); WidgetList widgetsWithFontProperty; TQWidget *widget; TQFont font; bool oneFontSelected = true; for (WidgetListIterator it(*wlist); (widget = it.current()); ++it) { if (m_active->library()->isPropertyVisible(widget->className(), widget, "font")) { widgetsWithFontProperty.append(widget); if (oneFontSelected) { if (widgetsWithFontProperty.count()==1) font = widget->font(); else if (font != widget->font()) oneFontSelected = false; } } } if (widgetsWithFontProperty.isEmpty()) return; if (!oneFontSelected) //many different fonts selected: pick a font from toplevel conatiner font = m_active->widget()->font(); if (1==widgetsWithFontProperty.count()) { //single widget's settings widget = widgetsWithFontProperty.first(); KoProperty::Property &fontProp = m_propSet->property("font"); if (TQDialog::Accepted != KFontDialog::getFont(font, false, m_active->widget())) return; fontProp = font; return; } //multiple widgets int diffFlags=0; if (TQDialog::Accepted != KFontDialog::getFontDiff(font, diffFlags, false, m_active->widget()) || 0==diffFlags) return; //update font for (WidgetListIterator it(widgetsWithFontProperty); (widget = it.current()); ++it) { TQFont prevFont( widget->font() ); if (diffFlags & KFontChooser::FontDiffFamily) prevFont.setFamily( font.family() ); if (diffFlags & KFontChooser::FontDiffStyle) { prevFont.setBold( font.bold() ); prevFont.setItalic( font.italic() ); } if (diffFlags & KFontChooser::FontDiffSize) prevFont.setPointSize( font.pointSize() ); /*! @todo this modification is not added to UNDO BUFFER: do it when KoProperty::Set supports multiple selections */ widget->setFont( prevFont ); //temporary fix for dirty flag: emit dirty(m_active, true); } } #include "formmanager.moc"