kcharselectdia.cc 11.5 KB
Newer Older
Constantin Berzan's avatar
Constantin Berzan committed
1
2
3
4
5
/*
 * Copyright 1999  Reginald Stadlbauer <reggie@kde.org>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
6
 * published by the Free Software Foundation; either version 2 of
Constantin Berzan's avatar
Constantin Berzan committed
7
8
9
10
11
12
13
14
15
16
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
17

Constantin Berzan's avatar
Constantin Berzan committed
18
19
#include "kcharselectdia.h"

Christoph Feck's avatar
Christoph Feck committed
20
21
#include <QAction>
#include <QApplication>
Laurent Montel's avatar
Laurent Montel committed
22
#include <QClipboard>
Christoph Feck's avatar
Christoph Feck committed
23
24
#include <QDir>
#include <QFontDatabase>
Laurent Montel's avatar
Laurent Montel committed
25
#include <QGridLayout>
Christoph Feck's avatar
Christoph Feck committed
26
27
#include <QIcon>
#include <QMenu>
Christoph Feck's avatar
Christoph Feck committed
28

Constantin Berzan's avatar
Constantin Berzan committed
29
#include <KActionCollection>
30
#include <kbookmarks_version.h>
Christoph Feck's avatar
Christoph Feck committed
31
32
#include <KBookmarkManager>
#include <KBookmarkMenu>
Christoph Feck's avatar
Christoph Feck committed
33
34
#include <KConfigGroup>
#include <KLocalizedString>
Constantin Berzan's avatar
Constantin Berzan committed
35
36
#include <KStandardAction>
#include <KStandardShortcut>
Christoph Feck's avatar
Christoph Feck committed
37
#include <KSharedConfig>
38
#include <KToggleAction>
Laurent Montel's avatar
Laurent Montel committed
39
#include <KBookmarkOwner>
40

Christoph Feck's avatar
Christoph Feck committed
41
42
43
44
45
46
47
class KCharSelectBookmarkOwner : public KBookmarkOwner
{
public:
    KCharSelectBookmarkOwner(KCharSelectDia *dia)
        : d(dia) { }
    ~KCharSelectBookmarkOwner() { }

Laurent Montel's avatar
Laurent Montel committed
48
    QString currentTitle() const override
Christoph Feck's avatar
Christoph Feck committed
49
50
51
52
53
54
55
56
57
    {
        uint ucs4 = d->charSelect->currentCodePoint();
        if (QChar::isPrint(ucs4)) {
            return QString::fromUcs4(&ucs4, 1) + QLatin1Char(' ') + formatCodePoint(ucs4);
        } else {
            return formatCodePoint(ucs4);
        }
    }

Laurent Montel's avatar
Laurent Montel committed
58
    QUrl currentUrl() const override
Christoph Feck's avatar
Christoph Feck committed
59
60
61
62
    {
        return QUrl(formatCodePoint(d->charSelect->currentCodePoint()));
    }

Laurent Montel's avatar
Laurent Montel committed
63
    void openBookmark(const KBookmark &bm, Qt::MouseButtons, Qt::KeyboardModifiers) override
Christoph Feck's avatar
Christoph Feck committed
64
65
66
    {
        QString c = bm.url().toString(QUrl::PreferLocalFile | QUrl::RemoveScheme);
        if (c.startsWith(QLatin1String("U+"))) {
Laurent Montel's avatar
Laurent Montel committed
67
            uint uc = c.midRef(2).toUInt(Q_NULLPTR, 16);
Christoph Feck's avatar
Christoph Feck committed
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
            d->charSelect->setCurrentCodePoint(uc);
        }
    }

private:
    static QString formatCodePoint(uint ucs4)
    {
        QString c = QString::number(ucs4, 16).toUpper();
        while (c.length() < 4) {
            c.prepend(QLatin1Char('0'));
        }
        return QStringLiteral("U+") + c;
    }

private:
    KCharSelectDia *d;
};

86
87
88
89
90
/******************************************************************/
/* class KCharSelectDia                                           */
/******************************************************************/

//==================================================================
Laurent Montel's avatar
Laurent Montel committed
91
92
KCharSelectDia::KCharSelectDia(QWidget *parent)
    : KXmlGuiWindow(parent)
