kig_part.cpp 32.9 KB
Newer Older
1 2
/**
 This file is part of Kig, a KDE program for Interactive Geometry...
3
 Copyright (C) 2002  Dominique Devriese <devriese@kde.org>
4

5 6 7 8 9 10 11 12 13
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
14

15 16
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
Dirk Mueller's avatar
Dirk Mueller committed
17
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
18 19 20
 USA
**/

21 22
#include "kig_part.h"

23 24
#include <kigpart_export.h>

25
#include "aboutdata.h"
26
#include "kig_commands.h"
27
#include "kig_document.h"
28
#include "kig_view.h"
29

30 31 32 33 34
#include "../filters/exporter.h"
#include "../filters/filter.h"
#include "../misc/builtin_stuff.h"
#include "../misc/calcpaths.h"
#include "../misc/coordinate_system.h"
Dominique Devriese's avatar
Dominique Devriese committed
35
#include "../misc/guiaction.h"
36
#include "../misc/kigcoordinateprecisiondialog.h"
37
#include "../misc/kigpainter.h"
Dominique Devriese's avatar
oops  
Dominique Devriese committed
38
#include "../misc/lists.h"
Dominique Devriese's avatar
Dominique Devriese committed
39
#include "../misc/object_constructor.h"
40 41
#include "../misc/screeninfo.h"
#include "../modes/normal.h"
42
#include "../objects/object_drawer.h"
Dominique Devriese's avatar
Dominique Devriese committed
43
#include "../objects/point_imp.h"
44

45 46
#include <algorithm>
#include <functional>
Carlo Segato's avatar
Carlo Segato committed
47
#include <iterator>
48

49
#include <QDirIterator>
50 51
#include <QFileDialog>
#include <QFile>
52 53
#include <QMimeType>
#include <QMimeDatabase>
54
#include <QPrintDialog>
55 56
#include <QPrinter>
#include <QPrintPreviewDialog>
57
#include <QStandardPaths>
58
#include <QTimer>
David Narváez's avatar
David Narváez committed
59 60

#include <KAboutData>
61 62 63 64
#include <KActionCollection>
#include <KIconLoader>
#include <KIconEngine>
#include <KMessageBox>
David Narváez's avatar
David Narváez committed
65
#include <KUndoActions>
David Narváez's avatar
David Narváez committed
66
#include <KPluginFactory>
67 68
#include <KStandardAction>
#include <KToggleAction>
David Narváez's avatar
David Narváez committed
69 70

#include <KParts/OpenUrlArguments>
71

72
using namespace std;
73

74 75
static const QString typesFile = "macros.kigt";

76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
QStringList getDataFiles( const QString & folder )
{
  QStringList dataFiles;
  const QStringList allFolders = QStandardPaths::locateAll( QStandardPaths::DataLocation, folder, QStandardPaths::LocateDirectory );

  for( const QString & folderPath : allFolders )
  {
    QDirIterator folderIterator( folderPath, QDirIterator::Subdirectories );

    while ( folderIterator.hasNext() )
    {
      const QString fileName = folderIterator.next();

      if ( fileName.endsWith( ".kigt" ) )
      {
        dataFiles << fileName;
      }
    }
  }

  return dataFiles;
}

99
// export this library...
100
K_PLUGIN_FACTORY( KigPartFactory, registerPlugin< KigPart >(); )
101

102
SetCoordinateSystemAction::SetCoordinateSystemAction(
103
  KigPart& d, KActionCollection* parent )
Thomas Zander's avatar
Thomas Zander committed
104
  : KSelectAction( i18n( "&Set Coordinate System" ), &d),
105
    md( d )
106
{
107 108
  setItems( CoordinateSystemFactory::names() );
  setCurrentItem( md.document().coordinateSystem().id() );
Pino Toscano's avatar
Pino Toscano committed
109
  connect( this, SIGNAL( triggered( int ) ), this, SLOT( slotActivated( int ) ) );
Thomas Zander's avatar
Thomas Zander committed
110 111
  if(parent)
    parent->addAction("settings_set_coordinate_system", this);
Dirk Mueller's avatar
Dirk Mueller committed
112
}
113

114
void SetCoordinateSystemAction::slotActivated( int index )
115
{
116
  CoordinateSystem* sys = CoordinateSystemFactory::build( index );
117
  assert( sys );
118
  md.history()->push( KigCommand::changeCoordSystemCommand( md, sys ) );
119
  setCurrentItem( index );
Dirk Mueller's avatar
Dirk Mueller committed
120
}
121

