Subversion Repositories Scribus

Rev

Rev 5434 | Rev 5711 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5352 cbradney 1
/*
2
For general Scribus (>=1.3.2) copyright and licensing information please refer
3
to the COPYING file provided with the program. Following this notice may exist
4
a copyright and/or license notice that predates the release of Scribus 1.3.2
5
for which a new license (GPL+exception) is in place.
6
*/
7
/***************************************************************************
8
*   Copyright (C) 2006 by Craig Bradney                                   *
9
*   cbradney@zip.com.au                                                   *
10
*                                                                         *
11
*   This program is free software; you can redistribute it and/or modify  *
12
*   it under the terms of the GNU General Public License as published by  *
13
*   the Free Software Foundation; either version 2 of the License, or     *
14
*   (at your option) any later version.                                   *
15
*                                                                         *
16
*   This program is distributed in the hope that it will be useful,       *
17
*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
18
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
19
*   GNU General Public License for more details.                          *
20
*                                                                         *
21
*   You should have received a copy of the GNU General Public License     *
22
*   along with this program; if not, write to the                         *
23
*   Free Software Foundation, Inc.,                                       *
24
*   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
25
***************************************************************************/
26
#include "tabkeyboardshortcutswidget.h"
27
#include "tabkeyboardshortcutswidget.moc"
28
 
29
#include <qcombobox.h>
30
#include <qdir.h>
31
#include <qdom.h>
32
#include <qfile.h>
33
#include <qfileinfo.h>
34
#include <qfiledialog.h>
35
#include <qinputdialog.h>
36
#include <qkeysequence.h>
37
#include <qlabel.h>
38
#include <qlistview.h>
39
#include <qmessagebox.h>
40
#include <qpushbutton.h>
41
#include <qradiobutton.h>
42
#include <qstring.h>
43
#include <qstringlist.h>
44
 
45
#include "actionmanager.h"
46
#include "commonstrings.h"
47
#include "prefsmanager.h"
48
#include "prefsfile.h"
49
#include "prefscontext.h"
50
#include "scpaths.h"
51
#include "scraction.h"
52
#include "util.h"
53
 
54
TabKeyboardShortcutsWidget::TabKeyboardShortcutsWidget(QMap<QString, Keys> oldKeyMap, QWidget *parent, const char *name)
55
    :TabKeyboardShortcutsWidgetBase(parent, name)
56
{
5367 cbradney 57
        ActionManager::createDefaultMenus();
58
        defMenus=ActionManager::defaultMenus();
59
        Q_CHECK_PTR(defMenus);
5352 cbradney 60
        lviToActionMap.clear();
5378 cbradney 61
        lviToMenuMap.clear();
5352 cbradney 62
        keyTable->clear();
63
        keyMap.clear();
64
        keyMap = oldKeyMap;
65
        Part0 = "";
66
        Part1 = "";
67
        Part2 = "";
68
        Part3 = "";
69
        Part4 = "";
70
        keyCode = 0;
71
        keyDisplay->setMinimumWidth(fontMetrics().width("CTRL+ALT+SHIFT+W"));
72
        keyDisplay->setText("");
73
 
74
        loadableSets->insertStringList(scanForSets());
75
        keyTable->setSorting(-1);
76
        insertActions();
77
        dispKey(0);
5367 cbradney 78
        clearSearchButton->setPixmap(loadIcon("clear_right.png"));
5352 cbradney 79
        // signals and slots connections
80
        connect( keyTable, SIGNAL(clicked(QListViewItem*)), this, SLOT(dispKey(QListViewItem*)));
81
        connect( noKey, SIGNAL(clicked()), this, SLOT(setNoKey()));
82
        connect( setKeyButton, SIGNAL(clicked()), this, SLOT(setKeyText()));
83
        connect( loadSetButton, SIGNAL(clicked()), this, SLOT(loadKeySetFile()));
84
        connect( importSetButton, SIGNAL(clicked()), this, SLOT(importKeySetFile()));
85
        connect( exportSetButton, SIGNAL(clicked()), this, SLOT(exportKeySetFile()));
86
        connect( resetSetButton, SIGNAL(clicked()), this, SLOT(resetKeySet()));
5367 cbradney 87
        connect( clearSearchButton, SIGNAL(clicked()), this, SLOT(clearSearchString()));
5378 cbradney 88
        connect( searchTextLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(applySearch(const QString&)));
5352 cbradney 89
}
90
 
