maindlg.cpp 25 KB
Newer Older
1 2 3
/*
* KmPlot - a math. function plotter for the KDE-Desktop
*
David Saxton's avatar
David Saxton committed
4 5
* Copyright (C) 1998, 1999, 2000, 2002  Klaus-Dieter M�ler <kd.moeller@t-online.de>
*                                 2006  David Saxton <david@bluehaze.org>
6
*
7 8 9 10 11 12 13
* This file is part of the KDE Project.
* KmPlot is part of the KDE-EDU Project.
*
* 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.
14
*
15 16 17 18
* 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.
19
*
20 21
* 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
22
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
23 24 25
*
*/

Peter Hedlund's avatar
Peter Hedlund committed
26 27
#include "maindlg.h"

28
// Qt includes
29
#include <QMainWindow>
30
#include <QPainter>
Laurent Montel's avatar
Laurent Montel committed
31
#include <QPixmap>
32 33
#include <QSlider>
#include <QSvgGenerator>
David Saxton's avatar
David Saxton committed
34
#include <QTimer>
35 36

// KDE includes
37
#include <kaboutdata.h>
38
#include <kconfigdialog.h>
39
#include <kconfigdialogmanager.h>
40
#include <kdebug.h>
41
#include <kedittoolbar.h>
42
#include <kimageio.h>
43
#include <kio/netaccess.h>
44
#include <kcomponentdata.h>
45
#include <klineedit.h>
46 47
#include <klocale.h>
#include <kmessagebox.h>
48
#include <kstandarddirs.h>
Aaron J. Seigo's avatar
Aaron J. Seigo committed
49
#include <kstandardaction.h>
Jaison Lee's avatar
Jaison Lee committed
50
#include <ktemporaryfile.h>
51
#include <ktoolbar.h>
Laurent Montel's avatar
Laurent Montel committed
52
#include <ktoolinvocation.h>
Stephan Kulow's avatar
Stephan Kulow committed
53
#include <krecentfilesaction.h>
54
#include <kactioncollection.h>
Thorsten Roeder's avatar
Thorsten Roeder committed
55
#include <kicon.h>
56
#include <kiconloader.h>
57
#include <kapplication.h>
Peter Hedlund's avatar
Peter Hedlund committed
58
#include <kglobal.h>
59

60
// local includes
61
#include "calculator.h"
62
#include "functiontools.h"
63
#include "functioneditor.h"
64
#include "kprinterdlg.h"
65
#include "kconstanteditor.h"
66
#include "xparser.h"
67

68
#include "settings.h"
69 70
#include "ui_settingspagecolor.h"
#include "ui_settingspagefonts.h"
71
#include "ui_settingspagegeneral.h"
David Saxton's avatar
David Saxton committed
72
#include "ui_settingspagediagram.h"
73
#include "ksliderwindow.h"
74
#include "maindlgadaptor.h"
75

76 77
#include <assert.h>

78 79
class XParser;
class KmPlotIO;
80

81 82 83 84 85 86

class SettingsPageColor : public QWidget, public Ui::SettingsPageColor
{
    public:
        SettingsPageColor( QWidget * parent = 0 )
    : QWidget( parent )
87 88 89 90
        {
			setupUi(this);
			layout()->setMargin(0);
		}
91 92 93 94 95 96
};

class SettingsPageFonts : public QWidget, public Ui::SettingsPageFonts
{
    public:
        SettingsPageFonts( QWidget * parent = 0 )
97 98 99 100 101
	: QWidget( parent )
		{
			setupUi(this);
			layout()->setMargin(0);
		}
102 103 104 105 106 107
};

class SettingsPageGeneral : public QWidget, public Ui::SettingsPageGeneral
{
    public:
        SettingsPageGeneral( QWidget * parent = 0 )
108 109 110 111 112
	: QWidget( parent )
		{
			setupUi(this);
			layout()->setMargin(0);
		}
113 114
};

David Saxton's avatar
David Saxton committed
115 116 117 118 119
class SettingsPageDiagram : public QWidget, public Ui::SettingsPageDiagram
{
	public:
		SettingsPageDiagram( QWidget * parent = 0 )
	: QWidget( parent )
120 121 122 123
		{
			setupUi(this);
			layout()->setMargin(0);
		}
David Saxton's avatar
David Saxton committed
124 125
};

126
bool MainDlg::oldfileversion;
127 128
MainDlg * MainDlg::m_self = 0;

129

130
//BEGIN class MainDlg
Pino Toscano's avatar
Pino Toscano committed
131
MainDlg::MainDlg(QWidget *parentWidget, QObject *parent, const QStringList& ) :
132
		KParts::ReadWritePart( parent ),