122
class KigPrintDialogPage
123
  : public QWidget
124 125
{
public:
Pino Toscano's avatar
Pino Toscano committed
126
  KigPrintDialogPage( QWidget* parent = 0 );
127 128
  ~KigPrintDialogPage();

129 130 131 132 133 134
  bool printShowGrid();
  void setPrintShowGrid( bool status );

  bool printShowAxes();
  void setPrintShowAxes( bool status );

135 136 137 138 139 140 141
  bool isValid( QString& );

private:
  QCheckBox *showgrid;
  QCheckBox *showaxes;
};

Pino Toscano's avatar
Pino Toscano committed
142
KigPrintDialogPage::KigPrintDialogPage( QWidget* parent )
143
 : QWidget( parent )
144
{
145
  setWindowTitle( i18n( "Kig Options" ) );
146

Pino Toscano's avatar
Pino Toscano committed
147
  QVBoxLayout* vl = new QVBoxLayout( this );
148

149 150
  showgrid = new QCheckBox( i18n( "Show grid" ), this );
  vl->addWidget( showgrid );
151

152 153
  showaxes = new QCheckBox( i18n( "Show axes" ), this );
  vl->addWidget( showaxes );
154

155
  vl->addItem( new QSpacerItem( 10, 10, QSizePolicy::Fixed, QSizePolicy::Expanding ) );
156 157 158 159 160 161
}

KigPrintDialogPage::~KigPrintDialogPage()
{
}

162
bool KigPrintDialogPage::printShowGrid()
163
{
164
  return showgrid->isChecked();
165 166
}

167
void KigPrintDialogPage::setPrintShowGrid( bool status )
168
{
169 170 171 172 173 174 175 176 177 178 179
  showgrid->setChecked( status );
}

bool KigPrintDialogPage::printShowAxes()
{
  return showaxes->isChecked();
}

void KigPrintDialogPage::setPrintShowAxes( bool status )
{
  showaxes->setChecked( status );
180 181 182 183 184 185 186
}

bool KigPrintDialogPage::isValid( QString& )
{
  return true;
}

187
KigPart::KigPart( QWidget *parentWidget, QObject *parent,
188
                  const QVariantList& )
189
  : KParts::ReadWritePart( parent ),
190
    mMode( 0 ), mRememberConstruction( 0 ), mdocument( new KigDocument() )
191 192
{
  // we need an instance
David Narváez's avatar
David Narváez committed
193
  setComponentData( kigAboutData( "kig", I18N_NOOP( "KigPart" ) ) );
194

195 196
  mMode = new NormalMode( *this );

197
  // we need a widget, to actually show the document
198 199
  m_widget = new KigView( this, false, parentWidget );
  m_widget->setObjectName( "kig_view" );
200
  // notify the part that this is our internal widget
201 202
  setWidget( m_widget );

203 204 205
  // create our actions...
  setupActions();

206 207 208
  // set our XML-UI resource file
  setXMLFile("kigpartui.rc");

209 210 211
  // our types...
  setupTypes();

212
  // construct our command history
David Narváez's avatar
David Narváez committed
213 214 215
  mhistory = new QUndoStack();
  KUndoActions::createUndoAction( mhistory, actionCollection() );
  KUndoActions::createRedoAction( mhistory, actionCollection() );
216
  connect( mhistory, SIGNAL( cleanChanged( bool ) ), this, SLOT( setHistoryClean( bool ) ) );
217

218 219 220 221
  // we are read-write by default
  setReadWrite(true);

  setModified (false);
222

223
  GUIActionList::instance()->regDoc( this );
224 225
}

