1 /**
2 * \file kdemainwindow.cpp
3 * KDE Kid3 main window.
4 *
5 * \b Project: Kid3
6 * \author Urs Fleisch
7 * \date 9 Jan 2003
8 *
9 * Copyright (C) 2003-2018 Urs Fleisch
10 *
11 * This file is part of Kid3.
12 *
13 * Kid3 is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * Kid3 is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25 */
26
27 #include "kdemainwindow.h"
28 #include <kconfigwidgets_version.h>
29 #include <KConfig>
30 #include <KToggleAction>
31 #include <KStandardAction>
32 #include <KShortcutsDialog>
33 #include <KRecentFilesAction>
34 #include <KActionCollection>
35 #include <KEditToolBar>
36 #include <KConfigSkeleton>
37 #include <QApplication>
38 #include <QUrl>
39 #include <QAction>
40 #include "config.h"
41 #include "kid3form.h"
42 #include "filelist.h"
43 #include "sectionactions.h"
44 #include "kid3application.h"
45 #include "kdeconfigdialog.h"
46 #include "guiconfig.h"
47 #include "tagconfig.h"
48 #include "useractionsconfig.h"
49 #include "serverimporter.h"
50 #include "servertrackimporter.h"
51
52 /**
53 * Constructor.
54 *
55 * @param platformTools platform specific tools
56 * @param app application context
57 * @param parent parent widget
58 */
KdeMainWindow(IPlatformTools * platformTools,Kid3Application * app,QWidget * parent)59 KdeMainWindow::KdeMainWindow(IPlatformTools* platformTools,
60 Kid3Application* app, QWidget* parent)
61 : KXmlGuiWindow(parent),
62 BaseMainWindow(this, platformTools, app),
63 m_platformTools(platformTools), m_fileOpenRecent(nullptr),
64 m_settingsShowStatusbar(nullptr),
65 m_settingsAutoHideTags(nullptr), m_settingsShowHidePicture(nullptr)
66 {
67 init();
68 }
69
70 /** Only defined for generation of translation files */
71 #define MAIN_TOOLBAR_FOR_PO QT_TRANSLATE_NOOP("@default", "Main Toolbar")
72
73 /**
74 * Init menu and toolbar actions.
75 */
initActions()76 void KdeMainWindow::initActions()
77 {
78 KActionCollection* collection = actionCollection();
79 #if KCONFIGWIDGETS_VERSION >= 0x051700
80 QAction* action = KStandardAction::open(
81 impl(), &BaseMainWindowImpl::slotFileOpen, collection);
82 #else
83 QAction* action = KStandardAction::open(
84 impl(), SLOT(slotFileOpen()), collection);
85 #endif
86 action->setStatusTip(tr("Open files"));
87 #if KCONFIGWIDGETS_VERSION >= 0x051700
88 m_fileOpenRecent = KStandardAction::openRecent(
89 this, &KdeMainWindow::slotFileOpenRecentUrl, collection);
90 #else
91 m_fileOpenRecent = KStandardAction::openRecent(
92 this, SLOT(slotFileOpenRecentUrl(QUrl)), collection);
93 #endif
94 m_fileOpenRecent->setStatusTip(tr("Opens a recently used folder"));
95 #if KCONFIGWIDGETS_VERSION >= 0x051700
96 action = KStandardAction::revert(
97 app(), &Kid3Application::revertFileModifications, collection);
98 #else
99 action = KStandardAction::revert(
100 app(), SLOT(revertFileModifications()), collection);
101 #endif
102 action->setStatusTip(
103 tr("Reverts the changes of all or the selected files"));
104 collection->setDefaultShortcuts(action,
105 KStandardShortcut::shortcut(KStandardShortcut::Undo));
106 #if KCONFIGWIDGETS_VERSION >= 0x051700
107 action = KStandardAction::save(
108 impl(), &BaseMainWindowImpl::slotFileSave, collection);
109 #else
110 action = KStandardAction::save(
111 impl(), SLOT(slotFileSave()), collection);
112 #endif
113 action->setStatusTip(tr("Saves the changed files"));
114 #if KCONFIGWIDGETS_VERSION >= 0x051700
115 action = KStandardAction::quit(
116 impl(), &BaseMainWindowImpl::slotFileQuit, collection);
117 #else
118 action = KStandardAction::quit(
119 impl(), SLOT(slotFileQuit()), collection);
120 #endif
121 action->setStatusTip(tr("Quits the application"));
122 #if KCONFIGWIDGETS_VERSION >= 0x051700
123 action = KStandardAction::selectAll(
124 form(), &Kid3Form::selectAllFiles, collection);
125 #else
126 action = KStandardAction::selectAll(
127 form(), SLOT(selectAllFiles()), collection);
128 #endif
129 action->setStatusTip(tr("Select all files"));
130 action->setShortcut(QKeySequence(QLatin1String("Alt+Shift+A")));
131 #if KCONFIGWIDGETS_VERSION >= 0x051700
132 action = KStandardAction::deselect(
133 form(), &Kid3Form::deselectAllFiles, collection);
134 #else
135 action = KStandardAction::deselect(
136 form(), SLOT(deselectAllFiles()), collection);
137 #endif
138 action->setStatusTip(tr("Deselect all files"));
139 #if KCONFIGWIDGETS_VERSION >= 0x051700
140 action = KStandardAction::find(
141 impl(), &BaseMainWindowImpl::find, collection);
142 #else
143 action = KStandardAction::find(
144 impl(), SLOT(find()), collection);
145 #endif
146 action->setStatusTip(tr("Find"));
147 #if KCONFIGWIDGETS_VERSION >= 0x051700
148 action = KStandardAction::replace(
149 impl(), &BaseMainWindowImpl::findReplace, collection);
150 #else
151 action = KStandardAction::replace(
152 impl(), SLOT(findReplace()), collection);
153 #endif
154 action->setStatusTip(tr("Find and replace"));
155 setStandardToolBarMenuEnabled(true);
156 createStandardStatusBarAction();
157 #if KCONFIGWIDGETS_VERSION >= 0x051700
158 action = KStandardAction::keyBindings(
159 this, &KdeMainWindow::slotSettingsShortcuts, collection);
160 #else
161 action = KStandardAction::keyBindings(
162 this, SLOT(slotSettingsShortcuts()), collection);
163 #endif
164 action->setStatusTip(tr("Configure Shortcuts"));
165 #if KCONFIGWIDGETS_VERSION >= 0x051700
166 action = KStandardAction::configureToolbars(
167 this, &KdeMainWindow::slotSettingsToolbars, collection);
168 #else
169 action = KStandardAction::configureToolbars(
170 this, SLOT(slotSettingsToolbars()), collection);
171 #endif
172 action->setStatusTip(tr("Configure Toolbars"));
173 #if KCONFIGWIDGETS_VERSION >= 0x051700
174 m_settingsShowStatusbar = KStandardAction::showStatusbar(
175 this, &KdeMainWindow::slotSettingsShowStatusbar, collection);
176 #else
177 m_settingsShowStatusbar = KStandardAction::showStatusbar(
178 this, SLOT(slotSettingsShowStatusbar()), collection);
179 #endif
180 m_settingsShowStatusbar->setStatusTip(tr("Enables/disables the statusbar"));
181 #if KCONFIGWIDGETS_VERSION >= 0x051700
182 action = KStandardAction::preferences(
183 this, &KdeMainWindow::slotSettingsConfigure, collection);
184 #else
185 action = KStandardAction::preferences(
186 this, SLOT(slotSettingsConfigure()), collection);
187 #endif
188 action->setStatusTip(tr("Preferences dialog"));
189
190 action = new QAction(QIcon::fromTheme(QLatin1String("document-open")),
191 tr("O&pen Folder..."), this);
192 action->setStatusTip(tr("Opens a folder"));
193 collection->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::Key_D));
194 collection->addAction(QLatin1String("open_directory"), action);
195 connect(action, &QAction::triggered,
196 impl(), &BaseMainWindowImpl::slotFileOpenDirectory);
197
198 action = new QAction(QIcon::fromTheme(QLatin1String("view-refresh")),
199 tr("Re&load"), this);
200 action->setStatusTip(tr("Reload folder"));
201 // When using the KDE version on GNOME, a dialog appears "There are two
202 // actions (Replace..., Reload) that want to use the same shortcut (Ctrl+R)".
203 // Avoid this by assigning Qt::Key_F5 instead of QKeySequence::Refresh.
204 // The section "Standard Shortcuts" in the QKeySequence documentation lists
205 // F5 as a key for "Refresh" on all platforms.
206 collection->setDefaultShortcut(action, QKeySequence(Qt::Key_F5));
207 collection->addAction(QLatin1String("reload"), action);
208 connect(action, &QAction::triggered,
209 impl(), &BaseMainWindowImpl::slotFileReload);
210
211 action = new QAction(tr("Unload"), this);
212 collection->addAction(QLatin1String("unload"), action);
213 connect(action, &QAction::triggered, app(), &Kid3Application::unloadAllTags);
214
215 action = new QAction(QIcon::fromTheme(QLatin1String("document-import")),
216 tr("&Import..."), this);
217 action->setStatusTip(tr("Import from file or clipboard"));
218 action->setData(-1);
219 collection->addAction(QLatin1String("import"), action);
220 connect(action, &QAction::triggered, impl(), &BaseMainWindowImpl::slotImport);
221
222 int importerIdx = 0;
223 const auto sis = app()->getServerImporters();
224 for (const ServerImporter* si : sis) {
225 QString serverName(QCoreApplication::translate("@default", si->name()));
226 QString actionName = QString::fromLatin1(si->name()).toLower()
227 .remove(QLatin1Char(' '));
228 int dotPos = actionName.indexOf(QLatin1Char('.'));
229 if (dotPos != -1)
230 actionName.truncate(dotPos);
231 actionName = QLatin1String("import_") + actionName;
232 action = new QAction(tr("Import from %1...").arg(serverName), this);
233 action->setData(importerIdx);
234 action->setStatusTip(tr("Import from %1").arg(serverName));
235 collection->addAction(actionName, action);
236 connect(action, &QAction::triggered, impl(), &BaseMainWindowImpl::slotImport);
237 ++importerIdx;
238 }
239
240 const auto stis = app()->getServerTrackImporters();
241 for (const ServerTrackImporter* si : stis) {
242 QString serverName(QCoreApplication::translate("@default", si->name()));
243 QString actionName = QString::fromLatin1(si->name()).toLower()
244 .remove(QLatin1Char(' '));
245 int dotPos = actionName.indexOf(QLatin1Char('.'));
246 if (dotPos != -1)
247 actionName.truncate(dotPos);
248 actionName = QLatin1String("import_") + actionName;
249 action = new QAction(tr("Import from %1...").arg(serverName), this);
250 action->setStatusTip(tr("Import from %1").arg(serverName));
251 action->setData(importerIdx);
252 collection->addAction(actionName, action);
253 connect(action, &QAction::triggered, impl(), &BaseMainWindowImpl::slotImport);
254 ++importerIdx;
255 }
256
257 action = new QAction(tr("Import from Tags..."), this);
258 action->setStatusTip(tr("Import from Tags"));
259 collection->addAction(QLatin1String("import_tags"), action);
260 connect(action, &QAction::triggered, impl(), &BaseMainWindowImpl::slotTagImport);
261
262 action = new QAction(tr("Automatic I&mport..."), this);
263 action->setStatusTip(tr("Automatic import"));
264 collection->addAction(QLatin1String("batch_import"), action);
265 connect(action, &QAction::triggered, impl(), &BaseMainWindowImpl::slotBatchImport);
266
267 action = new QAction(tr("&Browse Cover Art..."), this);
268 action->setStatusTip(tr("Browse album cover artwork"));
269 collection->addAction(QLatin1String("browse_cover_art"), action);
270 connect(action, &QAction::triggered, impl(), &BaseMainWindowImpl::slotBrowseCoverArt);
271 action = new QAction(QIcon::fromTheme(QLatin1String("document-export")),
272 tr("&Export..."), this);
273 action->setStatusTip(tr("Export to file or clipboard"));
274 collection->addAction(QLatin1String("export"), action);
275 connect(action, &QAction::triggered, impl(), &BaseMainWindowImpl::slotExport);
276 action = new QAction(QIcon::fromTheme(QLatin1String("view-media-playlist")),
277 tr("&Create Playlist..."), this);
278 action->setStatusTip(tr("Create M3U Playlist"));
279 collection->addAction(QLatin1String("create_playlist"), action);
280 connect(action, &QAction::triggered, impl(), &BaseMainWindowImpl::slotPlaylistDialog);
281 action = new QAction(tr("Apply &Filename Format"), this);
282 action->setStatusTip(tr("Apply Filename Format"));
283 collection->addAction(QLatin1String("apply_filename_format"), action);
284 connect(action, &QAction::triggered, app(), &Kid3Application::applyFilenameFormat);
285 action = new QAction(tr("Apply &Tag Format"), this);
286 action->setStatusTip(tr("Apply Tag Format"));
287 collection->addAction(QLatin1String("apply_id3_format"), action);
288 connect(action, &QAction::triggered, app(), &Kid3Application::applyTagFormat);
289 action = new QAction(tr("Apply Text &Encoding"), this);
290 action->setStatusTip(tr("Apply Text Encoding"));
291 collection->addAction(QLatin1String("apply_text_encoding"), action);
292 connect(action, &QAction::triggered, app(), &Kid3Application::applyTextEncoding);
293 action = new QAction(tr("&Rename Folder..."), this);
294 action->setStatusTip(tr("Rename Folder"));
295 collection->addAction(QLatin1String("rename_directory"), action);
296 connect(action, &QAction::triggered, impl(), &BaseMainWindowImpl::slotRenameDirectory);
297 action = new QAction(tr("&Number Tracks..."), this);
298 action->setStatusTip(tr("Number Tracks"));
299 collection->addAction(QLatin1String("number_tracks"), action);
300 connect(action, &QAction::triggered, impl(), &BaseMainWindowImpl::slotNumberTracks);
301 action = new QAction(tr("F&ilter..."), this);
302 action->setStatusTip(tr("Filter"));
303 collection->addAction(QLatin1String("filter"), action);
304 connect(action, &QAction::triggered, impl(), &BaseMainWindowImpl::slotFilter);
305 const TagConfig& tagCfg = TagConfig::instance();
306 if (tagCfg.taggedFileFeatures() & TaggedFile::TF_ID3v24) {
307 action = new QAction(tr("Convert ID3v2.3 to ID3v2.&4"), this);
308 action->setStatusTip(tr("Convert ID3v2.3 to ID3v2.4"));
309 collection->addAction(QLatin1String("convert_to_id3v24"), action);
310 connect(action, &QAction::triggered, app(), &Kid3Application::convertToId3v24);
311 if (tagCfg.taggedFileFeatures() & TaggedFile::TF_ID3v23) {
312 action = new QAction(tr("Convert ID3v2.4 to ID3v2.&3"), this);
313 action->setStatusTip(tr("Convert ID3v2.4 to ID3v2.3"));
314 collection->addAction(QLatin1String("convert_to_id3v23"), action);
315 connect(action, &QAction::triggered, app(), &Kid3Application::convertToId3v23);
316 }
317 }
318 #ifdef HAVE_QTMULTIMEDIA
319 action = new QAction(QIcon::fromTheme(QLatin1String("media-playback-start")),
320 tr("&Play"), this);
321 action->setStatusTip(tr("Play"));
322 collection->addAction(QLatin1String("play"), action);
323 connect(action, &QAction::triggered, app(), &Kid3Application::playAudio);
324 #endif
325 m_settingsShowHidePicture = new KToggleAction(tr("Show &Picture"), this);
326 m_settingsShowHidePicture->setStatusTip(tr("Show Picture"));
327 m_settingsShowHidePicture->setCheckable(true);
328 collection->addAction(QLatin1String("hide_picture"), m_settingsShowHidePicture);
329 connect(m_settingsShowHidePicture, &QAction::triggered,
330 impl(), &BaseMainWindowImpl::slotSettingsShowHidePicture);
331 m_settingsAutoHideTags = new KToggleAction(tr("Auto &Hide Tags"), this);
332 m_settingsAutoHideTags->setStatusTip(tr("Auto Hide Tags"));
333 m_settingsAutoHideTags->setCheckable(true);
334 collection->addAction(QLatin1String("auto_hide_tags"), m_settingsAutoHideTags);
335 connect(m_settingsAutoHideTags, &QAction::triggered,
336 impl(), &BaseMainWindowImpl::slotSettingsAutoHideTags);
337 action = new QAction(tr("Select All in &Folder"), this);
338 action->setStatusTip(tr("Select all files in the current folder"));
339 collection->addAction(QLatin1String("select_all_in_directory"), action);
340 connect(action, &QAction::triggered, app(), &Kid3Application::selectAllInDirectory);
341 action = new QAction(tr("&Invert Selection"), this);
342 collection->addAction(QLatin1String("invert_selection"), action);
343 connect(action, &QAction::triggered, app(), &Kid3Application::invertSelection);
344 action = new QAction(QIcon::fromTheme(QLatin1String("go-previous")),
345 tr("&Previous File"), this);
346 action->setStatusTip(tr("Select previous file"));
347 collection->setDefaultShortcuts(action,
348 KStandardShortcut::shortcut(KStandardShortcut::Prior));
349 collection->addAction(QLatin1String("previous_file"), action);
350 connect(action, &QAction::triggered, form(), &Kid3Form::selectPreviousTaggedFile);
351 action = new QAction(QIcon::fromTheme(QLatin1String("go-next")),
352 tr("&Next File"), this);
353 action->setStatusTip(tr("Select next file"));
354 collection->setDefaultShortcuts(action,
355 KStandardShortcut::shortcut(KStandardShortcut::Next));
356 collection->addAction(QLatin1String("next_file"), action);
357 connect(action, &QAction::triggered, form(), &Kid3Form::selectNextTaggedFile);
358 FOR_ALL_TAGS(tagNr) {
359 Frame::TagNumber otherTagNr = tagNr == Frame::Tag_1
360 ? Frame::Tag_2
361 : tagNr == Frame::Tag_2 ? Frame::Tag_1 : Frame::Tag_NumValues;
362 QString tagStr = Frame::tagNumberToString(tagNr);
363 Kid3ApplicationTagContext* appTag = app()->tag(tagNr);
364 Kid3FormTagContext* formTag = form()->tag(tagNr);
365 QString actionPrefix = tr("Tag %1").arg(tagStr) +
366 QLatin1String(": ");
367 action = new QAction(tr("Filename") + QLatin1String(": ") +
368 tr("From Tag %1").arg(tagStr), this);
369 collection->addAction(QLatin1String("filename_from_v") + tagStr, action);
370 connect(action, &QAction::triggered,
371 appTag, &Kid3ApplicationTagContext::getFilenameFromTags);
372 tagStr = QLatin1Char('v') + tagStr + QLatin1Char('_');
373 action = new QAction(actionPrefix + tr("From Filename"), this);
374 collection->addAction(tagStr + QLatin1String("from_filename"), action);
375 connect(action, &QAction::triggered,
376 appTag, &Kid3ApplicationTagContext::getTagsFromFilename);
377 if (otherTagNr < Frame::Tag_NumValues) {
378 QString otherTagStr = Frame::tagNumberToString(otherTagNr);
379 action = new QAction(actionPrefix + tr("From Tag %1").arg(otherTagStr),
380 this);
381 collection->addAction(tagStr + QLatin1String("from_v") + otherTagStr,
382 action);
383 connect(action, &QAction::triggered,
384 appTag, &Kid3ApplicationTagContext::copyToOtherTag);
385 }
386 action = new QAction(actionPrefix + tr("Copy"), this);
387 collection->addAction(tagStr + QLatin1String("copy"), action);
388 connect(action, &QAction::triggered,
389 appTag, &Kid3ApplicationTagContext::copyTags);
390 action = new QAction(actionPrefix + tr("Paste"), this);
391 collection->addAction(tagStr + QLatin1String("paste"), action);
392 connect(action, &QAction::triggered,
393 appTag, &Kid3ApplicationTagContext::pasteTags);
394 action = new QAction(actionPrefix + tr("Remove"), this);
395 collection->addAction(tagStr + QLatin1String("remove"), action);
396 connect(action, &QAction::triggered,
397 appTag, &Kid3ApplicationTagContext::removeTags);
398 action = new QAction(actionPrefix + tr("Focus"), this);
399 collection->addAction(tagStr + QLatin1String("focus"), action);
400 connect(action, &QAction::triggered,
401 formTag, &Kid3FormTagContext::setFocusTag);
402 if (tagNr != Frame::Tag_Id3v1) {
403 actionPrefix += tr("Frames:") + QLatin1Char(' ');
404 action = new QAction(actionPrefix + tr("Edit"), this);
405 collection->addAction(tagStr + QLatin1String("frames_edit"), action);
406 connect(action, &QAction::triggered,
407 appTag, &Kid3ApplicationTagContext::editFrame);
408 action = new QAction(actionPrefix + tr("Add"), this);
409 collection->addAction(tagStr + QLatin1String("frames_add"), action);
410 connect(action, &QAction::triggered,
411 appTag, &Kid3ApplicationTagContext::addFrame);
412 action = new QAction(actionPrefix + tr("Delete"), this);
413 collection->addAction(tagStr + QLatin1String("frames_delete"), action);
414 connect(action, &QAction::triggered,
415 appTag, &Kid3ApplicationTagContext::deleteFrame);
416 }
417 }
418
419 action = new QAction(tr("Filename") + QLatin1String(": ") + tr("Focus"),
420 this);
421 collection->addAction(QLatin1String("filename_focus"), action);
422 connect(action, &QAction::triggered, form(), &Kid3Form::setFocusFilename);
423
424 action = new QAction(tr("File List") + QLatin1String(": ") + tr("Focus"),
425 this);
426 collection->addAction(QLatin1String("filelist_focus"), action);
427 connect(action, &QAction::triggered, form(), &Kid3Form::setFocusFileList);
428 action = new QAction(tr("&Rename"), this);
429 collection->setDefaultShortcut(action, QKeySequence(Qt::Key_F2));
430 action->setShortcutContext(Qt::WidgetShortcut);
431 connect(action, &QAction::triggered, impl(), &BaseMainWindowImpl::renameFile);
432 // This action is not made configurable because its shortcut F2 conflicts
433 // with a section shortcut and there seems to be no way to avoid it with
434 // KShortcutsDialog. The same applies to the shortcut with the Delete key.
435 // collection->addAction(QLatin1String("filelist_rename"), action);
436 form()->getFileList()->setRenameAction(action);
437 action = new QAction(tr("&Move to Trash"), this);
438 collection->setDefaultShortcut(action, QKeySequence::Delete);
439 action->setShortcutContext(Qt::WidgetShortcut);
440 connect(action, &QAction::triggered, impl(), &BaseMainWindowImpl::deleteFile);
441 // collection->addAction(QLatin1String("filelist_delete"), action);
442 form()->getFileList()->setDeleteAction(action);
443 action = new QAction(tr("Folder List") + QLatin1String(": ") + tr("Focus"),
444 this);
445 collection->addAction(QLatin1String("dirlist_focus"), action);
446 connect(action, &QAction::triggered, form(), &Kid3Form::setFocusDirList);
447
448 FileList* fileList = form()->getFileList();
449 // Do not support user action keyboard shortcuts with KDE 4, it would only
450 // print "Attempt to use QAction (..) with KXMLGUIFactory!" warnings.
451 connect(fileList, &FileList::userActionAdded,
452 this, &KdeMainWindow::onUserActionAdded);
453 connect(fileList, &FileList::userActionRemoved,
454 this, &KdeMainWindow::onUserActionRemoved);
455 fileList->initUserActions();
456 const UserActionsConfig& userActionsCfg = UserActionsConfig::instance();
457 connect(&userActionsCfg, &UserActionsConfig::contextMenuCommandsChanged,
458 fileList, &FileList::initUserActions);
459
460 const auto sectionShortcuts = SectionActions::defaultShortcuts();
461 QString actionPrefix = tr("Section") + QLatin1String(": ");
462 for (auto it = sectionShortcuts.constBegin();
463 it != sectionShortcuts.constEnd();
464 ++it) {
465 const auto& tpl = *it;
466 action = new QAction(actionPrefix + std::get<1>(tpl), this);
467 action->setShortcutContext(Qt::WidgetShortcut);
468 // The action is only used to configure the shortcuts. Disabling it will
469 // also avoid "that want to use the same shortcut" error dialogs.
470 action->setEnabled(false);
471 collection->setDefaultShortcut(action, std::get<2>(tpl));
472 collection->addAction(std::get<0>(tpl), action);
473 }
474
475 createGUI();
476 }
477
478 /**
479 * Get keyboard shortcuts.
480 * @return mapping of action names to key sequences.
481 */
shortcutsMap() const482 QMap<QString, QKeySequence> KdeMainWindow::shortcutsMap() const
483 {
484 QMap<QString, QKeySequence> map;
485 if (KActionCollection* collection = actionCollection()) {
486 const auto actions = collection->actions();
487 for (QAction* action : actions) {
488 if (action) {
489 QString name = action->objectName();
490 if (!name.isEmpty()) {
491 map.insert(name, action->shortcut());
492 }
493 }
494 }
495 }
496 return map;
497 }
498
499 /**
500 * Add directory to recent files list.
501 *
502 * @param dirName path to directory
503 */
addDirectoryToRecentFiles(const QString & dirName)504 void KdeMainWindow::addDirectoryToRecentFiles(const QString& dirName)
505 {
506 QUrl url;
507 url.setPath(dirName);
508 m_fileOpenRecent->addUrl(url);
509 }
510
511 /**
512 * Read settings from the configuration.
513 */
readConfig()514 void KdeMainWindow::readConfig()
515 {
516 setAutoSaveSettings();
517 m_settingsShowHidePicture->setChecked(!GuiConfig::instance().hidePicture());
518 m_settingsAutoHideTags->setChecked(GuiConfig::instance().autoHideTags());
519 auto cfg = KSharedConfig::openConfig();
520 m_fileOpenRecent->loadEntries(cfg->group("Recent Files"));
521
522 QString entry = cfg->group("MainWindow").readEntry("StatusBar", "Enabled");
523 bool statusBarVisible = entry != QLatin1String("Disabled");
524 if (m_settingsShowStatusbar) {
525 m_settingsShowStatusbar->setChecked(statusBarVisible);
526 }
527 setStatusBarVisible(statusBarVisible);
528 }
529
530 /**
531 * Store geometry and recent files in settings.
532 */
saveConfig()533 void KdeMainWindow::saveConfig()
534 {
535 m_fileOpenRecent->saveEntries(KSharedConfig::openConfig()->group("Recent Files"));
536 }
537
538 /**
539 * Set main window caption.
540 *
541 * @param caption caption without application name
542 * @param modified true if any file is modified
543 */
setWindowCaption(const QString & caption,bool modified)544 void KdeMainWindow::setWindowCaption(const QString& caption, bool modified)
545 {
546 setCaption(caption, modified);
547 }
548
549 /**
550 * Get action for Settings/Auto Hide Tags.
551 * @return action.
552 */
autoHideTagsAction()553 QAction* KdeMainWindow::autoHideTagsAction()
554 {
555 return m_settingsAutoHideTags;
556 }
557
558 /**
559 * Get action for Settings/Hide Picture.
560 * @return action.
561 */
showHidePictureAction()562 QAction* KdeMainWindow::showHidePictureAction()
563 {
564 return m_settingsShowHidePicture;
565 }
566
567 /**
568 * Update modification state before closing.
569 * Called on closeEvent() of window.
570 * If anything was modified, save after asking user.
571 * Save options before closing.
572 * This method is called by closeEvent(), which occurs when the
573 * window is closed or slotFileQuit() (Quit menu) is selected.
574 *
575 * @return false if user canceled,
576 * true will quit the application.
577 */
queryClose()578 bool KdeMainWindow::queryClose()
579 {
580 return queryBeforeClosing();
581 }
582
583 /**
584 * Saves the window properties to the session config file.
585 *
586 * @param cfg application configuration
587 */
saveProperties(KConfigGroup & cfg)588 void KdeMainWindow::saveProperties(KConfigGroup& cfg)
589 {
590 cfg.writeEntry("dirname", app()->getDirName());
591 }
592
593 /**
594 * Reads the session config file and restores the application's state.
595 *
596 * @param cfg application configuration
597 */
readProperties(const KConfigGroup & cfg)598 void KdeMainWindow::readProperties(const KConfigGroup& cfg)
599 {
600 app()->openDirectory({cfg.readEntry("dirname", "")});
601 }
602
603 /**
604 * Open recent directory.
605 *
606 * @param dir directory to open
607 */
slotFileOpenRecentUrl(const QUrl & url)608 void KdeMainWindow::slotFileOpenRecentUrl(const QUrl& url)
609 {
610 openRecentDirectory(url.path());
611 }
612
613 /**
614 * Shortcuts configuration.
615 */
slotSettingsShortcuts()616 void KdeMainWindow::slotSettingsShortcuts()
617 {
618 if (KShortcutsDialog::configure(
619 actionCollection(),
620 KShortcutsEditor::LetterShortcutsAllowed, this) ==
621 QDialog::Accepted) {
622 impl()->applyChangedShortcuts();
623 }
624 }
625
626 /**
627 * Toolbars configuration.
628 */
slotSettingsToolbars()629 void KdeMainWindow::slotSettingsToolbars()
630 {
631 KEditToolBar dlg(actionCollection());
632 if (dlg.exec()) {
633 createGUI();
634 }
635 }
636
637 /**
638 * Statusbar configuration.
639 */
slotSettingsShowStatusbar()640 void KdeMainWindow::slotSettingsShowStatusbar()
641 {
642 setStatusBarVisible(m_settingsShowStatusbar->isChecked());
643 setSettingsDirty();
644 }
645
646 /**
647 * Preferences.
648 */
slotSettingsConfigure()649 void KdeMainWindow::slotSettingsConfigure()
650 {
651 QString caption(tr("Configure - Kid3"));
652 KConfigSkeleton* configSkeleton = new KConfigSkeleton;
653 auto dialog = new KdeConfigDialog(m_platformTools, this, caption,
654 configSkeleton);
655 dialog->setConfig();
656 if (dialog->exec() == QDialog::Accepted) {
657 dialog->getConfig();
658 impl()->applyChangedConfiguration();
659 }
660 delete configSkeleton;
661 }
662
663 /**
664 * Add user action to collection.
665 * @param name name of action
666 * @param action action to add
667 */
onUserActionAdded(const QString & name,QAction * action)668 void KdeMainWindow::onUserActionAdded(const QString& name, QAction* action)
669 {
670 KActionCollection* collection = actionCollection();
671 collection->addAction(name, action);
672 }
673
674 /**
675 * Remove user action from collection.
676 * @param name name of action
677 * @param action action to remove
678 */
onUserActionRemoved(const QString & name,QAction * action)679 void KdeMainWindow::onUserActionRemoved(const QString& name, QAction* action)
680 {
681 Q_UNUSED(name)
682 KActionCollection* collection = actionCollection();
683 collection->takeAction(action);
684 }
685