133 134 135
		m_recentFiles( 0 ),
		m_modified(false),
		m_parent(parentWidget)
Matthias Messmer's avatar
Matthias Messmer committed
136
{
137 138
	assert( !m_self ); // this class should only be constructed once
	m_self = this;
Stephan Kulow's avatar
Stephan Kulow committed
139

140
	// we need an instance
141
	setComponentData( KmPlotPartFactory::componentData() );
142

143
	kDebug() << "parentWidget->objectName():" << parentWidget->objectName() << endl;
Fredrik Edemar's avatar
Fredrik Edemar committed
144
	if ( QString(parentWidget->objectName()).startsWith("KmPlot") )
145 146 147 148 149 150 151 152 153 154
	{
		setXMLFile("kmplot_part.rc");
		m_readonly = false;
	}
	else
	{
		setXMLFile("kmplot_part_readonly.rc");
		m_readonly = true;
		new BrowserExtension(this); // better integration with Konqueror
	}
Stephan Kulow's avatar
Stephan Kulow committed
155

156
	m_coordsDialog = 0;
157
	m_constantEditor = 0;
158 159
	m_popupmenu = new KMenu( parentWidget );
	m_newPlotMenu = new KMenu( parentWidget );
160
	(void) new View( m_readonly, m_popupmenu, parentWidget );
161
	connect( View::self(), SIGNAL( setStatusBarText(const QString &)), this, SLOT( setReadOnlyStatusBarText(const QString &) ) );
Stephan Kulow's avatar
Stephan Kulow committed
162

163
	m_functionEditor = 0;
164 165
	if ( !m_readonly )
	{
166
		m_functionEditor = new FunctionEditor( m_newPlotMenu, parentWidget );
167 168
		static_cast<QMainWindow*>(parentWidget)->addDockWidget( Qt::LeftDockWidgetArea, m_functionEditor );
	}
Stephan Kulow's avatar
Stephan Kulow committed
169

170 171
	setWidget( View::self() );
	View::self()->setFocusPolicy(Qt::ClickFocus);
172
	m_functionTools = new FunctionTools(m_parent);
173
	m_calculator = new Calculator( m_parent );
174
	setupActions();
175
	XParser::self()->constants()->load();
176
	kmplotio = new KmPlotIO();
Laurent Montel's avatar
Laurent Montel committed
177
	m_config = KGlobal::config();
Stephan Kulow's avatar
ported  
Stephan Kulow committed
178
	m_recentFiles->loadEntries( m_config->group( QString() ) );
Stephan Kulow's avatar
Stephan Kulow committed
179 180


David Saxton's avatar
David Saxton committed
181 182 183 184 185 186
	//BEGIN undo/redo stuff
	m_currentState = kmplotio->currentState();
	m_saveCurrentStateTimer = new QTimer( this );
	m_saveCurrentStateTimer->setSingleShot( true );
	connect( m_saveCurrentStateTimer, SIGNAL(timeout()), this, SLOT(saveCurrentState()) );
	//END undo/redo stuff
Stephan Kulow's avatar
Stephan Kulow committed
187 188 189



190 191
	// Allow config manager to read from equation edits
	KConfigDialogManager::changedMap()->insert( "EquationEdit", SIGNAL(textEdited(const QString &)) );
192
	// Let's create a Configure Diloag
193
	m_settingsDialog = new KConfigDialog( parentWidget, "settings", Settings::self() );
194
	m_settingsDialog->setHelp("general-config");
195

196
	// create and add the page(s)
197 198 199
	m_generalSettings = new SettingsPageGeneral( View::self() );
	m_colorSettings = new SettingsPageColor( View::self() );
	m_fontsSettings = new SettingsPageFonts( View::self() );
David Saxton's avatar
David Saxton committed
200
	m_diagramSettings = new SettingsPageDiagram( View::self() );
201

202 203 204 205
	// Make sure the dialog is at a good default size (hmm kdialog should do this automatically?)
	QSize minSize = m_generalSettings->layout()->minimumSize()
			.expandedTo( m_colorSettings->layout()->minimumSize() )
			.expandedTo( m_fontsSettings->layout()->minimumSize() )
206
			.expandedTo( m_diagramSettings->layout()->minimumSize() );
207
	m_generalSettings->setMinimumSize( minSize );
Stephan Kulow's avatar
Stephan Kulow committed
208

209
	m_settingsDialog->addPage( m_generalSettings, i18n("General"), "tool", i18n("General Settings") );
David Saxton's avatar
David Saxton committed
210
	m_settingsDialog->addPage( m_diagramSettings, i18n("Diagram"), "coords", i18n("Diagram Appearance") );
211 212
	m_settingsDialog->addPage( m_colorSettings, i18n("Colors"), "colorscm", i18n("Colors") );
	m_settingsDialog->addPage( m_fontsSettings, i18n("Fonts"), "text", i18n("Fonts") );
213 214
	// User edited the configuration - update your local copies of the
	// configuration data
215
	connect( m_settingsDialog, SIGNAL( settingsChanged( const QString &) ), View::self(), SLOT(drawPlot() ) );
216 217 218


    new MainDlgAdaptor(this);
219
    QDBusConnection::sessionBus().registerObject("/maindlg", this);
220

221 222 223 224
}

