2
JuffEd - An advanced text editor
3
Copyright 2007-2009 Mikhail Murzin
5
This program is free software; you can redistribute it and/or
6
modify it under the terms of the GNU General Public License
7
version 2 as published by the Free Software Foundation.
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU General Public License for more details.
14
You should have received a copy of the GNU General Public License
15
along with this program; if not, write to the Free Software
16
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
//#define JUFF_RICH_DOC
23
#include <QtCore/QFile>
24
#include <QtCore/QMap>
25
#include <QtGui/QActionGroup>
26
#include <QtGui/QApplication>
27
#include <QtGui/QClipboard>
28
#include <QtGui/QInputDialog>
29
#include <QtGui/QMenu>
30
#include <QtGui/QMessageBox>
31
#include <QtGui/QPushButton>
32
#include <QtGui/QToolBar>
35
#include "CharsetsSettings.h"
36
#include "CommandStorage.h"
37
#include "DocHandler.h"
39
#include "Functions.h"
40
#include "MainSettings.h"
42
#include "Parameter.h"
43
#include "PluginManager.h"
44
#include "SciDocHandler.h"
45
#include "gui/StatusLabel.h"
46
#include "gui/Viewer.h"
50
#include "gui/GUIManager.h"
53
#include "RichDocHandler.h"
56
static const char* EMPTY_SESSION = "_empty_session_";
60
class Manager::Interior {
62
Interior(Manager* m, GUI::GUI* gui) : stayAlive_(false) {
63
viewer_ = new GUI::Viewer();
67
mainTB_ = new QToolBar("Main");
68
fileMenu_ = new QMenu(QObject::tr("&File"));
69
editMenu_ = new QMenu(QObject::tr("&Edit"));
70
viewMenu_ = new QMenu(QObject::tr("&View"));
71
formatMenu_ = new QMenu(QObject::tr("Fo&rmat"));
72
charsetMenu_ = new QMenu(QObject::tr("&Charset"));
73
recentFilesMenu_ = new QMenu(QObject::tr("Recent files"));
74
sessionsMenu_ = new QMenu(QObject::tr("Sessions"));
75
connect(recentFilesMenu_, SIGNAL(aboutToShow()), m, SLOT(initRecentFilesMenu()));
76
connect(sessionsMenu_, SIGNAL(aboutToShow()), m, SLOT(initSessionsMenu()));
78
chActGr_ = new QActionGroup(m);
80
QString recentFiles = MainSettings::recentFiles();
81
if ( !recentFiles.isEmpty() ) {
82
QStringList fileList = recentFiles.split(";");
83
int count = fileList.count();
84
for(int i = count - 1; i >= 0; --i) {
85
const QString& fileName = fileList.at(i);
86
addToRecentFiles(fileName);
90
posL_ = new GUI::StatusLabel("");
91
nameL_ = new GUI::StatusLabel("");
92
charsetL_ = new GUI::StatusLabel("");
93
linesL_ = new GUI::StatusLabel("");
94
posL_->setMinimumWidth(130);
95
posL_->setToolTip(QObject::tr("Cursor position"));
96
nameL_->setToolTip(QObject::tr("File full name"));
97
charsetL_->setToolTip(QObject::tr("Current character set"));
98
linesL_->setToolTip(QObject::tr("Lines count"));
99
charsetL_->setMenu(charsetMenu_);
101
gui_->addStatusWidget(posL_);
102
gui_->addStatusWidget(nameL_);
103
gui_->addStatusWidget(linesL_);
104
gui_->addStatusWidget(charsetL_);
111
fileNameStatusMenu_ = new QMenu();
112
nameL_->setMenu(fileNameStatusMenu_);
115
delete recentFilesMenu_;
123
if ( pluginManager_ )
124
delete pluginManager_;
125
delete fileNameStatusMenu_;
128
Document* getDocByView(QWidget* w) {
130
foreach (Document* doc, docs1_) {
131
if ( doc->widget() == w )
134
foreach (Document* doc, docs2_) {
135
if ( doc->widget() == w )
139
return NullDoc::instance();
141
DocHandler* getHandlerByDoc(Document* doc) {
142
if ( doc && !doc->isNull() ) {
143
QString type = doc->type();
144
if ( handlers_.contains(type) ) {
145
return handlers_[type];
151
void addToRecentFiles(const QString& fileName) {
152
recentFiles_.removeAll(fileName);
153
recentFiles_.push_front(fileName);
154
if ( recentFiles_.count() > MainSettings::recentFilesCount() )
155
recentFiles_.removeLast();
157
MainSettings::setRecentFiles(recentFiles_.join(";"));
160
void displayFileName(const QString& fileName) {
161
if ( Juff::isNoname(fileName) )
162
nameL_->setText(QString(" %1 ").arg(Juff::getDocTitle(fileName)));
164
nameL_->setText(QString(" %1 ").arg(fileName));
167
void displayCharset(const QString& charset) {
168
charsetL_->setText(QString(" %1 ").arg(charset));
169
charsetL_->setToolTip(QObject::tr("Current character set: %1").arg(charset));
170
if ( QAction* chAct = charsetActions_[charset] )
171
chAct->setChecked(true);
174
QMap<QString, DocHandler*> handlers_;
175
QMap<QString, QWidgetList> statusWidgets_;
177
QMap<QString, Document*> docs1_;
178
QMap<QString, Document*> docs2_;
179
QString sessionName_;
180
GUI::Viewer* viewer_;
182
PluginManager* pluginManager_;
189
QMap<QString, QAction*> charsetActions_;
190
QActionGroup* chActGr_;
191
QMenu* recentFilesMenu_;
192
QMenu* sessionsMenu_;
193
QStringList recentFiles_;
194
GUI::StatusLabel* posL_;
195
GUI::StatusLabel* nameL_;
196
GUI::StatusLabel* charsetL_;
197
GUI::StatusLabel* linesL_;
200
QMenu* fileNameStatusMenu_;
203
Manager::Manager(GUI::GUI* gui) : QObject(), ManagerInterface() {
207
mInt_ = new Interior(this, gui);
209
CommandStorage::instance()->registerCommand(ID_DOC_NEXT, mInt_->viewer_, SLOT(nextDoc()));
210
CommandStorage::instance()->registerCommand(ID_DOC_PREV, mInt_->viewer_, SLOT(prevDoc()));
216
gui->updateTitle("", "", false);
217
gui->setCentralWidget(mInt_->viewer_->widget());
220
// TODO : add a proper engines loading
222
/* SimpleDocHandler* simpleDH = new SimpleDocHandler();
223
addDocHandler(simpleDH);
227
RichDocHandler* richDH = new RichDocHandler();
228
addDocHandler(richDH);
231
SciDocHandler* sciDH = new SciDocHandler();
233
// Need to call it here because Keybindings plugin
234
// needs to have updated shortcuts
235
CommandStorage::instance()->updateShortcuts();
237
// TODO : add a proper engines list initialization
238
mInt_->pluginManager_ = new PluginManager(QStringList() << /*"simple" <<*/ "rich" << "sci", this, gui);
239
mInt_->pluginManager_->loadPlugins();
241
addDocHandler(sciDH);
244
QAction* saveAct = CommandStorage::instance()->action(ID_FILE_SAVE);
245
if ( mInt_->fileMenu_ && saveAct ) {
246
mInt_->fileMenu_->insertMenu(saveAct, mInt_->recentFilesMenu_);
249
mInt_->formatMenu_->addMenu(mInt_->charsetMenu_);
253
mInt_->viewer_->widget()->addAction(CommandStorage::instance()->action(ID_DOC_NEXT));
254
mInt_->viewer_->widget()->addAction(CommandStorage::instance()->action(ID_DOC_PREV));
256
connect(mInt_->viewer_, SIGNAL(curDocChanged(QWidget*)), SLOT(onCurDocChanged(QWidget*)));
257
connect(mInt_->viewer_, SIGNAL(requestDocName(QWidget*, QString&)), SLOT(onDocNameRequested(QWidget*, QString&)));
258
connect(mInt_->viewer_, SIGNAL(requestDocClose(QWidget*)), SLOT(onDocCloseRequested(QWidget*)));
259
connect(mInt_->viewer_, SIGNAL(requestNewDoc()), SLOT(fileNew()));
260
connect(gui, SIGNAL(settingsApplied()), SLOT(applySettings()));
261
connect(gui, SIGNAL(closeRequested(bool&)), this, SLOT(onCloseEvent(bool&)));
262
connect(mInt_->viewer_, SIGNAL(requestOpenDoc(const QString&)), this, SLOT(openDoc(const QString&)));
263
connect(mInt_->posL_, SIGNAL(clicked()), SLOT(gotoLine()));
264
connect(mInt_->linesL_, SIGNAL(clicked()), SLOT(gotoLine()));
265
#if QT_VERSION >= 0x040500
266
connect(mInt_->viewer_, SIGNAL(tabMoved(int, int)), mInt_->pluginManager_, SLOT(notifyTabMoved(int, int)));
269
mInt_->fileNameStatusMenu_->addAction(tr("Copy to clipboard"), this, SLOT(copyFileName()));
273
// menus from engines
274
MenuList standardMenus;
275
standardMenus << mInt_->fileMenu_ << mInt_->editMenu_
276
<< mInt_->viewMenu_ << mInt_->formatMenu_;
277
MenuList sciMenus = sciDH->menus();
278
sciMenus << mInt_->pluginManager_->getMenus("sci");
279
mInt_->gui_->addMenus("all", standardMenus);
280
mInt_->gui_->addMenus("sci", sciMenus);
281
// toolbars from engines
282
mInt_->gui_->addToolBar("all", mInt_->mainTB_);
283
mInt_->gui_->addToolBars("sci", sciDH->toolBars());
286
MenuList richMenus = richDH->menus();
287
richMenus << mInt_->pluginManager_->getMenus("rich");
288
mInt_->gui_->addMenus("rich", richMenus);
289
mInt_->gui_->addToolBars("rich", richDH->toolBars());
292
// controls from plugins
293
MenuID ids[] = { ID_MENU_FILE, ID_MENU_EDIT, ID_MENU_VIEW, ID_MENU_FORMAT, ID_MENU_TOOLS, ID_MENU_NONE };
294
QString engines[] = { "sci", "rich", "all", "" };
296
while ( !engines[ei].isEmpty() ) {
297
QString engine = engines[ei];
300
mInt_->gui_->addToolBars(engine, mInt_->pluginManager_->getToolBars(engine));
303
QWidgetList docks = mInt_->pluginManager_->getDocks(engine);
304
mInt_->gui_->addDocks(engine, docks);
306
// items to main menus
308
while ( ids[i] != ID_MENU_NONE ) {
312
case ID_MENU_FILE : menu = mInt_->fileMenu_; break;
313
case ID_MENU_EDIT : menu = mInt_->editMenu_; break;
314
case ID_MENU_VIEW : menu = mInt_->viewMenu_; break;
315
case ID_MENU_FORMAT : menu = mInt_->formatMenu_; break;
316
case ID_MENU_TOOLS : menu = mInt_->gui_->toolsMenu(); break;
320
ActionList actions = mInt_->pluginManager_->getMainMenuActions(engine, id);
321
mInt_->gui_->addActions(engine, actions);
322
foreach (QAction* act, actions)
323
menu->addAction(act);
331
mInt_->gui_->addMenus("all", mInt_->pluginManager_->getMenus("all"));
333
applySettings(false);
335
// restore toolbars and docks positions
336
mInt_->gui_->restoreState();
339
Manager::~Manager() {
343
void Manager::registerCommands() {
344
CommandStorage* st = CommandStorage::instance();
345
st->registerCommand(ID_FILE_NEW, this, SLOT(fileNew()));
346
// st->registerCommand(ID_FILE_NEW_RICH, this, SLOT(fileNewRich()));
347
st->registerCommand(ID_FILE_OPEN, this, SLOT(fileOpen()));
348
st->registerCommand(ID_FILE_SAVE, this, SLOT(fileSave()));
349
st->registerCommand(ID_FILE_SAVE_AS, this, SLOT(fileSaveAs()));
350
st->registerCommand(ID_FILE_SAVE_ALL, this, SLOT(fileSaveAll()));
351
st->registerCommand(ID_FILE_RELOAD, this, SLOT(fileReload()));
352
st->registerCommand(ID_FILE_CLOSE, this, SLOT(fileClose()));
353
st->registerCommand(ID_FILE_CLOSE_ALL, this, SLOT(fileCloseAll()));
354
st->registerCommand(ID_FILE_PRINT, this, SLOT(filePrint()));
355
st->registerCommand(ID_EXIT, this, SLOT(exit()));
357
st->registerCommand(ID_FILE_NEW_RICH, this, SLOT(fileNewRich()));
359
st->registerCommand(ID_SESSION_NEW, this, SLOT(sessionNew()));
360
st->registerCommand(ID_SESSION_OPEN, this, SLOT(sessionOpen()));
361
st->registerCommand(ID_SESSION_SAVE, this, SLOT(sessionSave()));
362
st->registerCommand(ID_SESSION_SAVE_AS, this, SLOT(sessionSaveAs()));
364
st->registerCommand(ID_EDIT_UNDO, this, SLOT(editUndo()));
365
st->registerCommand(ID_EDIT_REDO, this, SLOT(editRedo()));
366
st->registerCommand(ID_EDIT_CUT, this, SLOT(editCut()));
367
st->registerCommand(ID_EDIT_COPY, this, SLOT(editCopy()));
368
st->registerCommand(ID_EDIT_PASTE, this, SLOT(editPaste()));
370
st->registerCommand(ID_FIND, this, SLOT(find()));
371
st->registerCommand(ID_FIND_NEXT, this, SLOT(findNext()));
372
st->registerCommand(ID_FIND_PREV, this, SLOT(findPrev()));
373
st->registerCommand(ID_REPLACE, this, SLOT(replace()));
374
st->registerCommand(ID_GOTO_LINE, this, SLOT(gotoLine()));
377
void Manager::initMainMenu() {
378
CommandStorage* st = CommandStorage::instance();
379
mInt_->fileMenu_->addAction(st->action(ID_FILE_NEW));
380
// mInt_->fileMenu_->addAction(st->action(ID_FILE_NEW_RICH));
381
mInt_->fileMenu_->addAction(st->action(ID_FILE_OPEN));
382
mInt_->fileMenu_->addAction(st->action(ID_FILE_SAVE));
383
mInt_->fileMenu_->addAction(st->action(ID_FILE_SAVE_AS));
384
mInt_->fileMenu_->addAction(st->action(ID_FILE_SAVE_ALL));
385
mInt_->fileMenu_->addAction(st->action(ID_FILE_RELOAD));
386
mInt_->fileMenu_->addAction(st->action(ID_SEPARATOR));
387
mInt_->fileMenu_->addAction(st->action(ID_FILE_CLOSE));
388
mInt_->fileMenu_->addAction(st->action(ID_FILE_CLOSE_ALL));
389
mInt_->fileMenu_->addAction(st->action(ID_FILE_PRINT));
390
mInt_->fileMenu_->addAction(st->action(ID_SEPARATOR));
391
mInt_->fileMenu_->addMenu(mInt_->sessionsMenu_);
392
mInt_->fileMenu_->addAction(st->action(ID_SEPARATOR));
393
mInt_->fileMenu_->addAction(st->action(ID_EXIT));
395
mInt_->editMenu_->addAction(st->action(ID_EDIT_UNDO));
396
mInt_->editMenu_->addAction(st->action(ID_EDIT_REDO));
397
mInt_->editMenu_->addAction(st->action(ID_SEPARATOR));
398
mInt_->editMenu_->addAction(st->action(ID_EDIT_CUT));
399
mInt_->editMenu_->addAction(st->action(ID_EDIT_COPY));
400
mInt_->editMenu_->addAction(st->action(ID_EDIT_PASTE));
401
mInt_->editMenu_->addAction(st->action(ID_SEPARATOR));
402
mInt_->editMenu_->addAction(st->action(ID_FIND));
403
mInt_->editMenu_->addAction(st->action(ID_FIND_NEXT));
404
mInt_->editMenu_->addAction(st->action(ID_FIND_PREV));
405
mInt_->editMenu_->addAction(st->action(ID_REPLACE));
406
mInt_->editMenu_->addAction(st->action(ID_SEPARATOR));
407
mInt_->editMenu_->addAction(st->action(ID_GOTO_LINE));
410
void Manager::initMainToolBar() {
411
QToolBar* tb = mInt_->mainTB_;
412
CommandStorage* st = CommandStorage::instance();
413
QString tbStr = MainSettings::toolBar();
414
if ( tbStr.isEmpty() ) {
415
tb->addAction(st->action(ID_FILE_NEW));
416
tb->addAction(st->action(ID_FILE_OPEN));
417
tb->addAction(st->action(ID_FILE_SAVE));
418
tb->addAction(st->action(ID_SEPARATOR));
419
tb->addAction(st->action(ID_FILE_PRINT));
420
tb->addAction(st->action(ID_SEPARATOR));
421
tb->addAction(st->action(ID_EDIT_UNDO));
422
tb->addAction(st->action(ID_EDIT_REDO));
423
tb->addAction(st->action(ID_SEPARATOR));
424
tb->addAction(st->action(ID_EDIT_CUT));
425
tb->addAction(st->action(ID_EDIT_COPY));
426
tb->addAction(st->action(ID_EDIT_PASTE));
429
QStringList items = tbStr.split('|');
430
foreach (QString item, items) {
431
CommandID id = ID_NONE;
434
else if ( item == "new" )
436
else if ( item == "open" )
438
else if ( item == "save" )
440
else if ( item == "print" )
442
else if ( item == "undo" )
444
else if ( item == "redo" )
446
else if ( item == "cut" )
448
else if ( item == "copy" )
450
else if ( item == "paste" )
452
else if ( item == "find" )
454
else if ( item == "replace" )
458
tb->addAction(st->action(id));
463
void Manager::initCharsetMenu() {
466
mInt_->charsetMenu_->clear();
467
mInt_->charsetActions_.clear();
468
foreach (QAction* a, mInt_->chActGr_->actions())
469
mInt_->chActGr_->removeAction(a);
472
QStringList charsets = CharsetsSettings::getCharsetsList();
473
foreach (QString charset, charsets) {
474
if ( CharsetsSettings::charsetEnabled(charset) ) {
475
QAction* action = mInt_->charsetMenu_->addAction(charset, this, SLOT(charsetSelected()));
476
action->setCheckable(true);
477
mInt_->charsetActions_[charset] = action;
478
mInt_->chActGr_->addAction(action);
483
void Manager::initRecentFilesMenu() {
486
if ( mInt_->recentFilesMenu_ == 0 )
489
mInt_->recentFilesMenu_->clear();
491
foreach (QString fileName, mInt_->recentFiles_) {
492
mInt_->recentFilesMenu_->addAction(fileName, this, SLOT(fileRecent()));
495
if ( mInt_->recentFiles_.count() == 0 )
496
mInt_->recentFilesMenu_->setEnabled(false);
498
mInt_->recentFilesMenu_->setEnabled(true);
501
void Manager::initSessionsMenu() {
504
CommandStorage* st = CommandStorage::instance();
505
mInt_->sessionsMenu_->clear();
506
mInt_->sessionsMenu_->addAction(st->action(ID_SESSION_NEW));
507
mInt_->sessionsMenu_->addAction(st->action(ID_SESSION_OPEN));
508
mInt_->sessionsMenu_->addAction(st->action(ID_SESSION_SAVE));
509
mInt_->sessionsMenu_->addAction(st->action(ID_SESSION_SAVE_AS));
511
QStringList sessions;
512
QDir sessionDir(AppInfo::configDirPath() + "/sessions/");
513
if (sessionDir.exists()) {
514
sessions = sessionDir.entryList(QDir::Files | QDir::NoSymLinks);
515
if ( !sessions.isEmpty() )
516
mInt_->sessionsMenu_->addSeparator();
518
foreach (QString session, sessions) {
519
if (session.compare(EMPTY_SESSION) != 0) {
520
mInt_->sessionsMenu_->addAction(session, this, SLOT(session()));
526
bool Manager::closeWithConfirmation(Document* doc) {
527
if ( !doc || doc->isNull() )
531
if ( doc->isModified() ) {
532
// TODO : move this question to GUI
533
QString str = tr("The document ") + doc->fileName();
534
str += tr(" has been modified.\nDo you want to save your changes?");
535
int ret = QMessageBox::warning(mInt_->viewer_->widget(), tr("Close document"),
536
str, QMessageBox::Save | QMessageBox::Discard
537
| QMessageBox::Cancel, QMessageBox::Save);
540
case QMessageBox::Save:
549
case QMessageBox::Discard:
553
case QMessageBox::Cancel:
565
bool Manager::confirmExit() {
568
MainSettings::setLastSessionName(mInt_->sessionName_);
569
if ( MainSettings::saveSessionOnClose() ) {
570
saveSess(mInt_->sessionName_);
576
void Manager::onCloseEvent(bool& confirm) {
577
confirm = confirmExit();
579
mInt_->gui_->saveState();
582
void Manager::exit() {
585
if ( confirmExit() ) {
586
mInt_->gui_->saveState();
591
void Manager::addDocHandler(DocHandler* handler) {
595
QString type = handler->type();
596
if ( mInt_->handlers_.contains(type) ) {
597
mInt_->handlers_[type]->disconnect();
598
delete mInt_->handlers_[type];
600
mInt_->handlers_[type] = handler;
601
mInt_->statusWidgets_[type] = handler->statusWidgets();
602
foreach (QWidget* w, mInt_->statusWidgets_[type]) {
603
mInt_->gui_->addStatusWidget(w);
606
handler->addContextMenuActions(mInt_->pluginManager_->getContextMenuActions(type));
609
foreach(act, handler->menuActions(ID_MENU_EDIT)) {
610
mInt_->editMenu_->addAction(act);
611
mInt_->gui_->addAction(type, act);
613
foreach(act, handler->menuActions(ID_MENU_VIEW)) {
614
mInt_->viewMenu_->addAction(act);
615
mInt_->gui_->addAction(type, act);
617
foreach(act, handler->menuActions(ID_MENU_FORMAT)) {
618
mInt_->formatMenu_->addAction(act);
619
mInt_->gui_->addAction(type, act);
621
QMenu* toolsMenu = mInt_->gui_->toolsMenu();
622
foreach(act, handler->menuActions(ID_MENU_TOOLS)) {
623
toolsMenu->addAction(act);
624
mInt_->gui_->addAction(type, act);
626
connect(handler, SIGNAL(getCurDoc()), SLOT(curDoc()));
629
void Manager::applySettings(bool save /* = true*/) {
630
mInt_->viewer_->applySettings();
631
mInt_->gui_->setToolBarIconSize(MainSettings::iconSize());
632
mInt_->gui_->setToolButtonStyle((Qt::ToolButtonStyle)MainSettings::toolButtonStyle());
633
IconManager::instance()->setCurrentIconTheme(MainSettings::iconTheme(), MainSettings::iconSize());
634
CommandStorage::instance()->updateIcons();
636
QMap<QString, Document*>::iterator it = mInt_->docs1_.begin();
637
for (; it != mInt_->docs1_.end(); it++) {
638
it.value()->applySettings();
641
it = mInt_->docs2_.begin();
642
for (; it != mInt_->docs2_.end(); it++) {
643
it.value()->applySettings();
648
mInt_->pluginManager_->applySettings();
650
// this needs to be called after
651
// PluginManager->applySettings() is called
652
CommandStorage::instance()->updateShortcuts();
658
Document* Manager::curDoc() const {
661
QWidget* w = mInt_->viewer_->curDoc();
663
JUFFDEBUG("widget is 0");
664
return mInt_->getDocByView(w);
668
void Manager::openDoc(const QString& fileName) {
670
mInt_->gui_->activateMW();
672
// check if this file is already opened
673
if ( mInt_->docs1_.contains(fileName) ) {
674
mInt_->viewer_->activateDoc(mInt_->docs1_[fileName]);
676
else if ( mInt_->docs2_.contains(fileName) ) {
677
mInt_->viewer_->activateDoc(mInt_->docs2_[fileName]);
680
if ( QFileInfo(fileName).isFile() ) {
681
Document* cur = curDoc();
682
createDoc("sci", fileName);
683
mInt_->addToRecentFiles(fileName);
685
// close the previous document if it was alone and not modified
686
if ( docCount() == 2 && cur && isNoname(cur->fileName()) && !cur->isModified() )
689
else if ( QFileInfo(fileName).isDir() ) {
691
QStringList files = dir.entryList(QDir::AllEntries | QDir::NoDotAndDotDot);
692
foreach (QString dirItem, files) {
693
openDoc(dir.absoluteFilePath(dirItem));
699
void Manager::createDoc(const QString& type, const QString& fileName) {
702
if ( !fileName.isEmpty() && !QFileInfo(fileName).exists() ) {
703
QMessageBox::information(NULL, tr("Warning"), tr("Document '%1' doesn't exist").arg(fileName));
706
DocHandler* h = mInt_->handlers_[type];
708
Document* doc = h->createDoc(fileName);
710
QString fName = doc->fileName();
712
connect(doc, SIGNAL(modified(bool)), SLOT(docModified(bool)));
713
connect(doc, SIGNAL(fileNameChanged(const QString&)), SLOT(docFileNameChanged(const QString&)));
714
connect(doc, SIGNAL(cursorPositionChanged(int, int)), this, SLOT(onCursorPositionChanged(int, int)));
715
connect(doc, SIGNAL(linesCountChanged(int)), this, SLOT(onLinesCountChanged(int)));
716
connect(doc, SIGNAL(contextMenuCalled(int, int)), this, SLOT(onContextMenuCalled(int, int)));
718
mInt_->docs1_[fName] = doc;
719
mInt_->viewer_->addDoc(doc, 1);
721
mInt_->pluginManager_->notifyDocCreated(fName);
723
if ( mInt_->posL_->isHidden() ) {
724
mInt_->posL_->show();
725
mInt_->nameL_->show();
726
mInt_->charsetL_->show();
727
mInt_->linesL_->show();
733
bool Manager::saveDoc(Document* doc, const QString& fileName, const QString& charset) {
736
if ( !doc || doc->isNull() )
739
QString name = fileName;
741
if ( QFile::exists(fileName) && !QFileInfo(fileName).isWritable() ) {
742
// file exists and is not writabe. Ask what to do.
744
QString msg = tr("File '%1' is read-only.").arg(QFileInfo(name).fileName()) + "\n";
745
msg += tr("What do you want to do?");
746
QMessageBox msgBox(QMessageBox::Information, tr("Warning"), msg, QMessageBox::NoButton, mInt_->viewer_->widget());
747
QPushButton* owrBtn = msgBox.addButton(tr("Overwrite"), QMessageBox::YesRole);
748
QPushButton* savBtn = msgBox.addButton(tr("Save as"), QMessageBox::ApplyRole);
749
msgBox.addButton(QMessageBox::Cancel);
750
bool resolved = false;
753
QAbstractButton* btn = msgBox.clickedButton();
754
if ( btn == owrBtn ) {
755
// Try to change permissions and save
756
QFile::Permissions perm = QFile::permissions(name);
757
if ( QFile::setPermissions(name, perm | QFile::WriteUser) ) {
761
// Can't change permissions
762
mInt_->gui_->displayError(tr("Can't change permissions: Access denied"));
766
else if ( btn == savBtn ) {
774
} while ( !resolved );
777
// make a backup copy if it is necessary
778
if ( MainSettings::makeBackupOnSave() ) {
779
QString bkpName = name + "~";
780
if ( QFile::exists(bkpName) ) {
781
QFile::remove(bkpName);
783
QFile::copy(name, bkpName);
786
MainSettings::setLastSaveDir(QFileInfo(name).absolutePath());
789
if ( !doc->save(name, charset, err) ) {
790
Log::debug("Not saved...");
791
mInt_->gui_->displayError(err);
795
mInt_->pluginManager_->notifyDocSaved(name);
800
void Manager::closeDoc(Document* doc) {
803
if ( !doc || doc->isNull() )
806
Log::debug(doc->fileName());
808
mInt_->docs1_.remove(doc->fileName());
809
mInt_->docs2_.remove(doc->fileName());
810
mInt_->viewer_->removeDoc(doc);
811
mInt_->pluginManager_->notifyDocClosed(doc->fileName());
814
Document* d = curDoc();
815
if ( d && !d->isNull() ) {
816
d->widget()->setFocus();
819
mInt_->posL_->hide();
820
mInt_->nameL_->hide();
821
mInt_->charsetL_->hide();
822
mInt_->linesL_->hide();
824
if ( !mInt_->stayAlive_ && MainSettings::exitOnLastDocClosed() )
829
bool Manager::closeAllDocs() {
832
// If this method was called we don't want to exit the app
833
// after the last document was closed (if this option was chosen
834
// in settings dialog). Set the 'stayAlive' flag and unset it afterwards.
835
mInt_->stayAlive_ = true;
836
while ( !curDoc()->isNull() ) {
837
if ( !fileClose() ) {
841
mInt_->stayAlive_ = false;
842
mInt_->gui_->updateTitle("", mInt_->sessionName_, false);
850
////////////////////////////////////////////////////////////////////////////////
851
////////////////////////////////////////////////////////////////////////////////
853
void Manager::fileNew() {
855
createDoc("sci", "");
858
void Manager::fileNewRich() {
861
createDoc("rich", "");
864
void Manager::fileOpen() {
866
QString startDir = MainSettings::lastOpenDir();
868
Document* doc = curDoc();
870
if ( MainSettings::syncOpenDialogToCurDoc() ) {
871
if ( !doc->isNull() && !isNoname(doc->fileName()) )
872
startDir = QFileInfo(doc->fileName()).absolutePath();
875
QString filters = "All files (*)";
876
DocHandler* handler = mInt_->getHandlerByDoc(doc);
878
filters = handler->fileFilters();
881
QStringList files = mInt_->gui_->getOpenFileNames(startDir, filters);
882
if ( files.count() > 0 ) {
883
QString fileName = "";
884
foreach (fileName, files) {
887
MainSettings::setLastOpenDir(QFileInfo(fileName).absolutePath());
891
void Manager::fileRecent() {
894
QAction* a = qobject_cast<QAction*>(sender());
898
QString fileName = a->text();
899
if ( !fileName.isEmpty() ) {
904
void Manager::session() {
907
QAction* a = qobject_cast<QAction*>(sender());
911
QString sessName = a->text();
912
if ( closeSess() && !sessName.isEmpty() ) {
913
if ( openSess(sessName) ) {
918
bool Manager::fileSave() {
921
Document* doc = curDoc();
923
if ( !doc->isNull() ) {
924
// we have a document opened
926
if ( !Juff::isNoname(doc->fileName()) && !doc->isModified() )
929
if ( Juff::isNoname(doc->fileName()) ) {
930
// document doesn't have a file name. Call "Save as"
935
if ( saveDoc(doc, doc->fileName(), doc->charset()) ) {
936
doc->setModified(false);
950
bool Manager::fileSaveAs() {
953
Document* doc = curDoc();
955
if ( !doc->isNull() ) {
956
QString filters = "All files (*)";
957
DocHandler* handler = mInt_->getHandlerByDoc(doc);
959
filters = handler->fileFilters();
963
QString charset = doc->charset();
964
QString fName = mInt_->gui_->getSaveFileName(doc->fileName(), filters, asCopy, charset);
965
if ( !fName.isEmpty() ) {
966
if ( saveDoc(doc, fName, charset) ) {
968
doc->setFileName(fName);
969
doc->setCharset(charset);
970
mInt_->displayCharset(doc->charset());
971
doc->setModified(false);
972
mInt_->displayFileName(fName);
981
void Manager::fileSaveAll() {
984
QMap<QString, Document*>::iterator it = mInt_->docs1_.begin();
985
while ( it != mInt_->docs1_.end() ) {
986
Document* doc = it.value();
987
if ( doc && doc->isModified() ) {
988
if ( Juff::isNoname(doc->fileName()) ) {
989
mInt_->viewer_->activateDoc(doc);
993
if ( saveDoc(doc, doc->fileName(), doc->charset()) ) {
994
doc->setModified(false);
1002
void Manager::fileReload() {
1003
Document* doc = curDoc();
1005
if ( !doc->isNull() ) {
1010
bool Manager::fileClose() {
1013
Document* doc = curDoc();
1014
bool result = closeWithConfirmation(doc);
1017
if ( curDoc()->isNull() )
1018
mInt_->gui_->updateTitle("", mInt_->sessionName_, false);
1023
void Manager::fileCloseAll() {
1027
void Manager::filePrint() {
1030
Document* doc = curDoc();
1031
if ( !doc->isNull() )
1036
void Manager::sessionNew() {
1039
if ( closeAllDocs() ) {
1040
mInt_->sessionName_ = "";
1045
void Manager::sessionOpen() {
1048
saveSess(mInt_->sessionName_);
1050
bool accepted = false;
1051
QString sessName = mInt_->gui_->getOpenSessionName(accepted);
1052
if ( accepted && closeSess() ) {
1053
if ( !sessName.isEmpty() ) {
1055
if ( openSess(sessName) ) {
1065
void Manager::sessionSave() {
1068
if ( mInt_->sessionName_.isEmpty() ) {
1072
saveSess(mInt_->sessionName_);
1076
void Manager::sessionSaveAs() {
1079
QString sessName = mInt_->gui_->getSaveSessionName(mInt_->sessionName_);
1080
if ( !sessName.isEmpty() ) {
1082
mInt_->sessionName_ = sessName;
1083
Document* doc = curDoc();
1084
QString fileName = doc->isNull() ? "" : doc->fileName();
1085
mInt_->gui_->updateTitle(fileName, sessName, false);
1089
void Manager::writePanelViews(QFile& file, int panel) {
1092
mInt_->viewer_->getViewsList(panel, views);
1093
foreach (QWidget* w, views) {
1094
Document* doc = mInt_->getDocByView(w);
1095
if ( doc && !doc->isNull() && !isNoname(doc->fileName()) ) {
1096
int scrPos = doc->curScrollPos();
1097
int line = doc->curLine();
1098
file.write((QString("%1:%2:%3\n")
1099
.arg(doc->fileName()).arg(scrPos).arg(line)).toLocal8Bit());
1104
bool Manager::openSess(const QString& name) {
1107
QString sessName = name.isEmpty() ? EMPTY_SESSION : name;
1109
QFile sess(AppInfo::configDirPath() + "/sessions/" + sessName);
1110
if ( sess.open(QIODevice::ReadOnly) ) {
1111
QString fileName("");
1112
while ( !sess.atEnd() ) {
1113
QString lineStr = QString::fromLocal8Bit(sess.readLine()).simplified();
1115
fileName = lineStr.section(':', -4, -3);
1117
fileName = lineStr.section(':', -3, -3);
1119
Log::debug(QString(" Opening file '%1'").arg(fileName));
1120
int scrPos = lineStr.section(':', -2, -2).toInt();
1121
int line = lineStr.section(':', -1, -1).toInt();
1122
Log::debug(QString(" Position: %1, scroll: %2").arg(line).arg(scrPos));
1123
if ( !fileName.isEmpty() ) {
1124
createDoc("sci", fileName);
1125
Log::debug(" Doc created");
1126
Document* doc = curDoc();
1127
if ( !doc->isNull() ) {
1128
doc->gotoLine(line);
1129
doc->setScrollPos(scrPos);
1136
mInt_->sessionName_ = sessName;
1137
Document* doc = curDoc();
1138
QString curFileName = doc->isNull() ? "" : doc->fileName();
1139
mInt_->gui_->updateTitle(curFileName, sessName, false);
1146
bool Manager::saveSess(const QString& name) {
1149
QString sessName = name.isEmpty() ? EMPTY_SESSION : name;
1151
QFile sess(AppInfo::configDirPath() + "/sessions/" + sessName);
1152
if ( sess.open(QIODevice::WriteOnly | QIODevice::Truncate) ) {
1153
writePanelViews(sess, 1);
1158
// TODO : Add error display here
1163
bool Manager::closeSess() {
1164
if ( !closeAllDocs() )
1167
mInt_->sessionName_ = "";
1168
mInt_->gui_->updateTitle("", "", false);
1172
void Manager::restoreSession() {
1175
int startupVariant = MainSettings::startupVariant();
1176
switch ( startupVariant ) {
1179
QString sessName = MainSettings::lastSessionName();
1180
if ( openSess(sessName) ) {
1182
if ( docCount() == 0 )
1196
Log::debug("Session restored");
1202
void Manager::editUndo() {
1205
Document* doc = curDoc();
1206
if ( !doc->isNull() )
1210
void Manager::editRedo() {
1213
Document* doc = curDoc();
1214
if ( !doc->isNull() )
1218
void Manager::editCut() {
1221
Document* doc = curDoc();
1222
if ( !doc->isNull() )
1226
void Manager::editCopy() {
1229
Document* doc = curDoc();
1230
if ( !doc->isNull() )
1234
void Manager::editPaste() {
1237
Document* doc = curDoc();
1238
if ( !doc->isNull() )
1242
void Manager::findImpl(bool replc) {
1243
Document* doc = curDoc();
1244
if ( !doc->isNull() ) {
1245
DocFindFlags flags(replc);
1247
int line1, col1, line2, col2;
1248
doc->getSelection(line1, col1, line2, col2);
1249
if ( line1 == line2 ) {
1250
if ( col1 != col2 ) {
1251
str1 = doc->selectedText();
1254
str1 = doc->wordUnderCursor();
1257
if ( mInt_->gui_->getFindParams(str1, str2, flags) ) {
1258
if ( flags.replace ) {
1259
doc->replace(str1, str2, flags);
1262
doc->find(str1, flags);
1268
void Manager::find() {
1273
void Manager::replace() {
1278
void Manager::findNext() {
1281
Document* doc = curDoc();
1282
if ( !doc->isNull() ) {
1283
QString lastText = mInt_->gui_->lastFindText();
1284
if ( lastText.isEmpty() ) {
1288
DocFindFlags flags = mInt_->gui_->lastFlags();
1289
flags.replace = false;
1290
flags.backwards = false;
1291
doc->find(lastText, flags);
1296
void Manager::findPrev() {
1299
Document* doc = curDoc();
1300
if ( !doc->isNull() ) {
1301
QString lastText = mInt_->gui_->lastFindText();
1302
if ( lastText.isEmpty() ) {
1306
DocFindFlags flags = mInt_->gui_->lastFlags();
1307
flags.replace = false;
1308
flags.backwards = true;
1309
doc->find(lastText, flags);
1314
void Manager::gotoLine() {
1317
Document* doc = curDoc();
1318
if ( !doc->isNull() ) {
1320
int line = QInputDialog::getInteger(doc->widget(), tr("Go to line"),
1321
tr("Go to line") + QString(" (1 - %1):").arg(doc->lineCount()),
1322
1, 1, doc->lineCount(), 1, &ok);
1324
doc->gotoLine(line - 1);
1328
void Manager::charsetSelected() {
1331
QAction* a = qobject_cast<QAction*>(sender());
1333
Document* doc = curDoc();
1334
if ( doc && !doc->isNull() ) {
1335
doc->setCharset(a->text(), true);
1336
mInt_->displayCharset(doc->charset());
1343
void Manager::docModified(bool mod) {
1346
Document* doc = qobject_cast<Document*>(sender());
1349
mInt_->gui_->updateTitle(doc->fileName(), mInt_->sessionName_, mod);
1350
mInt_->viewer_->setDocModified(doc, mod);
1351
mInt_->pluginManager_->notifyDocModified(doc->fileName(), mod);
1355
void Manager::onCursorPositionChanged(int line, int col) {
1356
mInt_->posL_->setText(tr("Row: %1, Col: %2").arg(line+1).arg(col+1));
1359
void Manager::onLinesCountChanged(int lines) {
1360
mInt_->linesL_->setText(tr(" Lines: %1 ").arg(lines));
1361
mInt_->linesL_->setToolTip(QObject::tr("Lines count: %1").arg(lines));
1364
void Manager::onContextMenuCalled(int line, int col) {
1365
mInt_->pluginManager_->notifyContextMenuCalled(line, col);
1368
void Manager::docFileNameChanged(const QString& oldName) {
1371
Document* doc = qobject_cast<Document*>(sender());
1374
if ( mInt_->docs1_.contains(oldName) ) {
1375
mInt_->docs1_.remove(oldName);
1376
mInt_->docs1_[doc->fileName()] = doc;
1378
else if ( mInt_->docs2_.contains(oldName) ) {
1379
mInt_->docs2_.remove(oldName);
1380
mInt_->docs2_[doc->fileName()] = doc;
1385
mInt_->gui_->updateTitle(doc->fileName(), mInt_->sessionName_, doc->isModified());
1386
mInt_->viewer_->updateDocTitle(doc);
1387
mInt_->pluginManager_->notifyDocRenamed(oldName, doc->fileName());
1392
void Manager::onCurDocChanged(QWidget* w) {
1396
Document* doc = mInt_->getDocByView(w);
1397
if ( !doc->isNull() ) {
1398
QString type = doc->type();
1399
DocHandler* handler = mInt_->handlers_[type];
1401
handler->docActivated(doc);
1404
Log::debug("<no type>");
1408
mInt_->displayFileName(doc->fileName());
1409
mInt_->displayCharset(doc->charset());
1410
int line = -1, col = -1;
1411
doc->getCursorPos(line, col);
1412
mInt_->posL_->setText(tr(" Row: %1, Col: %2 ").arg(line+1).arg(col+1));
1413
mInt_->linesL_->setText(tr(" Lines: %1 ").arg(doc->lineCount()));
1414
mInt_->linesL_->setToolTip(tr("Lines count: %1 ").arg(doc->lineCount()));
1416
if ( type != mInt_->docOldType_ ) {
1417
if ( mInt_->statusWidgets_.contains(mInt_->docOldType_) ) {
1418
foreach (QWidget* w, mInt_->statusWidgets_[mInt_->docOldType_] ) {
1422
if ( mInt_->statusWidgets_.contains(type) ) {
1423
foreach (QWidget* w, mInt_->statusWidgets_[type] ) {
1427
mInt_->docOldType_ = type;
1430
if ( QAction* chAct = mInt_->charsetActions_[doc->charset()] )
1431
chAct->setChecked(true);
1432
else if ( mInt_->chActGr_->checkedAction() )
1433
mInt_->chActGr_->checkedAction()->setChecked(false);
1435
doc->updateActivated();
1436
mInt_->gui_->updateTitle(doc->fileName(), mInt_->sessionName_, doc->isModified());
1437
mInt_->pluginManager_->notifyDocActivated(doc->fileName());
1439
mInt_->gui_->setCurType(type);
1442
mInt_->gui_->updateTitle("", "", false);
1445
mInt_->displayFileName("");
1446
mInt_->displayCharset("");
1447
mInt_->posL_->setText(" ");
1448
if ( mInt_->statusWidgets_.contains(mInt_->docOldType_) ) {
1449
foreach (QWidget* w, mInt_->statusWidgets_[mInt_->docOldType_] ) {
1453
mInt_->docOldType_ = "";
1458
mInt_->displayFileName("");
1459
mInt_->displayCharset("");
1460
mInt_->posL_->setText(" ");
1461
if ( mInt_->statusWidgets_.contains(mInt_->docOldType_) ) {
1462
foreach (QWidget* w, mInt_->statusWidgets_[mInt_->docOldType_] ) {
1466
mInt_->docOldType_ = "";
1467
mInt_->gui_->setCurType("all");
1471
void Manager::onDocCloseRequested(QWidget* w) {
1474
Document* doc = mInt_->getDocByView(w);
1475
closeWithConfirmation(doc);
1477
if ( curDoc()->isNull() )
1478
mInt_->gui_->updateTitle("", mInt_->sessionName_, false);
1481
void Manager::onDocNameRequested(QWidget* w, QString& fileName) {
1483
Document* doc = mInt_->getDocByView(w);
1484
fileName = doc->isNull() ? "" : doc->fileName();
1495
int Manager::docCount() const {
1496
return mInt_->docs1_.count() + mInt_->docs2_.count();
1499
void Manager::getDocList(QStringList& list) const {
1503
list << mInt_->docs1_.keys();
1504
list << mInt_->docs2_.keys();
1507
void Manager::getCurDocName(QString& fileName) const {
1510
Document* doc = curDoc();
1511
if ( !doc->isNull() ) {
1512
fileName = doc->fileName();
1519
void Manager::getDocText(const QString& fileName, QString& text) {
1522
if ( mInt_->docs1_.contains(fileName) ) {
1523
text = mInt_->docs1_[fileName]->text();
1525
else if ( mInt_->docs2_.contains(fileName) ) {
1526
text = mInt_->docs2_[fileName]->text();
1533
void Manager::getDocText(const QString& fileName, int line, QString& text) {
1536
if ( mInt_->docs1_.contains(fileName) ) {
1537
text = mInt_->docs1_[fileName]->text(line);
1539
else if ( mInt_->docs2_.contains(fileName) ) {
1540
text = mInt_->docs2_[fileName]->text(line);
1547
void Manager::getCurrentDocText(QString& text) {
1548
Document* doc = curDoc();
1549
if ( !doc->isNull() ) {
1550
getDocText(doc->fileName(), text);
1557
void Manager::getCurrentDocText(int line, QString& text) {
1558
Document* doc = curDoc();
1559
if ( !doc->isNull() ) {
1560
getDocText(doc->fileName(), line, text);
1567
QString Manager::getCurDocCharset() {
1568
Document* doc = curDoc();
1569
if ( !doc->isNull() ) {
1570
return doc->charset();
1577
void Manager::setCurDocCharset(const QString& charset) {
1578
Document* doc = curDoc();
1579
if ( !doc->isNull() ) {
1580
doc->setCharset(charset, true);
1581
mInt_->displayCharset(doc->charset());
1586
void Manager::getCursorPos(int& line, int& col) {
1589
Document* doc = curDoc();
1590
if ( !doc->isNull() ) {
1591
doc->getCursorPos(line, col);
1598
void Manager::getSelection(int& line1, int& col1, int& line2, int& col2) {
1601
Document* doc = curDoc();
1602
if ( !doc->isNull() ) {
1603
doc->getSelection(line1, col1, line2, col2);
1607
void Manager::getSelectedText(QString& text) {
1610
Document* doc = curDoc();
1611
if ( !doc->isNull() ) {
1612
text = doc->selectedText();
1616
void Manager::setCursorPos(int line, int col) {
1619
Document* doc = curDoc();
1620
if ( !doc->isNull() ) {
1621
doc->setCursorPos(line, col);
1625
void Manager::setSelection(int line1, int col1, int line2, int col2) {
1628
Document* doc = curDoc();
1629
if ( !doc->isNull() ) {
1630
doc->setSelection(line1, col1, line2, col2);
1634
void Manager::removeSelectedText() {
1637
Document* doc = curDoc();
1638
if ( !doc->isNull() ) {
1639
doc->removeSelectedText();
1643
void Manager::replaceSelectedText(const QString& text) {
1646
Document* doc = curDoc();
1647
if ( !doc->isNull() ) {
1648
doc->replaceSelectedText(text);
1652
void Manager::insertText(const QString& text) {
1655
Document* doc = curDoc();
1656
if ( !doc->isNull() ) {
1657
doc->insertText(text);
1661
bool Manager::closeDoc(const QString& fileName) {
1664
if ( mInt_->docs1_.contains(fileName) ) {
1665
Document* doc = mInt_->docs1_[fileName];
1666
return closeWithConfirmation(doc);
1668
else if ( mInt_->docs2_.contains(fileName) ) {
1669
Document* doc = mInt_->docs2_[fileName];
1670
return closeWithConfirmation(doc);
1677
void Manager::saveDoc(const QString& fileName) {
1679
if ( mInt_->docs1_.contains(fileName) ) {
1680
doc = mInt_->docs1_[fileName];
1682
else if ( mInt_->docs2_.contains(fileName) ) {
1683
doc = mInt_->docs2_[fileName];
1686
if ( Juff::isNoname(fileName) ) {
1687
// document doesn't have a file name. Call "Save as"
1692
if ( saveDoc(doc, fileName, doc->charset()) ) {
1693
doc->setModified(false);
1698
QWidget* Manager::mainWindow() const {
1699
return mInt_->viewer_->widget();
1704
void Manager::copyFileName() {
1705
QApplication::clipboard()->setText(mInt_->nameL_->text().trimmed());