5556 subik 91
void TabKeyboardShortcutsWidget::restoreDefaults()
92
{
93
        loadableSets->clear();
94
        loadableSets->insertStringList(scanForSets());
95
        keyTable->setSorting(-1);
96
        insertActions();
97
        dispKey(0);
98
}
5352 cbradney 99
 
100
const QMap<QString, Keys> TabKeyboardShortcutsWidget::getNewKeyMap()
101
{
102
        return keyMap;
103
}
104
 
105
void TabKeyboardShortcutsWidget::setNoKey()
106
{
107
        if (noKey->isChecked())
108
        {
109
                if (selectedLVI!=0)
110
                {
111
                        selectedLVI->setText(1,"");
112
                        keyMap[lviToActionMap[selectedLVI]].keySequence=QKeySequence();
113
                }
114
                keyDisplay->setText("");
115
                noKey->setChecked(true);
116
        }
117
}
118
 
119
void TabKeyboardShortcutsWidget::loadKeySetFile()
120
{
121
        if (keySetList[loadableSets->currentText()])
122
                importKeySet(keySetList[loadableSets->currentText()]);
123
}
124
 
125
void TabKeyboardShortcutsWidget::importKeySetFile()
126
{
127
        PrefsContext* dirs = PrefsManager::instance()->prefsFile->getContext("dirs");
128
        QString currentPath = dirs->get("keymapprefs_import", ".");
129
        QString s = QFileDialog::getOpenFileName(currentPath, tr("Key Set XML Files (*.ksxml)"), this, "load open file dialog", "Choose a file to open" );
130
        if (!s.isEmpty())
131
                importKeySet(s);
132
}
133
void TabKeyboardShortcutsWidget::exportKeySetFile()
134
{  
135
        PrefsContext* dirs = PrefsManager::instance()->prefsFile->getContext("dirs");
136
        QString currentPath= dirs->get("keymapprefs_export", ".");
137
        QString s = QFileDialog::getSaveFileName(currentPath, tr("Key Set XML Files (*.ksxml)"), this, "save open file dialog", "Choose a file to save" );
138
        if (!s.isEmpty())
139
                exportKeySet(s);
140
}
141
 
142
void TabKeyboardShortcutsWidget::importKeySet(QString filename)
143
{
5378 cbradney 144
        searchTextLineEdit->clear();
5352 cbradney 145
        QFileInfo fi = QFileInfo(filename);
146
        if (fi.exists())
147
        {
148
                //import the file into qdomdoc
149
                QDomDocument doc( "keymapentries" );
150
                QFile file( filename );
151
                if ( !file.open( IO_ReadOnly ) )
152
                        return;
153
                QTextStream ts(&file);
154
                ts.setEncoding(QTextStream::UnicodeUTF8);
155
                QString errorMsg;
156
                int eline;
157
                int ecol;
158
                if ( !doc.setContent( ts.read(), &errorMsg, &eline, &ecol ))
159
                {
160
                        qDebug("%s", QString("Could not open key set file: %1\nError:%2 at line: %3, row: %4").arg(filename).arg(errorMsg).arg(eline).arg(ecol).ascii());
161
                        file.close();
162
                        return;
163
                }
164
                file.close();
165
                //load the file now
166
                QDomElement docElem = doc.documentElement();
167
                if (docElem.tagName()=="shortcutset" && docElem.hasAttribute("name"))
168
                {
169
                        QDomAttr keysetAttr = docElem.attributeNode( "name" );
170
 
171
                        //clear current menu entries
172
                        for (QMap<QString,Keys>::Iterator it=keyMap.begin(); it!=keyMap.end(); ++it)
173
                                it.data().keySequence = QKeySequence();
174
 
175
                        //load in new set
176
                        QDomNode n = docElem.firstChild();
177
                        while( !n.isNull() )
178
                        {
179
                                QDomElement e = n.toElement(); // try to convert the node to an element.
180
                                if( !e.isNull() )
181
                                {
182
                                        if (e.hasAttribute("name")  && e.hasAttribute( "shortcut" ))
183
                                        {
184
                                                QDomAttr nameAttr = e.attributeNode( "name" );
185
                                                QDomAttr shortcutAttr = e.attributeNode( "shortcut" );
186
                                                if (keyMap.contains(nameAttr.value()))
187
                                                        keyMap[nameAttr.value()].keySequence=QKeySequence(shortcutAttr.value());
188
                                        }
189
                                }
190
                                n = n.nextSibling();
191
                        }
192
                }
193
        }
194
        insertActions();
195
}
196
 