MainDlg::~MainDlg()
{
Stephan Kulow's avatar
ported  
Stephan Kulow committed
225
        m_recentFiles->saveEntries( m_config->group( QString() ) );
226
	XParser::self()->constants()->save();
227
	delete kmplotio;
228 229 230
}

void MainDlg::setupActions()
Matthias Messmer's avatar
Matthias Messmer committed
231
{
232
	// standard actions
233 234 235
        m_recentFiles = KStandardAction::openRecent( this, SLOT( slotOpenRecent( const KUrl& ) ), this );
        actionCollection()->addAction( "file_openrecent", m_recentFiles );
	actionCollection()->addAction( KStandardAction::Print, "file_print", this, SLOT( slotPrint() ) );
Aaron J. Seigo's avatar
Aaron J. Seigo committed
236 237
	KStandardAction::save( this, SLOT( slotSave() ), actionCollection() );
	KStandardAction::saveAs( this, SLOT( slotSaveas() ), actionCollection() );
Matthias Messmer's avatar
Matthias Messmer committed
238
	connect( kapp, SIGNAL( lastWindowClosed() ), kapp, SLOT( quit() ) );
239

240
	QAction *prefs  = KStandardAction::preferences( this, SLOT( slotSettings() ), actionCollection());
241
	prefs->setText( i18n( "Configure KmPlot..." ) );
Aaron J. Seigo's avatar
Aaron J. Seigo committed
242 243
	KStandardAction::keyBindings(this, SLOT(optionsConfigureKeys()), actionCollection());
	KStandardAction::configureToolbars(this, SLOT(optionsConfigureToolbars()), actionCollection());
244

245

246
	// KmPlot specific actions
Stephan Kulow's avatar
Stephan Kulow committed
247

248
	//BEGIN file menu
249 250
	QAction * exportAction = actionCollection()->addAction( "export" );
        exportAction->setText( i18n( "E&xport..." ) );
251 252 253
	connect( exportAction, SIGNAL(triggered(bool)), this, SLOT( slotExport() ) );
	//END file menu

Stephan Kulow's avatar
Stephan Kulow committed
254

David Saxton's avatar
David Saxton committed
255
	//BEGIN edit menu
Aaron J. Seigo's avatar
Aaron J. Seigo committed
256
	m_undoAction = KStandardAction::undo( this, SLOT(undo()), actionCollection() );
David Saxton's avatar
David Saxton committed
257
	m_undoAction->setEnabled( false );
Stephan Kulow's avatar
Stephan Kulow committed
258

Aaron J. Seigo's avatar
Aaron J. Seigo committed
259
	m_redoAction = KStandardAction::redo( this, SLOT(redo()), actionCollection() );
David Saxton's avatar
David Saxton committed
260
	m_redoAction->setEnabled( false );
Stephan Kulow's avatar
Stephan Kulow committed
261

262 263
	QAction * editAxes = actionCollection()->addAction( "editaxes" );
        editAxes->setText( i18n( "&Coordinate System..." ) );
David Saxton's avatar
David Saxton committed
264 265
	editAxes->setIcon( KIcon("coords.png") );
	connect( editAxes, SIGNAL(triggered(bool)), this, SLOT( editAxes() ) );
266

267 268
	QAction * editConstants = actionCollection()->addAction( "editconstants" );
        editConstants->setText( i18n( "&Constants..." ) );
269 270
	editConstants->setIcon( KIcon("editconstants.png") );
	connect( editConstants, SIGNAL(triggered(bool)), this, SLOT( editConstants() ) );
David Saxton's avatar
David Saxton committed
271
	//END edit menu
Stephan Kulow's avatar
Stephan Kulow committed
272 273


274
	//BEGIN view menu
David Saxton's avatar
David Saxton committed
275
	/// \todo check that new shortcuts work
Stephan Kulow's avatar
Stephan Kulow committed
276

277 278
	QAction * zoomIn = actionCollection()->addAction( "zoom_in" );
        zoomIn->setText( i18n("Zoom &In") );
279
	zoomIn->setShortcut( QKeySequence(Qt::ControlModifier | Qt::Key_1) );
Aaron J. Seigo's avatar
Aaron J. Seigo committed
280
	zoomIn->setIcon( KIcon("zoom-in") );
281
	connect( zoomIn, SIGNAL(triggered(bool)), View::self(), SLOT(zoomIn()) );
Stephan Kulow's avatar
Stephan Kulow committed
282

283 284
	QAction * zoomOut = actionCollection()->addAction( "zoom_out" );
        zoomOut->setText(i18n("Zoom &Out"));
285
	zoomOut->setShortcut( QKeySequence(Qt::ControlModifier | Qt::Key_2) );
Aaron J. Seigo's avatar
Aaron J. Seigo committed
286
	zoomOut->setIcon( KIcon("zoom-out") );
287
	connect( zoomOut, SIGNAL(triggered(bool)), View::self(), SLOT( zoomOut() ) );
Stephan Kulow's avatar
Stephan Kulow committed
288

289 290
	QAction * zoomTrig = actionCollection()->addAction( "zoom_trig" );
        zoomTrig->setText( i18n("&Fit Widget to Trigonometric Functions") );
291
	connect( zoomTrig, SIGNAL(triggered(bool)), View::self(), SLOT( zoomToTrigonometric() ) );
Stephan Kulow's avatar
Stephan Kulow committed
292

293 294 295 296
	QAction * resetView = actionCollection()->addAction( "reset_view" );
	resetView->setText( i18n( "Reset View" ) );
	resetView->setIcon( KIcon("resetview") );
	connect( resetView, SIGNAL(triggered(bool)), this, SLOT( slotResetView() ) );
297
	//END view menu
Stephan Kulow's avatar
Stephan Kulow committed
298 299


300
	//BEGIN tools menu
301 302 303 304
	QAction *mnuCalculator = actionCollection()->addAction( "calculator" );
	mnuCalculator->setText( i18n( "Calculator") );
	mnuCalculator->setIcon( KIcon("exec") );
	connect( mnuCalculator, SIGNAL(triggered(bool)), this, SLOT( calculator() ) );
Stephan Kulow's avatar
Stephan Kulow committed
305

306 307
	QAction *mnuArea = actionCollection()->addAction( "grapharea" );
        mnuArea->setText( i18n( "Plot &Area..." ) );
308
	connect( mnuArea, SIGNAL(triggered(bool)),this, SLOT( graphArea() )  );
Stephan Kulow's avatar
Stephan Kulow committed
309

310 311
	QAction *mnuMaxValue = actionCollection()->addAction( "maximumvalue" );
        mnuMaxValue->setText( i18n( "Find Ma&ximum..." ) );
312 313
	mnuMaxValue->setIcon( KIcon("maximum") );
	connect( mnuMaxValue, SIGNAL(triggered(bool)), this, SLOT( findMaximumValue() ) );
Stephan Kulow's avatar
Stephan Kulow committed
314

315 316
	QAction *mnuMinValue = actionCollection()->addAction( "minimumvalue" );
        mnuMinValue->setText( i18n( "Find Mi&nimum..." ) );
317 318
	mnuMinValue->setIcon( KIcon("minimum") );
	connect( mnuMinValue, SIGNAL(triggered(bool)), this, SLOT( findMinimumValue() ) );
319
	//END tools menu
320

Stephan Kulow's avatar
Stephan Kulow committed
321

322
	//BEGIN help menu
323 324
	QAction * namesAction = actionCollection()->addAction( "names" );
        namesAction->setText( i18n( "Predefined &Math Functions" ) );
325 326 327
	namesAction->setIcon( KIcon("functionhelp") );
	connect( namesAction, SIGNAL(triggered(bool)), this, SLOT( slotNames() ) );
	//END help menu
Stephan Kulow's avatar
Stephan Kulow committed
328 329


330
	//BEGIN new plots menu
331 332
	QAction * newFunction = actionCollection()->addAction( "newcartesian" );
        newFunction->setText( i18n( "Cartesian Plot" ) );
333 334
	newFunction->setIcon( KIcon("newfunction") );
	connect( newFunction, SIGNAL(triggered(bool)), m_functionEditor, SLOT( createCartesian() ) );
335
	m_newPlotMenu->addAction( newFunction );
Stephan Kulow's avatar
Stephan Kulow committed
336

337 338
	QAction * newParametric = actionCollection()->addAction( "newparametric" );
        newParametric->setText( i18n( "Parametric Plot" ) );
339 340
	newParametric->setIcon( KIcon("newparametric") );
	connect( newParametric, SIGNAL(triggered(bool)), m_functionEditor, SLOT( createParametric() ) );
341
	m_newPlotMenu->addAction( newParametric );
Stephan Kulow's avatar
Stephan Kulow committed
342

343 344
	QAction * newPolar = actionCollection()->addAction( "newpolar" );
        newPolar->setText( i18n( "Polar Plot" ) );
345 346
	newPolar->setIcon( KIcon("newpolar") );
	connect( newPolar, SIGNAL(triggered(bool)), m_functionEditor, SLOT( createPolar() ) );
347
	m_newPlotMenu->addAction( newPolar );
Stephan Kulow's avatar
Stephan Kulow committed
348

349 350
	QAction * newImplicit = actionCollection()->addAction( "newimplicit" );
        newImplicit->setText( i18n( "Implicit Plot" ) );
351 352 353
	newImplicit->setIcon( KIcon("newimplicit") );
	connect( newImplicit, SIGNAL(triggered(bool)), m_functionEditor, SLOT( createImplicit() ) );
	m_newPlotMenu->addAction( newImplicit );
Stephan Kulow's avatar
Stephan Kulow committed
354

355 356
	QAction * newDifferential = actionCollection()->addAction( "newdifferential" );
        newDifferential->setText( i18n( "Differential Plot" ) );
357 358 359
	newDifferential->setIcon( KIcon("newdifferential") );
	connect( newDifferential, SIGNAL(triggered(bool)), m_functionEditor, SLOT( createDifferential() ) );
	m_newPlotMenu->addAction( newDifferential );
360
	//END new plots menu
Stephan Kulow's avatar
Stephan Kulow committed
361 362


363
	kDebug() << "KStandardDirs::resourceDirs( icon )="<<KGlobal::dirs()->resourceDirs( "icon" )<<endl;
364

365 366
	View::self()->m_menuSliderAction = actionCollection()->add<KToggleAction>( "options_configure_show_sliders" );
        View::self()->m_menuSliderAction->setText( i18n( "Show Sliders" ) );
367
	connect( View::self()->m_menuSliderAction, SIGNAL(triggered(bool)), this, SLOT( toggleShowSliders() ) );
Stephan Kulow's avatar
Stephan Kulow committed
368

369

370
	//BEGIN function popup menu
371 372
	QAction *mnuEdit = actionCollection()->addAction( "mnuedit"  );
        mnuEdit->setText(i18n("&Edit"));
373 374 375 376
	m_firstFunctionAction = mnuEdit;
	mnuEdit->setIcon( KIcon("editplots") );
	connect(mnuEdit , SIGNAL(triggered(bool)), View::self(), SLOT( editCurrentPlot() ) );
	m_popupmenu->addAction( mnuEdit );
377 378 379

	QAction *mnuHide = actionCollection()->addAction( "mnuhide" );
        mnuHide->setText( i18n("&Hide") );
380
	connect( mnuHide, SIGNAL(triggered(bool)), View::self(), SLOT( hideCurrentFunction() ) );
381
	m_popupmenu->addAction( mnuHide );
Stephan Kulow's avatar
Stephan Kulow committed
382

383 384
	QAction *mnuRemove = actionCollection()->addAction( "mnuremove"  );
        mnuRemove->setText(i18n("&Remove"));
Aaron J. Seigo's avatar
Aaron J. Seigo committed
385
	mnuRemove->setIcon( KIcon("edit-delete") );
386
	connect( mnuRemove, SIGNAL(triggered(bool)), View::self(), SLOT( removeCurrentPlot() ) );
387
	m_popupmenu->addAction( mnuRemove );
Stephan Kulow's avatar
Stephan Kulow committed
388

David Saxton's avatar
David Saxton committed
389
	m_popupmenu->addSeparator();
Stephan Kulow's avatar
Stephan Kulow committed
390

391 392
	QAction * animateFunction = actionCollection()->addAction( "animateFunction" );
        animateFunction->setText(i18n("Animate Plot..."));
393 394
	connect( animateFunction, SIGNAL(triggered(bool)), View::self(), SLOT( animateFunction() ) );
	m_popupmenu->addAction( animateFunction );
395
	m_popupmenu->addSeparator();
Stephan Kulow's avatar
Stephan Kulow committed
396

397
	m_popupmenu->addAction( mnuCalculator );
398 399 400
	m_popupmenu->addAction( mnuMinValue );
	m_popupmenu->addAction( mnuMaxValue );
	m_popupmenu->addAction( mnuArea );
401
	//END function popup menu
402
}
403 404