93
{
Christoph Feck's avatar
Christoph Feck committed
94
  KSharedConfig::Ptr config = KSharedConfig::openConfig();
95
96
  KConfigGroup gr = config->group("General");

Christoph Feck's avatar
Christoph Feck committed
97
  vFont = gr.readEntry("selectedFont", QFontDatabase::systemFont(QFontDatabase::GeneralFont));
98
  vChr = gr.readEntry("char", 33);
99
  _rtl = gr.readEntry("rtl", false);
100

101
102
103
  QWidget *mainWidget = new QWidget(this);
  setCentralWidget(mainWidget);

Stephan Kulow's avatar
Stephan Kulow committed
104
  grid = new QGridLayout( mainWidget );
105

106
  // Add character selection widget from library kdeui
107
  charSelect = new KCharSelect(mainWidget, actionCollection());
108
109
  charSelect->setAllPlanesEnabled(true);
  charSelect->setCurrentCodePoint(vChr);
Pino Toscano's avatar
Pino Toscano committed
110
  charSelect->setCurrentFont(vFont);
111
  charSelect->resize(charSelect->sizeHint());
112
113
114
  connect(charSelect, &KCharSelect::currentCodePointChanged, this, &KCharSelectDia::charChanged);
  connect(charSelect,SIGNAL(codePointSelected(uint)),
         SLOT(add(uint)));
Laurent Montel's avatar
Laurent Montel committed
115
116

  connect(charSelect, &KCharSelect::currentFontChanged, this, &KCharSelectDia::fontSelected);
117
  grid->addWidget(charSelect, 0, 0, 1, 4);
118

119
  // Build line editor
Christoph Feck's avatar
Christoph Feck committed
120
  lined = new QLineEdit(mainWidget);
121
  lined->resize(lined->sizeHint());
Christoph Feck's avatar
Christoph Feck committed
122
  lined->setClearButtonEnabled(true);
Nadeem Hasan's avatar
Nadeem Hasan committed
123

124
  lined->setFont( vFont );
Nadeem Hasan's avatar
Nadeem Hasan committed
125

Laurent Montel's avatar
Laurent Montel committed
126
  connect(lined, &QLineEdit::textChanged, this, &KCharSelectDia::lineEditChanged);
127
  grid->addWidget(lined, 1, 0, 1, 3);
128

Christoph Feck's avatar
Christoph Feck committed
129
  bClip = new QPushButton( i18n( "&To Clipboard" ), mainWidget );
Laurent Montel's avatar
Laurent Montel committed
130
  bClip->setIcon( QIcon::fromTheme( QStringLiteral( "edit-copy" ) ));
Nadeem Hasan's avatar
Nadeem Hasan committed
131
  bClip->setFixedSize( bClip->sizeHint() );
Laurent Montel's avatar
Laurent Montel committed
132
  connect(bClip, &QPushButton::clicked, this, &KCharSelectDia::toClip);
133
  grid->addWidget(bClip, 1, 3);
Laurent Montel's avatar
Laurent Montel committed
134

135
  // Build menu
136
  KStandardAction::quit( this, SLOT(close()), actionCollection() );
Stephan Kulow's avatar
Stephan Kulow committed
137

Laurent Montel's avatar
Laurent Montel committed
138
  QAction *action = actionCollection()->addAction( QStringLiteral( "copy_clip" ) );
Laurent Montel's avatar
Port++    
Laurent Montel committed
139
  action->setText( i18n("&To Clipboard") );
Laurent Montel's avatar
Laurent Montel committed
140
  action->setIcon( QIcon::fromTheme( QStringLiteral( "edit-copy" )) );
Laurent Montel's avatar
Laurent Montel committed
141
  connect(action, &QAction::triggered, this, &KCharSelectDia::toClip);
Christoph Feck's avatar
Christoph Feck committed
142
  actionCollection()->setDefaultShortcuts(action, KStandardShortcut::shortcut(KStandardShortcut::Copy));
143

Laurent Montel's avatar
Laurent Montel committed
144
  action = actionCollection()->addAction( QStringLiteral( "copy_utf_8" ) );
Laurent Montel's avatar
Port++    
Laurent Montel committed
145
  action->setText( i18n("To Clipboard &UTF-8") );
Laurent Montel's avatar
Laurent Montel committed
146
  connect(action, &QAction::triggered, this, &KCharSelectDia::toClipUTF8);
Laurent Montel's avatar
Laurent Montel committed
147
  action = actionCollection()->addAction( QStringLiteral( "copy_html" ) );
Laurent Montel's avatar
Port++    
Laurent Montel committed
148
  action->setText( i18n("To Clipboard &HTML") );
Laurent Montel's avatar
Laurent Montel committed
149
  connect(action, &QAction::triggered, this, &KCharSelectDia::toClipHTML);
Stephan Kulow's avatar
Stephan Kulow committed
150

Laurent Montel's avatar
Laurent Montel committed
151
  action = actionCollection()->addAction( QStringLiteral( "from_clip" ) );
Laurent Montel's avatar
Port++    
Laurent Montel committed
152
  action->setText( i18n("&From Clipboard") );
Laurent Montel's avatar
Laurent Montel committed
153
  action->setIcon( QIcon::fromTheme( QStringLiteral( "edit-paste" )) );
Laurent Montel's avatar
Laurent Montel committed
154
  connect(action, &QAction::triggered, this, &KCharSelectDia::fromClip);
Christoph Feck's avatar
Christoph Feck committed
155
  actionCollection()->setDefaultShortcuts(action, KStandardShortcut::shortcut(KStandardShortcut::Paste));
Laurent Montel's avatar
Laurent Montel committed
156
  action = actionCollection()->addAction( QStringLiteral( "from_clip_utf8" ) );
Laurent Montel's avatar
Port++    
Laurent Montel committed
157
  action->setText( i18n( "From Clipboard UTF-8") );
Laurent Montel's avatar
Laurent Montel committed
158
  connect(action, &QAction::triggered, this, &KCharSelectDia::fromClipUTF8);
Stephan Kulow's avatar
Stephan Kulow committed
159

160
  i18n("From Clipboard HTML");      // Intended for future use
Stephan Kulow's avatar
Stephan Kulow committed
161

Laurent Montel's avatar
Laurent Montel committed
162
  action = actionCollection()->addAction( QStringLiteral( "flip" ) );
163
  action->setText( i18n("&Flip Text") );
Laurent Montel's avatar
Laurent Montel committed
164
  connect(action, &QAction::triggered, this, &KCharSelectDia::flipText);
165
166
167

  action = new KToggleAction( i18n("&Reverse Direction"), this );
  action->setChecked(_rtl);
Laurent Montel's avatar
Laurent Montel committed
168
  actionCollection()->addAction( QStringLiteral( "rtl" ), action );
Laurent Montel's avatar
Laurent Montel committed
169
  connect(action, &QAction::toggled, this, &KCharSelectDia::setRtl);
Stephan Kulow's avatar
Stephan Kulow committed
170

171
172
  charSelect->setFocus();

173
  if(_rtl)
174
175
176
    lined->setAlignment( Qt::AlignRight );
  else
    lined->setAlignment( Qt::AlignLeft );
177

Christoph Feck's avatar
Christoph Feck committed
178
179
180
181
182
183
184
185
186
187
188
189
  QString filename = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kcharselect/bookmarks.xml"));
  if (filename.isEmpty()) {
    filename = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/kcharselect");
    QDir().mkpath(filename);
    filename += QStringLiteral("/bookmarks.xml");
  }
  KBookmarkManager* manager = KBookmarkManager::managerForFile(filename, QStringLiteral("kcharselect"));

  action = actionCollection()->addAction(QStringLiteral("bookmarks"));
  action->setText(i18n("Bookmarks"));
  QMenu *bmmenu = new QMenu(this);
  action->setMenu(bmmenu);
190
191

#if KBOOKMARKS_VERSION < QT_VERSION_CHECK(5, 69, 0)
Christoph Feck's avatar
Christoph Feck committed
192
  KBookmarkMenu *bm = new KBookmarkMenu(manager, new KCharSelectBookmarkOwner(this), bmmenu, actionCollection());
193
194
195
196
197
#else
  KBookmarkMenu *bm = new KBookmarkMenu(manager, new KCharSelectBookmarkOwner(this), bmmenu);
  actionCollection()->addActions(bmmenu->actions());
#endif

Christoph Feck's avatar
Christoph Feck committed
198
199
  bm->setParent(this);

Daniel Laidig's avatar
Daniel Laidig committed
200
  setupGUI(ToolBar|Keys|Save|Create);
201
202
}