226
void KigPart::setupActions()
227
{
228
  // save actions..
Aaron J. Seigo's avatar
Aaron J. Seigo committed
229 230
  (void) KStandardAction::saveAs(this, SLOT(fileSaveAs()), actionCollection());
  (void) KStandardAction::save(this, SLOT(fileSave()), actionCollection());
231 232

  // print actions
Aaron J. Seigo's avatar
Aaron J. Seigo committed
233 234
  (void) KStandardAction::print( this, SLOT( filePrint() ), actionCollection() );
  (void) KStandardAction::printPreview( this, SLOT( filePrintPreview() ), actionCollection() );
235

236
  // selection actions
Aaron J. Seigo's avatar
Aaron J. Seigo committed
237
  aSelectAll = KStandardAction::selectAll(
238
    this, SLOT( slotSelectAll() ), actionCollection() );
Aaron J. Seigo's avatar
Aaron J. Seigo committed
239
  aDeselectAll = KStandardAction::deselect(
240
    this, SLOT( slotDeselectAll() ), actionCollection() );
David Narváez's avatar
David Narváez committed
241
  aInvertSelection  = new QAction(i18n("Invert Selection"), this);
Thomas Zander's avatar
Thomas Zander committed
242
  actionCollection()->addAction("edit_invert_selection", aInvertSelection );
Stephan Kulow's avatar
Stephan Kulow committed
243
  connect(aInvertSelection, SIGNAL(triggered(bool) ), SLOT( slotInvertSelection() ));
244

245
  // we need icons...
246
  KIconLoader* l = iconLoader();
247

David Narváez's avatar
David Narváez committed
248
  aDeleteObjects  = new QAction(QIcon::fromTheme("edit-delete"), i18n("&Delete Objects"), this);
Thomas Zander's avatar
Thomas Zander committed
249
  actionCollection()->addAction("delete_objects", aDeleteObjects );
Stephan Kulow's avatar
Stephan Kulow committed
250
  connect(aDeleteObjects, SIGNAL(triggered(bool) ), SLOT(deleteObjects()));
251
  aDeleteObjects->setShortcut(QKeySequence(Qt::Key_Delete));
252 253
  aDeleteObjects->setToolTip(i18n("Delete the selected objects"));

David Narváez's avatar
David Narváez committed
254
  aCancelConstruction  = new QAction(QIcon::fromTheme("process-stop"), i18n("Cancel Construction"), this);
Thomas Zander's avatar
Thomas Zander committed
255
  actionCollection()->addAction("cancel_construction", aCancelConstruction );
Stephan Kulow's avatar
Stephan Kulow committed
256
  connect(aCancelConstruction, SIGNAL(triggered(bool) ), SLOT(cancelConstruction()));
257
  aCancelConstruction->setShortcut(QKeySequence(Qt::Key_Escape));
258 259 260 261
  aCancelConstruction->setToolTip(
      i18n("Cancel the construction of the object being constructed"));
  aCancelConstruction->setEnabled(false);

David Narváez's avatar
David Narváez committed
262
  aRepeatLastConstruction = new QAction(QIcon::fromTheme("system-run"), i18n("Repeat Construction"), this);
263 264 265 266 267 268 269
  actionCollection()->addAction("repeat_last_construction", aRepeatLastConstruction );
  connect(aRepeatLastConstruction, SIGNAL(triggered(bool) ), SLOT(repeatLastConstruction()));
  aRepeatLastConstruction->setShortcut(QKeySequence(Qt::Key_Z));
  aRepeatLastConstruction->setToolTip(
      i18n("Repeat the last construction (with new data)"));
  aRepeatLastConstruction->setEnabled(false);

David Narváez's avatar
David Narváez committed
270
  aShowHidden  = new QAction(i18n("U&nhide All"), this);
Thomas Zander's avatar
Thomas Zander committed
271
  actionCollection()->addAction("edit_unhide_all", aShowHidden );
Stephan Kulow's avatar
Stephan Kulow committed
272
  connect(aShowHidden, SIGNAL(triggered(bool) ), SLOT( showHidden() ));
273 274 275
  aShowHidden->setToolTip(i18n("Show all hidden objects"));
  aShowHidden->setEnabled( true );

David Narváez's avatar
David Narváez committed
276
  aNewMacro  = new QAction(QIcon::fromTheme("system-run"), i18n("&New Macro..."), this);
Thomas Zander's avatar
Thomas Zander committed
277
  actionCollection()->addAction("macro_action", aNewMacro );
Stephan Kulow's avatar
Stephan Kulow committed
278
  connect(aNewMacro, SIGNAL(triggered(bool) ), SLOT(newMacro()));
279 280
  aNewMacro->setToolTip(i18n("Define a new macro"));

David Narváez's avatar
David Narváez committed
281
  aConfigureTypes  = new QAction(i18n("Manage &Types..."), this);
Thomas Zander's avatar
Thomas Zander committed
282
  actionCollection()->addAction("types_edit", aConfigureTypes );
Stephan Kulow's avatar
Stephan Kulow committed
283
  connect(aConfigureTypes, SIGNAL(triggered(bool) ), SLOT(editTypes()));
284
  aConfigureTypes->setToolTip(i18n("Manage macro types."));
285

David Narváez's avatar
David Narváez committed
286
  aBrowseHistory  = new QAction(QIcon::fromTheme("view-history"), i18n("&Browse History..."), this);
Thomas Zander's avatar
Thomas Zander committed
287
  actionCollection()->addAction("browse_history", aBrowseHistory );
288
  connect( aBrowseHistory, SIGNAL( triggered( bool ) ), SLOT( browseHistory() ) );
Pino Toscano's avatar
Pino Toscano committed
289
  aBrowseHistory->setToolTip( i18n( "Browse the history of the current construction." ) );
290

Dominique Devriese's avatar
Dominique Devriese committed
291
  KigExportManager::instance()->addMenuAction( this, m_widget->realWidget(),
292
                                               actionCollection() );
293

Thomas Zander's avatar
Thomas Zander committed
294
  QAction * a = KStandardAction::zoomIn( m_widget, SLOT( slotZoomIn() ),
295
                                   actionCollection() );
296 297
  a->setToolTip( i18n( "Zoom in on the document" ) );
  a->setWhatsThis( i18n( "Zoom in on the document" ) );
298

Aaron J. Seigo's avatar
Aaron J. Seigo committed
299
  a = KStandardAction::zoomOut( m_widget, SLOT( slotZoomOut() ),
300
                           actionCollection() );
301 302
  a->setToolTip( i18n( "Zoom out of the document" ) );
  a->setWhatsThis( i18n( "Zoom out of the document" ) );
303

Aaron J. Seigo's avatar
Aaron J. Seigo committed
304
  a = KStandardAction::fitToPage( m_widget, SLOT( slotRecenterScreen() ),
305
                             actionCollection() );
306
  // grr.. why isn't there an icon for this..
David Narváez's avatar
David Narváez committed
307
  a->setIcon( QIcon( new KIconEngine( "view_fit_to_page", l ) ) );
308 309
  a->setToolTip( i18n( "Recenter the screen on the document" ) );
  a->setWhatsThis( i18n( "Recenter the screen on the document" ) );
310

Thomas Zander's avatar
Thomas Zander committed
311
  a = actionCollection()->addAction(KStandardAction::FullScreen, "fullscreen", m_widget, SLOT( toggleFullScreen() ));
312 313
  a->setToolTip( i18n( "View this document full-screen." ) );
  a->setWhatsThis( i18n( "View this document full-screen." ) );
314

315
  // TODO: an icon for this..
David Narváez's avatar
David Narváez committed
316
  a  = new QAction(QIcon::fromTheme("zoom-fit-best"), i18n("&Select Shown Area"), this);
Thomas Zander's avatar
Thomas Zander committed
317
  actionCollection()->addAction("view_select_shown_rect", a );
Stephan Kulow's avatar
Stephan Kulow committed
318
  connect(a, SIGNAL(triggered(bool) ), m_widget, SLOT( zoomRect() ));
319 320
  a->setToolTip( i18n( "Select the area that you want to be shown in the window." ) );
  a->setWhatsThis( i18n( "Select the area that you want to be shown in the window." ) );
321

David Narváez's avatar
David Narváez committed
322
  a  = new QAction(QIcon::fromTheme("zoom-original"), i18n("S&elect Zoom Area"), this);
Thomas Zander's avatar
Thomas Zander committed
323
  actionCollection()->addAction("view_zoom_area", a );
Stephan Kulow's avatar
Stephan Kulow committed
324
  connect(a, SIGNAL(triggered(bool) ), m_widget, SLOT( zoomArea() ));
325 326 327
//  a->setToolTip( i18n( "Select the area that you want to be shown in the window." ) );
//  a->setWhatsThis( i18n( "Select the area that you want to be shown in the window." ) );

David Narváez's avatar
David Narváez committed
328
  aSetCoordinatePrecision = new QAction(i18n("Set Coordinate &Precision..."), this);
329 330 331 332
  actionCollection()->addAction("settings_set_coordinate_precision", aSetCoordinatePrecision);
  aSetCoordinatePrecision->setToolTip( i18n("Set the floating point precision of coordinates in the document. " ));
  connect(aSetCoordinatePrecision, SIGNAL( triggered() ), this, SLOT( setCoordinatePrecision() ));
  
Thomas Zander's avatar
Thomas Zander committed
333 334
  aToggleGrid  = new KToggleAction(i18n("Show &Grid"), this);
  actionCollection()->addAction("settings_show_grid", aToggleGrid );
335 336
  aToggleGrid->setToolTip( i18n( "Show or hide the grid." ) );
  aToggleGrid->setChecked( true );
Pino Toscano's avatar
Pino Toscano committed
337
  connect( aToggleGrid, SIGNAL( triggered() ), this, SLOT( toggleGrid() ) );
338

Thomas Zander's avatar
Thomas Zander committed
339 340
  aToggleAxes  = new KToggleAction(i18n("Show &Axes"), this);
  actionCollection()->addAction("settings_show_axes", aToggleAxes );
341 342
  aToggleAxes->setToolTip( i18n( "Show or hide the axes." ) );
  aToggleAxes->setChecked( true );
Pino Toscano's avatar
Pino Toscano committed
343
  connect( aToggleAxes, SIGNAL( triggered() ), this, SLOT( toggleAxes() ) );
344

Thomas Zander's avatar
Thomas Zander committed
345 346
  aToggleNightVision  = new KToggleAction(i18n("Wear Infrared Glasses"), this);
  actionCollection()->addAction("settings_toggle_nightvision", aToggleNightVision );
Andrew Coles's avatar
Andrew Coles committed
347
  aToggleNightVision->setToolTip( i18n( "Enable/disable hidden objects' visibility." ) );
348
  aToggleNightVision->setChecked( false );
Pino Toscano's avatar
Pino Toscano committed
349
  connect( aToggleNightVision, SIGNAL( triggered() ), this, SLOT( toggleNightVision() ) );
350

351
  // select coordinate system KActionMenu..
352
  aCoordSystem = new SetCoordinateSystemAction( *this, actionCollection() );
Dirk Mueller's avatar
Dirk Mueller committed
353
}
354