David Saxton's avatar
David Saxton committed
405 406 407
void MainDlg::undo()
{
	kDebug() << k_funcinfo << endl;
Stephan Kulow's avatar
Stephan Kulow committed
408

David Saxton's avatar
David Saxton committed
409 410
	if ( m_undoStack.isEmpty() )
		return;
Stephan Kulow's avatar
Stephan Kulow committed
411

David Saxton's avatar
David Saxton committed
412 413
	m_redoStack.push( m_currentState );
	m_currentState = m_undoStack.pop();
Stephan Kulow's avatar
Stephan Kulow committed
414

David Saxton's avatar
David Saxton committed
415
	kmplotio->restore( m_currentState );
416
	View::self()->drawPlot();
Stephan Kulow's avatar
Stephan Kulow committed
417

David Saxton's avatar
David Saxton committed
418 419 420 421 422 423 424 425
	m_undoAction->setEnabled( !m_undoStack.isEmpty() );
	m_redoAction->setEnabled( true );
}


void MainDlg::redo()
{
	kDebug() << k_funcinfo << endl;
Stephan Kulow's avatar
Stephan Kulow committed
426

David Saxton's avatar
David Saxton committed
427 428
	if ( m_redoStack.isEmpty() )
		return;
Stephan Kulow's avatar
Stephan Kulow committed
429

David Saxton's avatar
David Saxton committed
430 431
	m_undoStack.push( m_currentState );
	m_currentState = m_redoStack.pop();
Stephan Kulow's avatar
Stephan Kulow committed
432

David Saxton's avatar
David Saxton committed
433
	kmplotio->restore( m_currentState );
434
	View::self()->drawPlot();
Stephan Kulow's avatar
Stephan Kulow committed
435

David Saxton's avatar
David Saxton committed
436 437 438 439 440 441 442 443 444 445 446 447 448 449
	m_undoAction->setEnabled( true );
	m_redoAction->setEnabled( !m_redoStack.isEmpty() );
}