203
//==================================================================
204
void KCharSelectDia::closeEvent(QCloseEvent *event)
205
{
Christoph Feck's avatar
Christoph Feck committed
206
  KSharedConfig::Ptr config = KSharedConfig::openConfig();
207
208
  KConfigGroup gr = config->group("General");

209
  gr.writeEntry("selectedFont", vFont);
210
  gr.writeEntry("char", vChr);
211
  gr.writeEntry("rtl", _rtl);
212

213
  KXmlGuiWindow::closeEvent(event);
214
215
}

216
//==================================================================
217
void KCharSelectDia::charChanged(uint _chr)
218
219
220
221
222
{
  vChr = _chr;
}

//==================================================================
223
void KCharSelectDia::fontSelected(const QFont &_font)
224
{
225
  lined->setFont( _font );
Nadeem Hasan's avatar
Nadeem Hasan committed
226

227
228
229
230
  vFont = _font;
}

//==================================================================
231
void KCharSelectDia::add(uint _chr)
232
{
233
  charChanged(_chr);
234

235
  QString str = lined->text();
Laurent Montel's avatar
Laurent Montel committed
236
  const int pos = lined->cursorPosition();
237
  str.insert(pos, QString::fromUcs4(&_chr, 1));
238
  lined->setText(str);
239
  lined->setCursorPosition(pos + QString::fromUcs4(&_chr, 1).size());
240
241
242
243
244
}