355
void KigPart::setupTypes()
356
{
357
  setupBuiltinStuff();
358
  setupBuiltinMacros();
359
  setupMacroTypes();
360
  GUIActionList& l = *GUIActionList::instance();
361 362
  typedef GUIActionList::avectype::const_iterator iter;
  for ( iter i = l.actions().begin(); i != l.actions().end(); ++i )
363
  {
364
    KigGUIAction* ret = new KigGUIAction( *i, *this );
365 366
    aActions.push_back( ret );
    ret->plug( this );
367
  };
Dirk Mueller's avatar
Dirk Mueller committed
368
}
369

370 371 372 373 374 375 376 377 378
void KigPart::rememberConstruction( ConstructibleAction* ca )
{
  // mp:
  // mRememberConstruction holds a pointer to the last construction
  // done by the user, so that it can be quickly repeated

  mRememberConstruction = ca;
  aRepeatLastConstruction->setEnabled(true);
  aRepeatLastConstruction->setText( 
Pino Toscano's avatar
Pino Toscano committed
379
      i18n( "Repeat Construction (%1)", ca->descriptiveName() ) );
380
  aRepeatLastConstruction->setToolTip(
Pino Toscano's avatar
Pino Toscano committed
381
      i18n( "Repeat %1 (with new data)", ca->descriptiveName() ) );
382 383
}