void MainDlg::requestSaveCurrentState()
{
	m_saveCurrentStateTimer->start( 0 );
}
void MainDlg::saveCurrentState( )
{
	m_redoStack.clear();
	m_undoStack.push( m_currentState );
	m_currentState = kmplotio->currentState();
Stephan Kulow's avatar
Stephan Kulow committed
450

David Saxton's avatar
David Saxton committed
451 452 453
	// limit stack size to 100 items
	while ( m_undoStack.count() > 100 )
		m_undoStack.pop_front();
Stephan Kulow's avatar
Stephan Kulow committed
454

David Saxton's avatar
David Saxton committed
455 456
	m_undoAction->setEnabled( true );
	m_redoAction->setEnabled( false );
Stephan Kulow's avatar
Stephan Kulow committed
457

458
	m_modified = true;
David Saxton's avatar
David Saxton committed
459 460 461
}


462 463 464 465 466 467 468 469 470 471
void MainDlg::resetUndoRedo()
{
	m_redoStack.clear();
	m_undoStack.clear();
	m_currentState = kmplotio->currentState();
	m_undoAction->setEnabled( false );
	m_redoAction->setEnabled( false );
}


472 473 474 475
bool MainDlg::checkModified()
{
	if( m_modified )
	{
476
		int saveit = KMessageBox::warningYesNoCancel( m_parent, i18n( "The plot has been modified.\n"
477
		             "Do you want to save it?" ), QString(), KStandardGuiItem::save(), KStandardGuiItem::discard() );
478 479
		switch( saveit )
		{
480 481 482 483 484 485
			case KMessageBox::Yes:
				slotSave();
				if ( m_modified) // the user didn't saved the file
					return false;
				break;
			case KMessageBox::Cancel:
486 487 488 489 490
				return false;
		}
	}
	return true;
}
David Saxton's avatar
David Saxton committed
491 492