//==================================================================
void KCharSelectDia::toClip()
{
245
246
  QString str = lined->text();
  if (str.isEmpty())
247
    str = QString::fromUcs4(&vChr, 1);
248
  QClipboard *cb = QApplication::clipboard();
249
250
  cb->setText(str,QClipboard::Clipboard);
  cb->setText(str,QClipboard::Selection);
251
252
}

253
//==================================================================
Dirk Mueller's avatar
Dirk Mueller committed
254
// UTF-8 is rapidly becoming the favored 8-bit encoding for
255
256
257
258
259
// Unicode (iso10646-1).
//
void KCharSelectDia::toClipUTF8()
{
  QClipboard *cb = QApplication::clipboard();
260
261
  QString str = lined->text();
  if (str.isEmpty())
262
    str = QString::fromUcs4(&vChr, 1);
263
  cb->setText(QLatin1String( str.toUtf8() ));
264
265
266
}

//==================================================================
Laurent Montel's avatar
Laurent Montel committed
267
//  Put valid HTML 4.0 into the clipboard.  Valid ISO-8859-1 Latin 1
268
//  characters are left undisturbed.  Everything else, including the
Laurent Montel's avatar
Laurent Montel committed
269
//  "c0 control characters" often used by Windows, are clipped
270
271
272
273
274
275
276
277
//  as a HTML entity.
//
void KCharSelectDia::toClipHTML()
{
  QClipboard *cb = QApplication::clipboard();
  QString input;
  QString html;
  QChar   tempchar;
Laurent Montel's avatar
Laurent Montel committed
278
  int i = 0;
279
280

  input = lined->text();
281
  if (input.isEmpty())
282
    input = QString::fromUcs4(&vChr, 1);
Laurent Montel's avatar
Laurent Montel committed
283
284
  const int inputLength = input.length();
  for(i=0; i< inputLength; ++i )
285
286
    {
      tempchar = input.at(i);
Laurent Montel's avatar
Laurent Montel committed
287
      if(  tempchar.toLatin1() && ((tempchar.unicode() < 128) || (tempchar.unicode() >= 128+32)) )
288
289
290
291
292
        {
          html.append(input.at(i));
        }
      else
        {
293
          html.append(QString::asprintf("&#x%x;", tempchar.unicode()));
294
295
296
297
298
        }
    }
  cb->setText(html);
}

299
300
301
302
303
304
305
306
307
//==================================================================
//
void KCharSelectDia::fromClip()
{
  QClipboard *cb = QApplication::clipboard();
  lined->setText( cb->text() );
}

//==================================================================
Dirk Mueller's avatar
Dirk Mueller committed
308
// UTF-8 is rapidly becoming the favored 8-bit encoding for
309
310
311
312
313
314
315
// Unicode (iso10646-1).  This function is handy for decoding
// UTF-8 found in legacy applications, consoles, filenames, webpages,
// etc.
//
void KCharSelectDia::fromClipUTF8()
{
  QClipboard *cb = QApplication::clipboard();
Laurent Montel's avatar
Laurent Montel committed
316
  const QString str = cb->text();
317

Laurent Montel's avatar
Laurent Montel committed
318
  lined->setText( str.fromUtf8( str.toLatin1() ) );
319
320
}

321
322
//==================================================================
//  Reverse the text held in the line edit buffer.  This is crucial
Laurent Montel's avatar
Laurent Montel committed
323
//  for dealing with visual vs. logical representations of
324
325
326
327
328
329
330
//  right to left languages, and handy for working around all
//  manner of legacy character order issues.
//
void KCharSelectDia::flipText()
{
  QString input;
  QString output;
Laurent Montel's avatar
Laurent Montel committed
331
  int i;
Laurent Montel's avatar
Laurent Montel committed
332

333
  input = lined->text();
Laurent Montel's avatar
Laurent Montel committed
334
335
  const int nbLength = input.length();
  for(i=0; i< nbLength; ++i )
336
337
338
339
340
341
342
    {
      output.prepend( input.at(i) );
    }
  lined->setText(output);
}

//==================================================================
343
void KCharSelectDia::setRtl(bool rtl)
Laurent Montel's avatar
Laurent Montel committed
344
{
345
346
    _rtl = rtl;
    if(_rtl)
347
348
349
350
351
352
        lined->setAlignment( Qt::AlignRight );
    else
        lined->setAlignment( Qt::AlignLeft );
}

//==================================================================
Nadeem Hasan's avatar
Nadeem Hasan committed
353
void KCharSelectDia::lineEditChanged()
354
{
355
    if(_rtl)
356
357
358
359
360
      {
        if(lined->cursorPosition())
            lined->setCursorPosition( lined->cursorPosition() - 1 );
      }
}