384
KigPart::~KigPart()
385
{
386
  GUIActionList::instance()->unregDoc( this );
387

388
  // save our types...
389
  saveTypes();
390

391 392
  // objects get deleted automatically, when mobjsref gets
  // destructed..
Dominique Devriese's avatar
Dominique Devriese committed
393

394 395 396
  delete_all( aActions.begin(), aActions.end() );
  aActions.clear();

Dominique Devriese's avatar
Dominique Devriese committed
397
  // cleanup
398
  delete mMode;
399
  delete mhistory;
400 401

  delete mdocument;
402 403
}

404
bool KigPart::openFile()
405
{
406
  QFileInfo fileinfo( localFilePath() );
407 408 409
  if ( ! fileinfo.exists() )
  {
    KMessageBox::sorry( widget(),
410
                        i18n( "The file \"%1\" you tried to open does not exist. "
411
                              "Please verify that you entered the correct path.", localFilePath() ),
412 413 414 415
                        i18n( "File Not Found" ) );
    return false;
  };

416 417 418
  const QMimeDatabase mimeDb;
  QMimeType mimeType = mimeDb.mimeTypeForName( arguments().mimeType() );
  if ( !mimeType.isValid() )
419 420
  {
    // we can always use findByPath instead of findByURL with localFilePath()
421
    mimeType = mimeDb.mimeTypeForFile( localFilePath() );
422
  }
423 424
  qDebug() << "mimetype: " << mimeType.name();
  KigFilter* filter = KigFilters::instance()->find( mimeType.name() );
425 426 427 428 429 430
  if ( !filter )
  {
    // we don't support this mime type...
    KMessageBox::sorry
      (
        widget(),
431
        i18n( "You tried to open a document of type \"%1\"; unfortunately, Kig does not support this format. If you think the format in question would be worth implementing support for, you can open a feature request in <a href=\"https://bugs.kde.org/enter_bug.cgi?product=kig&bug_severity=wishlist\">KDE's bug tracking system</a>"
432
          , mimeType.name()),
433 434
        i18n( "Format Not Supported" ),
        KMessageBox::Notify | KMessageBox::AllowLink
435 436 437
        );
    return false;
  };
438

439
  KigDocument* newdoc = filter->load (localFilePath());
440 441 442
  if ( !newdoc )
  {
    closeUrl();
David Narváez's avatar
David Narváez committed
443
    setUrl( QUrl() );
444 445
    return false;
  }
446 447
  delete mdocument;
  mdocument = newdoc;
448 449 450
  coordSystemChanged( mdocument->coordinateSystem().id() );
  aToggleGrid->setChecked( mdocument->grid() );
  aToggleAxes->setChecked( mdocument->axes() );
451
  aToggleNightVision->setChecked( mdocument->getNightVision() );
452

453
  setModified(false);
454
  mhistory->clear();
455

456
  std::vector<ObjectCalcer*> tmp = calcPath( getAllParents( getAllCalcers( document().objects() ) ) );
457
  for ( std::vector<ObjectCalcer*>::iterator i = tmp.begin(); i != tmp.end(); ++i )
458
    ( *i )->calc( document() );
459
  emit recenterScreen();
460

461
  redrawScreen();
Dominique Devriese's avatar
Dominique Devriese committed
462

463 464 465
  return true;
}