197
bool TabKeyboardShortcutsWidget::exportKeySet(QString filename)
198
{
199
        QFileInfo fi = QFileInfo(filename);
200
        QString exportFileName;
201
        if (filename.endsWith(".ksxml"))
202
                exportFileName = filename;
203
        else
204
                exportFileName = filename+".ksxml";
205
        if (overwrite(this, exportFileName))
206
        {
207
                bool ok;
208
                QString setName = QInputDialog::getText("Export Keyboard Shortcuts to File", "Enter the name of the shortcut set:", QLineEdit::Normal, QString::null, &ok, this );
209
                if (!( ok && !setName.isEmpty()) )
210
                        return false;
211
 
212
                QDomDocument doc( "keymapentries" );
213
                QString keyset=QString("<shortcutset name=\"%1\"></shortcutset>").arg(setName);
214
                doc.setContent(keyset);
215
                QDomElement keySetElement=doc.documentElement();
216
                QMap<QString,Keys>::Iterator itEnd=keyMap.end();
217
                for (QMap<QString,Keys>::Iterator it=keyMap.begin(); it!=itEnd; ++it)
218
                {
219
                        if (it.data().keySequence.isEmpty() && it.key().isEmpty())
220
                                continue;
221
                        QDomElement function_shortcut=doc.createElement("function");
222
                        function_shortcut.setAttribute("name",it.key());
223
                        function_shortcut.setAttribute("shortcut",getKeyText(it.data().keySequence));
224
                        keySetElement.appendChild(function_shortcut);
225
                }
226
                QFile f(filename);
227
                if(!f.open(IO_WriteOnly))
228
                        return false;
229
                QTextStream s(&f);
230
                s.setEncoding(QTextStream::UnicodeUTF8);
231
                QString xmltag("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
232
                s.writeRawBytes(xmltag, xmltag.length());
233
                QString xmldoc = doc.toString(4);
234
                s.writeRawBytes(xmldoc, xmldoc.length());
235
                f.close();
236
        }
237
        return true;
238
}
239
 
240
void TabKeyboardShortcutsWidget::resetKeySet()
241
{
242
        QString location=ScPaths::instance().libDir();
243
        QString defaultKeySetFileName=QDir::convertSeparators(location+"keysets/scribus13.ksxml");
244
        importKeySet(defaultKeySetFileName);   
245
}
246
 
247
QStringList TabKeyboardShortcutsWidget::scanForSets()
248
{
249
        keySetList.clear();
250
        QString location=ScPaths::instance().libDir();
251
        QString keySetLocation=QDir::convertSeparators(location+"keysets/");
252
        QDir keySetsDir(keySetLocation, "*.ksxml", QDir::Name, QDir::Files | QDir::NoSymLinks);
253
        if ((keySetsDir.exists()) && (keySetsDir.count() != 0))
254
        {
255
                QStringList appNames;
256
                for (uint fileCounter = 0; fileCounter < keySetsDir.count(); ++fileCounter)
257
                {
258
                        QString filename=QDir::convertSeparators(location+"keysets/"+keySetsDir[fileCounter]);
259
 
260
                        QDomDocument doc( "keymapentries" );
261
                        QFile file( filename );
262
                        if ( !file.open( IO_ReadOnly ) )
263
                                continue;
264
                        QString errorMsg;
265
                        int eline;
266
                        int ecol;
267
 
268
                        if ( !doc.setContent( &file, &errorMsg, &eline, &ecol ))
269
                        {
270
                                qDebug("%s", QString("Could not open key set file: %1\nError:%2 at line: %3, row: %4").arg(keySetsDir[fileCounter]).arg(errorMsg).arg(eline).arg(ecol).ascii());
271
                                file.close();
272
                                continue;
273
                        }
274
                        file.close();
275
 
276
                        QDomElement docElem = doc.documentElement();
277
                        if (docElem.tagName()=="shortcutset" && docElem.hasAttribute("name"))
278
                        {
279
                                QDomAttr nameAttr = docElem.attributeNode( "name" );
280
                                appNames.append(nameAttr.value());
281
                                keySetList.insert(nameAttr.value(), filename);
282
                        }
283
                }
284
                return QStringList(appNames);
285
        }
286
        return NULL;
287
}
288
 
289
QString TabKeyboardShortcutsWidget::getKeyText(int KeyC)
290
{
291
        if ((KeyC & ~(Qt::META | Qt::CTRL | Qt::ALT | Qt::SHIFT)) == 0)
292
                return "";
293
        // on OSX Qt translates modifiers to forsaken symbols, arrows and the like
294
        // we prefer plain English
295
        QString res;
296
        if ((KeyC & Qt::META) != 0)
297
                res += "Meta+";
298
        if ((KeyC & Qt::CTRL) != 0)
299
                res += "Ctrl+";
300
        if ((KeyC & Qt::ALT) != 0)
301
                res += "Alt+";
302
        if ((KeyC & Qt::SHIFT) != 0)
303
                res += "Shift+";
304
        return res + QString(QKeySequence(KeyC & ~(Qt::META | Qt::CTRL | Qt::ALT | Qt::SHIFT)));
305
}
306
 
307
void TabKeyboardShortcutsWidget::setKeyText()
308
{
309
        if (setKeyButton->isOn())
310
        {
311
                keyCode = 0;
312
                Part0 = "";
313
                Part1 = "";
314
                Part2 = "";
315
                Part3 = "";
316
                Part4 = "";
317
                grabKeyboard();
318
        }
319
        else
320
                releaseKeyboard();
321
}
322
 
323
void TabKeyboardShortcutsWidget::insertActions()
324
{
325
        lviToActionMap.clear();
5378 cbradney 326
        lviToMenuMap.clear();
5352 cbradney 327
        keyTable->clear();
328
        bool first, firstMenu=true;
329
        QListViewItem *currLVI, *currMenuLVI;
330
        QListViewItem *prevLVI, *prevMenuLVI;
331
        for (QValueVector< QPair<QString, QStringList> >::Iterator itmenu = defMenus->begin(); itmenu != defMenus->end(); ++itmenu )
332
        {
333
                if (firstMenu)
334
                {
335
                        currMenuLVI=new QListViewItem(keyTable);
336
                        firstMenu=false;
337
                }
338
                else
339
                        currMenuLVI=new QListViewItem(keyTable, prevMenuLVI);
340
                Q_CHECK_PTR(currMenuLVI);
5378 cbradney 341
                lviToMenuMap.append(currMenuLVI);
5352 cbradney 342
                currMenuLVI->setText(0, itmenu->first);
343
                currMenuLVI->setOpen(true);
344
                prevMenuLVI=currMenuLVI;
345
                first=true;
346
                currLVI=0;
347
                prevLVI=0;
348
                for ( QStringList::Iterator it = itmenu->second.begin(); it != itmenu->second.end(); ++it )
349
                {
350
                        if (first)
351
                        {
352
                                currLVI=new QListViewItem(currMenuLVI);
353
                                first=false;
354
                        }
355
                        else
356
                                currLVI=new QListViewItem(currMenuLVI, prevLVI);
5367 cbradney 357
                        Q_CHECK_PTR(currLVI);
5378 cbradney 358
                        lviToActionMap.insert(currLVI, *it);
5352 cbradney 359
                        currLVI->setText(0, keyMap[*it].cleanMenuText);
360
                        currLVI->setText(1, keyMap[*it].keySequence);
361
                        prevLVI=currLVI;
362
                }
363
        }
364
}
365
 
5378 cbradney 366
void TabKeyboardShortcutsWidget::applySearch( const QString & newss )
367
{
368
        //Must run this as if newss is not empty and we go to the next for loop, the set visible doesnt work
369
        for (QPtrList<QListViewItem>::iterator it=lviToMenuMap.begin(); it!=lviToMenuMap.end(); ++it)
370
                (*it)->setVisible(true);
371
        if (newss.isEmpty())
372
        {                      
373
                for (QMap<QListViewItem*, QString>::iterator it=lviToActionMap.begin(); it!=lviToActionMap.end(); ++it)
374
                        it.key()->setVisible(true);
375
                return;
376
        }
377
        //Seem to need to do this.. isOpen doesnt seem to do what it says
378
        for (QMap<QListViewItem*, QString>::iterator it=lviToActionMap.begin(); it!=lviToActionMap.end(); ++it)
379
        {
380
                if (it.key()->text(0).contains(newss, false))
381
                        it.key()->setVisible(true);
382
                else
383
                        it.key()->setVisible(false);
384
        }
385
        for (QPtrList<QListViewItem>::iterator it=lviToMenuMap.begin(); it!=lviToMenuMap.end(); ++it)
386
        {
387
                bool toBeVisible=false;
388
                QListViewItem* fc=(*it)->firstChild();
389
                if (fc!=0)
390
                {
391
                        if (fc->isVisible())
392
                                toBeVisible=true;
393
                        else
394
                        {
395
                                QListViewItem* sibling=fc->nextSibling();
396
                                while (sibling!=0)
397
                                {
398
                                        if (sibling->isVisible())
399
                                        {
400
                                                toBeVisible=true;
401
                                                break;
402
                                        }
403
                                        sibling=sibling->nextSibling();
404
                                }
405
                        }
406
                }
407
                (*it)->setVisible(toBeVisible);
408
        }
409
}
410
 
5352 cbradney 411
void TabKeyboardShortcutsWidget::dispKey(QListViewItem* qlvi)
412
{
413
        if (qlvi!=0 && lviToActionMap.contains(qlvi))
414
        {
415
                selectedLVI=qlvi;
416
                QString actionName=lviToActionMap[qlvi];
417
                if (actionName.isEmpty())
418
                        return;
419
                keyDisplay->setText(keyMap[actionName].keySequence);
420
                if (keyMap[actionName].keySequence.isEmpty())
421
                        noKey->setChecked(true);
422
                else
423
                        userDef->setChecked(true);
424
        }
425
        else
426
        {
427
                noKey->setChecked(true);
428
                keyDisplay->setText("");
429
                selectedLVI=0;
430
        }
431
}
432
 
433
bool TabKeyboardShortcutsWidget::event( QEvent* ev )
434
{
435
        bool ret = QWidget::event( ev );
436
        if ( ev->type() == QEvent::KeyPress )
437
                keyPressEvent((QKeyEvent*)ev);
438
        if ( ev->type() == QEvent::KeyRelease )
439
                keyReleaseEvent((QKeyEvent*)ev);
440
        return ret;
441
}
442
 
443
void TabKeyboardShortcutsWidget::keyPressEvent(QKeyEvent *k)
444
{
445
        if (setKeyButton->isOn())
446
        {
447
                QStringList tl;
448
                if (!keyDisplay->text().isEmpty())
449
                {
450
                        tl = tl.split("+", keyDisplay->text());
451
                        Part4 = tl[tl.count()-1];
452
                        if (Part4 == tr("Alt") || Part4 == tr("Ctrl") || Part4 == tr("Shift") || Part4 == tr("Meta"))
453
                                Part4 = "";
454
                }
455
                else
456
                        Part4 = "";
457
                switch (k->key())
458
                {
459
                        case Key_Meta:
460
                                Part0 = tr("Meta+");
461
                                keyCode |= Qt::META;
462
                                break;
463
                        case Key_Shift:
464
                                Part3 = tr("Shift+");
465
                                keyCode |= Qt::SHIFT;
466
                                break;
467
                        case Key_Alt:
468
                                Part2 = tr("Alt+");
469
                                keyCode |= Qt::ALT;
470
                                break;
471
                        case Key_Control:
472
                                Part1 = tr("Ctrl+");
473
                                keyCode |= Qt::CTRL;
474
                                break;
475
                        default:
476
                                keyCode |= k->key();
477
                                keyDisplay->setText(getKeyText(keyCode));
478
                                if (checkKey(keyCode))
479
                                {
480
                                        QMessageBox::information(this,
481
                                                                                        CommonStrings::trWarning,
482
                                                                                        tr("This key sequence is already in use"),
483
                                                                                        CommonStrings::tr_OK);
484
                                        selectedLVI->setText(1,"");
485
                                        keyDisplay->setText("");
486
                                        keyMap[lviToActionMap[selectedLVI]].keySequence=QKeySequence();
487
                                        noKey->setChecked(true);
488
                                }
489
                                else
490
                                {
491
                                        QKeySequence newKeySequence(keyCode);
492
                                        selectedLVI->setText(1, QString(newKeySequence));
493
                                        keyMap[lviToActionMap[selectedLVI]].keySequence=newKeySequence;
494
                                        userDef->setChecked(true);
495
                                }
496
                                setKeyButton->setOn(false);
497
                                releaseKeyboard();
498
                }
499
        }
500
        if (setKeyButton->isOn())
501
                keyDisplay->setText(Part0+Part1+Part2+Part3+Part4);
502
}
503
 
504
void TabKeyboardShortcutsWidget::keyReleaseEvent(QKeyEvent *k)
505
{
506
        if (setKeyButton->isOn())
507
        {
508
                if (!keyDisplay->text().isEmpty())
509
                {
510
                        QStringList tl;
511
                        tl = tl.split("+", keyDisplay->text());
512
                        Part4 = tl[tl.count()-1];
513
                        if (Part4 == tr("Alt") || Part4 == tr("Ctrl") || Part4 == tr("Shift") || Part4 == tr("Meta"))
514
                                Part4 = "";
515
                }
516
                else
517
                        Part4 = "";
518
                if (k->key() == Qt::Key_Meta)
519
                {
520
                        Part0 = "";
521
                        keyCode &= ~Qt::META;
522
                }
523
                if (k->key() == Qt::Key_Shift)
524
                {
525
                        Part3 = "";
526
                        keyCode &= ~Qt::SHIFT;
527
                }
528
                if (k->key() == Qt::Key_Alt)
529
                {
530
                        Part2 = "";
531
                        keyCode &= ~ALT;
532
                }
533
                if (k->key() == Qt::Key_Control)
534
                {
535
                        Part1 = "";
536
                        keyCode &= ~Qt::CTRL;
537
                }
538
                keyDisplay->setText(Part0+Part1+Part2+Part3+Part4);
539
        }
540
}
541
 
542
 
543
bool TabKeyboardShortcutsWidget::checkKey(int code)
544
{
545
        bool ret = false;
546
        QKeySequence key = QKeySequence(code);
547
        for (QMap<QString,Keys>::Iterator it=keyMap.begin(); it!=keyMap.end(); ++it)
548
        {
549
                if (key.matches(it.data().keySequence) != Qt::NoMatch)
550
                {
551
                        ret = true;
552
                        break;
553
                }
554
        }
555
        return ret;
556
}
5367 cbradney 557
 
558
void TabKeyboardShortcutsWidget::clearSearchString( )
559
{
560
        searchTextLineEdit->clear();
561
}