493
void MainDlg::slotSave()
Matthias Messmer's avatar
Matthias Messmer committed
494
{
495
	if ( !m_modified || m_readonly) //don't save if no changes are made or readonly is enabled
496
		return;
497
	if ( url().isEmpty() )            // if there is no file name set yet
498
		slotSaveas();
499
	else
500
	{
501 502
		if ( !m_modified) //don't save if no changes are made
			return;
503

504 505
		if ( oldfileversion)
		{
506
			if ( KMessageBox::warningContinueCancel( m_parent, i18n( "This file is saved with an old file format; if you save it, you cannot open the file with older versions of KmPlot. Are you sure you want to continue?" ), QString(), KGuiItem(i18n("Save New Format")) ) == KMessageBox::Cancel)
507 508
				return;
		}
509
		kmplotio->save( this->url() );
Pino Toscano's avatar
Pino Toscano committed
510
		kDebug() << "saved" << endl;
511 512
		m_modified = false;
	}
Matthias Messmer's avatar
Matthias Messmer committed
513

Matthias Messmer's avatar
Matthias Messmer committed
514
}
515

516
void MainDlg::slotSaveas()
Matthias Messmer's avatar
Matthias Messmer committed
517
{
518 519
	if (m_readonly)
		return;
David Saxton's avatar
David Saxton committed
520
	const KUrl url = KFileDialog::getSaveUrl( QDir::currentPath(), i18n( "*.fkt|KmPlot Files (*.fkt)\n*|All Files" ), m_parent, i18n( "Save As" ) );
521

522 523
	if ( url.isEmpty() )
		return;
524

525 526
	bool exists = KIO::NetAccess::exists( url,false,m_parent );
	if ( exists )
527
	{
528
		// check if file exists and overwriting is ok.
529

530
		int answer = KMessageBox::warningContinueCancel( m_parent, i18n( "A file named \"%1\" already exists. Are you sure you want to continue and overwrite this file?", url.url()), i18n( "Overwrite File?" ), KGuiItem( i18n( "&Overwrite" ) ) );
531

532
		if ( answer != KMessageBox::Continue )
533
			return;
534
	}
535

536 537 538 539
	if ( !kmplotio->save( url ) )
		KMessageBox::error(m_parent, i18n("The file could not be saved") );
	else
	{
540
		setUrl(url);
541
		m_recentFiles->addUrl( url );
542
		setWindowCaption( this->url().prettyUrl(KUrl::LeaveTrailingSlash) );
543
		m_modified = false;
544
	}
Matthias Messmer's avatar
Matthias Messmer committed
545
}
546