466
bool KigPart::saveFile()
467
{
468
  if ( url().isEmpty() ) return internalSaveAs();
469
  // mimetype:
470 471 472
  const QMimeDatabase mimeDb;
  const QMimeType mimeType = mimeDb.mimeTypeForFile( localFilePath() );
  if ( mimeType.name() != "application/x-kig" )
473 474
  {
    // we don't support this mime type...
475 476 477
    if( KMessageBox::warningYesNo( widget(),
                     i18n( "Kig does not support saving to any other file format than "
                           "its own. Save to Kig's format instead?" ),
478
                     i18n( "Format Not Supported" ), KGuiItem( i18n( "Save Kig Format" ) ), KStandardGuiItem::cancel() ) == KMessageBox::No )
479 480
      return false;
    internalSaveAs();
481 482
  };

483
  if ( KigFilters::instance()->save( document(), localFilePath() ) )
484 485
  {
    setModified ( false );
486
    mhistory->setClean();
487 488
    return true;
  }
489
  return false;
Dirk Mueller's avatar
Dirk Mueller committed
490
}
491

492 493 494 495 496 497 498 499 500 501 502 503 504
bool KigPart::queryClose()
{
  if ( KParts::ReadWritePart::queryClose() )
  {
    if ( mode()->eventLoop() != 0 )
    {
      cancelConstruction();
    }
    return true;
  }
  return false;
}

505
void KigPart::addObject(ObjectHolder* o)
506
{
507 508 509 510 511 512 513
  if ( !misGroupingObjects )
    mhistory->push( KigCommand::addCommand( *this, o ) );
  else
  {
    _addObject( o );
    mcurrentObjectGroup.push_back( o );
  }
Dirk Mueller's avatar
Dirk Mueller committed
514
}
515

516
void KigPart::addObjects( const std::vector<ObjectHolder*>& os )
517
{
518 519 520 521 522 523 524
  if ( !misGroupingObjects )
    mhistory->push( KigCommand::addCommand( *this, os ) );
  else
  {
    _addObjects( os );
    mcurrentObjectGroup.insert( mcurrentObjectGroup.end(), os.begin(), os.end() );
  }
525 526
}

527
void KigPart::_addObject( ObjectHolder* o )
528
{
529
  document().addObject( o );
530
  setModified(true);
Dirk Mueller's avatar
Dirk Mueller committed
531
}
532

