00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "floatingtextwidget.h"
00014
00015
00016 #include <qregexp.h>
00017 #include <qpainter.h>
00018 #include <qevent.h>
00019 #include <qvalidator.h>
00020 #include <klocale.h>
00021 #include <kdebug.h>
00022 #include <kinputdialog.h>
00023
00024
00025 #include "floatingtextwidgetcontroller.h"
00026 #include "association.h"
00027 #include "umlview.h"
00028 #include "umldoc.h"
00029 #include "uml.h"
00030 #include "classifier.h"
00031 #include "listpopupmenu.h"
00032 #include "operation.h"
00033 #include "model_utils.h"
00034 #include "object_factory.h"
00035 #include "messagewidget.h"
00036 #include "dialogs/assocpropdlg.h"
00037 #include "dialogs/selectopdlg.h"
00038
00039
00040 FloatingTextWidget::FloatingTextWidget(UMLView * view, Uml::Text_Role role,
00041 const QString& text, Uml::IDType id)
00042 : UMLWidget(view, id, new FloatingTextWidgetController(this))
00043 {
00044 init();
00045 m_Text = text;
00046 m_Role = role;
00047 if ( ! UMLApp::app()->getDocument()->loading() ) {
00048 updateComponentSize();
00049 setZ( 10 );
00050 update();
00051 }
00052 }
00053
00054 void FloatingTextWidget::init() {
00055
00056 m_PreText = "";
00057 m_Text = "";
00058 m_PostText = "";
00059 m_Role = Uml::tr_Floating;
00060 m_Type = Uml::wt_Text;
00061
00062 m_pLink = NULL;
00063 UMLWidget::m_bResizable = false;
00064 }
00065
00066 FloatingTextWidget::~FloatingTextWidget() {
00067 }
00068
00069 void FloatingTextWidget::draw(QPainter & p, int offsetX, int offsetY) {
00070 int w = width();
00071 int h = height();
00072 p.setFont( UMLWidget::getFont() );
00073 QColor textColor(50, 50, 50);
00074 p.setPen(textColor);
00075 p.drawText( offsetX , offsetY,w,h, Qt::AlignCenter, getDisplayText() );
00076 if(m_bSelected)
00077 drawSelected(&p, offsetX, offsetY);
00078 }
00079
00080 void FloatingTextWidget::resizeEvent(QResizeEvent * ) {}
00081
00082 QSize FloatingTextWidget::calculateSize() {
00083 const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
00084 int h = fm.lineSpacing();
00085 int w = fm.width( getDisplayText() );
00086 return QSize(w + 8, h + 4);
00087 }
00088
00089 void FloatingTextWidget::slotMenuSelection(int sel) {
00090 switch(sel) {
00091 case ListPopupMenu::mt_Properties:
00092 showProperties();
00093 break;
00094
00095 case ListPopupMenu::mt_Delete:
00096 m_pView -> removeWidget(this);
00097 break;
00098
00099 case ListPopupMenu::mt_Operation:
00100 {
00101 kDebug() << "FloatingTextWidget::slotMenuSelection(mt_Operation) is called."
00102 << endl;
00103 if (m_pLink == NULL) {
00104 kDebug() << "FloatingTextWidget::slotMenuSelection(mt_Operation): "
00105 << "m_pLink is NULL" << endl;
00106 return;
00107 }
00108 UMLClassifier* c = m_pLink->getOperationOwner();
00109 if (c == NULL) {
00110 bool ok = false;
00111 QString opText = KInputDialog::getText(i18n("Name"),
00112 i18n("Enter operation name:"),
00113 getText(), &ok, m_pView);
00114 if (ok)
00115 m_pLink->setCustomOpText(opText);
00116 return;
00117 }
00118 UMLClassifierListItem* umlObj = Object_Factory::createChildObject(c, Uml::ot_Operation);
00119 if (umlObj) {
00120 UMLOperation* newOperation = static_cast<UMLOperation*>( umlObj );
00121 m_pLink->setOperation(newOperation);
00122 }
00123 }
00124 break;
00125
00126 case ListPopupMenu::mt_Select_Operation:
00127 showOpDlg();
00128 break;
00129
00130 case ListPopupMenu::mt_Rename:
00131 handleRename();
00132 break;
00133
00134 case ListPopupMenu::mt_Change_Font:
00135 {
00136 QFont font = getFont();
00137 if( KFontDialog::getFont( font, false, m_pView ) ) {
00138 if( m_Role == Uml::tr_Floating || m_Role == Uml::tr_Seq_Message ) {
00139 setFont( font );
00140 } else if (m_pLink) {
00141 m_pLink->lwSetFont(font);
00142 }
00143 }
00144 }
00145 break;
00146
00147 case ListPopupMenu::mt_Reset_Label_Positions:
00148 if (m_pLink)
00149 m_pLink->resetTextPositions();
00150 break;
00151
00152 default:
00153 UMLWidget::slotMenuSelection(sel);
00154 break;
00155 }
00156 }
00157
00158 void FloatingTextWidget::handleRename() {
00159 QRegExpValidator v(QRegExp(".*"), 0);
00160 QString t;
00161 if( m_Role == Uml::tr_RoleAName || m_Role == Uml::tr_RoleBName ) {
00162 t = i18n("Enter role name:");
00163 } else if (m_Role == Uml::tr_MultiA || m_Role == Uml::tr_MultiB) {
00164 t = i18n("Enter multiplicity:");
00165
00166
00167
00168
00169
00170 } else if (m_Role == Uml::tr_Name) {
00171 t = i18n("Enter association name:");
00172 } else if (m_Role == Uml::tr_Floating) {
00173 t = i18n("Enter new text:");
00174 } else {
00175 t = i18n("ERROR");
00176 }
00177 bool ok = false;
00178 QString newText = KInputDialog::getText(i18n("Rename"), t, getText(), &ok,
00179 m_pView, NULL, &v);
00180 if (!ok || newText == getText())
00181 return;
00182 if (m_pLink && !isTextValid(newText)) {
00183 AssociationWidget *assoc = dynamic_cast<AssociationWidget*>(m_pLink);
00184 if (assoc) {
00185 switch (m_Role) {
00186 case Uml::tr_MultiA:
00187 assoc->setMulti(QString::null, Uml::A);
00188 break;
00189 case Uml::tr_MultiB:
00190 assoc->setMulti(QString::null, Uml::B);
00191 break;
00192 case Uml::tr_RoleAName:
00193 assoc->setRoleName(QString::null, Uml::A);
00194 break;
00195 case Uml::tr_RoleBName:
00196 assoc->setRoleName(QString::null, Uml::B);
00197 break;
00198 case Uml::tr_ChangeA:
00199 assoc->setChangeability(Uml::chg_Changeable, Uml::A);
00200 break;
00201 case Uml::tr_ChangeB:
00202 assoc->setChangeability(Uml::chg_Changeable, Uml::B);
00203 break;
00204 default:
00205 assoc->setName(QString::null);
00206 break;
00207 }
00208 } else {
00209 MessageWidget *msg = dynamic_cast<MessageWidget*>(m_pLink);
00210 if (msg) {
00211 msg->setName(QString::null);
00212 m_pView->removeWidget(this);
00213 }
00214 }
00215 return;
00216 }
00217 if (m_pLink && m_Role != Uml::tr_Seq_Message && m_Role != Uml::tr_Seq_Message_Self) {
00218 m_pLink->setText(this, newText);
00219 } else {
00220 setText( newText );
00221 UMLApp::app()->getDocument()->setModified(true);
00222 }
00223 setVisible( true );
00224 updateComponentSize();
00225 update();
00226 }
00227
00228 void FloatingTextWidget::setText(const QString &t) {
00229 if (m_Role == Uml::tr_Seq_Message || m_Role == Uml::tr_Seq_Message_Self) {
00230 QString seqNum, op;
00231 m_pLink->getSeqNumAndOp(seqNum, op);
00232 if (seqNum.length() > 0 || op.length() > 0) {
00233 if (! m_pView->getShowOpSig())
00234 op.replace( QRegExp("\\(.*\\)"), "()" );
00235 m_Text = seqNum.append(": ").append( op );
00236 } else
00237 m_Text = t;
00238 } else
00239 m_Text = t;
00240 updateComponentSize();
00241 update();
00242 }
00243
00244 void FloatingTextWidget::setPreText (const QString &t)
00245 {
00246 m_PreText = t;
00247 updateComponentSize();
00248 update();
00249 }
00250
00251 void FloatingTextWidget::setPostText(const QString &t) {
00252 m_PostText = t;
00253 updateComponentSize();
00254 update();
00255 }
00256
00257 void FloatingTextWidget::changeTextDlg() {
00258 bool ok = false;
00259 QString newText = KInputDialog::getText(i18n("Change Text"), i18n("Enter new text:"), getText(), &ok, m_pView);
00260
00261 if(ok && newText != getText() && isTextValid(newText)) {
00262 setText( newText );
00263 setVisible( ( getText().length() > 0 ) );
00264 updateComponentSize();
00265 update();
00266 }
00267 if(!isTextValid(newText))
00268 hide();
00269 }
00270
00271 void FloatingTextWidget::showOpDlg() {
00272 if (m_pLink == NULL) {
00273 kError() << "FloatingTextWidget::showOpDlg: m_pLink is NULL" << endl;
00274 return;
00275 }
00276 QString seqNum, opText;
00277 UMLClassifier* c = m_pLink->getSeqNumAndOp(seqNum, opText);
00278 if (c == NULL) {
00279 kError() << "FloatingTextWidget::showOpDlg: "
00280 << "m_pLink->getSeqNumAndOp() returns a NULL classifier"
00281 << endl;
00282 return;
00283 }
00284
00285 SelectOpDlg selectDlg(m_pView, c);
00286 selectDlg.setSeqNumber( seqNum );
00287 if (m_pLink->getOperation() == NULL) {
00288 selectDlg.setCustomOp( opText );
00289 } else {
00290 selectDlg.setClassOp( opText );
00291 }
00292 int result = selectDlg.exec();
00293 if(!result) {
00294 return;
00295 }
00296 seqNum = selectDlg.getSeqNumber();
00297 opText = selectDlg.getOpText();
00298 if (selectDlg.isClassOp()) {
00299 Model_Utils::OpDescriptor od;
00300 Model_Utils::Parse_Status st = Model_Utils::parseOperation(opText, od, c);
00301 if (st == Model_Utils::PS_OK) {
00302 UMLClassifierList selfAndAncestors = c->findSuperClassConcepts();
00303 selfAndAncestors.prepend(c);
00304 UMLOperation *op = NULL;
00305 for (UMLClassifier *cl = selfAndAncestors.first(); cl; cl = selfAndAncestors.next()) {
00306 op = cl->findOperation(od.m_name, od.m_args);
00307 if (op != NULL)
00308 break;
00309 }
00310 if (op == NULL) {
00311
00312 UMLObject *o = c->createOperation(od.m_name, NULL, &od.m_args);
00313 op = static_cast<UMLOperation*>(o);
00314 }
00315 if (od.m_pReturnType)
00316 op->setType(od.m_pReturnType);
00317 m_pLink->setOperation(op);
00318 opText = QString::null;
00319 } else {
00320 m_pLink->setOperation(NULL);
00321 }
00322 } else {
00323 m_pLink->setOperation(NULL);
00324 }
00325 m_pLink->setSeqNumAndOp(seqNum, opText);
00326 setMessageText();
00327 }
00328
00329 QString FloatingTextWidget::getPreText() const {
00330 return m_PreText;
00331 }
00332
00333 QString FloatingTextWidget::getPostText() const {
00334 return m_PostText;
00335 }
00336
00337 QString FloatingTextWidget::getText() const {
00338
00339
00340
00341
00342 if(m_Role == Uml::tr_Seq_Message || m_Role == Uml::tr_Seq_Message_Self ||
00343 m_Role == Uml::tr_Coll_Message || m_Role == Uml::tr_Coll_Message_Self) {
00344 if( m_Text.length() <= 1 || m_Text == ": " )
00345 return "";
00346 }
00347 return m_Text;
00348 }
00349
00350 QString FloatingTextWidget::getDisplayText() const
00351 {
00352 QString displayText = m_Text;
00353 displayText.prepend(m_PreText);
00354 displayText.append(m_PostText);
00355 return displayText;
00356 }
00357
00358 bool FloatingTextWidget::activate( IDChangeLog* ChangeLog ) {
00359 if (! UMLWidget::activate(ChangeLog))
00360 return false;
00361 update();
00362 return true;
00363 }
00364
00365 void FloatingTextWidget::setLink(LinkWidget * l) {
00366 m_pLink = l;
00367 }
00368
00369 LinkWidget * FloatingTextWidget::getLink() {
00370 return m_pLink;
00371 }
00372
00373 void FloatingTextWidget::setRole(Uml::Text_Role role) {
00374 m_Role = role;
00375 }
00376
00377 Uml::Text_Role FloatingTextWidget::getRole() const {
00378 return m_Role;
00379 }
00380
00381 bool FloatingTextWidget::isTextValid( const QString &text ) {
00382 int length = text.length();
00383 if(length < 1)
00384 return false;
00385 for(int i=0;i<length;i++)
00386 if(!text.at(i).isSpace())
00387 return true;
00388 return false;
00389 }
00390
00391 void FloatingTextWidget::showProperties() {
00392 if (m_Role == Uml::tr_Coll_Message || m_Role == Uml::tr_Coll_Message_Self ||
00393 m_Role == Uml::tr_Seq_Message || m_Role == Uml::tr_Seq_Message_Self) {
00394 showOpDlg();
00395 } else if (m_Role == Uml::tr_Floating) {
00396
00397 handleRename();
00398 } else if (m_pLink) {
00399 m_pLink->showDialog();
00400 }
00401 }
00402
00403 void FloatingTextWidget::saveToXMI( QDomDocument & qDoc, QDomElement & qElement ) {
00404 QDomElement textElement = qDoc.createElement( "floatingtext" );
00405 UMLWidget::saveToXMI( qDoc, textElement );
00406 textElement.setAttribute( "text", m_Text );
00407 textElement.setAttribute( "pretext", m_PreText );
00408 textElement.setAttribute( "posttext", m_PostText );
00409
00410
00411
00412
00413
00414
00415 textElement.setAttribute( "role", m_Role );
00416 qElement.appendChild( textElement );
00417 }
00418
00419 bool FloatingTextWidget::loadFromXMI( QDomElement & qElement ) {
00420 if( !UMLWidget::loadFromXMI( qElement ) )
00421 return false;
00422
00423 QString role = qElement.attribute( "role", "" );
00424 if( !role.isEmpty() )
00425 m_Role = (Uml::Text_Role)role.toInt();
00426
00427 m_PreText = qElement.attribute( "pretext", "" );
00428 m_PostText = qElement.attribute( "posttext", "" );
00429 m_Text = qElement.attribute( "text", "" );
00430
00431
00432
00433
00434
00435 bool isDummy = (m_Text.isEmpty() && m_PreText.isEmpty() && m_PostText.isEmpty());
00436 return !isDummy;
00437 }
00438
00439 void FloatingTextWidget::setMessageText() {
00440 if (m_pLink)
00441 m_pLink->setMessageText(this);
00442 setVisible(getText().length() > 0);
00443 updateComponentSize();
00444 }
00445
00446
00447 #include "floatingtextwidget.moc"
00448