547
void MainDlg::slotExport()
548
{
549 550
	QString filter = KImageIO::pattern( KImageIO::Writing );
	filter += i18n("\n*.svg|Scalable Vector Graphics");
551

552 553
	KFileDialog * kfd = new KFileDialog( QDir::currentPath(), filter, m_parent );
	kfd->setCaption( i18n( "Export as Image" ) );
554

555 556 557 558 559
	if ( !kfd->exec() )
		return;

	KUrl url = kfd->selectedUrl();
	delete kfd;
560 561 562 563 564 565 566 567 568 569 570
	
	bool exists = KIO::NetAccess::exists( url,false,m_parent );
	if ( exists )
	{
		// check if file exists and overwriting is ok.

		int answer = KMessageBox::warningContinueCancel( m_parent, i18n( "A file named \"%1\" already exists. Are you sure you want to continue and overwrite this file?", url.url()), i18n( "Overwrite File?" ), KGuiItem( i18n( "&Overwrite" ) ) );

		if ( answer != KMessageBox::Continue )
			return;
	}
571

572
	KMimeType::Ptr mimeType = KMimeType::findByUrl( url );
573
	kDebug() << k_funcinfo << "mimetype: " << mimeType->name() << endl;
574

575
	bool isSvg = mimeType->name() == "image/svg+xml";
576

577
	if ( !KImageIO::isSupported( mimeType->name(), KImageIO::Writing ) && !isSvg )
578
	{
579
		KMessageBox::sorry( m_parent, i18n( "Sorry, this file format is not supported." ) );
580
		return;
581
	};
Stephan Kulow's avatar
Stephan Kulow committed
582

583
	bool saveOk = true;
584

585
	if ( isSvg )
586
	{
587 588 589 590 591 592
		QSvgGenerator img;
		img.setSize( View::self()->size() );
		
		QFile file;
		KTemporaryFile tmp;
		
593
		if ( url.isLocalFile() )
594 595 596 597
		{
			file.setFileName( url.path() );
			img.setOutputDevice( &file );
		}
598 599
		else
		{
600 601
			tmp.setSuffix( ".svg" );
			img.setOutputDevice( &tmp );
602
		}
603 604 605 606 607
		
		View::self()->draw( &img, View::SVG );
		
		if ( !url.isLocalFile() )
			saveOk &= KIO::NetAccess::upload(tmp.fileName(), url, 0);
608
	}
609
	else
610
	{
611 612
		QPixmap img( View::self()->size() );
		View::self()->draw( & img, View::Pixmap );
613

614 615 616
		QStringList types = KImageIO::typeForMime( mimeType->name() );
		if ( types.isEmpty() )
			return; // TODO error dialog?
617

618 619 620
		if ( url.isLocalFile() )
			saveOk = img.save( url.path(), types.at(0).toLatin1() );
		else
621
		{
Jaison Lee's avatar
Jaison Lee committed
622 623 624 625
			KTemporaryFile tmp;
			tmp.open();
			img.save( tmp.fileName(), types.at(0).toLatin1() );
			saveOk = KIO::NetAccess::upload(tmp.fileName(), url, 0);
626 627
		}
	}
628

629 630
	if ( !saveOk )
		KMessageBox::error( m_parent, i18n( "Sorry, something went wrong while saving to image \"%1\"", url.prettyUrl() ) );
631
}
632 633