533
void KigPart::delObject( ObjectHolder* o )
534
{
535
  // we delete all children and their children etc. too...
536 537 538
  std::vector<ObjectHolder*> os;
  os.push_back( o );
  delObjects( os );
Dirk Mueller's avatar
Dirk Mueller committed
539
}
540

541
void KigPart::_delObjects( const std::vector<ObjectHolder*>& o )
542
{
543
  document().delObjects( o );
544 545 546
  setModified( true );
}

547
void KigPart::_delObject(ObjectHolder* o)
548
{
549
  document().delObject( o );
550
  setModified(true);
Dirk Mueller's avatar
Dirk Mueller committed
551
}
552

553
void KigPart::setMode( KigMode* m )
554
{
555 556
  mMode = m;
  m->enableActions();
557
  redrawScreen();
558
}
559

560
void KigPart::_addObjects( const std::vector<ObjectHolder*>& os )
561
{
562
  document().addObjects( os );
563
  setModified( true );
564 565
}

566
void KigPart::deleteObjects()
567
{
568
  mode()->deleteObjects();
569
}
570

571 572 573
void KigPart::startObjectGroup()
{
  if ( mcurrentObjectGroup.size() > 0 )
David Narváez's avatar
David Narváez committed
574
    qWarning() << "New object group started while already having objects in object group. Current group will be lost";
575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594
  
  mcurrentObjectGroup.clear();
  misGroupingObjects = true;
}

void KigPart::cancelObjectGroup()
{
  misGroupingObjects = false;
  _delObjects( mcurrentObjectGroup );
  mcurrentObjectGroup.clear();
}

void KigPart::finishObjectGroup()
{
  misGroupingObjects = false;
  _delObjects( mcurrentObjectGroup );
  addObjects( mcurrentObjectGroup );
  mcurrentObjectGroup.clear();
}

595
void KigPart::cancelConstruction()
596
{
597
  mode()->cancelConstruction();
598
}
599

600 601 602 603 604 605 606 607 608
void KigPart::repeatLastConstruction()
{
  if ( mRememberConstruction )
  {
    ConstructibleAction* ca = mRememberConstruction;
    ca->act( *this );
  }
}

609
void KigPart::showHidden()
610
{
611
  mode()->showHidden();
612 613
}

614
void KigPart::newMacro()
615
{
616
  mode()->newMacro();
617
}
618

619
void KigPart::editTypes()
620
{
621
  mode()->editTypes();
622 623
}

624 625 626 627 628
void KigPart::browseHistory()
{
  mode()->browseHistory();
}

629
void KigPart::setHistoryClean( bool clean )
630
{
631
  setModified( !clean );
632
}
633

634 635 636 637 638 639 640 641 642 643 644 645
void KigPart::setCoordinatePrecision()
{
  KigCoordinatePrecisionDialog dlg(document().isUserSpecifiedCoordinatePrecision(), document().getCoordinatePrecision() );
  
  if( dlg.exec() == QDialog::Accepted )
  {
    int coordinatePrecision = dlg.getUserSpecifiedCoordinatePrecision();
    
    document().setCoordinatePrecision( coordinatePrecision );
  }
}

646
QUndoStack* KigPart::history()
647
{
648
  return mhistory;
649
}
650

651
void KigPart::delObjects( const std::vector<ObjectHolder*>& os )
652
{
653 654 655
  if ( os.size() < 1 ) return;
  std::set<ObjectHolder*> delobjs;

656
  std::set<ObjectCalcer*> delcalcers = getAllChildren( getAllCalcers( os ) );
657 658
  std::map<ObjectCalcer*, ObjectHolder*> holdermap;

659 660 661 662
  std::set<ObjectHolder*> curobjs = document().objectsSet();

  for ( std::set<ObjectHolder*>::iterator i = curobjs.begin();
        i != curobjs.end(); ++i )
663 664 665 666 667 668 669 670 671 672 673
    holdermap[( *i )->calcer()] = *i;

  for ( std::set<ObjectCalcer*>::iterator i = delcalcers.begin();
        i != delcalcers.end(); ++i )
  {
    std::map<ObjectCalcer*, ObjectHolder*>::iterator j = holdermap.find( *i );
    if ( j != holdermap.end() )
      delobjs.insert( j->second );
  }

  assert( delobjs.size() >= os.size() );
674

675
  std::vector<ObjectHolder*> delobjsvect( delobjs.begin(), delobjs.end() );
676
  mhistory->push( KigCommand::removeCommand( *this, delobjsvect ) );
677
}
678