634
bool MainDlg::openFile()
Matthias Messmer's avatar
Matthias Messmer committed
635
{
636
	if (url()==m_currentfile || !kmplotio->load( url() ) )
637
	{
638 639
		m_recentFiles->removeUrl( url() ); //remove the file from the recent-opened-file-list
		setUrl(KUrl());
640 641
		return false;
	}
642
	
643 644 645
	m_currentfile = url();
	m_recentFiles->addUrl( url().prettyUrl(KUrl::LeaveTrailingSlash)  );
	setWindowCaption( url().prettyUrl(KUrl::LeaveTrailingSlash) );
646
	resetUndoRedo();
647 648
	View::self()->updateSliders();
	View::self()->drawPlot();
649
	return true;
Matthias Messmer's avatar
Matthias Messmer committed
650 651
}

652 653 654 655 656 657
bool MainDlg::saveFile()
{
    slotSave();
    return !isModified();
}

Laurent Montel's avatar
Laurent Montel committed
658
void MainDlg::slotOpenRecent( const KUrl &url )
Matthias Messmer's avatar
Matthias Messmer committed
659
{
660
 	if( isModified() || !this->url().isEmpty() ) // open the file in a new window
661
 	{
662
		QDBusReply<void> reply = QDBusInterface( QDBusConnection::sessionBus().baseService(), "/kmplot", "org.kde.kmplot.KmPlot" ).call( QDBus::Block, "openFileInNewWindow", url.url() );
663 664 665 666 667 668 669 670
		return;
	}

	if ( !kmplotio->load( url ) ) //if the loading fails
	{
		m_recentFiles->removeUrl(url ); //remove the file from the recent-opened-file-list
		return;
	}
671 672
    m_currentfile = url;
    setUrl(url);
673
    m_recentFiles->setCurrentItem(-1); //don't select the item in the open-recent menu
674
    setWindowCaption( this->url().prettyUrl(KUrl::LeaveTrailingSlash) );
675
	resetUndoRedo();
676 677
    View::self()->updateSliders();
    View::self()->drawPlot();
678
}
679

680
void MainDlg::slotPrint()
681
{
682
	KPrinter prt( QPrinter::PrinterResolution );
683
	prt.setResolution( 72 );
684 685 686
	KPrinterDlg* printdlg = new KPrinterDlg( m_parent );
	printdlg->setObjectName( "KmPlot page" );
	prt.addDialogPage( printdlg );
687
	if ( prt.setup( m_parent, i18n( "Print Plot" ) ) )
688
		View::self()->draw(&prt, View::Printer);
689 690
}

691

692 693
void MainDlg::editAxes()
{
694
	coordsDialog()->show();
695 696 697
}


698 699 700 701
void MainDlg::editConstants()
{
	if ( !m_constantEditor)
		m_constantEditor = new KConstantEditor(m_parent);
702

703 704 705 706
	m_constantEditor->show();
}


707
void MainDlg::slotNames()
Matthias Messmer's avatar
Matthias Messmer committed
708
{
Laurent Montel's avatar
Laurent Montel committed
709
	KToolInvocation::invokeHelp( "func-predefined", "kmplot" );
710 711 712
}


713
void MainDlg::slotResetView()
Matthias Messmer's avatar
Matthias Messmer committed
714
{
715
	View::self()->animateZoom( QRectF( -8, -8, 16, 16 ) );
716 717
}

718 719
void MainDlg::slotSettings()
{
720 721 722
	// An instance of your dialog has already been created and has been cached,
	// so we want to display the cached dialog instead of creating
	// another one
723 724 725
	KConfigDialog::showDialog( "settings" );
}

726

727
void MainDlg::calculator()
728
{
729
	m_calculator->show();
730 731 732 733
}

void MainDlg::findMinimumValue()
{
734 735
	m_functionTools->init( FunctionTools::FindMinimum );
	m_functionTools->show();
736 737 738 739
}

void MainDlg::findMaximumValue()
{
740 741
	m_functionTools->init( FunctionTools::FindMaximum );
	m_functionTools->show();
742 743 744 745
}

void MainDlg::graphArea()
{
746 747
	m_functionTools->init( FunctionTools::CalculateArea );
	m_functionTools->show();
748
}
Matthias Messmer's avatar