679
void KigPart::enableConstructActions( bool enabled )
680
{
681
  for_each( aActions.begin(), aActions.end(),
David Narváez's avatar
David Narváez committed
682
            bind2nd( mem_fun( &QAction::setEnabled ),
683
                     enabled ) );
684 685
}

686
void KigPart::unplugActionLists()
687
{
688
  unplugActionList( "user_conic_types" );
689 690 691 692 693 694
  unplugActionList( "user_segment_types" );
  unplugActionList( "user_point_types" );
  unplugActionList( "user_circle_types" );
  unplugActionList( "user_line_types" );
  unplugActionList( "user_other_types" );
  unplugActionList( "user_types" );
Dirk Mueller's avatar
Dirk Mueller committed
695
}
696

697
void KigPart::plugActionLists()
698
{
699
  plugActionList( "user_conic_types", aMNewConic );
700 701 702 703 704 705
  plugActionList( "user_segment_types", aMNewSegment );
  plugActionList( "user_point_types", aMNewPoint );
  plugActionList( "user_circle_types", aMNewCircle );
  plugActionList( "user_line_types", aMNewLine );
  plugActionList( "user_other_types", aMNewOther );
  plugActionList( "user_types", aMNewAll );
Dirk Mueller's avatar
Dirk Mueller committed
706
}
707

708
void KigPart::emitStatusBarText( const QString& text )
709 710 711
{
  emit setStatusBarText( text );
}
712

713
void KigPart::fileSaveAs()
714 715 716 717
{
  internalSaveAs();
}

718
void KigPart::fileSave()
719 720 721 722
{
  save();
}

723
bool KigPart::internalSaveAs()
724
{
Aaron J. Seigo's avatar
Aaron J. Seigo committed
725
  // this slot is connected to the KStandardAction::saveAs action...
David Narváez's avatar
David Narváez committed
726
  QString formats = i18n( "Kig Documents (*.kig);;Compressed Kig Documents (*.kigz)" );
727
  QString currentDir = url().toLocalFile();
728

729 730 731 732
  if ( currentDir.isNull() )
  {
    currentDir = QStandardPaths::writableLocation( QStandardPaths::DocumentsLocation );
  }
733

734
  const QString file_name = QFileDialog::getSaveFileName( 0, QString(), currentDir, formats );
735
  if (file_name.isEmpty()) return false;
736
  else if ( QFileInfo( file_name ).exists() )
737
  {
738
    int ret = KMessageBox::warningContinueCancel( m_widget,
739
                                         i18n( "The file \"%1\" already exists. Do you wish to overwrite it?" ,
740
                                           file_name ), i18n( "Overwrite File?" ), KStandardGuiItem::overwrite() );
741
    if ( ret != KMessageBox::Continue )
742 743 744
    {
      return false;
    }
745
  }
David Narváez's avatar
David Narváez committed
746
  saveAs( QUrl::fromLocalFile( file_name ) );
747
  return true;
748
}
749

750
void KigPart::runMode( KigMode* m )
751 752 753 754 755
{
  KigMode* prev = mMode;

  setMode( m );

756 757 758
  QEventLoop e;
  m->setEventLoop( &e );
  e.exec( QEventLoop::AllEvents | QEventLoop::WaitForMoreEvents );
759 760

  setMode( prev );
Dominique Devriese's avatar
Dominique Devriese committed
761
  redrawScreen();
762 763
}

764
void KigPart::doneMode( KigMode* d )
765 766
{
  assert( d == mMode );
767 768 769

  if ( d->eventLoop() )
    d->eventLoop()->exit();
770
}
771

772
void KigPart::actionRemoved( GUIAction* a, GUIUpdateToken& t )
773 774
{
  KigGUIAction* rem = 0;
775
  for ( std::vector<KigGUIAction*>::iterator i = aActions.begin(); i != aActions.end(); ++i )
776
  {
777 778 779 780 781 782
    if ( (*i)->guiAction() == a )
    {
      rem = *i;
      aActions.erase( i );
      break;
    }
783 784
  };
  assert( rem );
785 786 787 788 789 790 791
  aMNewSegment.removeAll( rem );
  aMNewConic.removeAll( rem );
  aMNewPoint.removeAll( rem );
  aMNewCircle.removeAll( rem );
  aMNewLine.removeAll( rem );
  aMNewOther.removeAll( rem );
  aMNewAll.removeAll( rem );