diff --git a/NEWS b/NEWS
index 37ff6b7005..9254bf8ad0 100644
--- a/NEWS
+++ b/NEWS
@@ -1,677 +1,678 @@
digiKam 6.0.0 - Release date: 2019-02-10
*****************************************************************************************************
NEW FEATURES:
ImageEditor : Add Web services Import and Export tools.
Showfoto : Add Web services Import and Export tools.
LightTable : Add Web services Import and Export tools.
Database : Similarity database has been moved to a dedicated file to not bloat core database with computed
finger-prints. This will speed-up query in core database in case of Similarity feature is used.
Database : New video metadata parser based on ffmpeg to populate database.
Search : Add video support to find files based on properties registered on database.
General : Add new Exiv2 0.27 support.
General : Add new Lensfun 0.4 support.
General : Use DrMinGW has crash handler under Windows.
General : Port all export/import tool to OAuth2 authentification.
General : New tool to adjust quickly time and date information from items.
Tool will be available in AlbumView, ImageEditor, LightTable, and Showfoto.
General : New function to group images by timelapse / burst
General : New tool to export to Pinterest social network.
General : New tool to export to OneDrive webservice.
General : New tool to export to Box webservice.
General : New tool to export to Ipfs webservice.
General : All bundles use last Lenfun 0.3.95 to process automatic lens correction.
General : Add QWebEngine support.
General : Fix all Krazy static analyzer reports.
General : Update internal Libraw to last 0.19.2.
New camera supported:
* Apple: Phone 8, iPhone 8 plus, iPhone X
* BlackMagic: URSA Mini 4k, URSA Mini 4.6k, URSA Mini Pro 4.6k
* Canon: PowerShot A410, A540, D10, ELPH 130 IS, ELPH 160 IS, SD750, SX100 IS,SX130 IS, SX160 IS, SX510 HS, SX10 IS, IXUS 900Ti
PowerShot G1 X Mark III, G9 X Mark II, EOS 6D Mark II, EOS 77D, EOS 200D, EOS 800D, EOS M6, EOS M100
* Casio: EX-ZR4100/5100
* DJI: Phantom4 Pro/Pro+, Zenmuse X5, Zenmuse X5R
* FujiFilm: S6500fd, GFX 50S, X100f, X-A3, X-A5, X-A10, X-A20, X-E3, X-H1, X-T20
* Hasselblad: H6D-100c, A6D-100c
* Huawei: P9 (EVA-L09/AL00), Honor6a, Honor9, Mate10 (BLA-L29)
* Leica: CL, M10, TL2
* LG: V20 (F800K), VS995
* Nikon: D850, D5600, D7500, Coolpix B700
* Olympus: E-PL9, E-M10 Mark III, TG-5
* OnePlus: A3303, A5000
* Panasonic: DMC-FZ45, DMC-FZ72, DC-FZ80/82, DC-G9 (std. res mode only), DC-GF10/GF90, DC-GH5, DC-GX9, DC-GX800/850/GF9, DMC-LX1, DC-ZS70 (DC-TZ90/91/92, DC-T93), DC-TZ100/101/ZS100, DC-TZ200/ZS200
* PARROT: Bebop 2, Bebop Drone
* Pentax: KP
* PhaseOne: IQ3 100MP Trichromatic
* Samsung: Galaxy Nexus, Galaxy S3, S6 (SM-G920F), S7, S7 Edge, S8 (SM-G950U)
* Sony: A7R III, A9, DSC-RX0, DSC-RX10IV
* Yi: M1
* YUNEEC: CGO3, CGO3P
* Xiaoyi: YIAC3 (YI 4k)
Collection : Add tool button to update an existing collection to the new drive or path.
Tags : Add possibility to merge tags by drag & drop.
IconView : Add capability to re-organize the contents manually.
IconView : Add capability to separate the contents by month.
HTML Gallery : New Vanilla theme to emulate export to HTML from Adobe LightRoom.
HTML Gallery : New Blue Frame theme.
HTML Gallery : New Kiosk-Mode theme.
*****************************************************************************************************
BUGFIXES:
001 ==> 172650 - No export tools available.
002 ==> 149591 - The export menu is blank.
003 ==> 300424 - Export tools not detected.
004 ==> 327743 - MediaWiki export not displayed.
005 ==> 348146 - Export tools configuration module.
006 ==> 243275 - Crashing when calling configuration.
007 ==> 257134 - Crashes when entering its settings.
008 ==> 230666 - Crash during start.
009 ==> 306698 - Crashes after update to KDE.
010 ==> 207640 - Crashes immediately at startup, sometimes at closing.
011 ==> 245628 - Crash when enabling/disabling Facebook import/export.
012 ==> 097317 - sigsegv [New Thread 1100241184 (LWP 5665)].
013 ==> 245776 - Crashes when selecting Settings.
014 ==> 245775 - Crashes even without export tools installed.
015 ==> 254283 - Crash as soon as i click settings.
016 ==> 255733 - crash when reopening configuration dialog.
017 ==> 262050 - Crash after new install and scan to mysql database.
018 ==> 263871 - Crashed after searching for duplicates.
019 ==> 268242 - Crashes after I clicked on 'Settings'.
020 ==> 276882 - Add export tool buttons to toolbar.
021 ==> 284801 - Export to picasaweb crashes.
022 ==> 277669 - Crash after files moved.
023 ==> 281250 - Crash after disabling Export tools.
024 ==> 202637 - Crash trying to start export tool.
025 ==> 306693 - after update to KDE host application crashes on startup.
026 ==> 282781 - Crashes when reopening configuration dialog after disabling export tools.
027 ==> 285499 - Crash when settings window opened.
028 ==> 297629 - Crashed when importing from Nikon P7000.
029 ==> 303338 - Crashes when clicking "send to" button.
030 ==> 307619 - Refuses to load Export tools.
031 ==> 311812 - Export tools not loading, SO version not defined.
032 ==> 313186 - Crashes on attempt to use the "Send to" menu.
033 ==> 313356 - Crashed when clicking the "send to" button.
034 ==> 313577 - Crashes when pressing the "send to" button.
035 ==> 313890 - Crash when clicking "Send to...".
036 ==> 315033 - Crashes on pressing Send To... button.
037 ==> 315914 - The facebook tool crashes everytime on initialization.
038 ==> 326556 - Export tools are not loaded when starting host application for second time.
039 ==> 095175 - crash on loading, signal 11 SIGSEGV.
040 ==> 175844 - Crashes at startup loading Export tools.
041 ==> 306511 - Crash during start.
042 ==> 234021 - Crash on loading.
043 ==> 219772 - Opening the application causes crash.
044 ==> 294173 - Crash after Image resize start.
045 ==> 306881 - Crashed when attempting to open Export tools.
046 ==> 306495 - Crash changing settings linux ubuntu lucid.
047 ==> 306497 - Crash after changing settings segmentation fault possible 2nd report?
048 ==> 185470 - "Import from facebook" is listed twice in import menu.
049 ==> 334045 - MediaWiki option not available in Export menu when plugin activated.
050 ==> 142112 - Can't save on my webspace with ShowFoto.
051 ==> 167417 - Showfoto cannot save files of CIFS mount.
052 ==> 125164 - Flickr export tool should respect host application selection.
053 ==> 238927 - Host application quits when uploading to Flickr.
054 ==> 326740 - Selection of tools is set to default after each update.
055 ==> 233063 - Add progress indicator when moving or copy files [patch].
056 ==> 361829 - Rotated MP4 video with "Orientation" flag are not played back in the correct rotation angle.
057 ==> 329854 - digiKam doesn't rotate video thumbnail.
058 ==> 376661 - When importing ~200,000 video files Digikam crashes in about 2-5 seconds of starting.
059 ==> 377072 - Cannot read video metadata.
060 ==> 374453 - Extract right video date from MP4 files metadata.
061 ==> 377177 - Geolocation / GPS information doesn't appear in video metadata.
062 ==> 383588 - Imported video files have time shifted exactly 2 hours later.
063 ==> 380847 - MP4 video not importing with correct date.
064 ==> 373682 - geolocalisation filter does not take care of the videos geolocalisation tags.
065 ==> 340925 - digiKam crash when start it.
066 ==> 331506 - digiKam crashes on startup.
067 ==> 335816 - Crash when trying to add a big collection.
068 ==> 353295 - digiKam repeatedly crashes while importing pictures.
069 ==> 341433 - Crash when opening digiKam application.
070 ==> 375562 - digiKam crashes while scanning images into sqlite database.
071 ==> 334782 - Crash while doing nothing.
072 ==> 362672 - Crash on start of digiKam.
073 ==> 341023 - Crash after startup during check for updated images.
074 ==> 386891 - Crashed while adding pictures.
075 ==> 342666 - digiKam crashes during find new items.
076 ==> 341274 - digiKam crash on startup.
077 ==> 343708 - Crash when scanning album.
078 ==> 332721 - Crash when reading a certain MP4 video file.
079 ==> 343736 - Crashes when rebuilding thumbnails from database.
080 ==> 346356 - digiKam crashes when adding 90.000 pictures to library.
081 ==> 343714 - digiKam crash when scanning for new items.
082 ==> 341091 - digiKam crashes when updating the MySQL database of a a hudge photo collection.
083 ==> 340879 - digiKam crashes after getting unexpected but reasonable output from libexiv2.
084 ==> 342712 - Crash on collection scanning.
085 ==> 356704 - digiKam still crashes while scanning a new photo directory and subdirs.
086 ==> 339269 - Segfault when opening a folder that contains unknown file types (mov, avi, xcf).
087 ==> 364635 - digiKam crashes on startup.
088 ==> 357356 - digiKam crash on startup while scanning photos.
089 ==> 341554 - digiKam crashed by Data-Import from NFS.
090 ==> 345457 - digiKam crashes at "loading tools".
091 ==> 349635 - Crash of digiKam - moving album.
092 ==> 342604 - digiKam crash.
093 ==> 331450 - Signal 8 on album opening.
094 ==> 342030 - digiKam crashes when checking an AVI video file using exiv2.
095 ==> 352777 - Crash during scan.
096 ==> 352944 - digiKam crashes on start.
097 ==> 343643 - digiKam crashes while perform initial scanning of custom photo folder.
098 ==> 342000 - digiKam crash when opening folder with Videos (Album or SD Card import).
099 ==> 353447 - digiKam crashes when scanning files.
100 ==> 346807 - Crashes on startup.
101 ==> 364639 - digiKam crashed while opening database.
102 ==> 341504 - Crash while using application.
103 ==> 367691 - Searching for pictures crashes at 30% every time.
104 ==> 334604 - Crash after changing disk partions.
105 ==> 351689 - Crash on opening digiKam.
106 ==> 149267 - digiKam crashes after finding avi and so on.
107 ==> 170387 - Add movies management.
108 ==> 369629 - digiKam does not use GPS data from video files.
109 ==> 367880 - Nexus 5X videos show up upside-down in digiKam.
110 ==> 330116 - digiKam does not take care about GPS info stored in MP4 video files.
111 ==> 339150 - digikam crashes when trying to display video file.
112 ==> 344406 - Crash at start.
113 ==> 339909 - digiKam Segmentation Fault on open.
114 ==> 343231 - Crash at scanning for new fotos.
115 ==> 340373 - Crash on scanning video directory.
116 ==> 134679 - Video and audio files are not imported.
117 ==> 375357 - No video preview.
118 ==> 261773 - Batch renaming does not complete when MP4 video file is processed.
119 ==> 185915 - Album View: "Created" time of video set to "00:00".
120 ==> 303218 - digiKam import crashes when you select video files.
121 ==> 374241 - Bad video date rename.
122 ==> 375646 - Be able to scan only photo, not video and audio.
123 ==> 262499 - Cannot rename .AVI files.
124 ==> 199261 - Import avi movies from sdcard wrong date and no thumbnail.
125 ==> 181521 - NEF's in descending order, AVI in ascending order in import from SD-card.
126 ==> 392019 - Two persons can point to the same face tag in pictures.
127 ==> 392013 - Metadata explorer does not show XMP face rectangles.
128 ==> 389508 - Dates Side Menu Is Not Updated Automatically After Exif Date Change [patch].
129 ==> 331864 - Merge Tags with same name when moving to same hierarchy level.
130 ==> 347302 - Reassign name to face.
131 ==> 391747 - BQM Tool "Remove Metadata" doesn't remove all metadata from image.
132 ==> 285683 - Already imported pictures not recognized after daylight savings time.
133 ==> 392309 - Icons are pixelated when my display scale factor is 1.2
134 ==> 392405 - Function 'getImageIdsFromArea' argument order different.
135 ==> 386224 - Metadata is not updated when moving tags.
136 ==> 370245 - Be able to rename tags which have been setted in pictures.
137 ==> 374470 - Deleted tags are not removed from file metadata.
138 ==> 374516 - Persons metadata are not updated after a tag removed.
139 ==> 392436 - Count Files in directory.
140 ==> 363859 - digiKam core port from QWebKit to QWebEngine [patch].
141 ==> 392427 - Cannot add collection on network drive.
142 ==> 392022 - Position of a face tag appears on top of bottom of the list, instead of being sorted alphabetically.
143 ==> 372763 - Rename does not give options on Conflict.
144 ==> 391533 - Feature request: add "NOT" tag matching condition in "Filters" panel.
145 ==> 381222 - digiKam crash on fuzzy search.
146 ==> 386275 - Crash caused by QtAV.
147 ==> 372342 - Face tag area is very short [patch].
148 ==> 391348 - People Side Menu Shows Only Faces Not People Tagged Images.
149 ==> 385630 - Views Requiring Maps Takes ~30s to Launch.
150 ==> 192908 - Allow to split icon-view in order to show multiple albums at the same time.
151 ==> 339088 - GIT master: crash when clicking through images in preview, with face recognition running in background.
152 ==> 341605 - Crash if I attempt to use left-sidebar tags tab.
153 ==> 227266 - Handle Video Date from metadata.
154 ==> 227259 - Needs to Edit Video Date.
155 ==> 373284 - digiKam crashed with SIGSEGV in QSortFilterProxyModel::parent().
156 ==> 384807 - digikam 5.7.0 AppImage bundle : provide a more recent ffmpeg version for video support.
157 ==> 391835 - Deleted pictures still appear in group.
158 ==> 387483 - Elegant theme: Selected frame colors swapped [patch].
159 ==> 375424 - Thumbnails are not being removed from AlbumsView after moving the images to Trash.
160 ==> 368796 - Problem with Exif-tags: ImageDescription and UserComment.
161 ==> 392417 - AppImage (5.9.0-01-x86-64) does not support "--install" cli parameter.
162 ==> 392922 - digikam-6.0.0 fail to start.
163 ==> 391399 - Not possible to add location bookmarks in Digikam >5.6.0.
164 ==> 380876 - Tags in Digikam DB maintained after being removed from file and file re-scanned.
165 ==> 392017 - Merging, renaming and removing face tags.
166 ==> 352711 - Externally removed tags are not removed from digiKam.
167 ==> 393108 - Tags not always visible when selecting multiple pictures in a group.
168 ==> 392656 - Selecting a root album for face scan doesn't include subfolders, but rather scans an unexpected album set.
169 ==> 329438 - Rename function with Date & Time does not work with NTFS.
170 ==> 376473 - Can"t set empty IPTC country code when using metadata templates.
171 ==> 380289 - Cannot write to Albums residing on NFS.
172 ==> 384465 - With Compact Flash Card Created date in thumbnails is wrong.
173 ==> 381958 - Cannot add additional collection.
174 ==> 383747 - "Rotate only by setting a flag" Changes Image Instead.
175 ==> 387977 - No icon only view of "Extras sidebar": sidebar taking up a lot of space.
176 ==> 277502 - All versions of version set always displayed in Album view [patch].
177 ==> 393283 - Caption not updating Exif.Image.ImageDescription field.
178 ==> 391060 - Crashes on undo of very large tif.
179 ==> 366305 - Add a message at startup about the lack of temporary space to perform Undo operations.
180 ==> 366391 - Rotating an image seems to forget to reset the orientation flag.
181 ==> 393654 - Not able to select gpx file.
182 ==> 367596 - Sub-folder count images but don't show them (unsupported JPEG file?).
183 ==> 379922 - Digikam won't remove tags set by Windows Explorer.
184 ==> 379081 - GPS data are in file but geolocation indicator is not shown and map view empty.
185 ==> 354819 - Specific pictures not showing up in digikam.
186 ==> 393855 - MySQL/MariaDB upgrade fails.
187 ==> 384603 - Camera Creation Date not set from EXIF data.
188 ==> 386959 - Properties view: wrong creation date [patch].
189 ==> 393970 - No mts video thumbnails.
190 ==> 393728 - Reread metadata from Video uses sidecar only.
191 ==> 393925 - UpdateSchemaFromV7ToV9 fails due to duplicate key in album_2.
192 ==> 393773 - showfoto crashes when geotagging.
193 ==> 388199 - No context menu to copy coordinates from map.
194 ==> 393399 - Windows defender freaks out in windows 10 and Edge.
195 ==> 392134 - SIGSEGV While Scanning Faces [patch].
196 ==> 394168 - OSM Search Yields No Results.
197 ==> 377719 - Cannot rename file with overwrite [patch].
198 ==> 388002 - remove kio related legacy [patch]
199 ==> 394242 - Import settings unneccesarily asks to overwrite image database, and crashes when I decline.
200 ==> 394278 - A slideshow theme for kiosk mode.
201 ==> 340389 - digiKam crashes while editing pictures for color balancing on OSX [patch].
202 ==> 394413 - Unify group handling [patch].
203 ==> 394573 - Revers geodata from open street map does not work.
204 ==> 394590 - Feature request: being able to filter on all metadatas fields.
205 ==> 394671 - Distortion on Panasonic DMC-LX15.
206 ==> 393205 - Advanced rename very slow.
207 ==> 382474 - Thumbnail regeneration.
208 ==> 394865 - digikam suspicious crash on exit.
209 ==> 390541 - Tooltip background cannot be changed.
210 ==> 391521 - "Tool-tip" box difficult to read due to default color scheme.
211 ==> 377849 - Albums disappear when the network is interrupted.
212 ==> 394988 - PgDown and PgUp hardcoded in preview mode.
213 ==> 366312 - Efficient photo tagging workflow got lost in transition from 4.x to 5.
214 ==> 395093 - Being able to export a list of paths from a selection of thumbnails.
215 ==> 395144 - When zooming in preview, face tags show on wrong places.
216 ==> 275671 - Scan single image for faces.
217 ==> 395199 - Uploading large video files to flickr fails.
218 ==> 348274 - "Change Account" immediately opens web page in browser, before I click Continue
219 ==> 263347 - Print wizard ignores selected paper size, reverts to A4.
220 ==> 395579 - Only one tag being exported to flickr.
221 ==> 395790 - Rename with nested tags breaks due to | bar character.
222 ==> 395875 - ImageEditor window is blank when opened a second time.
223 ==> 385822 - [Suggested feature] Re-use thumbnails from the database for the items in Trash.
224 ==> 382174 - Not creating thumbnails and not editing (F4) files created for Samsung panorama jpgs [patch].
225 ==> 376124 - Some Photos are not previewed.
226 ==> 386188 - Preview Does Not Display Some JPGs Editor Crashes Program.
227 ==> 394906 - Toggling "use file metadata" for input will make Digikam forget all imported photos.
228 ==> 388391 - Windows x64 installer crashes at 60%.
229 ==> 377433 - Crash on opening settings.
230 ==> 390286 - Please update version of lensfun.
231 ==> 386649 - Crash on opening RAW file from OnePlus One.
232 ==> 172836 - No menu item for lensfun.
233 ==> 319462 - Crash while applying lensfun distortion correction a second time.
234 ==> 380844 - Demosaicing choosing VCD & AHD then update.
235 ==> 380843 - Demosaicing.
236 ==> 301219 - digiKam crash.
237 ==> 216013 - try to open extras/ batch raw converter was followed by a crash.
238 ==> 102045 - RAW conversion in digikam fails to convert or generate preview.
239 ==> 137281 - Cannot convert nef into raw.
240 ==> 230763 - Exif ISO data missing when converting Olympus ORF.
241 ==> 137278 - 16-bit/channel workspace when working with RAW conversions.
242 ==> 133004 - Canon CRW portrait preview upside-down.
243 ==> 221345 - Do not process search immediately when enter text to query.
244 ==> 396234 - Add a feature which allow to switch latitude and longitude.
245 ==> 396283 - Missing images in album preview.
246 ==> 396352 - Some iptc tags are not displayed in the metadata part.
247 ==> 396434 - Uncontrolled log messages oversize log file up to run out of disk space.
248 ==> 396482 - Empty folder selector window after select and click on "Import selected elements".
249 ==> 396170 - Gallery creation error.
250 ==> 140374 - HTML Gallery export fails to parse xml from non-UTF8 metadata in jpeg.
251 ==> 396712 - "Save Search" does not work.
252 ==> 396944 - Integrity constraint violation on Albums.icons when migrating from sqlite to mysql.
253 ==> 396952 - Cut and Paste Into Caption Has Incorrect Font Initially.
254 ==> 091562 - Change order of pictures in the virtual album manually.
255 ==> 098340 - Re-sort images in albums
256 ==> 177355 - Feature request: export slideshow in lighttable.
257 ==> 158520 - Wishlist sort thumbnails manually and rename images.
258 ==> 191000 - Wish: Visual tool to change the sort order of photos.
259 ==> 216802 - digiKam ability to sort album with "picture is before picture".
260 ==> 230136 - It lacks the ability to sort photos manually.
261 ==> 236249 - Wish: custom sort in album view.
262 ==> 323559 - Wish: Albums like Playlists in Amarok.
263 ==> 337002 - Manual image sort.
264 ==> 397167 - Some tags are not displayed on the preview.
265 ==> 397207 - Too many open files, when reverse geocoding many images.
266 ==> 397278 - DNG conversion not possible.
267 ==> 397311 - DIN A relation in "Aspect Ratio Crop".
268 ==> 222716 - digiKam does not start. Showing: Reading database.
269 ==> 276633 - Crash when using map view inside of digiKam.
270 ==> 224706 - digiKam for KDE on Windows "Failed to rename Album" (KDirWatch Relevant).
271 ==> 383016 - digiKam with incomplete German translation.
272 ==> 244982 - digiKam crashes at initial configuration.
273 ==> 366453 - digiKam crash while using mouse over title bar.
274 ==> 278490 - Incorrect tab layout with slider/spinbox/reset button.
275 ==> 324642 - digiKam crash when starting a bug report while offline.
276 ==> 238392 - digiKam Camera interface : rename dialog interprets alt-s as plain s when button greyed out.
277 ==> 397177 - image editor does not export exif and IPTC data when saving to PNG.
278 ==> 341276 - Picture bigger than 5MB are not previewed.
279 ==> 388908 - Error while scanning with HP F300 series.
280 ==> 381723 - digiKam crashed when I tried to close the window opened by clicking import button.
281 ==> 345288 - Crash from digiKam when try customizing a shortcut to a Tag.
282 ==> 381193 - digiKam crashes after uploading photos from smartphone via USB.
283 ==> 275670 - Face preview image incorrect on 'rotated' images.
284 ==> 395199 - Uploading large video files to flickr fails [patch].
285 ==> 240144 - digiKam : When I press the left button of the mouse on a photo, a menu appears, but no items are seen.
286 ==> 240229 - White contextual menu problem.
287 ==> 309508 - Export to Flickr does not send the geodata.
288 ==> 383987 - Flickr tool no longer authenticates to Flickr.
289 ==> 338333 - Account problem.
290 ==> 397001 - The "maximise" button is missing in decoration of the geolocation editor window [patch].
291 ==> 397406 - Digikam shouldn't use parentheses when renaming files.
292 ==> 397411 - Not being able to move files in a removable media collection which is not mounted.
293 ==> 227566 - digiKam does not allow smb:// shared folder as picture collection.
294 ==> 395201 - SSL broken in 5.9.0 AppImage bundle.
295 ==> 385363 - digiKam crashes when authorizing access to Google photo because of SSL error in AppImage.
296 ==> 348277 - Please focus auth code input field in the GDrive authentication dialog.
297 ==> 383174 - Google photo, export stops after a random quantity of photos.
298 ==> 387422 - Flickr export authorization does not work.
299 ==> 397126 - Fail to replace a photo in google photo.
300 ==> 387201 - kioslave needed by flickr export but not included in appimage.
301 ==> 389785 - 'Open in Filemanager' dolphin not working.
302 ==> 396619 - All Exports fail - cannot find ioslave.
303 ==> 254512 - Crash when initializing the export to Flickr.com.
304 ==> 237818 - Crash when uploading multiple images to Flickr.
305 ==> 286754 - Crash when when entering collection name in flickr uploader.
306 ==> 337980 - Flickr Export tool can no longer obtain a new token.
307 ==> 151018 - Requires new token with every invokation.
308 ==> 132922 - Export to flickr doesn't work.
309 ==> 149864 - Dialog box pops up saying 'Error Occured: Missing signature. We can not proceed further".
310 ==> 196179 - Flickr export does not work.
311 ==> 391734 - Can't export to google photos: SSL Handshake failed.
312 ==> 386402 - Not all page sizes for selected printer can be selected.
313 ==> 395557 - Printformat not selectable.
314 ==> 340644 - Allow to use standard photo paper sizes.
315 ==> 330906 - Crashes when exporting to HTML.
316 ==> 309316 - Html gallery export crash and other bugs.
317 ==> 314248 - digiKam crashing when exporting pictures to html.
318 ==> 225725 - Crash using HTML export.
319 ==> 396092 - Don't init search till user press a buttom specifically for this task.
320 ==> 397376 - Search in Geolocation doesn't work for Streets / location, only for City.
321 ==> 393259 - Configuration conflicts.
322 ==> 391329 - Two actions that wants to use same shortcut (Ctrl+Shift+,).
323 ==> 391655 - Kubuntu 18.04 beta, Digikam 5.6.0 Ambiguous Shortcuts - Zoom to 100% and Configure Digikam share the same shortcut (Ctrl+Shift+,).
324 ==> 393031 - Two actions for digikam[helpfully identified as a bug].
325 ==> 395518 - When manually typing face name, sort the filtered tags by recent usage.
326 ==> 304202 - No option to re-read metadata from XMP sidecar file.
327 ==> 289445 - Allow to create Contact Sheet from an album.
328 ==> 164750 - Picture alignment and background picture.
329 ==> 338180 - Add "Toggle auto-refresh" option in search view.
330 ==> 359235 - digiKam doesn't response after start when StatusBar=Disabled in digikamrc.
331 ==> 090550 - Linking error with jpeg.
332 ==> 393974 - Appimage bundle does not automatically recognize Gphoto2 devices connected.
333 ==> 141288 - Error KIoexec usb camera.
334 ==> 397554 - digiKam crashes while running BatchQueueManager.
335 ==> 379261 - Crash on attempting camera import.
336 ==> 379335 - digiKam crashes when deleting images in the download window [patch].
337 ==> 394291 - Cannot upgrade mysql db from v7 to v9.
338 ==> 389468 - Immediate Crash On Metadata Sync.
339 ==> 379807 - ShowFoto crashes when clicking Color Effects from menu.
340 ==> 257301 - showfoto reaches an assert when saving file with "~/" in the path.
341 ==> 183629 - Digikam/Showfoto Dark Theme: The selected photo filename is nearly invisible.
342 ==> 249379 - All versions of Digikam/Showfoto/KDE download is missing a file.
343 ==> 237286 - digiKam crash after to scan collection (upgrate from 9.10 to 10.04).
344 ==> 254878 - digiKam error segmentation fault when open it.
345 ==> 255759 - digikam crash when open it kunbuntu lucid.
346 ==> 249009 - digiKam crashes at initialisation.
347 ==> 236647 - After upgrading to Ubuntu 10.04 digiKam crashes everytime it is launched.
348 ==> 235905 - digiKam crash after upgrade.
349 ==> 185265 - digiKam constantly using some CPU in a poll loop due a timeout
350 ==> 250364 - digiKam crashes at start-up in xubuntu 10.04.
351 ==> 253205 - digiKam crashes while loading on Ubunu 10.04.
352 ==> 249033 - After upgrade to 10.04 digiKam crashes after starting always.
353 ==> 300713 - Crash while editing tag in digiKam.
354 ==> 184443 - digiKam save as "JPEG" appends a ".JPEG" file extension. Bad!
355 ==> 189084 - Crash while editing toolbars (here from digiKam camera GUI).
356 ==> 205275 - After changing symbols in bar on preview digikam closes.
357 ==> 214418 - Crash while importing into digiKam.
358 ==> 279909 - digiKam crashed when I tried to import photos from my iPhone 4.
359 ==> 287616 - digiKam crash when selecting folder to store photos.
360 ==> 327714 - digiKam crashes when starting up [Qt Bmp Image IO].
361 ==> 396892 - digiKam font sizes cannot be changed. Mostly too small.
362 ==> 371726 - Dates view empty using MYSQL due to SQL query error (fix supplied).
363 ==> 382217 - Use normalized connects [patch].
364 ==> 113692 - digiKam thumbnail hangs on .mov movie.
365 ==> 185638 - digiKam crash on startup.
366 ==> 350404 - digiKam crashes at startup.
367 ==> 301583 - digiKam crash on preview avi.
368 ==> 236960 - No video in digiKam embedded viewer no way to change codec?
369 ==> 227113 - digiKam crashes when selecting a movie.
370 ==> 274333 - digiKam crashed upon startup.
371 ==> 247019 - digiKam crashes in Album view with Canon IXUS 90 video clip.
372 ==> 238525 - digiKam crashes on browsing in album view.
373 ==> 317437 - digiKam crashes on startup.
374 ==> 237183 - digiKam crashes on playing Quicktime movies.
375 ==> 256644 - digiKam crashes after adding photos to light table.
376 ==> 245033 - digiKam falls on video files.
377 ==> 252411 - digiKam crashes when .AVI videoclip is launched.
378 ==> 247399 - digiKam crashes when viewing videos.
379 ==> 261706 - digiKam crashed after downloading pictures.
380 ==> 172170 - digiKam embedded video player - video not synchronized with sound.
381 ==> 293173 - digiKam does not play videos.
382 ==> 182401 - Wrong color palette on playback videos within digiKam.
383 ==> 219419 - digiKam crashes after splash screen with PTP.
384 ==> 397565 - Unable to launch in OS X after install.
385 ==> 337978 - digiKam crashes on startup - always.
386 ==> 215673 - digiKam movie no preview.
387 ==> 204481 - digikam: Wizard not translated in French.
388 ==> 365694 - digiKam 5.0.0 : every menus are in French, excepted the menu bar.
389 ==> 394434 - Installation problem mysql internal on mac os high sierra [patch].
390 ==> 397696 - [Website] On Fedora, use dnf instead of yum.
391 ==> 392970 - Website: Mention KDE Familly.
392 ==> 394694 - Showfoto crashes on change picture size.
393 ==> 326006 - digiKam Raw engine generates pink & black stripe on the right.
394 ==> 379984 - ASSERT failure in Q_GLOBAL_STATIC: "The global static was used after being destroyed".
395 ==> 373572 - File synchronization.
396 ==> 296768 - When creating thumbnails, digiKam uses 80% CPU - quadcore 3800, 9GB RAM.
397 ==> 397777 - Need to default to native filesystem browser on first run to see external drives.
398 ==> 279818 - digiKam crashed when updating fingerprints.
399 ==> 275931 - digiKam crashed when trying to stop a batch queue.
400 ==> 272144 - Alphabetically sorting of the tools in BQM.
401 ==> 271531 - Cannot edit canon crw-pics.
402 ==> 397739 - Menu icons are not scaled correctly on external/secondary screen (2560x1440) while using MacBookPro.
403 ==> 380841 - Crash while correcting color manually.
404 ==> 378176 - Using tool causes program to crash.
405 ==> 395842 - digiKam crashes adjusting color balance on a RAW file.
406 ==> 388608 - Faces engine hangs and crashes.
407 ==> 397855 - Not compatible with Windows 10.
408 ==> 391039 - digiKam stalled after trying to make a panorama.
409 ==> 184318 - Starting digiKam it crashed and caused the signal 11 (SIGSEGV).
410 ==> 222740 - Starting digiKam cause sound system to report pulseaudio is removed.
411 ==> 378697 - Add image carousel to front page screenshots.
412 ==> 180375 - Web page: Wrong link to Alpenglow Webpage.
413 ==> 331141 - Broken link to database schema in web site digikam.org pointing to project.kde.org.
414 ==> 397862 - Reordering geolocation bookmarks will remove them from the list.
415 ==> 223348 - digiKam crash during album view browsing AVIs with PgUp/PgDown.
416 ==> 156146 - Reading data base, digiKam don't start.
417 ==> 118090 - digiKam crashed while attempting to save scanned (tiff) image.
418 ==> 397828 - Operation cancelled when exporting to flickr.
419 ==> 397924 - Merge tag names of people.
420 ==> 397425 - Bug when trying find duplicates.
421 ==> 397496 - Wish: Read facetags from jpg files edited in Mylio.
422 ==> 397727 - Don't show "Mod."" label when no modified timestamp exists on an image.
423 ==> 397893 - MacOS : digiKam do not link with libksane 18.08.0.
424 ==> 397990 - Carousel images too large.
425 ==> 389273 - Copy/move selected items to anothor Album doesn't work correctly [patch].
426 ==> 261471 - Crashes when trying to delete photos or albums.
427 ==> 342108 - Crashes when trying to import images
428 ==> 341268 - digiKam freeze each time I select a photograph in a collection.
429 ==> 388551 - Error message at startup showing that Marble plugins are not loading but they do.
430 ==> 342110 - Bug reporting feature gives error wont report bug.
431 ==> 387047 - Easily accessible signatures.
432 ==> 286286 - digiKam crashes if I request fullscreen mode.
433 ==> 292522 - digiKam crashes on startup.
434 ==> 294791 - digiKam and Showfoto crashes while switching to fullscreen mode.
435 ==> 347589 - Menu icons size is not unified - text overlapping.
436 ==> 382053 - digiKam preferences when using mysql host port resets to default (3306) when accessing preferences.
437 ==> 388227 - Image version always shown.
438 ==> 386561 - Cannot import images from mac /Volumes/.
439 ==> 396491 - Versions are not grouped despite the correct setting.
440 ==> 389505 - Database port reset to 3306 when oppening digiKam setup (working with maiaDB10).
441 ==> 266165 - Advanced slideshow crash.
442 ==> 387372 - With Digikam Version 5.7 is no preview possible.
443 ==> 286341 - Crash at startup with a "Bus Error".
444 ==> 329050 - Application crashes while starts.
445 ==> 396374 - editing a picture (F4) presents an empty screen.
446 ==> 336874 - After exiting full screen, Menu Bar disappear and crash.
447 ==> 237494 - B&W JPEG displayed incorrectly.
448 ==> 265749 - Blank context menus.
449 ==> 274733 - Delete file permanentry works wrong.
450 ==> 383711 - All Albums Disappear.
451 ==> 378929 - DNG conversion fails in Windows 10 for Olympus ORF files.
452 ==> 170458 - Object position on pictures.
453 ==> 184638 - Generate XMP for raw files.
454 ==> 200380 - Usability of editing exif comments.
455 ==> 195090 - Thumbnails bar should have no empty space.
456 ==> 196730 - Add Color Space converter to batch queue tool.
457 ==> 207921 - Using image editing tools in fullscreen modes leaves right sidebar open.
458 ==> 211066 - TIFFs written by digiKam not readable with GIMP.
459 ==> 224603 - One-touch download when connecting media.
460 ==> 282021 - Impossible to start...
461 ==> 202430 - Crash after startup on Mac OS X.
462 ==> 139153 - Can't compile from source.
463 ==> 380971 - Albums disappear when the network is interrupted. (5.6.0).
464 ==> 342673 - Rebuild fingerprints crashes with large number (>110000) of images.
465 ==> 261134 - Drag a folder into album view - deletes source folder.
466 ==> 365809 - Menu bar disappears after having used full screen mode.
467 ==> 383924 - Tags syncing and reading from file not working.
468 ==> 395788 - If tags have a in them rename effectively deletes the file.
469 ==> 388596 - Main area remains empty with Qt 5.9.3.
470 ==> 387552 - digiKam suddenly is unable to read or display any images.
471 ==> 397972 - Unable to navigate in DK during flickr export.
472 ==> 390228 - No clear rule on where digikam wants to import.
473 ==> 187274 - The dialogue to export to an HTML gallery has an album selected but the Next button is greyed out.
474 ==> 129762 - Flickr export tool should export whole host application albums.
475 ==> 130966 - Exporting to html gallery doesn't include subalbums.
476 ==> 097396 - Export to HTML stops/ slow.
477 ==> 128035 - HTML export adds extra .jpg extention to all image filenames.
478 ==> 129870 - Album sent to HTMLGallery tool doesn't respect the view order.
479 ==> 111462 - Exporting multiple "tag" albums in HTML produces invalid hyperlinks on main webpage.
480 ==> 147770 - Use a hierarchical treeview in HTMLExport (instead of a listview).
481 ==> 259748 - Xorg crashes when launching the "Export to flickr" tool.
482 ==> 398206 - Strongly underexposed areas of the jpeg file are white rather than pure black.
483 ==> 127498 - Reduce image size delete exif data.
484 ==> 219009 - Crashed when selecting photos for upload.
485 ==> 234395 - Unable to get list of albums.
486 ==> 241587 - Flickr export reencode jpeg before sending them.
487 ==> 278890 - Showfoto crashes with qt 4.8.
488 ==> 355744 - Segfault on SmugMug upload.
489 ==> 358704 - Request authorization does not occur and upload becomes impossible.
490 ==> 175233 - Showfoto crashes on windows.
491 ==> 259623 - Application: showFoto (showfoto), signal: Segmentation fault (opening jpg).
492 ==> 194832 - Showfoto open and crash after one second.
493 ==> 390287 - digiKam crashes when I do batch renames.
494 ==> 390290 - Trying to use "red eyes" reduction function make showfoto crash.
495 ==> 388542 - DNG crash when i open a .nef files.
496 ==> 390580 - First crashes when saving tiff file, then crashes when starting.
497 ==> 391721 - No photography is displayed in the main view.
498 ==> 392813 - Showfoto crashed when clicked on close button in title bar.
499 ==> 393069 - I do not see images in the file browser, only in calendar.
500 ==> 392189 - Database upgrade fails.
501 ==> 386653 - Message error on face detectior.
502 ==> 398287 - Print creator causes digiKam crash when orientation is changed.
503 ==> 397305 - Failed to add tag to database.
504 ==> 398462 - IPTC from Ligthroom.
505 ==> 397340 - Update image file timestamps if metadata is written to sidecar file [patch].
506 ==> 398331 - Xmp sidecar files are not reloaded on change.
507 ==> 380341 - Modified sidecar not rescanned.
508 ==> 339342 - SCAN : Search for new items does not recognize modified tags in sidecar files.
509 ==> 387351 - Meta data for RAW files checkbox disabled.
510 ==> 398676 - Time Adjust in Batch Queue Manager jumps from hour to second.
511 ==> 338533 - Sort by date should use picture created date not modified date.
512 ==> 398675 - Image Rotation Inflates File Size.
513 ==> 309520 - GROUP : add 'group by month' into 'View.. | group by...' menu.
514 ==> 398714 - MicrosoftPhoto:LastKeywordXMP does not show up in digkam tags list.
515 ==> 388386 - Time adjustment tool is misleading and potentially leads to data loss.
516 ==> 366777 - No preview for Time Adjust tool.
517 ==> 306092 - Creation date as file name - doesn't work in BQM.
518 ==> 089993 - Allow setting time to specific date/time.
519 ==> 099894 - TimeAdjust only modifies file modification date, not EXIF.
520 ==> 119232 - Mass changing date for jpegs without EXIF.
521 ==> 119634 - Batch operation to change the date to several images at the same time.
522 ==> 134306 - Image mass tagging feature.
523 ==> 211845 - Missing progress bar while changing images dates.
524 ==> 249320 - Unable to change time file.
525 ==> 282559 - Graphical interface for changing dates and time.
526 ==> 354668 - Crashes when adjusting time and date on two or more photos at a time.
527 ==> 360770 - Crash when adjusting time on many pictures.
528 ==> 362104 - digiKam crashes when changing date and time of more than 25 selected pictures
529 ==> 366450 - Batch time adjust is ok, but time not adjusted in digikam thumbnail.
530 ==> 378006 - Preview of the time adjust result.
531 ==> 398624 - Cannot edit Date in XMP video metadata.
532 ==> 398810 - "Dates" panel is not refreshed after a photo with a new year is added.
533 ==> 398986 - Deleting a tag while using it as filter removes all images from the current view.
534 ==> 370093 - Opening a picture (double-click) in Showfoto (default viewer) does not show the other pictures in the folder (similar to Bug 221245).
535 ==> 398479 - digiKam crashing at startup Thread 2 Crashed:: Digikam::ScanController.
536 ==> 397808 - digiKam Mac Package crashes after resume when screen configuration changes.
537 ==> 399071 - "Adjust Time Date" tool shows all times as "00:00:00".
538 ==> 399134 - Progress bar or status when importing from camera/card reader.
539 ==> 399153 - Selecting a picture with a tag and another without that tag, the checkbox is black instead of gray.
540 ==> 384759 - Can't adjust timestamp of RAW files.
541 ==> 399221 - Cannot scroll in videos by clicking on the progress bar (only by moving the progress slider).
542 ==> 399315 - Horizontal scroll bar aligned to the right by default.
543 ==> 397962 - digiKam 6.0 does not start after install.
544 ==> 399336 - Google maps – "For development purposes only" printed on the map.
545 ==> 399338 - Count of items in Tree Views does not match total number of items.
546 ==> 399292 - Video file datetime not shown correctly after editing.
547 ==> 370553 - Adjust date - not possible to update "digiKam timestamp".
548 ==> 329091 - MySQL : needs to set "max-allowed-packet" server settings from 4.096 to 16.777.216 to prevent Maintenance tool crash.
549 ==> 399406 - digiKam Crash on advance rename.
550 ==> 397386 - Add a separate checkbox to "Show Rating".
551 ==> 335870 - Nexus 4 in PTP mode gets error: The specified camera ("/org/kde/solid/udev/...") is not supported.
552 ==> 399917 - Fails to build with QT5.7.1
553 ==> 399762 - digiKam Geolocation Correlator ignores time offset.
554 ==> 400148 - Files exported in google photos does not have their filename as name, but their date.
555 ==> 373678 - Videos exported in google photos are not available (still processing state).
556 ==> 400139 - Titles are not exported anymore on google photos.
557 ==> 400216 - Components Information window: no standardized uppercase/lowercase.
558 ==> 400217 - Incorrect Video date/time information: shifted by 2 hours.
559 ==> 396961 - Empty space on interface on thumbnail view.
560 ==> 400436 - Crash when saving jpeg files with metadata.
561 ==> 400492 - Rotation does not work.
562 ==> 246727 - Add undo functionality to move to trash action.
563 ==> 400637 - IPFS icons have non-square size, causing them to get blurred.
564 ==> 400434 - Trash content disappears after selecting 'Map' or 'Table' view.
565 ==> 394660 - Crashes when refreshing.
566 ==> 400712 - File modification timestamp is updated when images are moved to collection on removable media.
567 ==> 394214 - Import .mp4 files does not preserve file mtime as date stamp.
568 ==> 400762 - Trash - "Delete All Permanently" button not visible.
569 ==> 400792 - Failure to export to JPEG 2000.
570 ==> 400777 - Group images by timelapse / burst [patch].
571 ==> 400902 - NAS Mysql cannot connect with instructions given by Dmitry Popov.
572 ==> 400918 - Tags are erroneously copied to untagged images in a selection when new tag added.
573 ==> 375197 - It is possible to rotate video thumbnails (but the video isn't rotated).
574 ==> 334678 - Thumbnails fail to generate for certain AVI files - infinite loop.
575 ==> 400917 - Rotation of picture in Preview mode: thumbnail not rotated.
576 ==> 400960 - Do not reset horizontal scroll bar slider position when selecting album.
577 ==> 400766 - Export to Onedrive: not possible to export into subfolder.
578 ==> 398207 - Box.com video upload fails despite successful authentication.
579 ==> 401160 - Build against lensfun-devel.
580 ==> 401173 - Wish for file saving: set changed datetime to exif datetime.
581 ==> 401423 - Video sidecar files nor read or written.
582 ==> 401438 - Calendar plugin prints improper month names (Czech localization).
583 ==> 401515 - Export to OneDrive: created subfolders not correctly managed.
584 ==> 401516 - Export to (Onedrive, Dropbox ...): list of subfolders not correctly displayed (problems if several subfolders have the same name).
585 ==> 401645 - digiKam crashes on possibly damaged video-file.
586 ==> 401676 - BQM resize tool : allow to resize by percentage (%).
587 ==> 401709 - Double clicking a name in a face-frame closes image preview.
588 ==> 401811 - DB migration (SQLite -> MySQL) fails if images are in trash.
589 ==> 401767 - digiKam unable to find existing path.
590 ==> 215486 - Collection not found in location on disk with UUID (LVM volume).
591 ==> 401834 - The "Scanning Faces" dialog box is too large and can't be resized in french language.
592 ==> 401664 - Trash shows list view only no thumbnails.
593 ==> 402029 - Find New Items process takes significantly longer to finish on 6.0.0.
594 ==> 402286 - Metadata settings don't display the combo value options.
595 ==> 402288 - The default Xmp.lr.hierarchicalSubject setting does not read darktable tags.
596 ==> 402300 - Template string in Help > About.
597 ==> 402283 - Duplicate entries drive to unpredictable performance.
598 ==> 402380 - Database schema upgrade to V10 is incomplete.
599 ==> 402379 - Moving location of RAW file causes loss of metadata.
600 ==> 366211 - When changing database, cannot open thumbnails into edit window.
601 ==> 402496 - digiKam crashed after a while during face recognition.
602 ==> 402726 - Piwigo export is missing.
603 ==> 401301 - digiKam Close crash.
604 ==> 401837 - Button Caption transcription error in french.
605 ==> 398880 - digiKam stays as a background process after closing.
606 ==> 398129 - ExpoBlend tool filename dialog shows previous file's name.
-607 ==>
+607 ==> 402556 - digikam-data conflict with dropbox installation.
+608 ==>
diff --git a/core/data/icons/box/16-apps-box.png b/core/data/icons/box/16-apps-dk-box.png
similarity index 100%
rename from core/data/icons/box/16-apps-box.png
rename to core/data/icons/box/16-apps-dk-box.png
diff --git a/core/data/icons/box/22-apps-box.png b/core/data/icons/box/22-apps-dk-box.png
similarity index 100%
rename from core/data/icons/box/22-apps-box.png
rename to core/data/icons/box/22-apps-dk-box.png
diff --git a/core/data/icons/box/32-apps-box.png b/core/data/icons/box/32-apps-dk-box.png
similarity index 100%
rename from core/data/icons/box/32-apps-box.png
rename to core/data/icons/box/32-apps-dk-box.png
diff --git a/core/data/icons/box/48-apps-box.png b/core/data/icons/box/48-apps-dk-box.png
similarity index 100%
rename from core/data/icons/box/48-apps-box.png
rename to core/data/icons/box/48-apps-dk-box.png
diff --git a/core/data/icons/dropbox/16-apps-dropbox.png b/core/data/icons/dropbox/16-apps-dk-dropbox.png
similarity index 100%
rename from core/data/icons/dropbox/16-apps-dropbox.png
rename to core/data/icons/dropbox/16-apps-dk-dropbox.png
diff --git a/core/data/icons/dropbox/22-apps-dropbox.png b/core/data/icons/dropbox/22-apps-dk-dropbox.png
similarity index 100%
rename from core/data/icons/dropbox/22-apps-dropbox.png
rename to core/data/icons/dropbox/22-apps-dk-dropbox.png
diff --git a/core/data/icons/dropbox/32-apps-dropbox.png b/core/data/icons/dropbox/32-apps-dk-dropbox.png
similarity index 100%
rename from core/data/icons/dropbox/32-apps-dropbox.png
rename to core/data/icons/dropbox/32-apps-dk-dropbox.png
diff --git a/core/data/icons/dropbox/48-apps-dropbox.png b/core/data/icons/dropbox/48-apps-dk-dropbox.png
similarity index 100%
rename from core/data/icons/dropbox/48-apps-dropbox.png
rename to core/data/icons/dropbox/48-apps-dk-dropbox.png
diff --git a/core/data/icons/facebook/16-apps-facebook-white.png b/core/data/icons/facebook/16-apps-dk-facebook-white.png
similarity index 100%
rename from core/data/icons/facebook/16-apps-facebook-white.png
rename to core/data/icons/facebook/16-apps-dk-facebook-white.png
diff --git a/core/data/icons/facebook/16-apps-facebook.png b/core/data/icons/facebook/16-apps-dk-facebook.png
similarity index 100%
rename from core/data/icons/facebook/16-apps-facebook.png
rename to core/data/icons/facebook/16-apps-dk-facebook.png
diff --git a/core/data/icons/facebook/22-apps-facebook-white.png b/core/data/icons/facebook/22-apps-dk-facebook-white.png
similarity index 100%
rename from core/data/icons/facebook/22-apps-facebook-white.png
rename to core/data/icons/facebook/22-apps-dk-facebook-white.png
diff --git a/core/data/icons/facebook/22-apps-facebook.png b/core/data/icons/facebook/22-apps-dk-facebook.png
similarity index 100%
rename from core/data/icons/facebook/22-apps-facebook.png
rename to core/data/icons/facebook/22-apps-dk-facebook.png
diff --git a/core/data/icons/facebook/32-apps-facebook-white.png b/core/data/icons/facebook/32-apps-dk-facebook-white.png
similarity index 100%
rename from core/data/icons/facebook/32-apps-facebook-white.png
rename to core/data/icons/facebook/32-apps-dk-facebook-white.png
diff --git a/core/data/icons/facebook/32-apps-facebook.png b/core/data/icons/facebook/32-apps-dk-facebook.png
similarity index 100%
rename from core/data/icons/facebook/32-apps-facebook.png
rename to core/data/icons/facebook/32-apps-dk-facebook.png
diff --git a/core/data/icons/facebook/48-apps-facebook-white.png b/core/data/icons/facebook/48-apps-dk-facebook-white.png
similarity index 100%
rename from core/data/icons/facebook/48-apps-facebook-white.png
rename to core/data/icons/facebook/48-apps-dk-facebook-white.png
diff --git a/core/data/icons/facebook/48-apps-facebook.png b/core/data/icons/facebook/48-apps-dk-facebook.png
similarity index 100%
rename from core/data/icons/facebook/48-apps-facebook.png
rename to core/data/icons/facebook/48-apps-dk-facebook.png
diff --git a/core/data/icons/facebook/sc-apps-facebook-white.svgz b/core/data/icons/facebook/sc-apps-dk-facebook-white.svgz
similarity index 100%
rename from core/data/icons/facebook/sc-apps-facebook-white.svgz
rename to core/data/icons/facebook/sc-apps-dk-facebook-white.svgz
diff --git a/core/data/icons/facebook/sc-apps-facebook.svgz b/core/data/icons/facebook/sc-apps-dk-facebook.svgz
similarity index 100%
rename from core/data/icons/facebook/sc-apps-facebook.svgz
rename to core/data/icons/facebook/sc-apps-dk-facebook.svgz
diff --git a/core/data/icons/flickr/16-apps-flickr.png b/core/data/icons/flickr/16-apps-dk-flickr.png
similarity index 100%
rename from core/data/icons/flickr/16-apps-flickr.png
rename to core/data/icons/flickr/16-apps-dk-flickr.png
diff --git a/core/data/icons/flickr/22-apps-flickr.png b/core/data/icons/flickr/22-apps-dk-flickr.png
similarity index 100%
rename from core/data/icons/flickr/22-apps-flickr.png
rename to core/data/icons/flickr/22-apps-dk-flickr.png
diff --git a/core/data/icons/flickr/32-apps-flickr.png b/core/data/icons/flickr/32-apps-dk-flickr.png
similarity index 100%
rename from core/data/icons/flickr/32-apps-flickr.png
rename to core/data/icons/flickr/32-apps-dk-flickr.png
diff --git a/core/data/icons/flickr/48-apps-flickr.png b/core/data/icons/flickr/48-apps-dk-flickr.png
similarity index 100%
rename from core/data/icons/flickr/48-apps-flickr.png
rename to core/data/icons/flickr/48-apps-dk-flickr.png
diff --git a/core/data/icons/flickr/sc-apps-flickr.svgz b/core/data/icons/flickr/sc-apps-dk-flickr.svgz
similarity index 100%
rename from core/data/icons/flickr/sc-apps-flickr.svgz
rename to core/data/icons/flickr/sc-apps-dk-flickr.svgz
diff --git a/core/data/icons/gdrive/16-apps-googledrive.png b/core/data/icons/gdrive/16-apps-dk-googledrive.png
similarity index 100%
rename from core/data/icons/gdrive/16-apps-googledrive.png
rename to core/data/icons/gdrive/16-apps-dk-googledrive.png
diff --git a/core/data/icons/gdrive/22-apps-googledrive.png b/core/data/icons/gdrive/22-apps-dk-googledrive.png
similarity index 100%
rename from core/data/icons/gdrive/22-apps-googledrive.png
rename to core/data/icons/gdrive/22-apps-dk-googledrive.png
diff --git a/core/data/icons/gdrive/32-apps-googledrive.png b/core/data/icons/gdrive/32-apps-dk-googledrive.png
similarity index 100%
rename from core/data/icons/gdrive/32-apps-googledrive.png
rename to core/data/icons/gdrive/32-apps-dk-googledrive.png
diff --git a/core/data/icons/gdrive/48-apps-googledrive.png b/core/data/icons/gdrive/48-apps-dk-googledrive.png
similarity index 100%
rename from core/data/icons/gdrive/48-apps-googledrive.png
rename to core/data/icons/gdrive/48-apps-dk-googledrive.png
diff --git a/core/data/icons/gphoto/16-apps-googlephoto.png b/core/data/icons/gphoto/16-apps-dk-googlephoto.png
similarity index 100%
rename from core/data/icons/gphoto/16-apps-googlephoto.png
rename to core/data/icons/gphoto/16-apps-dk-googlephoto.png
diff --git a/core/data/icons/gphoto/22-apps-googlephoto.png b/core/data/icons/gphoto/22-apps-dk-googlephoto.png
similarity index 100%
rename from core/data/icons/gphoto/22-apps-googlephoto.png
rename to core/data/icons/gphoto/22-apps-dk-googlephoto.png
diff --git a/core/data/icons/gphoto/32-apps-googlephoto.png b/core/data/icons/gphoto/32-apps-dk-googlephoto.png
similarity index 100%
rename from core/data/icons/gphoto/32-apps-googlephoto.png
rename to core/data/icons/gphoto/32-apps-dk-googlephoto.png
diff --git a/core/data/icons/gphoto/48-apps-googlephoto.png b/core/data/icons/gphoto/48-apps-dk-googlephoto.png
similarity index 100%
rename from core/data/icons/gphoto/48-apps-googlephoto.png
rename to core/data/icons/gphoto/48-apps-dk-googlephoto.png
diff --git a/core/data/icons/gphoto/sc-apps-googlephoto.svgz b/core/data/icons/gphoto/sc-apps-dk-googlephoto.svgz
similarity index 100%
rename from core/data/icons/gphoto/sc-apps-googlephoto.svgz
rename to core/data/icons/gphoto/sc-apps-dk-googlephoto.svgz
diff --git a/core/data/icons/imageshack/16-apps-imageshack.png b/core/data/icons/imageshack/16-apps-dk-imageshack.png
similarity index 100%
rename from core/data/icons/imageshack/16-apps-imageshack.png
rename to core/data/icons/imageshack/16-apps-dk-imageshack.png
diff --git a/core/data/icons/imageshack/22-apps-imageshack.png b/core/data/icons/imageshack/22-apps-dk-imageshack.png
similarity index 100%
rename from core/data/icons/imageshack/22-apps-imageshack.png
rename to core/data/icons/imageshack/22-apps-dk-imageshack.png
diff --git a/core/data/icons/imageshack/32-apps-imageshack.png b/core/data/icons/imageshack/32-apps-dk-imageshack.png
similarity index 100%
rename from core/data/icons/imageshack/32-apps-imageshack.png
rename to core/data/icons/imageshack/32-apps-dk-imageshack.png
diff --git a/core/data/icons/imageshack/48-apps-imageshack.png b/core/data/icons/imageshack/48-apps-dk-imageshack.png
similarity index 100%
rename from core/data/icons/imageshack/48-apps-imageshack.png
rename to core/data/icons/imageshack/48-apps-dk-imageshack.png
diff --git a/core/data/icons/imgur/16-apps-imgur.png b/core/data/icons/imgur/16-apps-dk-imgur.png
similarity index 100%
rename from core/data/icons/imgur/16-apps-imgur.png
rename to core/data/icons/imgur/16-apps-dk-imgur.png
diff --git a/core/data/icons/imgur/22-apps-imgur.png b/core/data/icons/imgur/22-apps-dk-imgur.png
similarity index 100%
rename from core/data/icons/imgur/22-apps-imgur.png
rename to core/data/icons/imgur/22-apps-dk-imgur.png
diff --git a/core/data/icons/imgur/32-apps-imgur.png b/core/data/icons/imgur/32-apps-dk-imgur.png
similarity index 100%
rename from core/data/icons/imgur/32-apps-imgur.png
rename to core/data/icons/imgur/32-apps-dk-imgur.png
diff --git a/core/data/icons/imgur/48-apps-imgur.png b/core/data/icons/imgur/48-apps-dk-imgur.png
similarity index 100%
rename from core/data/icons/imgur/48-apps-imgur.png
rename to core/data/icons/imgur/48-apps-dk-imgur.png
diff --git a/core/data/icons/imgur/sc-apps-imgur.svgz b/core/data/icons/imgur/sc-apps-dk-imgur.svgz
similarity index 100%
rename from core/data/icons/imgur/sc-apps-imgur.svgz
rename to core/data/icons/imgur/sc-apps-dk-imgur.svgz
diff --git a/core/data/icons/ipfs/16-apps-ipfs.png b/core/data/icons/ipfs/16-apps-dk-ipfs.png
similarity index 100%
rename from core/data/icons/ipfs/16-apps-ipfs.png
rename to core/data/icons/ipfs/16-apps-dk-ipfs.png
diff --git a/core/data/icons/ipfs/22-apps-ipfs.png b/core/data/icons/ipfs/22-apps-dk-ipfs.png
similarity index 100%
rename from core/data/icons/ipfs/22-apps-ipfs.png
rename to core/data/icons/ipfs/22-apps-dk-ipfs.png
diff --git a/core/data/icons/ipfs/32-apps-ipfs.png b/core/data/icons/ipfs/32-apps-dk-ipfs.png
similarity index 100%
rename from core/data/icons/ipfs/32-apps-ipfs.png
rename to core/data/icons/ipfs/32-apps-dk-ipfs.png
diff --git a/core/data/icons/ipfs/48-apps-ipfs.png b/core/data/icons/ipfs/48-apps-dk-ipfs.png
similarity index 100%
rename from core/data/icons/ipfs/48-apps-ipfs.png
rename to core/data/icons/ipfs/48-apps-dk-ipfs.png
diff --git a/core/data/icons/ipfs/sc-apps-ipfs.svgz b/core/data/icons/ipfs/sc-apps-dk-ipfs.svgz
similarity index 100%
rename from core/data/icons/ipfs/sc-apps-ipfs.svgz
rename to core/data/icons/ipfs/sc-apps-dk-ipfs.svgz
diff --git a/core/data/icons/mediawiki/16-apps-mediawiki.png b/core/data/icons/mediawiki/16-apps-dk-mediawiki.png
similarity index 100%
rename from core/data/icons/mediawiki/16-apps-mediawiki.png
rename to core/data/icons/mediawiki/16-apps-dk-mediawiki.png
diff --git a/core/data/icons/mediawiki/22-apps-mediawiki.png b/core/data/icons/mediawiki/22-apps-dk-mediawiki.png
similarity index 100%
rename from core/data/icons/mediawiki/22-apps-mediawiki.png
rename to core/data/icons/mediawiki/22-apps-dk-mediawiki.png
diff --git a/core/data/icons/mediawiki/32-apps-mediawiki.png b/core/data/icons/mediawiki/32-apps-dk-mediawiki.png
similarity index 100%
rename from core/data/icons/mediawiki/32-apps-mediawiki.png
rename to core/data/icons/mediawiki/32-apps-dk-mediawiki.png
diff --git a/core/data/icons/mediawiki/48-apps-mediawiki.png b/core/data/icons/mediawiki/48-apps-dk-mediawiki.png
similarity index 100%
rename from core/data/icons/mediawiki/48-apps-mediawiki.png
rename to core/data/icons/mediawiki/48-apps-dk-mediawiki.png
diff --git a/core/data/icons/mediawiki/sc-apps-mediawiki.svgz b/core/data/icons/mediawiki/sc-apps-dk-mediawiki.svgz
similarity index 100%
rename from core/data/icons/mediawiki/sc-apps-mediawiki.svgz
rename to core/data/icons/mediawiki/sc-apps-dk-mediawiki.svgz
diff --git a/core/data/icons/onedrive/16-apps-onedrive.png b/core/data/icons/onedrive/16-apps-dk-onedrive.png
similarity index 100%
rename from core/data/icons/onedrive/16-apps-onedrive.png
rename to core/data/icons/onedrive/16-apps-dk-onedrive.png
diff --git a/core/data/icons/onedrive/22-apps-onedrive.png b/core/data/icons/onedrive/22-apps-dk-onedrive.png
similarity index 100%
rename from core/data/icons/onedrive/22-apps-onedrive.png
rename to core/data/icons/onedrive/22-apps-dk-onedrive.png
diff --git a/core/data/icons/onedrive/32-apps-onedrive.png b/core/data/icons/onedrive/32-apps-dk-onedrive.png
similarity index 100%
rename from core/data/icons/onedrive/32-apps-onedrive.png
rename to core/data/icons/onedrive/32-apps-dk-onedrive.png
diff --git a/core/data/icons/onedrive/48-apps-onedrive.png b/core/data/icons/onedrive/48-apps-dk-onedrive.png
similarity index 100%
rename from core/data/icons/onedrive/48-apps-onedrive.png
rename to core/data/icons/onedrive/48-apps-dk-onedrive.png
diff --git a/core/data/icons/pinterest/16-apps-pinterest.png b/core/data/icons/pinterest/16-apps-dk-pinterest.png
similarity index 100%
rename from core/data/icons/pinterest/16-apps-pinterest.png
rename to core/data/icons/pinterest/16-apps-dk-pinterest.png
diff --git a/core/data/icons/pinterest/22-apps-pinterest.png b/core/data/icons/pinterest/22-apps-dk-pinterest.png
similarity index 100%
rename from core/data/icons/pinterest/22-apps-pinterest.png
rename to core/data/icons/pinterest/22-apps-dk-pinterest.png
diff --git a/core/data/icons/pinterest/32-apps-pinterest.png b/core/data/icons/pinterest/32-apps-dk-pinterest.png
similarity index 100%
rename from core/data/icons/pinterest/32-apps-pinterest.png
rename to core/data/icons/pinterest/32-apps-dk-pinterest.png
diff --git a/core/data/icons/pinterest/48-apps-pinterest.png b/core/data/icons/pinterest/48-apps-dk-pinterest.png
similarity index 100%
rename from core/data/icons/pinterest/48-apps-pinterest.png
rename to core/data/icons/pinterest/48-apps-dk-pinterest.png
diff --git a/core/data/icons/piwigo/16-apps-piwigo.png b/core/data/icons/piwigo/16-apps-dk-piwigo.png
similarity index 100%
rename from core/data/icons/piwigo/16-apps-piwigo.png
rename to core/data/icons/piwigo/16-apps-dk-piwigo.png
diff --git a/core/data/icons/piwigo/22-apps-piwigo.png b/core/data/icons/piwigo/22-apps-dk-piwigo.png
similarity index 100%
rename from core/data/icons/piwigo/22-apps-piwigo.png
rename to core/data/icons/piwigo/22-apps-dk-piwigo.png
diff --git a/core/data/icons/piwigo/32-apps-piwigo.png b/core/data/icons/piwigo/32-apps-dk-piwigo.png
similarity index 100%
rename from core/data/icons/piwigo/32-apps-piwigo.png
rename to core/data/icons/piwigo/32-apps-dk-piwigo.png
diff --git a/core/data/icons/piwigo/48-apps-piwigo.png b/core/data/icons/piwigo/48-apps-dk-piwigo.png
similarity index 100%
rename from core/data/icons/piwigo/48-apps-piwigo.png
rename to core/data/icons/piwigo/48-apps-dk-piwigo.png
diff --git a/core/data/icons/piwigo/sc-apps-piwigo.svgz b/core/data/icons/piwigo/sc-apps-dk-piwigo.svgz
similarity index 100%
rename from core/data/icons/piwigo/sc-apps-piwigo.svgz
rename to core/data/icons/piwigo/sc-apps-dk-piwigo.svgz
diff --git a/core/data/icons/rajce/16-apps-rajce.png b/core/data/icons/rajce/16-apps-dk-rajce.png
similarity index 100%
rename from core/data/icons/rajce/16-apps-rajce.png
rename to core/data/icons/rajce/16-apps-dk-rajce.png
diff --git a/core/data/icons/rajce/22-apps-rajce.png b/core/data/icons/rajce/22-apps-dk-rajce.png
similarity index 100%
rename from core/data/icons/rajce/22-apps-rajce.png
rename to core/data/icons/rajce/22-apps-dk-rajce.png
diff --git a/core/data/icons/rajce/32-apps-rajce.png b/core/data/icons/rajce/32-apps-dk-rajce.png
similarity index 100%
rename from core/data/icons/rajce/32-apps-rajce.png
rename to core/data/icons/rajce/32-apps-dk-rajce.png
diff --git a/core/data/icons/rajce/48-apps-rajce.png b/core/data/icons/rajce/48-apps-dk-rajce.png
similarity index 100%
rename from core/data/icons/rajce/48-apps-rajce.png
rename to core/data/icons/rajce/48-apps-dk-rajce.png
diff --git a/core/data/icons/smugmug/16-apps-smugmug.png b/core/data/icons/smugmug/16-apps-dk-smugmug.png
similarity index 100%
rename from core/data/icons/smugmug/16-apps-smugmug.png
rename to core/data/icons/smugmug/16-apps-dk-smugmug.png
diff --git a/core/data/icons/smugmug/22-apps-smugmug.png b/core/data/icons/smugmug/22-apps-dk-smugmug.png
similarity index 100%
rename from core/data/icons/smugmug/22-apps-smugmug.png
rename to core/data/icons/smugmug/22-apps-dk-smugmug.png
diff --git a/core/data/icons/smugmug/32-apps-smugmug.png b/core/data/icons/smugmug/32-apps-dk-smugmug.png
similarity index 100%
rename from core/data/icons/smugmug/32-apps-smugmug.png
rename to core/data/icons/smugmug/32-apps-dk-smugmug.png
diff --git a/core/data/icons/smugmug/48-apps-smugmug.png b/core/data/icons/smugmug/48-apps-dk-smugmug.png
similarity index 100%
rename from core/data/icons/smugmug/48-apps-smugmug.png
rename to core/data/icons/smugmug/48-apps-dk-smugmug.png
diff --git a/core/data/icons/smugmug/sc-apps-smugmug.svgz b/core/data/icons/smugmug/sc-apps-dk-smugmug.svgz
similarity index 100%
rename from core/data/icons/smugmug/sc-apps-smugmug.svgz
rename to core/data/icons/smugmug/sc-apps-dk-smugmug.svgz
diff --git a/core/libs/widgets/mainview/dxmlguiwindow.cpp b/core/libs/widgets/mainview/dxmlguiwindow.cpp
index cbd9a958b8..753750868c 100644
--- a/core/libs/widgets/mainview/dxmlguiwindow.cpp
+++ b/core/libs/widgets/mainview/dxmlguiwindow.cpp
@@ -1,1381 +1,1381 @@
/* ============================================================
*
* This file is a part of digiKam project
* http://www.digikam.org
*
* Date : 2013-04-29
* Description : digiKam XML GUI window
*
* Copyright (C) 2013-2019 by Gilles Caulier
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General
* Public License as published by the Free Software Foundation;
* either version 2, 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.
*
* ============================================================ */
#include "dxmlguiwindow.h"
// Qt includes
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
// KDE includes
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef HAVE_KNOTIFYCONFIG
# include
#endif
// Local includes
#include "digikam_debug.h"
#include "digikam_globals.h"
#include "daboutdata.h"
#include "webbrowserdlg.h"
#include "wsstarter.h"
namespace Digikam
{
class Q_DECL_HIDDEN DXmlGuiWindow::Private
{
public:
explicit Private()
{
fsOptions = FS_NONE;
fullScreenAction = 0;
fullScreenBtn = 0;
dirtyMainToolBar = false;
fullScreenHideToolBars = false;
fullScreenHideThumbBar = true;
fullScreenHideSideBars = false;
thumbbarVisibility = true;
menubarVisibility = true;
statusbarVisibility = true;
libsInfoAction = 0;
showMenuBarAction = 0;
showStatusBarAction = 0;
about = 0;
dbStatAction = 0;
anim = 0;
}
public:
/**
* Settings taken from managed window configuration to handle toolbar visibility in full-screen mode
*/
bool fullScreenHideToolBars;
/**
* Settings taken from managed window configuration to handle thumbbar visibility in full-screen mode
*/
bool fullScreenHideThumbBar;
/**
* Settings taken from managed window configuration to handle toolbar visibility in full-screen mode
*/
bool fullScreenHideSideBars;
/**
* Full-Screen options. See FullScreenOptions enum and setFullScreenOptions() for details.
*/
int fsOptions;
/**
* Action plug in managed window to switch fullscreen state
*/
KToggleFullScreenAction* fullScreenAction;
/**
* Show only if toolbar is hidden
*/
QToolButton* fullScreenBtn;
/**
* Used by slotToggleFullScreen() to manage state of full-screen button on managed window
*/
bool dirtyMainToolBar;
/**
* Store previous visibility of toolbars before ful-screen mode.
*/
QMap toolbarsVisibility;
/**
* Store previous visibility of thumbbar before ful-screen mode.
*/
bool thumbbarVisibility;
/**
* Store previous visibility of menubar before ful-screen mode.
*/
bool menubarVisibility;
/**
* Store previous visibility of statusbar before ful-screen mode.
*/
bool statusbarVisibility;
// Common Help actions
QAction* dbStatAction;
QAction* libsInfoAction;
QAction* showMenuBarAction;
QAction* showStatusBarAction;
DAboutData* about;
DLogoAction* anim;
QString configGroupName;
};
// --------------------------------------------------------------------------------------------------
DXmlGuiWindow::DXmlGuiWindow(QWidget* const parent, Qt::WindowFlags f)
: KXmlGuiWindow(parent, f),
d(new Private)
{
m_expoBlendingAction = 0;
m_panoramaAction = 0;
m_videoslideshowAction = 0;
m_htmlGalleryAction = 0;
m_sendByMailAction = 0;
m_printCreatorAction = 0;
m_calendarAction = 0;
m_presentationAction = 0;
m_metadataEditAction = 0;
m_geolocationEditAction = 0;
m_mediaServerAction = 0;
m_timeAdjustAction = 0;
m_animLogo = 0;
// Export tools
m_exportDropboxAction = 0;
m_exportOnedriveAction = 0;
m_exportPinterestAction = 0;
m_exportBoxAction = 0;
m_exportFacebookAction = 0;
m_exportFlickrAction = 0;
m_exportGdriveAction = 0;
m_exportGphotoAction = 0;
m_exportImageshackAction = 0;
m_exportImgurAction = 0;
m_exportIpfsAction = 0;
m_exportPiwigoAction = 0;
m_exportRajceAction = 0;
m_exportSmugmugAction = 0;
m_exportYandexfotkiAction = 0;
m_exportMediawikiAction = 0;
#ifdef HAVE_VKONTAKTE
m_exportVkontakteAction = 0;
#endif
#ifdef HAVE_KIO
m_exportFileTransferAction = 0;
#endif
// Import tools
m_importGphotoAction = 0;
m_importSmugmugAction = 0;
#ifdef HAVE_KIO
m_importFileTransferAction = 0;
#endif
#ifdef HAVE_KSANE
m_ksaneAction = 0;
#endif
installEventFilter(this);
}
DXmlGuiWindow::~DXmlGuiWindow()
{
delete d;
}
void DXmlGuiWindow::setConfigGroupName(const QString& name)
{
d->configGroupName = name;
}
QString DXmlGuiWindow::configGroupName() const
{
return d->configGroupName;
}
void DXmlGuiWindow::closeEvent(QCloseEvent* e)
{
if (fullScreenIsActive())
slotToggleFullScreen(false);
if (!testAttribute(Qt::WA_DeleteOnClose))
{
setVisible(false);
e->ignore();
return;
}
KXmlGuiWindow::closeEvent(e);
e->accept();
}
void DXmlGuiWindow::setFullScreenOptions(int options)
{
d->fsOptions = options;
}
void DXmlGuiWindow::createHelpActions(bool coreOptions)
{
d->libsInfoAction = new QAction(QIcon::fromTheme(QLatin1String("help-about")), i18n("Components Information"), this);
connect(d->libsInfoAction, SIGNAL(triggered()), this, SLOT(slotComponentsInfo()));
actionCollection()->addAction(QLatin1String("help_librariesinfo"), d->libsInfoAction);
d->about = new DAboutData(this);
QAction* const rawCameraListAction = new QAction(QIcon::fromTheme(QLatin1String("image-x-adobe-dng")), i18n("Supported RAW Cameras"), this);
connect(rawCameraListAction, SIGNAL(triggered()), this, SLOT(slotRawCameraList()));
actionCollection()->addAction(QLatin1String("help_rawcameralist"), rawCameraListAction);
QAction* const donateMoneyAction = new QAction(QIcon::fromTheme(QLatin1String("globe")), i18n("Donate..."), this);
connect(donateMoneyAction, SIGNAL(triggered()), this, SLOT(slotDonateMoney()));
actionCollection()->addAction(QLatin1String("help_donatemoney"), donateMoneyAction);
QAction* const recipesBookAction = new QAction(QIcon::fromTheme(QLatin1String("globe")), i18n("Recipes Book..."), this);
connect(recipesBookAction, SIGNAL(triggered()), this, SLOT(slotRecipesBook()));
actionCollection()->addAction(QLatin1String("help_recipesbook"), recipesBookAction);
QAction* const contributeAction = new QAction(QIcon::fromTheme(QLatin1String("globe")), i18n("Contribute..."), this);
connect(contributeAction, SIGNAL(triggered()), this, SLOT(slotContribute()));
actionCollection()->addAction(QLatin1String("help_contribute"), contributeAction);
QAction* const helpAction = new QAction(QIcon::fromTheme(QLatin1String("help-contents")), i18n("Online Handbook..."), this);
connect(helpAction, SIGNAL(triggered()), this, SLOT(slotHelpContents()));
actionCollection()->addAction(QLatin1String("help_handbook"), helpAction);
m_animLogo = new DLogoAction(this);
actionCollection()->addAction(QLatin1String("logo_action"), m_animLogo);
// Add options only for core components (typically all excepted Showfoto)
if (coreOptions)
{
d->dbStatAction = new QAction(QIcon::fromTheme(QLatin1String("network-server-database")), i18n("Database Statistics"), this);
connect(d->dbStatAction, SIGNAL(triggered()), this, SLOT(slotDBStat()));
actionCollection()->addAction(QLatin1String("help_dbstat"), d->dbStatAction);
}
}
void DXmlGuiWindow::cleanupActions()
{
QAction* ac = actionCollection()->action(QLatin1String("help_about_kde"));
if (ac) actionCollection()->removeAction(ac);
ac = actionCollection()->action(QLatin1String("help_donate"));
if (ac) actionCollection()->removeAction(ac);
ac = actionCollection()->action(QLatin1String("help_contents"));
if (ac) actionCollection()->removeAction(ac);
/*
QList lst = actionCollection()->actions();
foreach (QAction* const act, lst)
qCDebug(DIGIKAM_WIDGETS_LOG) << "action: " << act->objectName();
*/
}
void DXmlGuiWindow::createSidebarActions()
{
KActionCollection* const ac = actionCollection();
QAction* const tlsb = new QAction(i18n("Toggle Left Side-bar"), this);
connect(tlsb, SIGNAL(triggered()), this, SLOT(slotToggleLeftSideBar()));
ac->addAction(QLatin1String("toggle-left-sidebar"), tlsb);
ac->setDefaultShortcut(tlsb, Qt::CTRL + Qt::META + Qt::Key_Left);
QAction* const trsb = new QAction(i18n("Toggle Right Side-bar"), this);
connect(trsb, SIGNAL(triggered()), this, SLOT(slotToggleRightSideBar()));
ac->addAction(QLatin1String("toggle-right-sidebar"), trsb);
ac->setDefaultShortcut(trsb, Qt::CTRL + Qt::META + Qt::Key_Right);
QAction* const plsb = new QAction(i18n("Previous Left Side-bar Tab"), this);
connect(plsb, SIGNAL(triggered()), this, SLOT(slotPreviousLeftSideBarTab()));
ac->addAction(QLatin1String("previous-left-sidebar-tab"), plsb);
ac->setDefaultShortcut(plsb, Qt::CTRL + Qt::META + Qt::Key_Home);
QAction* const nlsb = new QAction(i18n("Next Left Side-bar Tab"), this);
connect(nlsb, SIGNAL(triggered()), this, SLOT(slotNextLeftSideBarTab()));
ac->addAction(QLatin1String("next-left-sidebar-tab"), nlsb);
ac->setDefaultShortcut(nlsb, Qt::CTRL + Qt::META + Qt::Key_End);
QAction* const prsb = new QAction(i18n("Previous Right Side-bar Tab"), this);
connect(prsb, SIGNAL(triggered()), this, SLOT(slotPreviousRightSideBarTab()));
ac->addAction(QLatin1String("previous-right-sidebar-tab"), prsb);
ac->setDefaultShortcut(prsb, Qt::CTRL + Qt::META + Qt::Key_PageUp);
QAction* const nrsb = new QAction(i18n("Next Right Side-bar Tab"), this);
connect(nrsb, SIGNAL(triggered()), this, SLOT(slotNextRightSideBarTab()));
ac->addAction(QLatin1String("next-right-sidebar-tab"), nrsb);
ac->setDefaultShortcut(nrsb, Qt::CTRL + Qt::META + Qt::Key_PageDown);
}
void DXmlGuiWindow::createSettingsActions()
{
d->showMenuBarAction = KStandardAction::showMenubar(this, SLOT(slotShowMenuBar()), actionCollection());
#ifdef Q_OS_OSX
// Under MacOS the menu bar visibility is managed by desktop.
d->showMenuBarAction->setVisible(false);
#endif
d->showStatusBarAction = actionCollection()->action(QLatin1String("options_show_statusbar"));
if (!d->showStatusBarAction)
{
qCWarning(DIGIKAM_WIDGETS_LOG) << "Status bar menu action cannot be found in action collection";
d->showStatusBarAction = new QAction(i18n("Show Statusbar"), this);
d->showStatusBarAction->setCheckable(true);
d->showStatusBarAction->setChecked(true);
connect(d->showStatusBarAction, SIGNAL(toggled(bool)), this, SLOT(slotShowStatusBar()));
actionCollection()->addAction(QLatin1String("options_show_statusbar"), d->showStatusBarAction);
}
KStandardAction::keyBindings(this, SLOT(slotEditKeys()), actionCollection());
KStandardAction::preferences(this, SLOT(slotSetup()), actionCollection());
KStandardAction::configureToolbars(this, SLOT(slotConfToolbars()), actionCollection());
#ifdef HAVE_KNOTIFYCONFIG
KStandardAction::configureNotifications(this, SLOT(slotConfNotifications()), actionCollection());
#endif
}
QAction* DXmlGuiWindow::showMenuBarAction() const
{
return d->showMenuBarAction;
}
QAction* DXmlGuiWindow::showStatusBarAction() const
{
return d->showStatusBarAction;
}
void DXmlGuiWindow::slotShowMenuBar()
{
menuBar()->setVisible(d->showMenuBarAction->isChecked());
}
void DXmlGuiWindow::slotShowStatusBar()
{
statusBar()->setVisible(d->showStatusBarAction->isChecked());
}
void DXmlGuiWindow::slotConfNotifications()
{
#ifdef HAVE_KNOTIFYCONFIG
KNotifyConfigWidget::configure(this);
#endif
}
void DXmlGuiWindow::editKeyboardShortcuts(KActionCollection* const extraac, const QString& actitle)
{
KShortcutsDialog dialog(KShortcutsEditor::AllActions,
KShortcutsEditor::LetterShortcutsAllowed, this);
dialog.addCollection(actionCollection(), i18nc("general keyboard shortcuts", "General"));
if (extraac)
dialog.addCollection(extraac, actitle);
dialog.configure();
}
void DXmlGuiWindow::slotConfToolbars()
{
KConfigGroup group = KSharedConfig::openConfig()->group(configGroupName());
saveMainWindowSettings(group);
KEditToolBar dlg(factory(), this);
connect(&dlg, SIGNAL(newToolbarConfig()),
this, SLOT(slotNewToolbarConfig()));
dlg.exec();
}
void DXmlGuiWindow::slotNewToolbarConfig()
{
KConfigGroup group = KSharedConfig::openConfig()->group(configGroupName());
applyMainWindowSettings(group);
}
void DXmlGuiWindow::createGeolocationEditAction()
{
#ifdef HAVE_MARBLE
m_geolocationEditAction = new QAction(QIcon::fromTheme(QLatin1String("globe")), i18n("Edit Geolocation..."), this);
actionCollection()->addAction(QLatin1String("geolocation_edit"), m_geolocationEditAction);
actionCollection()->setDefaultShortcut(m_geolocationEditAction, Qt::CTRL + Qt::SHIFT + Qt::Key_G);
connect(m_geolocationEditAction, SIGNAL(triggered(bool)),
this, SLOT(slotEditGeolocation()));
#endif
}
void DXmlGuiWindow::createMetadataEditAction()
{
m_metadataEditAction = new QAction(QIcon::fromTheme(QLatin1String("format-text-code")), i18n("Edit Metadata..."), this);
actionCollection()->addAction(QLatin1String("metadata_edit"), m_metadataEditAction);
actionCollection()->setDefaultShortcut(m_metadataEditAction, Qt::CTRL + Qt::SHIFT + Qt::Key_M);
connect(m_metadataEditAction, SIGNAL(triggered(bool)),
this, SLOT(slotEditMetadata()));
}
void DXmlGuiWindow::createTimeAdjustAction()
{
m_timeAdjustAction = new QAction(QIcon::fromTheme(QLatin1String("appointment-new")), i18n("Adjust Time && Date..."), this);
actionCollection()->addAction(QLatin1String("timeadjust_edit"), m_timeAdjustAction);
actionCollection()->setDefaultShortcut(m_timeAdjustAction, Qt::CTRL + Qt::SHIFT + Qt::Key_D);
connect(m_timeAdjustAction, SIGNAL(triggered(bool)),
this, SLOT(slotTimeAdjust()));
}
void DXmlGuiWindow::createPresentationAction()
{
m_presentationAction = new QAction(QIcon::fromTheme(QLatin1String("view-presentation")), i18n("Presentation..."), this);
actionCollection()->addAction(QLatin1String("presentation"), m_presentationAction);
actionCollection()->setDefaultShortcut(m_presentationAction, Qt::ALT + Qt::SHIFT + Qt::Key_F9);
connect(m_presentationAction, SIGNAL(triggered()),
this, SLOT(slotPresentation()));
}
void DXmlGuiWindow::createExpoBlendingAction()
{
m_expoBlendingAction = new QAction(QIcon::fromTheme(QLatin1String("expoblending")),
i18nc("@action", "Create Stacked Images..."),
this);
actionCollection()->addAction(QLatin1String("expoblending"), m_expoBlendingAction);
connect(m_expoBlendingAction, SIGNAL(triggered(bool)),
this, SLOT(slotExpoBlending()));
}
void DXmlGuiWindow::createPanoramaAction()
{
#ifdef HAVE_PANORAMA
m_panoramaAction = new QAction(QIcon::fromTheme(QLatin1String("panorama")),
i18nc("@action", "Create panorama..."),
this);
actionCollection()->addAction(QLatin1String("panorama"), m_panoramaAction);
connect(m_panoramaAction, SIGNAL(triggered(bool)),
this, SLOT(slotPanorama()));
#endif
}
void DXmlGuiWindow::createVideoSlideshowAction()
{
#ifdef HAVE_MEDIAPLAYER
m_videoslideshowAction = new QAction(QIcon::fromTheme(QLatin1String("media-record")),
i18nc("@action", "Create video slideshow..."),
this);
actionCollection()->addAction(QLatin1String("videoslideshow"), m_videoslideshowAction);
connect(m_videoslideshowAction, SIGNAL(triggered(bool)),
this, SLOT(slotVideoSlideshow()));
#endif
}
void DXmlGuiWindow::createCalendarAction()
{
m_calendarAction = new QAction(QIcon::fromTheme(QLatin1String("view-calendar")),
i18nc("@action", "Create Calendar..."),
this);
actionCollection()->addAction(QLatin1String("calendar"), m_calendarAction);
connect(m_calendarAction, SIGNAL(triggered(bool)),
this, SLOT(slotCalendar()));
}
void DXmlGuiWindow::createSendByMailAction()
{
m_sendByMailAction = new QAction(QIcon::fromTheme(QLatin1String("mail-send")),
i18nc("@action", "Send by Mail..."),
this);
actionCollection()->addAction(QLatin1String("sendbymail"), m_sendByMailAction);
connect(m_sendByMailAction, SIGNAL(triggered(bool)),
this, SLOT(slotSendByMail()));
}
void DXmlGuiWindow::createPrintCreatorAction()
{
m_printCreatorAction = new QAction(QIcon::fromTheme(QLatin1String("document-print")),
i18nc("@action", "Print Creator..."),
this);
actionCollection()->addAction(QLatin1String("printcreator"), m_printCreatorAction);
connect(m_printCreatorAction, SIGNAL(triggered(bool)),
this, SLOT(slotPrintCreator()));
}
void DXmlGuiWindow::createHtmlGalleryAction()
{
#ifdef HAVE_HTMLGALLERY
m_htmlGalleryAction = new QAction(QIcon::fromTheme(QLatin1String("text-html")),
i18nc("@action", "Create Html gallery..."),
this);
actionCollection()->setDefaultShortcut(m_htmlGalleryAction, Qt::ALT + Qt::SHIFT + Qt::Key_H);
actionCollection()->addAction(QLatin1String("htmlgallery"), m_htmlGalleryAction);
connect(m_htmlGalleryAction, SIGNAL(triggered(bool)),
this, SLOT(slotHtmlGallery()));
#endif
}
void DXmlGuiWindow::createMediaServerAction()
{
m_mediaServerAction = new QAction(QIcon::fromTheme(QLatin1String("arrow-right-double")),
i18n("Share with DLNA"),
this);
actionCollection()->addAction(QLatin1String("mediaserver"), m_mediaServerAction);
connect(m_mediaServerAction, SIGNAL(triggered(bool)),
this, SLOT(slotMediaServer()));
}
void DXmlGuiWindow::createFullScreenAction(const QString& name)
{
d->fullScreenAction = KStandardAction::fullScreen(0, 0, this, this);
actionCollection()->addAction(name, d->fullScreenAction);
d->fullScreenBtn = new QToolButton(this);
d->fullScreenBtn->setDefaultAction(d->fullScreenAction);
d->fullScreenBtn->hide();
connect(d->fullScreenAction, SIGNAL(toggled(bool)),
this, SLOT(slotToggleFullScreen(bool)));
}
void DXmlGuiWindow::readFullScreenSettings(const KConfigGroup& group)
{
if (d->fsOptions & FS_TOOLBARS)
d->fullScreenHideToolBars = group.readEntry(s_configFullScreenHideToolBarsEntry, false);
if (d->fsOptions & FS_THUMBBAR)
d->fullScreenHideThumbBar = group.readEntry(s_configFullScreenHideThumbBarEntry, true);
if (d->fsOptions & FS_SIDEBARS)
d->fullScreenHideSideBars = group.readEntry(s_configFullScreenHideSideBarsEntry, false);
}
void DXmlGuiWindow::slotToggleFullScreen(bool set)
{
KToggleFullScreenAction::setFullScreen(this, set);
customizedFullScreenMode(set);
if (!set)
{
qCDebug(DIGIKAM_WIDGETS_LOG) << "TURN OFF fullscreen";
// restore menubar
if (d->menubarVisibility)
menuBar()->setVisible(true);
// restore statusbar
if (d->statusbarVisibility)
statusBar()->setVisible(true);
// restore sidebars
if ((d->fsOptions & FS_SIDEBARS) && d->fullScreenHideSideBars)
showSideBars(true);
// restore thumbbar
if ((d->fsOptions & FS_THUMBBAR) && d->fullScreenHideThumbBar)
showThumbBar(d->thumbbarVisibility);
// restore toolbars and manage full-screen button
showToolBars(true);
d->fullScreenBtn->hide();
if (d->dirtyMainToolBar)
{
KToolBar* const mainbar = mainToolBar();
if (mainbar)
{
mainbar->removeAction(d->fullScreenAction);
}
}
}
else
{
qCDebug(DIGIKAM_WIDGETS_LOG) << "TURN ON fullscreen";
// hide menubar
#ifdef Q_OS_WIN
d->menubarVisibility = d->showMenuBarAction->isChecked();
#else
d->menubarVisibility = menuBar()->isVisible();
#endif
menuBar()->setVisible(false);
// hide statusbar
#ifdef Q_OS_WIN
d->statusbarVisibility = d->showStatusBarAction->isChecked();
#else
d->statusbarVisibility = statusBar()->isVisible();
#endif
statusBar()->setVisible(false);
// hide sidebars
if ((d->fsOptions & FS_SIDEBARS) && d->fullScreenHideSideBars)
showSideBars(false);
// hide thumbbar
d->thumbbarVisibility = thumbbarVisibility();
if ((d->fsOptions & FS_THUMBBAR) && d->fullScreenHideThumbBar)
showThumbBar(false);
// hide toolbars and manage full-screen button
if ((d->fsOptions & FS_TOOLBARS) && d->fullScreenHideToolBars)
{
showToolBars(false);
}
else
{
showToolBars(true);
// add fullscreen action if necessary in toolbar
KToolBar* const mainbar = mainToolBar();
if (mainbar && !mainbar->actions().contains(d->fullScreenAction))
{
if (mainbar->actions().isEmpty())
{
mainbar->addAction(d->fullScreenAction);
}
else
{
mainbar->insertAction(mainbar->actions().first(), d->fullScreenAction);
}
d->dirtyMainToolBar = true;
}
else
{
// If FullScreen button is enabled in toolbar settings,
// we shall not remove it when leaving of fullscreen mode.
d->dirtyMainToolBar = false;
}
}
}
}
bool DXmlGuiWindow::fullScreenIsActive() const
{
if (d->fullScreenAction)
return d->fullScreenAction->isChecked();
qCDebug(DIGIKAM_WIDGETS_LOG) << "FullScreenAction is not initialized";
return false;
}
bool DXmlGuiWindow::eventFilter(QObject* obj, QEvent* ev)
{
if (obj == this)
{
if (ev && (ev->type() == QEvent::HoverMove) && fullScreenIsActive())
{
// We will handle a stand alone FullScreen button action on top/right corner of screen
// only if managed window tool bar is hidden, and if we switched already in Full Screen mode.
KToolBar* const mainbar = mainToolBar();
if (mainbar)
{
if (((d->fsOptions & FS_TOOLBARS) && d->fullScreenHideToolBars) || !mainbar->isVisible())
{
QHoverEvent* const mev = dynamic_cast(ev);
if (mev)
{
QPoint pos(mev->pos());
QRect desktopRect = QApplication::desktop()->screenGeometry(this);
QRect sizeRect(QPoint(0, 0), d->fullScreenBtn->size());
QRect topLeft, topRight;
QRect topRightLarger;
desktopRect = QRect(desktopRect.y(), desktopRect.y(), desktopRect.width(), desktopRect.height());
topLeft = sizeRect;
topRight = sizeRect;
topLeft.moveTo(desktopRect.x(), desktopRect.y());
topRight.moveTo(desktopRect.x() + desktopRect.width() - sizeRect.width() - 1, topLeft.y());
topRightLarger = topRight.adjusted(-25, 0, 0, 10);
if (topRightLarger.contains(pos))
{
d->fullScreenBtn->move(topRight.topLeft());
d->fullScreenBtn->show();
}
else
{
d->fullScreenBtn->hide();
}
return false;
}
}
}
}
}
// pass the event on to the parent class
return QObject::eventFilter(obj, ev);
}
void DXmlGuiWindow::keyPressEvent(QKeyEvent* e)
{
if (e->key() == Qt::Key_Escape)
{
if (fullScreenIsActive())
{
d->fullScreenAction->activate(QAction::Trigger);
}
}
}
KToolBar* DXmlGuiWindow::mainToolBar() const
{
QList toolbars = toolBars();
KToolBar* mainToolbar = 0;
foreach (KToolBar* const toolbar, toolbars)
{
if (toolbar && (toolbar->objectName() == QLatin1String("mainToolBar")))
{
mainToolbar = toolbar;
break;
}
}
return mainToolbar;
}
void DXmlGuiWindow::showToolBars(bool visible)
{
// We will hide toolbars: store previous state for future restoring.
if (!visible)
{
d->toolbarsVisibility.clear();
foreach (KToolBar* const toolbar, toolBars())
{
if (toolbar)
{
bool visibility = toolbar->isVisible();
d->toolbarsVisibility.insert(toolbar, visibility);
}
}
}
// Switch toolbars visibility
for (QMap::const_iterator it = d->toolbarsVisibility.constBegin(); it != d->toolbarsVisibility.constEnd(); ++it)
{
KToolBar* const toolbar = it.key();
bool visibility = it.value();
if (toolbar)
{
if (visible && visibility)
toolbar->show();
else
toolbar->hide();
}
}
// We will show toolbars: restore previous state.
if (visible)
{
for (QMap::const_iterator it = d->toolbarsVisibility.constBegin(); it != d->toolbarsVisibility.constEnd(); ++it)
{
KToolBar* const toolbar = it.key();
bool visibility = it.value();
if (toolbar)
{
visibility ? toolbar->show() : toolbar->hide();
}
}
}
}
void DXmlGuiWindow::showSideBars(bool visible)
{
Q_UNUSED(visible);
}
void DXmlGuiWindow::showThumbBar(bool visible)
{
Q_UNUSED(visible);
}
void DXmlGuiWindow::customizedFullScreenMode(bool set)
{
Q_UNUSED(set);
}
bool DXmlGuiWindow::thumbbarVisibility() const
{
return true;
}
void DXmlGuiWindow::slotHelpContents()
{
openHandbook();
}
void DXmlGuiWindow::openHandbook()
{
QUrl url = QUrl(QString::fromUtf8("https://docs.kde.org/trunk5/en/extragear-graphics/%1/index.html")
.arg(QApplication::applicationName()));
WebBrowserDlg* const browser = new WebBrowserDlg(url, qApp->activeWindow());
browser->show();
}
void DXmlGuiWindow::restoreWindowSize(QWindow* const win, const KConfigGroup& group)
{
KWindowConfig::restoreWindowSize(win, group);
}
void DXmlGuiWindow::saveWindowSize(QWindow* const win, KConfigGroup& group)
{
KWindowConfig::saveWindowSize(win, group);
}
QAction* DXmlGuiWindow::buildStdAction(StdActionType type, const QObject* const recvr,
const char* const slot, QObject* const parent)
{
switch(type)
{
case StdCopyAction:
return KStandardAction::copy(recvr, slot, parent);
break;
case StdPasteAction:
return KStandardAction::paste(recvr, slot, parent);
break;
case StdCutAction:
return KStandardAction::cut(recvr, slot, parent);
break;
case StdQuitAction:
return KStandardAction::quit(recvr, slot, parent);
break;
case StdCloseAction:
return KStandardAction::close(recvr, slot, parent);
break;
case StdZoomInAction:
return KStandardAction::zoomIn(recvr, slot, parent);
break;
case StdZoomOutAction:
return KStandardAction::zoomOut(recvr, slot, parent);
break;
case StdOpenAction:
#ifndef __clang_analyzer__
// NOTE: disable false positive report from scan build about open()
return KStandardAction::open(recvr, slot, parent);
#endif
break;
case StdSaveAction:
return KStandardAction::save(recvr, slot, parent);
break;
case StdSaveAsAction:
return KStandardAction::saveAs(recvr, slot, parent);
break;
case StdRevertAction:
return KStandardAction::revert(recvr, slot, parent);
break;
case StdBackAction:
return KStandardAction::back(recvr, slot, parent);
break;
case StdForwardAction:
return KStandardAction::forward(recvr, slot, parent);
break;
default:
return 0;
break;
}
}
void DXmlGuiWindow::slotRawCameraList()
{
showRawCameraList();
}
void DXmlGuiWindow::slotDonateMoney()
{
WebBrowserDlg* const browser
= new WebBrowserDlg(QUrl(QLatin1String("https://www.digikam.org/donate/")),
qApp->activeWindow());
browser->show();
}
void DXmlGuiWindow::slotRecipesBook()
{
WebBrowserDlg* const browser
= new WebBrowserDlg(QUrl(QLatin1String("https://www.digikam.org/recipes_book/")),
qApp->activeWindow());
browser->show();
}
void DXmlGuiWindow::slotContribute()
{
WebBrowserDlg* const browser
= new WebBrowserDlg(QUrl(QLatin1String("https://www.digikam.org/contribute/")),
qApp->activeWindow());
browser->show();
}
void DXmlGuiWindow::setupIconTheme()
{
// Let QStandardPaths handle this, it will look for app local stuff
// this means e.g. for mac: "/../Resources" and for win: "/data".
bool hasBreeze = false;
const QString breezeIcons = QStandardPaths::locate(QStandardPaths::DataLocation, QLatin1String("breeze.rcc"));
if (!breezeIcons.isEmpty() && QFile::exists(breezeIcons))
{
QResource::registerResource(breezeIcons);
hasBreeze = true;
}
bool hasBreezeDark = false;
const QString breezeDarkIcons = QStandardPaths::locate(QStandardPaths::DataLocation, QLatin1String("breeze-dark.rcc"));
if (!breezeDarkIcons.isEmpty() && QFile::exists(breezeDarkIcons))
{
QResource::registerResource(breezeDarkIcons);
hasBreezeDark = true;
}
if (hasBreeze || hasBreezeDark)
{
// Tell Qt about the theme
QIcon::setThemeSearchPaths(QStringList() << QLatin1String(":/icons"));
// Tell icons loader an co. about the theme
KConfigGroup cg(KSharedConfig::openConfig(), "Icons");
if (hasBreeze)
{
QIcon::setThemeName(QLatin1String("breeze"));
cg.writeEntry("Theme", "breeze");
qCDebug(DIGIKAM_WIDGETS_LOG) << "Breeze icons resource file found";
}
else if (hasBreezeDark)
{
QIcon::setThemeName(QLatin1String("breeze-dark"));
cg.writeEntry("Theme", "breeze-dark");
qCDebug(DIGIKAM_WIDGETS_LOG) << "Breeze-dark icons resource file found";
}
else
{
qCDebug(DIGIKAM_WIDGETS_LOG) << "No icons resource file found";
}
cg.sync();
}
}
void DXmlGuiWindow::createExportActions()
{
m_exportDropboxAction = new QAction(i18n("Export to &Dropbox..."), this);
- m_exportDropboxAction->setIcon(QIcon::fromTheme(QLatin1String("dropbox")));
+ m_exportDropboxAction->setIcon(QIcon::fromTheme(QLatin1String("dk-dropbox")));
actionCollection()->addAction(QLatin1String("export_dropbox"), m_exportDropboxAction);
actionCollection()->setDefaultShortcut(m_exportDropboxAction, Qt::ALT + Qt::SHIFT + Qt::CTRL + Qt::Key_D);
connect(m_exportDropboxAction, SIGNAL(triggered(bool)),
this, SLOT(slotExportTool()));
m_exportOnedriveAction = new QAction(i18n("Export to &Onedrive..."), this);
- m_exportOnedriveAction->setIcon(QIcon::fromTheme(QString::fromLatin1("onedrive")));
+ m_exportOnedriveAction->setIcon(QIcon::fromTheme(QLatin1String("dk-onedrive")));
actionCollection()->addAction(QLatin1String("export_onedrive"), m_exportOnedriveAction);
actionCollection()->setDefaultShortcut(m_exportOnedriveAction, Qt::ALT + Qt::SHIFT + Qt::CTRL + Qt::Key_O);
connect(m_exportOnedriveAction, SIGNAL(triggered(bool)),
this, SLOT(slotExportTool()));
m_exportPinterestAction = new QAction(i18n("Export to &Pinterest..."), this);
- m_exportPinterestAction->setIcon(QIcon::fromTheme(QString::fromLatin1("pinterest")));
+ m_exportPinterestAction->setIcon(QIcon::fromTheme(QLatin1String("dk-pinterest")));
actionCollection()->addAction(QLatin1String("export_pinterest"), m_exportPinterestAction);
actionCollection()->setDefaultShortcut(m_exportPinterestAction, Qt::ALT + Qt::SHIFT + Qt::CTRL + Qt::Key_I);
connect(m_exportPinterestAction, SIGNAL(triggered(bool)),
this, SLOT(slotExportTool()));
m_exportBoxAction = new QAction(i18n("Export to &Box..."), this);
- m_exportBoxAction->setIcon(QIcon::fromTheme(QString::fromLatin1("box")));
+ m_exportBoxAction->setIcon(QIcon::fromTheme(QLatin1String("dk-box")));
actionCollection()->addAction(QLatin1String("export_box"), m_exportBoxAction);
actionCollection()->setDefaultShortcut(m_exportBoxAction, Qt::ALT + Qt::SHIFT + Qt::CTRL + Qt::Key_B);
connect(m_exportBoxAction, SIGNAL(triggered(bool)),
this, SLOT(slotExportTool()));
m_exportFacebookAction = new QAction(i18n("Export to &Facebook..."), this);
- m_exportFacebookAction->setIcon(QIcon::fromTheme(QString::fromLatin1("facebook")));
+ m_exportFacebookAction->setIcon(QIcon::fromTheme(QString::fromLatin1("dk-facebook")));
actionCollection()->addAction(QLatin1String("export_facebook"), m_exportFacebookAction);
actionCollection()->setDefaultShortcut(m_exportFacebookAction, Qt::ALT + Qt::SHIFT + Qt::Key_F);
connect(m_exportFacebookAction, SIGNAL(triggered(bool)),
this, SLOT(slotExportTool()));
m_exportFlickrAction = new QAction(i18n("Export to Flick&r..."), this);
- m_exportFlickrAction->setIcon(QIcon::fromTheme(QLatin1String("flickr")));
+ m_exportFlickrAction->setIcon(QIcon::fromTheme(QLatin1String("dk-flickr")));
actionCollection()->addAction(QLatin1String("export_flickr"), m_exportFlickrAction);
actionCollection()->setDefaultShortcut(m_exportFlickrAction, Qt::ALT + Qt::SHIFT + Qt::Key_R);
connect(m_exportFlickrAction, SIGNAL(triggered(bool)),
this, SLOT(slotExportTool()));
m_exportGdriveAction = new QAction(i18n("Export to &Google Drive..."), this);
- m_exportGdriveAction->setIcon(QIcon::fromTheme(QLatin1String("googledrive")));
+ m_exportGdriveAction->setIcon(QIcon::fromTheme(QLatin1String("dk-googledrive")));
actionCollection()->addAction(QLatin1String("export_googledrive"), m_exportGdriveAction);
actionCollection()->setDefaultShortcut(m_exportGdriveAction, Qt::ALT + Qt::SHIFT + Qt::CTRL + Qt::Key_G);
connect(m_exportGdriveAction, SIGNAL(triggered(bool)),
this, SLOT(slotExportTool()));
m_exportGphotoAction = new QAction(i18n("Export to &Google Photos..."), this);
- m_exportGphotoAction->setIcon(QIcon::fromTheme(QLatin1String("googlephoto")));
+ m_exportGphotoAction->setIcon(QIcon::fromTheme(QLatin1String("dk-googlephoto")));
actionCollection()->addAction(QLatin1String("export_googlephoto"), m_exportGphotoAction);
actionCollection()->setDefaultShortcut(m_exportGphotoAction, Qt::ALT + Qt::SHIFT + Qt::Key_P);
connect(m_exportGphotoAction, SIGNAL(triggered(bool)),
this, SLOT(slotExportTool()));
m_exportImageshackAction = new QAction(i18n("Export to &Imageshack..."), this);
- m_exportImageshackAction->setIcon(QIcon::fromTheme(QLatin1String("imageshack")));
+ m_exportImageshackAction->setIcon(QIcon::fromTheme(QLatin1String("dk-imageshack")));
actionCollection()->addAction(QLatin1String("export_imageshack"), m_exportImageshackAction);
actionCollection()->setDefaultShortcut(m_exportImageshackAction, Qt::ALT + Qt::SHIFT + Qt::Key_M);
connect(m_exportImageshackAction, SIGNAL(triggered(bool)),
this, SLOT(slotExportTool()));
m_exportImgurAction = new QAction(i18n("Export to &Imgur.."), this);
- m_exportImgurAction->setIcon(QIcon::fromTheme(QLatin1String("imgur")));
+ m_exportImgurAction->setIcon(QIcon::fromTheme(QLatin1String("dk-imgur")));
actionCollection()->addAction(QLatin1String("export_imgur"), m_exportImgurAction);
connect(m_exportImgurAction, SIGNAL(triggered(bool)),
this, SLOT(slotExportTool()));
m_exportIpfsAction = new QAction(i18n("Export to &Ipfs.."), this);
- m_exportIpfsAction->setIcon(QIcon::fromTheme(QLatin1String("ipfs")));
+ m_exportIpfsAction->setIcon(QIcon::fromTheme(QLatin1String("dk-ipfs")));
actionCollection()->addAction(QLatin1String("export_ipfs"), m_exportIpfsAction);
connect(m_exportIpfsAction, SIGNAL(triggered(bool)),
this, SLOT(slotExportTool()));
m_exportPiwigoAction = new QAction(i18n("Export to &Piwigo..."), this);
- m_exportPiwigoAction->setIcon(QIcon::fromTheme(QLatin1String("piwigo")));
+ m_exportPiwigoAction->setIcon(QIcon::fromTheme(QLatin1String("dk-piwigo")));
actionCollection()->addAction(QLatin1String("export_piwigo"), m_exportPiwigoAction);
connect(m_exportPiwigoAction, SIGNAL(triggered(bool)),
this, SLOT(slotExportTool()));
m_exportRajceAction = new QAction(i18n("Export to &Rajce.net..."), this);
- m_exportRajceAction->setIcon(QIcon::fromTheme(QLatin1String("rajce")));
+ m_exportRajceAction->setIcon(QIcon::fromTheme(QLatin1String("dk-rajce")));
actionCollection()->addAction(QLatin1String("export_rajce"), m_exportRajceAction);
actionCollection()->setDefaultShortcut(m_exportRajceAction, Qt::ALT + Qt::SHIFT + Qt::Key_J);
connect(m_exportRajceAction, SIGNAL(triggered(bool)),
this, SLOT(slotExportTool()));
m_exportSmugmugAction = new QAction(i18n("Export to &SmugMug..."), this);
- m_exportSmugmugAction->setIcon(QIcon::fromTheme(QLatin1String("smugmug")));
+ m_exportSmugmugAction->setIcon(QIcon::fromTheme(QLatin1String("dk-smugmug")));
actionCollection()->addAction(QLatin1String("export_smugmug"), m_exportSmugmugAction);
actionCollection()->setDefaultShortcut(m_exportSmugmugAction, Qt::ALT + Qt::SHIFT + Qt::Key_S);
connect(m_exportSmugmugAction, SIGNAL(triggered(bool)),
this, SLOT(slotExportTool()));
m_exportYandexfotkiAction = new QAction(i18n("Export to &Yandex.Fotki..."), this);
m_exportYandexfotkiAction->setIcon(QIcon::fromTheme(QLatin1String("internet-web-browser")));
actionCollection()->addAction(QLatin1String("export_yandexfotki"), m_exportYandexfotkiAction);
actionCollection()->setDefaultShortcut(m_exportYandexfotkiAction, Qt::ALT + Qt::SHIFT + Qt::Key_Y);
connect(m_exportYandexfotkiAction, SIGNAL(triggered(bool)),
this, SLOT(slotExportTool()));
m_exportMediawikiAction = new QAction(i18n("Export to MediaWiki..."), this);
- m_exportMediawikiAction->setIcon(QIcon::fromTheme(QLatin1String("MediaWiki")));
+ m_exportMediawikiAction->setIcon(QIcon::fromTheme(QLatin1String("dk-mediawiki")));
actionCollection()->addAction(QLatin1String("export_MediaWiki"), m_exportMediawikiAction);
connect(m_exportMediawikiAction, SIGNAL(triggered(bool)),
this, SLOT(slotExportTool()));
#ifdef HAVE_VKONTAKTE
m_exportVkontakteAction = new QAction(i18n("Export to &VKontakte..."), this);
m_exportVkontakteAction->setIcon(QIcon::fromTheme(QLatin1String("preferences-web-browser-shortcuts")));
actionCollection()->addAction(QLatin1String("export_vkontakte"), m_exportVkontakteAction);
connect(m_exportVkontakteAction, SIGNAL(triggered(bool)),
this, SLOT(slotExportTool()));
#endif
#ifdef HAVE_KIO
m_exportFileTransferAction = new QAction(i18n("Export to remote storage..."), this);
m_exportFileTransferAction->setIcon(QIcon::fromTheme(QLatin1String("folder-html")));
actionCollection()->addAction(QLatin1String("export_filetransfer"), m_exportFileTransferAction);
actionCollection()->setDefaultShortcut(m_exportYandexfotkiAction, Qt::ALT + Qt::SHIFT + Qt::Key_K);
connect(m_exportFileTransferAction, SIGNAL(triggered(bool)),
this, SLOT(slotExportTool()));
#endif
}
void DXmlGuiWindow::createImportActions()
{
m_importGphotoAction = new QAction(i18n("Import from &Google Photos..."), this);
- m_importGphotoAction->setIcon(QIcon::fromTheme(QLatin1String("googlephoto")));
+ m_importGphotoAction->setIcon(QIcon::fromTheme(QLatin1String("dk-googlephoto")));
actionCollection()->addAction(QLatin1String("import_googlephoto"), m_importGphotoAction);
actionCollection()->setDefaultShortcut(m_importGphotoAction, Qt::ALT + Qt::SHIFT + Qt::CTRL + Qt::Key_P);
connect(m_importGphotoAction, SIGNAL(triggered(bool)),
this, SLOT(slotImportTool()));
m_importSmugmugAction = new QAction(i18n("Import from &SmugMug..."), this);
- m_importSmugmugAction->setIcon(QIcon::fromTheme(QLatin1String("smugmug")));
+ m_importSmugmugAction->setIcon(QIcon::fromTheme(QLatin1String("dk-smugmug")));
actionCollection()->addAction(QLatin1String("import_smugmug"), m_importSmugmugAction);
actionCollection()->setDefaultShortcut(m_importSmugmugAction, Qt::ALT + Qt::SHIFT + Qt::CTRL + Qt::Key_S);
connect(m_importSmugmugAction, SIGNAL(triggered(bool)),
this, SLOT(slotImportTool()));
#ifdef HAVE_KIO
m_importFileTransferAction = new QAction(i18n("Import from remote storage..."), this);
m_importFileTransferAction->setIcon(QIcon::fromTheme(QLatin1String("folder-html")));
actionCollection()->addAction(QLatin1String("import_filetransfer"), m_importFileTransferAction);
actionCollection()->setDefaultShortcut(m_importFileTransferAction, Qt::ALT + Qt::SHIFT + Qt::Key_I);
connect(m_importFileTransferAction, SIGNAL(triggered(bool)),
this, SLOT(slotImportTool()));
#endif
#ifdef HAVE_KSANE
m_ksaneAction = new KSaneAction(this);
actionCollection()->addAction(QLatin1String("import_scan"), m_ksaneAction);
connect(m_ksaneAction, SIGNAL(triggered(bool)),
this, SLOT(slotImportFromScanner()));
#endif
}
QList DXmlGuiWindow::exportActions() const
{
return QList() << m_exportDropboxAction
<< m_exportOnedriveAction
<< m_exportPinterestAction
<< m_exportBoxAction
<< m_exportFacebookAction
<< m_exportFlickrAction
<< m_exportGdriveAction
<< m_exportGphotoAction
<< m_exportImageshackAction
<< m_exportImgurAction
<< m_exportIpfsAction
<< m_exportPiwigoAction
<< m_exportRajceAction
<< m_exportSmugmugAction
<< m_exportYandexfotkiAction
<< m_exportMediawikiAction
#ifdef HAVE_VKONTAKTE
<< m_exportVkontakteAction
#endif
#ifdef HAVE_KIO
<< m_exportFileTransferAction;
#endif
;
}
QList DXmlGuiWindow::importActions() const
{
return QList() << m_importGphotoAction
<< m_importSmugmugAction
#ifdef HAVE_KIO
<< m_importFileTransferAction
#endif
#ifdef HAVE_KSANE
<< m_ksaneAction
#endif
;
}
int DXmlGuiWindow::actionToWebService(QAction* const action) const
{
if (action == m_exportBoxAction)
{
return WSStarter::ExportBox;
}
else if (action == m_exportDropboxAction)
{
return WSStarter::ExportDropbox;
}
else if (action == m_exportFacebookAction)
{
return WSStarter::ExportFacebook;
}
#ifdef HAVE_KIO
else if (action == m_exportFileTransferAction)
{
return WSStarter::ExportFileTransfer;
}
#endif
else if (action == m_exportFlickrAction)
{
return WSStarter::ExportFlickr;
}
else if (action == m_exportGdriveAction)
{
return WSStarter::ExportGdrive;
}
else if (action == m_exportGphotoAction)
{
return WSStarter::ExportGphoto;
}
else if (action == m_exportImageshackAction)
{
return WSStarter::ExportImageshack;
}
else if (action == m_exportImgurAction)
{
return WSStarter::ExportImgur;
}
else if (action == m_exportIpfsAction)
{
return WSStarter::ExportIpfs;
}
else if (action == m_exportMediawikiAction)
{
return WSStarter::ExportMediawiki;
}
else if (action == m_exportOnedriveAction)
{
return WSStarter::ExportOnedrive;
}
else if (action == m_exportPinterestAction)
{
return WSStarter::ExportPinterest;
}
else if (action == m_exportPiwigoAction)
{
return WSStarter::ExportPiwigo;
}
else if (action == m_exportRajceAction)
{
return WSStarter::ExportRajce;
}
else if (action == m_exportSmugmugAction)
{
return WSStarter::ExportSmugmug;
}
#ifdef HAVE_VKONTAKTE
else if (action == m_exportVkontakteAction)
{
return WSStarter::ExportVkontakte;
}
#endif
else if (action == m_exportYandexfotkiAction)
{
return WSStarter::ExportYandexfotki;
}
else if (action == m_importGphotoAction)
{
return WSStarter::ImportGphoto;
}
#ifdef HAVE_KIO
else if (action == m_importFileTransferAction)
{
return WSStarter::ImportFileTransfer;
}
#endif
else if (action == m_importSmugmugAction)
{
return WSStarter::ImportSmugmug;
}
return WSStarter::ExportUnknown;
}
} // namespace Digikam
diff --git a/core/utilities/assistants/webservices/box/boxwindow.cpp b/core/utilities/assistants/webservices/box/boxwindow.cpp
index c4ee70494e..3d885ddf5a 100644
--- a/core/utilities/assistants/webservices/box/boxwindow.cpp
+++ b/core/utilities/assistants/webservices/box/boxwindow.cpp
@@ -1,468 +1,468 @@
/* ============================================================
*
* This file is a part of digiKam project
* http://www.digikam.org
*
* Date : 2018-05-20
* Description : a tool to export images to Box web service
*
* Copyright (C) 2018 by Tarek Talaat
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General
* Public License as published by the Free Software Foundation;
* either version 2, 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.
*
* ============================================================ */
#include "boxwindow.h"
// Qt includes
#include
#include
#include
#include
#include
#include
// KDE includes
#include
#include
#include
// Local includes
#include "digikam_debug.h"
#include "ditemslist.h"
#include "digikam_version.h"
#include "boxtalker.h"
#include "boxitem.h"
#include "boxnewalbumdlg.h"
#include "boxwidget.h"
namespace Digikam
{
class Q_DECL_HIDDEN BOXWindow::Private
{
public:
explicit Private()
{
imagesCount = 0;
imagesTotal = 0;
widget = 0;
albumDlg = 0;
talker = 0;
}
unsigned int imagesCount;
unsigned int imagesTotal;
BOXWidget* widget;
BOXNewAlbumDlg* albumDlg;
BOXTalker* talker;
QString currentAlbumName;
QList transferQueue;
};
BOXWindow::BOXWindow(DInfoInterface* const iface,
QWidget* const /*parent*/)
: WSToolDialog(0),
d(new Private)
{
d->widget = new BOXWidget(this, iface, QLatin1String("Box"));
d->widget->imagesList()->setIface(iface);
setMainWidget(d->widget);
setModal(false);
setWindowTitle(i18n("Export to Box"));
startButton()->setText(i18n("Start Upload"));
startButton()->setToolTip(i18n("Start upload to Box"));
d->widget->setMinimumSize(700, 500);
connect(d->widget->imagesList(), SIGNAL(signalImageListChanged()),
this, SLOT(slotImageListChanged()));
connect(d->widget->getChangeUserBtn(), SIGNAL(clicked()),
this, SLOT(slotUserChangeRequest()));
connect(d->widget->getNewAlbmBtn(), SIGNAL(clicked()),
this, SLOT(slotNewAlbumRequest()));
connect(d->widget->getReloadBtn(), SIGNAL(clicked()),
this, SLOT(slotReloadAlbumsRequest()));
connect(startButton(), SIGNAL(clicked()),
this, SLOT(slotStartTransfer()));
d->albumDlg = new BOXNewAlbumDlg(this, QLatin1String("Box"));
d->talker = new BOXTalker(this);
connect(d->talker,SIGNAL(signalBusy(bool)),
this, SLOT(slotBusy(bool)));
connect(d->talker, SIGNAL(signalLinkingFailed()),
this, SLOT(slotSignalLinkingFailed()));
connect(d->talker, SIGNAL(signalLinkingSucceeded()),
this, SLOT(slotSignalLinkingSucceeded()));
connect(d->talker, SIGNAL(signalSetUserName(QString)),
this, SLOT(slotSetUserName(QString)));
connect(d->talker, SIGNAL(signalListAlbumsFailed(QString)),
this, SLOT(slotListAlbumsFailed(QString)));
connect(d->talker, SIGNAL(signalListAlbumsDone(QList >)), // krazy:exclude=normalize
this, SLOT(slotListAlbumsDone(QList >))); // krazy:exclude=normalize
connect(d->talker, SIGNAL(signalCreateFolderFailed(QString)),
this, SLOT(slotCreateFolderFailed(QString)));
connect(d->talker, SIGNAL(signalCreateFolderSucceeded()),
this, SLOT(slotCreateFolderSucceeded()));
connect(d->talker, SIGNAL(signalAddPhotoFailed(QString)),
this, SLOT(slotAddPhotoFailed(QString)));
connect(d->talker, SIGNAL(signalAddPhotoSucceeded()),
this, SLOT(slotAddPhotoSucceeded()));
connect(this, SIGNAL(finished(int)),
this, SLOT(slotFinished()));
readSettings();
buttonStateChange(false);
d->talker->link();
}
BOXWindow::~BOXWindow()
{
delete d->widget;
delete d->albumDlg;
delete d->talker;
delete d;
}
void BOXWindow::readSettings()
{
KConfig config;
KConfigGroup grp = config.group("Box Settings");
d->currentAlbumName = grp.readEntry("Current Album",QString());
if (grp.readEntry("Resize", false))
{
d->widget->getResizeCheckBox()->setChecked(true);
d->widget->getDimensionSpB()->setEnabled(true);
}
else
{
d->widget->getResizeCheckBox()->setChecked(false);
d->widget->getDimensionSpB()->setEnabled(false);
}
d->widget->getDimensionSpB()->setValue(grp.readEntry("Maximum Width", 1600));
d->widget->getImgQualitySpB()->setValue(grp.readEntry("Image Quality", 90));
KConfigGroup dialogGroup = config.group("Box Export Dialog");
winId();
KWindowConfig::restoreWindowSize(windowHandle(), dialogGroup);
resize(windowHandle()->size());
}
void BOXWindow::writeSettings()
{
KConfig config;
KConfigGroup grp = config.group("Box Settings");
grp.writeEntry("Current Album", d->currentAlbumName);
grp.writeEntry("Resize", d->widget->getResizeCheckBox()->isChecked());
grp.writeEntry("Maximum Width", d->widget->getDimensionSpB()->value());
grp.writeEntry("Image Quality", d->widget->getImgQualitySpB()->value());
KConfigGroup dialogGroup = config.group("Box Export Dialog");
KWindowConfig::saveWindowSize(windowHandle(), dialogGroup);
config.sync();
}
void BOXWindow::reactivate()
{
d->widget->imagesList()->loadImagesFromCurrentSelection();
d->widget->progressBar()->hide();
show();
}
void BOXWindow::setItemsList(const QList& urls)
{
d->widget->imagesList()->slotAddImages(urls);
}
void BOXWindow::slotBusy(bool val)
{
if (val)
{
setCursor(Qt::WaitCursor);
d->widget->getChangeUserBtn()->setEnabled(false);
buttonStateChange(false);
}
else
{
setCursor(Qt::ArrowCursor);
d->widget->getChangeUserBtn()->setEnabled(true);
buttonStateChange(true);
}
}
void BOXWindow::slotSetUserName(const QString& msg)
{
d->widget->updateLabels(msg, QLatin1String(""));
}
void BOXWindow::slotListAlbumsDone(const QList >& list)
{
d->widget->getAlbumsCoB()->clear();
for (int i = 0 ; i < list.size() ; ++i)
{
d->widget->getAlbumsCoB()->addItem(
QIcon::fromTheme(QLatin1String("system-users")),
list.value(i).second, list.value(i).second);
if (d->currentAlbumName == QString(list.value(i).second))
{
d->widget->getAlbumsCoB()->setCurrentIndex(i);
}
}
buttonStateChange(true);
d->talker->getUserName();
}
void BOXWindow::slotStartTransfer()
{
d->widget->imagesList()->clearProcessedStatus();
if (d->widget->imagesList()->imageUrls().isEmpty())
{
QMessageBox::critical(this, i18nc("@title:window", "Error"),
i18n("No image selected. Please select which images should be uploaded."));
return;
}
if (!(d->talker->authenticated()))
{
QPointer warn = new QMessageBox(QMessageBox::Warning,
i18n("Warning"),
i18n("Authentication failed. Click \"Continue\" to authenticate."),
QMessageBox::Yes | QMessageBox::No);
(warn->button(QMessageBox::Yes))->setText(i18n("Continue"));
(warn->button(QMessageBox::No))->setText(i18n("Cancel"));
if (warn->exec() == QMessageBox::Yes)
{
d->talker->link();
delete warn;
return;
}
else
{
delete warn;
return;
}
}
d->transferQueue = d->widget->imagesList()->imageUrls();
if (d->transferQueue.isEmpty())
{
return;
}
d->currentAlbumName = d->widget->getAlbumsCoB()->itemData(d->widget->getAlbumsCoB()->currentIndex()).toString();
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "StartTransfer:" << d->currentAlbumName << "INDEX: " << d->widget->getAlbumsCoB()->currentIndex();
d->imagesTotal = d->transferQueue.count();
d->imagesCount = 0;
d->widget->progressBar()->setFormat(i18n("%v / %m"));
d->widget->progressBar()->setMaximum(d->imagesTotal);
d->widget->progressBar()->setValue(0);
d->widget->progressBar()->show();
d->widget->progressBar()->progressScheduled(i18n("Box export"), true, true);
- d->widget->progressBar()->progressThumbnailChanged(QIcon(QLatin1String("box")).pixmap(22, 22));
+ d->widget->progressBar()->progressThumbnailChanged(QIcon(QLatin1String("dk-box")).pixmap(22, 22));
uploadNextPhoto();
}
void BOXWindow::uploadNextPhoto()
{
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "uploadNextPhoto:" << d->transferQueue.count();
if (d->transferQueue.isEmpty())
{
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "empty";
d->widget->progressBar()->progressCompleted();
return;
}
QString imgPath = d->transferQueue.first().toLocalFile();
QString temp = d->currentAlbumName;
bool result = d->talker->addPhoto(imgPath,
temp,
d->widget->getResizeCheckBox()->isChecked(),
d->widget->getDimensionSpB()->value(),
d->widget->getImgQualitySpB()->value());
if (!result)
{
slotAddPhotoFailed(QLatin1String(""));
return;
}
}
void BOXWindow::slotAddPhotoFailed(const QString& msg)
{
if (QMessageBox::question(this, i18n("Uploading Failed"),
i18n("Failed to upload photo to Box."
"\n%1\n"
"Do you want to continue?", msg))
!= QMessageBox::Yes)
{
d->transferQueue.clear();
d->widget->progressBar()->hide();
}
else
{
d->transferQueue.pop_front();
d->imagesTotal--;
d->widget->progressBar()->setMaximum(d->imagesTotal);
d->widget->progressBar()->setValue(d->imagesCount);
uploadNextPhoto();
}
}
void BOXWindow::slotAddPhotoSucceeded()
{
// Remove photo uploaded from the list
d->widget->imagesList()->removeItemByUrl(d->transferQueue.first());
d->transferQueue.pop_front();
d->imagesCount++;
d->widget->progressBar()->setMaximum(d->imagesTotal);
d->widget->progressBar()->setValue(d->imagesCount);
uploadNextPhoto();
}
void BOXWindow::slotImageListChanged()
{
startButton()->setEnabled(!(d->widget->imagesList()->imageUrls().isEmpty()));
}
void BOXWindow::slotNewAlbumRequest()
{
if (d->albumDlg->exec() == QDialog::Accepted)
{
BOXFolder newFolder;
d->albumDlg->getFolderTitle(newFolder);
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "slotNewAlbumRequest:" << newFolder.title;
d->currentAlbumName = d->widget->getAlbumsCoB()->itemData(d->widget->getAlbumsCoB()->currentIndex()).toString();
QString temp = d->currentAlbumName + newFolder.title;
d->talker->createFolder(temp);
}
}
void BOXWindow::slotReloadAlbumsRequest()
{
d->talker->listFolders();
}
void BOXWindow::slotSignalLinkingFailed()
{
slotSetUserName(QLatin1String(""));
d->widget->getAlbumsCoB()->clear();
if (QMessageBox::question(this, i18n("Login Failed"),
i18n("Authentication failed. Do you want to try again?"))
== QMessageBox::Yes)
{
d->talker->link();
}
}
void BOXWindow::slotSignalLinkingSucceeded()
{
slotBusy(false);
d->talker->listFolders();
}
void BOXWindow::slotListAlbumsFailed(const QString& msg)
{
QMessageBox::critical(this, QString(), i18n("Box call failed:\n%1", msg));
}
void BOXWindow::slotCreateFolderFailed(const QString& msg)
{
QMessageBox::critical(this, QString(), i18n("Box call failed:\n%1", msg));
}
void BOXWindow::slotCreateFolderSucceeded()
{
d->talker->listFolders();
}
void BOXWindow::slotTransferCancel()
{
d->transferQueue.clear();
d->widget->progressBar()->hide();
d->talker->cancel();
}
void BOXWindow::slotUserChangeRequest()
{
slotSetUserName(QLatin1String(""));
d->widget->getAlbumsCoB()->clear();
d->talker->unLink();
d->talker->link();
}
void BOXWindow::buttonStateChange(bool state)
{
d->widget->getNewAlbmBtn()->setEnabled(state);
d->widget->getReloadBtn()->setEnabled(state);
startButton()->setEnabled(state);
}
void BOXWindow::slotFinished()
{
writeSettings();
d->widget->imagesList()->listView()->clear();
}
void BOXWindow::closeEvent(QCloseEvent* e)
{
if (!e)
{
return;
}
slotFinished();
e->accept();
}
} // namespace Digikam
diff --git a/core/utilities/assistants/webservices/common/wizard/wsintropage.cpp b/core/utilities/assistants/webservices/common/wizard/wsintropage.cpp
index fc1c059954..93df615c4b 100644
--- a/core/utilities/assistants/webservices/common/wizard/wsintropage.cpp
+++ b/core/utilities/assistants/webservices/common/wizard/wsintropage.cpp
@@ -1,238 +1,238 @@
/* ============================================================
*
* This file is a part of digiKam project
* http://www.digikam.org
*
* Date : 2017-06-27
* Description : intro page to export tool where user can choose web service to export,
* existent accounts and function mode (export/import).
*
* Copyright (C) 2017-2019 by Gilles Caulier
* Copyright (C) 2018 by Thanh Trung Dinh
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General
* Public License as published by the Free Software Foundation;
* either version 2, 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.
*
* ============================================================ */
#include "wsintropage.h"
// Qt includes
#include
#include
#include
#include
#include
#include
#include
#include
#include
// KDE includes
#include
// Local includes
#include "digikam_debug.h"
#include "dlayoutbox.h"
#include "wswizard.h"
#include "wssettings.h"
namespace Digikam
{
class Q_DECL_HIDDEN WSIntroPage::Private
{
public:
explicit Private(QWizard* const dialog)
: imageGetOption(0),
hbox(0),
wizard(0),
iface(0),
wsOption(0),
accountOption(0)
{
wizard = dynamic_cast(dialog);
if (wizard)
{
iface = wizard->iface();
settings = wizard->settings();
}
}
QComboBox* imageGetOption;
DHBox* hbox;
WSWizard* wizard;
WSSettings* settings;
DInfoInterface* iface;
QComboBox* wsOption;
QComboBox* accountOption;
};
WSIntroPage::WSIntroPage(QWizard* const dialog, const QString& title)
: DWizardPage(dialog, title),
d(new Private(dialog))
{
DVBox* const vbox = new DVBox(this);
QLabel* const desc = new QLabel(vbox);
desc->setWordWrap(true);
desc->setOpenExternalLinks(true);
desc->setText(i18n(""
"Welcome to Web Services Tool
"
"This assistant will guide you step by step, to export "
"your items to popular Internet data hosting service.
"
"Before exporting contents, you will be able to adjust items' properties "
"according to your remote Web service capabilities.
"
""));
/* --------------------
* ComboBox for image selection method
*/
d->hbox = new DHBox(vbox);
QLabel* const getImageLabel = new QLabel(i18n("&Choose operation:"), d->hbox);
d->imageGetOption = new QComboBox(d->hbox);
d->imageGetOption->insertItem(WSSettings::EXPORT, i18n("Export to web services"));
d->imageGetOption->insertItem(WSSettings::IMPORT, i18n("Import from web services"));
getImageLabel->setBuddy(d->imageGetOption);
connect(d->imageGetOption, SIGNAL(currentIndexChanged(int)),
this, SLOT(slotImageGetOptionChanged(int)));
/* --------------------
* ComboBox for web service selection
*/
DHBox* const wsBox = new DHBox(vbox);
QLabel* const wsLabel = new QLabel(i18n("&Choose remote Web Service:"), wsBox);
d->wsOption = new QComboBox(wsBox);
QMap map = WSSettings::webServiceNames();
QMap::const_iterator it = map.constBegin();
while (it != map.constEnd())
{
QString wsName = it.value().toLower();
QIcon icon = QIcon::fromTheme(wsName.remove(QLatin1Char(' ')));
d->wsOption->addItem(icon, it.value(), (int)it.key());
++it;
}
wsLabel->setBuddy(d->wsOption);
connect(d->wsOption, SIGNAL(currentIndexChanged(QString)),
this, SLOT(slotWebServiceOptionChanged(QString)));
/* --------------------
* ComboBox for user account selection
*
* An empty option is added to accounts, so that user can choose to login with new account
*/
DHBox* const accountBox = new DHBox(vbox);
QLabel* const accountLabel = new QLabel(i18n("&Choose account:"), accountBox);
d->accountOption = new QComboBox(accountBox);
QStringList accounts = QStringList(QString(""))
<< d->settings->allUserNames(map.constBegin().value());
foreach(const QString& account, accounts)
{
d->accountOption->addItem(account);
}
accountLabel->setBuddy(d->accountOption);
/* --------------------
* Place widget in the view
*/
vbox->setStretchFactor(desc, 3);
vbox->setStretchFactor(d->hbox, 1);
vbox->setStretchFactor(wsBox, 3);
vbox->setStretchFactor(accountBox, 3);
setPageWidget(vbox);
setLeftBottomPix(QIcon::fromTheme(QLatin1String("folder-html")));
}
WSIntroPage::~WSIntroPage()
{
delete d;
}
void WSIntroPage::slotImageGetOptionChanged(int index)
{
QMap map = WSSettings::webServiceNames();
d->wsOption->clear();
/*
* index == 0 <=> Export
* index == 1 <=> Import, for now we only have Google Photo and Smugmug in this option
*/
if (index == 0)
{
QMap::const_iterator it = map.constBegin();
while (it != map.constEnd())
{
QString wsName = it.value().toLower();
QIcon icon = QIcon::fromTheme(wsName.remove(QLatin1Char(' ')));
qCDebug(DIGIKAM_WEBSERVICES_LOG) << wsName.remove(QLatin1Char(' '));
d->wsOption->addItem(icon, it.value(), (int)it.key());
++it;
}
}
else
{
- d->wsOption->addItem(QIcon::fromTheme(QLatin1String("smugmug")),
+ d->wsOption->addItem(QIcon::fromTheme(QLatin1String("dk-smugmug")),
map[WSSettings::WebService::SMUGMUG],
WSSettings::WebService::SMUGMUG);
- d->wsOption->addItem(QIcon::fromTheme(QLatin1String("googlephoto")),
+ d->wsOption->addItem(QIcon::fromTheme(QLatin1String("dk-googlephoto")),
map[WSSettings::WebService::GPHOTO],
WSSettings::WebService::GPHOTO);
}
}
void WSIntroPage::slotWebServiceOptionChanged(const QString& serviceName)
{
d->accountOption->clear();
// An empty option is added to accounts, so that user can choose to login with new account
QStringList accounts = QStringList(QString(""))
<< d->settings->allUserNames(serviceName);
foreach(const QString& account, accounts)
{
d->accountOption->addItem(account);
}
}
void WSIntroPage::initializePage()
{
d->imageGetOption->setCurrentIndex(d->wizard->settings()->selMode);
}
bool WSIntroPage::validatePage()
{
d->wizard->settings()->selMode = (WSSettings::Selection)d->imageGetOption->currentIndex();
d->wizard->settings()->webService = (WSSettings::WebService)d->wsOption->currentIndex();
d->wizard->settings()->userName = d->accountOption->currentText();
return true;
}
} // namespace Digikam
diff --git a/core/utilities/assistants/webservices/common/wsselectuserdlg.cpp b/core/utilities/assistants/webservices/common/wsselectuserdlg.cpp
index d412711907..2aac429010 100644
--- a/core/utilities/assistants/webservices/common/wsselectuserdlg.cpp
+++ b/core/utilities/assistants/webservices/common/wsselectuserdlg.cpp
@@ -1,163 +1,163 @@
/* ============================================================
*
* This file is a part of digiKam project
* http://www.digikam.org
*
* Date : 2015-16-05
* Description : a dialog to select user for Web Service tools
*
* Copyright (C) 2015 by Shourya Singh Gupta
* Copyright (C) 2016-2019 by Gilles Caulier
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General
* Public License as published by the Free Software Foundation;
* either version 2, 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.
*
* ============================================================ */
#include "wsselectuserdlg.h"
// Qt includes
#include
#include
#include
#include
#include
#include
// KDE includes
#include
#include
#include
namespace Digikam
{
class Q_DECL_HIDDEN WSSelectUserDlg::Private
{
public:
explicit Private()
{
userComboBox = 0;
label = 0;
okButton = 0;
}
QComboBox* userComboBox;
QLabel* label;
QPushButton* okButton;
QString userName;
QString serviceName;
};
WSSelectUserDlg::WSSelectUserDlg(QWidget* const parent, const QString& serviceName)
: QDialog(parent),
d(new Private)
{
d->serviceName = serviceName;
setWindowTitle(i18n("Account Selector"));
setModal(true);
QDialogButtonBox* const buttonBox = new QDialogButtonBox();
QPushButton* const buttonNewAccount = new QPushButton(buttonBox);
buttonNewAccount->setText(i18n("Add another account"));
buttonNewAccount->setIcon(QIcon::fromTheme(QLatin1String("network-workgroup")));
buttonBox->addButton(buttonNewAccount, QDialogButtonBox::AcceptRole);
buttonBox->addButton(QDialogButtonBox::Ok);
buttonBox->addButton(QDialogButtonBox::Close);
buttonBox->button(QDialogButtonBox::Close)->setDefault(true);
d->okButton = buttonBox->button(QDialogButtonBox::Ok);
if (d->serviceName == QLatin1String("23"))
{
setWindowIcon(QIcon::fromTheme(QLatin1String("hq")));
}
else
{
- setWindowIcon(QIcon::fromTheme(QLatin1String("flickr")));
+ setWindowIcon(QIcon::fromTheme(QLatin1String("dk-flickr")));
}
d->userName = QString();
d->label = new QLabel(this);
d->label->setText(i18n("Choose the %1 account to use for exporting images:", d->serviceName));
d->userComboBox = new QComboBox(this);
QVBoxLayout* const mainLayout = new QVBoxLayout(this);
mainLayout->addWidget(d->label);
mainLayout->addWidget(d->userComboBox);
mainLayout->addWidget(buttonBox);
setLayout(mainLayout);
connect(buttonBox, SIGNAL(accepted()),
this, SLOT(accept()));
connect(buttonBox, SIGNAL(rejected()),
this, SLOT(reject()));
connect(buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()),
this, SLOT(slotOkClicked()));
connect(buttonNewAccount, SIGNAL(clicked()),
this, SLOT(slotNewAccountClicked()));
}
WSSelectUserDlg::~WSSelectUserDlg()
{
delete d->userComboBox;
delete d->label;
delete d;
}
void WSSelectUserDlg::reactivate()
{
KConfig config;
d->userComboBox->clear();
foreach(const QString& group, config.groupList())
{
if (!(group.contains(d->serviceName)))
continue;
KConfigGroup grp = config.group(group);
if (QString::compare(grp.readEntry(QLatin1String("username")), QString(), Qt::CaseInsensitive) == 0)
continue;
d->userComboBox->addItem(grp.readEntry(QLatin1String("username")));
}
d->okButton->setEnabled(d->userComboBox->count() > 0);
exec();
}
void WSSelectUserDlg::slotOkClicked()
{
d->userName = d->userComboBox->currentText();
}
void WSSelectUserDlg::slotNewAccountClicked()
{
d->userName = QString();
}
QString WSSelectUserDlg::getUserName() const
{
return d->userName;
}
} // namespace Digikam
diff --git a/core/utilities/assistants/webservices/dropbox/dbwindow.cpp b/core/utilities/assistants/webservices/dropbox/dbwindow.cpp
index 61dc4f5ade..408745262a 100644
--- a/core/utilities/assistants/webservices/dropbox/dbwindow.cpp
+++ b/core/utilities/assistants/webservices/dropbox/dbwindow.cpp
@@ -1,461 +1,461 @@
/* ============================================================
*
* This file is a part of digiKam project
* http://www.digikam.org
*
* Date : 2013-11-18
* Description : a tool to export images to Dropbox web service
*
* Copyright (C) 2013 by Pankaj Kumar
* Copyright (C) 2013-2019 by Gilles Caulier
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General
* Public License as published by the Free Software Foundation;
* either version 2, 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.
*
* ============================================================ */
#include "dbwindow.h"
// Qt includes
#include
#include
#include
#include
#include
// KDE includes
#include
#include
#include
// Local includes
#include "digikam_debug.h"
#include "ditemslist.h"
#include "digikam_version.h"
#include "dbtalker.h"
#include "dbitem.h"
#include "dbnewalbumdlg.h"
#include "dbwidget.h"
namespace Digikam
{
class Q_DECL_HIDDEN DBWindow::Private
{
public:
explicit Private()
{
imagesCount = 0;
imagesTotal = 0;
widget = 0;
albumDlg = 0;
talker = 0;
}
unsigned int imagesCount;
unsigned int imagesTotal;
DBWidget* widget;
DBNewAlbumDlg* albumDlg;
DBTalker* talker;
QString currentAlbumName;
QList transferQueue;
};
DBWindow::DBWindow(DInfoInterface* const iface,
QWidget* const /*parent*/)
: WSToolDialog(0),
d(new Private)
{
d->widget = new DBWidget(this, iface, QLatin1String("Dropbox"));
d->widget->imagesList()->setIface(iface);
setMainWidget(d->widget);
setModal(false);
setWindowTitle(i18n("Export to Dropbox"));
startButton()->setText(i18n("Start Upload"));
startButton()->setToolTip(i18n("Start upload to Dropbox"));
d->widget->setMinimumSize(700, 500);
connect(d->widget->imagesList(), SIGNAL(signalImageListChanged()),
this, SLOT(slotImageListChanged()));
connect(d->widget->getChangeUserBtn(), SIGNAL(clicked()),
this, SLOT(slotUserChangeRequest()));
connect(d->widget->getNewAlbmBtn(), SIGNAL(clicked()),
this, SLOT(slotNewAlbumRequest()));
connect(d->widget->getReloadBtn(), SIGNAL(clicked()),
this, SLOT(slotReloadAlbumsRequest()));
connect(startButton(), SIGNAL(clicked()),
this, SLOT(slotStartTransfer()));
d->albumDlg = new DBNewAlbumDlg(this, QLatin1String("Dropbox"));
d->talker = new DBTalker(this);
connect(d->talker, SIGNAL(signalBusy(bool)),
this, SLOT(slotBusy(bool)));
connect(d->talker, SIGNAL(signalLinkingFailed()),
this, SLOT(slotSignalLinkingFailed()));
connect(d->talker, SIGNAL(signalLinkingSucceeded()),
this, SLOT(slotSignalLinkingSucceeded()));
connect(d->talker, SIGNAL(signalSetUserName(QString)),
this, SLOT(slotSetUserName(QString)));
connect(d->talker, SIGNAL(signalListAlbumsFailed(QString)),
this, SLOT(slotListAlbumsFailed(QString)));
connect(d->talker, SIGNAL(signalListAlbumsDone(QList >)), // krazy:exclude=normalize
this, SLOT(slotListAlbumsDone(QList >))); // krazy:exclude=normalize
connect(d->talker, SIGNAL(signalCreateFolderFailed(QString)),
this, SLOT(slotCreateFolderFailed(QString)));
connect(d->talker, SIGNAL(signalCreateFolderSucceeded()),
this, SLOT(slotCreateFolderSucceeded()));
connect(d->talker, SIGNAL(signalAddPhotoFailed(QString)),
this, SLOT(slotAddPhotoFailed(QString)));
connect(d->talker, SIGNAL(signalAddPhotoSucceeded()),
this, SLOT(slotAddPhotoSucceeded()));
connect(this, SIGNAL(finished(int)),
this, SLOT(slotFinished()));
readSettings();
buttonStateChange(false);
d->talker->link();
}
DBWindow::~DBWindow()
{
delete d->widget;
delete d->albumDlg;
delete d->talker;
delete d;
}
void DBWindow::setItemsList(const QList& urls)
{
d->widget->imagesList()->slotAddImages(urls);
}
void DBWindow::reactivate()
{
d->widget->imagesList()->loadImagesFromCurrentSelection();
d->widget->progressBar()->hide();
show();
}
void DBWindow::readSettings()
{
KConfig config;
KConfigGroup grp = config.group("Dropbox Settings");
d->currentAlbumName = grp.readEntry("Current Album",QString());
if (grp.readEntry("Resize", false))
{
d->widget->getResizeCheckBox()->setChecked(true);
d->widget->getDimensionSpB()->setEnabled(true);
}
else
{
d->widget->getResizeCheckBox()->setChecked(false);
d->widget->getDimensionSpB()->setEnabled(false);
}
d->widget->getDimensionSpB()->setValue(grp.readEntry("Maximum Width", 1600));
d->widget->getImgQualitySpB()->setValue(grp.readEntry("Image Quality", 90));
winId();
KConfigGroup dialogGroup = config.group("Dropbox Export Dialog");
KWindowConfig::restoreWindowSize(windowHandle(), dialogGroup);
resize(windowHandle()->size());
}
void DBWindow::writeSettings()
{
KConfig config;
KConfigGroup grp = config.group("Dropbox Settings");
grp.writeEntry("Current Album", d->currentAlbumName);
grp.writeEntry("Resize", d->widget->getResizeCheckBox()->isChecked());
grp.writeEntry("Maximum Width", d->widget->getDimensionSpB()->value());
grp.writeEntry("Image Quality", d->widget->getImgQualitySpB()->value());
KConfigGroup dialogGroup = config.group("Dropbox Export Dialog");
KWindowConfig::saveWindowSize(windowHandle(), dialogGroup);
config.sync();
}
void DBWindow::slotSetUserName(const QString& msg)
{
d->widget->updateLabels(msg, QLatin1String(""));
}
void DBWindow::slotListAlbumsDone(const QList >& list)
{
d->widget->getAlbumsCoB()->clear();
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "slotListAlbumsDone:" << list.size();
for (int i = 0 ; i < list.size() ; ++i)
{
d->widget->getAlbumsCoB()->addItem(
QIcon::fromTheme(QLatin1String("system-users")),
list.value(i).second, list.value(i).first);
if (d->currentAlbumName == list.value(i).first)
{
d->widget->getAlbumsCoB()->setCurrentIndex(i);
}
}
buttonStateChange(true);
d->talker->getUserName();
}
void DBWindow::slotBusy(bool val)
{
if (val)
{
setCursor(Qt::WaitCursor);
d->widget->getChangeUserBtn()->setEnabled(false);
buttonStateChange(false);
}
else
{
setCursor(Qt::ArrowCursor);
d->widget->getChangeUserBtn()->setEnabled(true);
buttonStateChange(true);
}
}
void DBWindow::slotStartTransfer()
{
d->widget->imagesList()->clearProcessedStatus();
if (d->widget->imagesList()->imageUrls().isEmpty())
{
QMessageBox::critical(this, i18nc("@title:window", "Error"),
i18n("No image selected. Please select which images should be uploaded."));
return;
}
if (!(d->talker->authenticated()))
{
if (QMessageBox::question(this, i18n("Login Failed"),
i18n("Authentication failed. Do you want to try again?"))
== QMessageBox::Yes)
{
d->talker->link();
return;
}
else
{
return;
}
}
d->transferQueue = d->widget->imagesList()->imageUrls();
if (d->transferQueue.isEmpty())
{
return;
}
d->currentAlbumName = d->widget->getAlbumsCoB()->itemData(d->widget->getAlbumsCoB()->currentIndex()).toString();
d->imagesTotal = d->transferQueue.count();
d->imagesCount = 0;
d->widget->progressBar()->setFormat(i18n("%v / %m"));
d->widget->progressBar()->setMaximum(d->imagesTotal);
d->widget->progressBar()->setValue(0);
d->widget->progressBar()->show();
d->widget->progressBar()->progressScheduled(i18n("Dropbox export"), true, true);
d->widget->progressBar()->progressThumbnailChanged(
- QIcon(QLatin1String("dropbox")).pixmap(22, 22));
+ QIcon(QLatin1String("dk-dropbox")).pixmap(22, 22));
uploadNextPhoto();
}
void DBWindow::uploadNextPhoto()
{
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "uploadNextPhoto:" << d->transferQueue.count();
if (d->transferQueue.isEmpty())
{
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "empty";
d->widget->progressBar()->progressCompleted();
return;
}
QString imgPath = d->transferQueue.first().toLocalFile();
QString temp = d->currentAlbumName + QLatin1Char('/');
bool res = d->talker->addPhoto(imgPath,
temp,
d->widget->getResizeCheckBox()->isChecked(),
d->widget->getDimensionSpB()->value(),
d->widget->getImgQualitySpB()->value());
if (!res)
{
slotAddPhotoFailed(QLatin1String(""));
return;
}
}
void DBWindow::slotAddPhotoFailed(const QString& msg)
{
if (QMessageBox::question(this, i18n("Uploading Failed"),
i18n("Failed to upload photo to Dropbox."
"\n%1\n"
"Do you want to continue?", msg))
!= QMessageBox::Yes)
{
d->transferQueue.clear();
d->widget->progressBar()->hide();
}
else
{
d->transferQueue.removeFirst();
d->imagesTotal--;
d->widget->progressBar()->setMaximum(d->imagesTotal);
d->widget->progressBar()->setValue(d->imagesCount);
uploadNextPhoto();
}
}
void DBWindow::slotAddPhotoSucceeded()
{
// Remove photo uploaded from the list
d->widget->imagesList()->removeItemByUrl(d->transferQueue.first());
d->transferQueue.removeFirst();
d->imagesCount++;
d->widget->progressBar()->setMaximum(d->imagesTotal);
d->widget->progressBar()->setValue(d->imagesCount);
uploadNextPhoto();
}
void DBWindow::slotImageListChanged()
{
startButton()->setEnabled(!(d->widget->imagesList()->imageUrls().isEmpty()));
}
void DBWindow::slotNewAlbumRequest()
{
if (d->albumDlg->exec() == QDialog::Accepted)
{
DBFolder newFolder;
d->albumDlg->getFolderTitle(newFolder);
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "slotNewAlbumRequest:" << newFolder.title;
d->currentAlbumName = d->widget->getAlbumsCoB()->itemData(d->widget->getAlbumsCoB()->currentIndex()).toString();
QString temp = d->currentAlbumName + newFolder.title;
d->talker->createFolder(temp);
}
}
void DBWindow::slotReloadAlbumsRequest()
{
d->talker->listFolders();
}
void DBWindow::slotSignalLinkingFailed()
{
slotSetUserName(QLatin1String(""));
d->widget->getAlbumsCoB()->clear();
if (QMessageBox::question(this, i18n("Login Failed"),
i18n("Authentication failed. Do you want to try again?"))
== QMessageBox::Yes)
{
d->talker->link();
}
}
void DBWindow::slotSignalLinkingSucceeded()
{
d->talker->listFolders();
}
void DBWindow::slotListAlbumsFailed(const QString& msg)
{
QMessageBox::critical(this, QString(), i18n("Dropbox call failed:\n%1", msg));
}
void DBWindow::slotCreateFolderFailed(const QString& msg)
{
QMessageBox::critical(this, QString(), i18n("Dropbox call failed:\n%1", msg));
}
void DBWindow::slotCreateFolderSucceeded()
{
d->talker->listFolders();
}
void DBWindow::slotTransferCancel()
{
d->transferQueue.clear();
d->widget->progressBar()->hide();
d->talker->cancel();
}
void DBWindow::slotUserChangeRequest()
{
slotSetUserName(QLatin1String(""));
d->widget->getAlbumsCoB()->clear();
d->talker->unLink();
d->talker->link();
}
void DBWindow::buttonStateChange(bool state)
{
d->widget->getNewAlbmBtn()->setEnabled(state);
d->widget->getReloadBtn()->setEnabled(state);
startButton()->setEnabled(state);
}
void DBWindow::slotFinished()
{
writeSettings();
d->widget->imagesList()->listView()->clear();
}
void DBWindow::closeEvent(QCloseEvent* e)
{
if (!e)
{
return;
}
slotFinished();
e->accept();
}
} // namespace Digikam
diff --git a/core/utilities/assistants/webservices/facebook/fbwindow.cpp b/core/utilities/assistants/webservices/facebook/fbwindow.cpp
index 6804160e5d..44fc0fb9e8 100644
--- a/core/utilities/assistants/webservices/facebook/fbwindow.cpp
+++ b/core/utilities/assistants/webservices/facebook/fbwindow.cpp
@@ -1,666 +1,666 @@
/* ============================================================
*
* This file is a part of digiKam project
* http://www.digikam.org
*
* Date : 2005-17-26
* Description : a tool to export items to Facebook web service
*
* Copyright (C) 2005-2008 by Vardhman Jain
* Copyright (C) 2008-2019 by Gilles Caulier
* Copyright (C) 2008-2009 by Luka Renko
* Copyright (C) 2018 by Thanh Trung Dinh
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General
* Public License as published by the Free Software Foundation;
* either version 2, 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.
*
* ============================================================ */
#include "fbwindow.h"
// Qt includes
#include
#include
#include
#include
#include
#include
#include
#include
#include
// KDE includes
#include
#include
#include
// Local includes
#include "digikam_debug.h"
#include "dmetadata.h"
#include "ditemslist.h"
#include "digikam_version.h"
#include "dprogresswdg.h"
#include "wstoolutils.h"
#include "fbitem.h"
#include "fbtalker.h"
#include "fbwidget.h"
#include "fbnewalbumdlg.h"
#include "previewloadthread.h"
namespace Digikam
{
class Q_DECL_HIDDEN FbWindow::Private
{
public:
explicit Private(QWidget* const parent, DInfoInterface* const interface)
{
iface = interface;
widget = new FbWidget(parent, iface, QLatin1String("Facebook"));
imgList = widget->imagesList();
progressBar = widget->progressBar();
changeUserBtn = widget->getChangeUserBtn();
albumsCoB = widget->getAlbumsCoB();
newAlbumBtn = widget->getNewAlbmBtn();
reloadAlbumsBtn = widget->getReloadBtn();
resizeChB = widget->getResizeCheckBox();
dimensionSpB = widget->getDimensionSpB();
imageQualitySpB = widget->getImgQualitySpB();
imagesCount = 0;
imagesTotal = 0;
talker = 0;
albumDlg = 0;
}
FbWidget* widget;
DItemsList* imgList;
QPushButton* changeUserBtn;
QComboBox* albumsCoB;
QPushButton* newAlbumBtn;
QPushButton* reloadAlbumsBtn;
QCheckBox* resizeChB;
QSpinBox* dimensionSpB;
QSpinBox* imageQualitySpB;
DProgressWdg* progressBar;
unsigned int imagesCount;
unsigned int imagesTotal;
QString tmpDir;
QString tmpPath;
QString profileAID;
QString currentAlbumID;
QList transferQueue;
FbTalker* talker;
FbNewAlbumDlg* albumDlg;
DInfoInterface* iface;
};
FbWindow::FbWindow(DInfoInterface* const iface,
QWidget* const /*parent*/)
: WSToolDialog(0),
d(new Private(this, iface))
{
d->tmpPath.clear();
d->tmpDir = WSToolUtils::makeTemporaryDir("facebook").absolutePath() + QLatin1Char('/');
setMainWidget(d->widget);
setModal(false);
setWindowTitle(i18n("Export to Facebook Web Service"));
startButton()->setText(i18n("Start Upload"));
startButton()->setToolTip(i18n("Start upload to Facebook web service"));
d->widget->setMinimumSize(700, 500);
d->changeUserBtn->setStyleSheet(QLatin1String("QPushButton {background-color: "
"#3b5998; color: #ffffff;}"));
- d->changeUserBtn->setIcon(QIcon::fromTheme(QLatin1String("facebook-white")));
+ d->changeUserBtn->setIcon(QIcon::fromTheme(QLatin1String("dk-facebook-white")));
d->changeUserBtn->setText(i18n("Continue with Facebook"));
// ------------------------------------------------------------------------
connect(d->imgList, SIGNAL(signalImageListChanged()),
this, SLOT(slotImageListChanged()));
connect(d->changeUserBtn, SIGNAL(clicked()),
this, SLOT(slotUserChangeRequest()));
connect(d->newAlbumBtn, SIGNAL(clicked()),
this, SLOT(slotNewAlbumRequest()));
connect(d->widget, SIGNAL(reloadAlbums(long long)),
this, SLOT(slotReloadAlbumsRequest(long long)));
connect(startButton(), SIGNAL(clicked()),
this, SLOT(slotStartTransfer()));
connect(this, SIGNAL(finished(int)),
this, SLOT(slotFinished()));
connect(this, SIGNAL(cancelClicked()),
this, SLOT(slotCancelClicked()));
d->albumDlg = new FbNewAlbumDlg(this, QLatin1String("Facebook"));
// ------------------------------------------------------------------------
d->talker = new FbTalker(this);
connect(d->talker, SIGNAL(signalBusy(bool)),
this, SLOT(slotBusy(bool)));
connect(d->talker, SIGNAL(signalLoginProgress(int,int,QString)),
this, SLOT(slotLoginProgress(int,int,QString)));
connect(d->talker, SIGNAL(signalLoginDone(int,QString)),
this, SLOT(slotLoginDone(int,QString)));
connect(d->talker, SIGNAL(signalAddPhotoDone(int,QString)),
this, SLOT(slotAddPhotoDone(int,QString)));
connect(d->talker, SIGNAL(signalCreateAlbumDone(int,QString,QString)),
this, SLOT(slotCreateAlbumDone(int,QString,QString)));
connect(d->talker, SIGNAL(signalListAlbumsDone(int,QString,QList)),
this, SLOT(slotListAlbumsDone(int,QString,QList)));
connect(d->progressBar, SIGNAL(signalProgressCanceled()),
this, SLOT(slotStopAndCloseProgressBar()));
// ------------------------------------------------------------------------
readSettings();
buttonStateChange(false);
authenticate(false);
}
FbWindow::~FbWindow()
{
WSToolUtils::removeTemporaryDir("facebook");
delete d->albumDlg;
delete d->talker;
delete d;
}
void FbWindow::slotStopAndCloseProgressBar()
{
// Cancel the operation
slotCancelClicked();
// Write settings and tidy up
slotFinished();
// Close the dialog
reject();
}
void FbWindow::slotFinished()
{
writeSettings();
d->imgList->listView()->clear();
d->progressBar->progressCompleted();
}
void FbWindow::slotCancelClicked()
{
setRejectButtonMode(QDialogButtonBox::Close);
d->talker->cancel();
d->transferQueue.clear();
d->imgList->cancelProcess();
d->progressBar->hide();
d->progressBar->progressCompleted();
}
void FbWindow::closeEvent(QCloseEvent* e)
{
if (!e)
{
return;
}
slotFinished();
e->accept();
}
void FbWindow::readSettings()
{
KConfig config;
KConfigGroup grp = config.group("Facebook Settings");
if (grp.readEntry("Resize", false))
{
d->resizeChB->setChecked(true);
d->dimensionSpB->setEnabled(true);
}
else
{
d->resizeChB->setChecked(false);
d->dimensionSpB->setEnabled(false);
}
d->currentAlbumID = grp.readEntry("Current Album", QString());
d->dimensionSpB->setValue(grp.readEntry("Maximum Width", 1600));
d->imageQualitySpB->setValue(grp.readEntry("Image Quality", 85));
winId();
KConfigGroup dialogGroup = config.group("Facebook Export Dialog");
KWindowConfig::restoreWindowSize(windowHandle(), dialogGroup);
resize(windowHandle()->size());
}
void FbWindow::writeSettings()
{
KConfig config;
KConfigGroup grp = config.group("Facebook Settings");
grp.writeEntry("Current Album", d->currentAlbumID);
grp.writeEntry("Resize", d->resizeChB->isChecked());
grp.writeEntry("Maximum Width", d->dimensionSpB->value());
grp.writeEntry("Image Quality", d->imageQualitySpB->value());
KConfigGroup dialogGroup = config.group("Facebook Export Dialog");
KWindowConfig::saveWindowSize(windowHandle(), dialogGroup);
config.sync();
}
void FbWindow::authenticate(bool forceLogin)
{
d->progressBar->show();
d->progressBar->setFormat(QLatin1String(""));
setRejectButtonMode(QDialogButtonBox::Cancel);
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Calling Login method ";
if (forceLogin)
{
d->talker->link();
}
else
{
d->talker->readSettings();
}
}
void FbWindow::slotLoginProgress(int step, int maxStep, const QString& label)
{
DProgressWdg* const progressBar = d->progressBar;
if (!label.isEmpty())
{
progressBar->setFormat(label);
}
if (maxStep > 0)
{
progressBar->setMaximum(maxStep);
}
progressBar->setValue(step);
}
void FbWindow::slotLoginDone(int errCode, const QString& errMsg)
{
setRejectButtonMode(QDialogButtonBox::Close);
d->progressBar->hide();
buttonStateChange(d->talker->linked());
if (d->talker->linked())
{
d->changeUserBtn->setText(i18n("Log Out of Facebook"));
}
else
{
d->changeUserBtn->setText(i18n("Continue with Facebook"));
}
FbUser user = d->talker->getUser();
setProfileAID(user.id.toLongLong());
d->widget->updateLabels(user.name, user.profileURL);
d->albumsCoB->clear();
if (errCode == 0 && d->talker->linked())
{
d->albumsCoB->addItem(i18n(""), QString());
d->talker->listAlbums(); // get albums to fill combo box
}
else if (errCode > 0)
{
QMessageBox::critical(this, QString(), i18n("Facebook Call Failed: %1\n", errMsg));
}
}
void FbWindow::slotListAlbumsDone(int errCode,
const QString& errMsg,
const QList& albumsList)
{
QString albumDebug = QLatin1String("");
foreach (const FbAlbum& album, albumsList)
{
albumDebug.append(QString::fromLatin1("%1: %2\n").arg(album.id).arg(album.title));
}
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Received albums (errCode = " << errCode << ", errMsg = "
<< errMsg << "): " << albumDebug;
if (errCode != 0)
{
QMessageBox::critical(this, QString(), i18n("Facebook Call Failed: %1\n", errMsg));
return;
}
d->albumsCoB->clear();
d->albumsCoB->addItem(i18n(""), QString());
for (int i = 0 ; i < albumsList.size() ; ++i)
{
QString albumIcon;
switch (albumsList.at(i).privacy)
{
case FB_ME:
albumIcon = QLatin1String("secure-card");
break;
case FB_FRIENDS:
albumIcon = QLatin1String("user-identity");
break;
case FB_FRIENDS_OF_FRIENDS:
albumIcon = QLatin1String("system-users");
break;
case FB_EVERYONE:
albumIcon = QLatin1String("folder-html");
break;
case FB_CUSTOM:
albumIcon = QLatin1String("configure");
break;
}
d->albumsCoB->addItem(QIcon::fromTheme(albumIcon),
albumsList.at(i).title,
albumsList.at(i).id);
if (d->currentAlbumID == albumsList.at(i).id)
{
d->albumsCoB->setCurrentIndex(i + 1);
}
}
}
void FbWindow::buttonStateChange(bool state)
{
d->newAlbumBtn->setEnabled(state);
d->reloadAlbumsBtn->setEnabled(state);
startButton()->setEnabled(state);
}
void FbWindow::slotBusy(bool val)
{
if (val)
{
setCursor(Qt::WaitCursor);
d->changeUserBtn->setEnabled(false);
buttonStateChange(false);
}
else
{
setCursor(Qt::ArrowCursor);
d->changeUserBtn->setEnabled(true);
buttonStateChange(d->talker->linked());
}
}
void FbWindow::slotUserChangeRequest()
{
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Slot Change User Request";
if (d->talker->linked())
{
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Slot User Logout";
d->talker->logout();
}
else
{
authenticate(true);
}
}
void FbWindow::slotReloadAlbumsRequest(long long userID)
{
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Reload Albums Request for UID:" << userID;
if (userID == 0)
{
FbUser user = d->talker->getUser();
setProfileAID(user.id.toLongLong());
d->talker->listAlbums(); // re-get albums from current user
}
else
{
setProfileAID(userID);
d->talker->listAlbums(userID); // re-get albums for friend
}
}
void FbWindow::slotNewAlbumRequest()
{
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Slot New Album Request";
if (d->albumDlg->exec() == QDialog::Accepted)
{
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Calling New Album method";
FbAlbum newAlbum;
d->albumDlg->getAlbumProperties(newAlbum);
d->talker->createAlbum(newAlbum);
}
}
void FbWindow::slotStartTransfer()
{
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "slotStartTransfer invoked";
d->imgList->clearProcessedStatus();
d->transferQueue = d->imgList->imageUrls();
if (d->transferQueue.isEmpty())
{
return;
}
d->currentAlbumID = d->albumsCoB->itemData(d->albumsCoB->currentIndex()).toString();
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "upload request got album id from widget: " << d->currentAlbumID;
d->imagesTotal = d->transferQueue.count();
d->imagesCount = 0;
setRejectButtonMode(QDialogButtonBox::Cancel);
d->progressBar->setFormat(i18n("%v / %m"));
d->progressBar->setMaximum(d->imagesTotal);
d->progressBar->setValue(0);
d->progressBar->show();
d->progressBar->progressScheduled(i18n("Facebook export"), true, true);
- d->progressBar->progressThumbnailChanged(QIcon::fromTheme(QLatin1String("facebook")).pixmap(22, 22));
+ d->progressBar->progressThumbnailChanged(QIcon::fromTheme(QLatin1String("dk-facebook")).pixmap(22, 22));
uploadNextPhoto();
}
void FbWindow::setProfileAID(long long userID)
{
// store AID of Profile Photos album
// http://wiki.developers.facebook.com/index.php/Profile_archive_album
d->profileAID = QString::number((userID << 32) + (-3 & 0xFFFFFFFF));
}
QString FbWindow::getImageCaption(const QString& fileName)
{
DItemInfo info(d->iface->itemInfo(QUrl::fromLocalFile(fileName)));
// Facebook doesn't support image titles. Include it in descriptions if needed.
QStringList descriptions = QStringList() << info.title() << info.comment();
descriptions.removeAll(QLatin1String(""));
return descriptions.join(QLatin1String("\n\n"));
}
bool FbWindow::prepareImageForUpload(const QString& imgPath, QString& caption)
{
QImage image = PreviewLoadThread::loadHighQualitySynchronously(imgPath).copyQImage();
if (image.isNull())
{
image.load(imgPath);
}
if (image.isNull())
{
return false;
}
// get temporary file name
d->tmpPath = d->tmpDir + QFileInfo(imgPath).baseName().trimmed() + QLatin1String(".jpg");
// rescale image if requested
int maxDim = d->dimensionSpB->value();
if (d->resizeChB->isChecked() &&
(image.width() > maxDim || image.height() > maxDim))
{
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Resizing to " << maxDim;
image = image.scaled(maxDim, maxDim, Qt::KeepAspectRatio,
Qt::SmoothTransformation);
}
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Saving to temp file: " << d->tmpPath;
image.save(d->tmpPath, "JPEG", d->imageQualitySpB->value());
// copy meta data to temporary image
DMetadata meta;
if (meta.load(imgPath))
{
caption = getImageCaption(imgPath);
meta.setItemDimensions(image.size());
meta.setItemOrientation(MetaEngine::ORIENTATION_NORMAL);
meta.setMetadataWritingMode((int)DMetadata::WRITE_TO_FILE_ONLY);
meta.save(d->tmpPath, true);
}
else
{
caption.clear();
}
return true;
}
void FbWindow::uploadNextPhoto()
{
if (d->transferQueue.isEmpty())
{
setRejectButtonMode(QDialogButtonBox::Close);
d->progressBar->hide();
d->progressBar->progressCompleted();
return;
}
d->imgList->processing(d->transferQueue.first());
QString imgPath = d->transferQueue.first().toLocalFile();
d->progressBar->setMaximum(d->imagesTotal);
d->progressBar->setValue(d->imagesCount);
QString caption;
if (d->resizeChB->isChecked())
{
if (!prepareImageForUpload(imgPath, caption))
{
slotAddPhotoDone(666, i18n("Cannot open file"));
return;
}
d->talker->addPhoto(d->tmpPath, d->currentAlbumID, caption);
}
else
{
caption = getImageCaption(imgPath);
d->tmpPath.clear();
d->talker->addPhoto(imgPath, d->currentAlbumID, caption);
}
}
void FbWindow::slotAddPhotoDone(int errCode, const QString& errMsg)
{
// Remove temporary file if it was used
if (!d->tmpPath.isEmpty())
{
QFile::remove(d->tmpPath);
d->tmpPath.clear();
}
d->imgList->processed(d->transferQueue.first(), (errCode == 0));
if (errCode == 0)
{
d->transferQueue.removeFirst();
d->imagesCount++;
}
else
{
if (QMessageBox::question(this, i18n("Uploading Failed"),
i18n("Failed to upload photo into Facebook: %1\n"
"Do you want to continue?", errMsg))
!= QMessageBox::Yes)
{
setRejectButtonMode(QDialogButtonBox::Close);
d->progressBar->hide();
d->progressBar->progressCompleted();
d->transferQueue.clear();
return;
}
}
uploadNextPhoto();
}
void FbWindow::slotCreateAlbumDone(int errCode, const QString& errMsg, const QString& newAlbumID)
{
if (errCode != 0)
{
QMessageBox::critical(this, QString(), i18n("Facebook Call Failed: %1", errMsg));
return;
}
// reload album list and automatically select new album
d->currentAlbumID = newAlbumID;
d->talker->listAlbums();
}
void FbWindow::slotImageListChanged()
{
startButton()->setEnabled(!(d->imgList->imageUrls().isEmpty()));
}
} // namespace Digikam
diff --git a/core/utilities/assistants/webservices/flickr/flickrwindow.cpp b/core/utilities/assistants/webservices/flickr/flickrwindow.cpp
index d227faf629..f60ec1c64c 100644
--- a/core/utilities/assistants/webservices/flickr/flickrwindow.cpp
+++ b/core/utilities/assistants/webservices/flickr/flickrwindow.cpp
@@ -1,888 +1,888 @@
/* ============================================================
*
* This file is a part of digiKam project
* http://www.digikam.org
*
* Date : 2005-17-06
* Description : a tool to export images to Flickr web service
*
* Copyright (C) 2005-2008 by Vardhman Jain
* Copyright (C) 2008-2019 by Gilles Caulier
* Copyright (C) 2009 by Luka Renko
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General
* Public License as published by the Free Software Foundation;
* either version 2, 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.
*
* ============================================================ */
#include "flickrwindow.h"
// Qt includes
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
// KDE includes
#include
#include
// Local includes
#include "dprogresswdg.h"
#include "flickrtalker.h"
#include "flickritem.h"
#include "flickrlist.h"
#include "wsselectuserdlg.h"
#include "digikam_debug.h"
#include "flickrnewalbumdlg.h"
#include "previewloadthread.h"
#include "flickrwidget_p.h"
namespace Digikam
{
class Q_DECL_HIDDEN FlickrWindow::Private
{
public:
explicit Private()
{
uploadCount = 0;
uploadTotal = 0;
newAlbumBtn = 0;
changeUserButton = 0;
removeAccount = 0;
albumsListComboBox = 0;
publicCheckBox = 0;
familyCheckBox = 0;
friendsCheckBox = 0;
exportHostTagsCheckBox = 0;
stripSpaceTagsCheckBox = 0;
addExtraTagsCheckBox = 0;
originalCheckBox = 0;
resizeCheckBox = 0;
dimensionSpinBox = 0;
imageQualitySpinBox = 0;
extendedPublicationButton = 0;
extendedTagsButton = 0;
contentTypeComboBox = 0;
safetyLevelComboBox = 0;
userNameDisplayLabel = 0;
authProgressDlg = 0;
tagsLineEdit = 0;
widget = 0;
talker = 0;
imglst = 0;
select = 0;
albumDlg = 0;
iface = 0;
}
unsigned int uploadCount;
unsigned int uploadTotal;
QString serviceName;
QPushButton* newAlbumBtn;
QPushButton* changeUserButton;
QPushButton* removeAccount;
QComboBox* albumsListComboBox;
QCheckBox* publicCheckBox;
QCheckBox* familyCheckBox;
QCheckBox* friendsCheckBox;
QCheckBox* exportHostTagsCheckBox;
QCheckBox* stripSpaceTagsCheckBox;
QCheckBox* addExtraTagsCheckBox;
QCheckBox* originalCheckBox;
QCheckBox* resizeCheckBox;
QSpinBox* dimensionSpinBox;
QSpinBox* imageQualitySpinBox;
QPushButton* extendedPublicationButton;
QPushButton* extendedTagsButton;
WSComboBoxIntermediate* contentTypeComboBox;
WSComboBoxIntermediate* safetyLevelComboBox;
QString username;
QString userId;
QString lastSelectedAlbum;
QLabel* userNameDisplayLabel;
QProgressDialog* authProgressDlg;
QList< QPair > uploadQueue;
QLineEdit* tagsLineEdit;
FlickrWidget* widget;
FlickrTalker* talker;
FlickrList* imglst;
WSSelectUserDlg* select;
FlickrNewAlbumDlg* albumDlg;
DInfoInterface* iface;
};
FlickrWindow::FlickrWindow(DInfoInterface* const iface,
QWidget* const /*parent*/,
const QString& serviceName)
: WSToolDialog(0),
d(new Private)
{
d->iface = iface;
d->serviceName = serviceName;
setWindowTitle(i18n("Export to %1 Web Service", d->serviceName));
setModal(false);
KConfig config;
KConfigGroup grp = config.group(QString::fromLatin1("%1Export Settings").arg(d->serviceName));
if (grp.exists())
{
qCDebug(DIGIKAM_WEBSERVICES_LOG) << QString::fromLatin1("%1Export Settings").arg(d->serviceName) << " exists, deleting it";
grp.deleteGroup();
}
d->select = new WSSelectUserDlg(0, serviceName);
d->uploadCount = 0;
d->uploadTotal = 0;
d->widget = new FlickrWidget(this, iface, serviceName);
d->albumDlg = new FlickrNewAlbumDlg(this, QLatin1String("Flickr"));
d->albumsListComboBox = d->widget->getAlbumsCoB();
d->newAlbumBtn = d->widget->getNewAlbmBtn();
d->originalCheckBox = d->widget->getOriginalCheckBox();
d->resizeCheckBox = d->widget->getResizeCheckBox();
d->publicCheckBox = d->widget->d->publicCheckBox;
d->familyCheckBox = d->widget->d->familyCheckBox;
d->friendsCheckBox = d->widget->d->friendsCheckBox;
d->dimensionSpinBox = d->widget->getDimensionSpB();
d->imageQualitySpinBox = d->widget->getImgQualitySpB();
d->extendedTagsButton = d->widget->d->extendedTagsButton;
d->addExtraTagsCheckBox = d->widget->d->addExtraTagsCheckBox;
d->extendedPublicationButton = d->widget->d->extendedPublicationButton;
d->safetyLevelComboBox = d->widget->d->safetyLevelComboBox;
d->contentTypeComboBox = d->widget->d->contentTypeComboBox;
d->tagsLineEdit = d->widget->d->tagsLineEdit;
d->exportHostTagsCheckBox = d->widget->d->exportHostTagsCheckBox;
d->stripSpaceTagsCheckBox = d->widget->d->stripSpaceTagsCheckBox;
d->changeUserButton = d->widget->getChangeUserBtn();
d->removeAccount = d->widget->d->removeAccount;
d->userNameDisplayLabel = d->widget->getUserNameLabel();
d->imglst = d->widget->d->imglst;
startButton()->setText(i18n("Start Uploading"));
startButton()->setToolTip(QString());
setMainWidget(d->widget);
d->widget->setMinimumSize(800, 600);
connect(d->imglst, SIGNAL(signalImageListChanged()),
this, SLOT(slotImageListChanged()));
// --------------------------------------------------------------------------
d->talker = new FlickrTalker(this, serviceName, d->iface);
connect(d->talker, SIGNAL(signalError(QString)),
d->talker, SLOT(slotError(QString)));
connect(d->talker, SIGNAL(signalBusy(bool)),
this, SLOT(slotBusy(bool)));
connect(d->talker, SIGNAL(signalAddPhotoSucceeded(QString)),
this, SLOT(slotAddPhotoSucceeded(QString)));
connect(d->talker, SIGNAL(signalAddPhotoFailed(QString)),
this, SLOT(slotAddPhotoFailed(QString)));
connect(d->talker, SIGNAL(signalAddPhotoSetSucceeded()),
this, SLOT(slotAddPhotoSetSucceeded()));
connect(d->talker, SIGNAL(signalListPhotoSetsSucceeded()),
this, SLOT(slotPopulatePhotoSetComboBox()));
connect(d->talker, SIGNAL(signalListPhotoSetsFailed(QString)),
this, SLOT(slotListPhotoSetsFailed(QString)));
connect(d->talker, SIGNAL(signalLinkingSucceeded()),
this, SLOT(slotLinkingSucceeded()));
connect(d->widget->progressBar(), SIGNAL(signalProgressCanceled()),
this, SLOT(slotAddPhotoCancelAndClose()));
connect(d->widget->getReloadBtn(), SIGNAL(clicked()),
this, SLOT(slotReloadPhotoSetRequest()));
// --------------------------------------------------------------------------
connect(d->changeUserButton, SIGNAL(clicked()),
this, SLOT(slotUserChangeRequest()));
connect(d->removeAccount, SIGNAL(clicked()),
this, SLOT(slotRemoveAccount()));
connect(d->newAlbumBtn, SIGNAL(clicked()),
this, SLOT(slotCreateNewPhotoSet()));
// --------------------------------------------------------------------------
d->authProgressDlg = new QProgressDialog(this);
d->authProgressDlg->setModal(true);
d->authProgressDlg->setAutoReset(true);
d->authProgressDlg->setAutoClose(true);
d->authProgressDlg->setMaximum(0);
d->authProgressDlg->reset();
connect(d->authProgressDlg, SIGNAL(canceled()),
this, SLOT(slotAuthCancel()));
d->talker->m_authProgressDlg = d->authProgressDlg;
// --------------------------------------------------------------------------
connect(this, &QDialog::finished,
this, &FlickrWindow::slotFinished);
connect(this, SIGNAL(cancelClicked()),
this, SLOT(slotCancelClicked()));
connect(startButton(), &QPushButton::clicked,
this, &FlickrWindow::slotUser1);
d->select->reactivate();
readSettings(d->select->getUserName());
d->talker->link(d->select->getUserName());
}
FlickrWindow::~FlickrWindow()
{
delete d->select;
delete d->authProgressDlg;
delete d->talker;
delete d->widget;
delete d;
}
void FlickrWindow::setItemsList(const QList& urls)
{
d->widget->imagesList()->slotAddImages(urls);
}
void FlickrWindow::closeEvent(QCloseEvent* e)
{
if (!e)
{
return;
}
slotFinished();
e->accept();
}
void FlickrWindow::slotFinished()
{
writeSettings();
d->imglst->listView()->clear();
}
void FlickrWindow::setUiInProgressState(bool inProgress)
{
setRejectButtonMode(inProgress ? QDialogButtonBox::Cancel : QDialogButtonBox::Close);
if (inProgress)
{
d->widget->progressBar()->show();
}
else
{
d->widget->progressBar()->hide();
d->widget->progressBar()->progressCompleted();
}
}
void FlickrWindow::slotCancelClicked()
{
d->talker->cancel();
d->uploadQueue.clear();
setUiInProgressState(false);
}
void FlickrWindow::slotAddPhotoCancelAndClose()
{
writeSettings();
d->imglst->listView()->clear();
d->uploadQueue.clear();
d->widget->progressBar()->reset();
setUiInProgressState(false);
d->talker->cancel();
reject();
}
void FlickrWindow::reactivate()
{
d->userNameDisplayLabel->setText(QString());
readSettings(d->select->getUserName());
d->talker->link(d->select->getUserName());
d->widget->d->imglst->loadImagesFromCurrentSelection();
show();
}
void FlickrWindow::readSettings(QString uname)
{
KConfig config;
QString groupName = QString::fromLatin1("%1%2Export Settings").arg(d->serviceName, uname);
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Group name is:" << groupName;
KConfigGroup grp = config.group(groupName);
d->exportHostTagsCheckBox->setChecked(grp.readEntry("Export Host Tags", false));
d->extendedTagsButton->setChecked(grp.readEntry("Show Extended Tag Options", false));
d->addExtraTagsCheckBox->setChecked(grp.readEntry("Add Extra Tags", false));
d->stripSpaceTagsCheckBox->setChecked(grp.readEntry("Strip Space From Tags", false));
d->publicCheckBox->setChecked(grp.readEntry("Public Sharing", false));
d->familyCheckBox->setChecked(grp.readEntry("Family Sharing", false));
d->friendsCheckBox->setChecked(grp.readEntry("Friends Sharing", false));
d->extendedPublicationButton->setChecked(grp.readEntry("Show Extended Publication Options", false));
int safetyLevel = d->safetyLevelComboBox->findData(QVariant(grp.readEntry("Safety Level", 0)));
if (safetyLevel == -1)
{
safetyLevel = 0;
}
d->safetyLevelComboBox->setCurrentIndex(safetyLevel);
int contentType = d->contentTypeComboBox->findData(QVariant(grp.readEntry("Content Type", 0)));
if (contentType == -1)
{
contentType = 0;
}
d->contentTypeComboBox->setCurrentIndex(contentType);
d->originalCheckBox->setChecked(grp.readEntry("Upload Original", false));
d->resizeCheckBox->setChecked(grp.readEntry("Resize", false));
d->dimensionSpinBox->setValue(grp.readEntry("Maximum Width", 1600));
d->imageQualitySpinBox->setValue(grp.readEntry("Image Quality", 85));
winId();
KConfigGroup dialogGroup = config.group(QString::fromLatin1("%1Export Dialog").arg(d->serviceName));
KWindowConfig::restoreWindowSize(windowHandle(), dialogGroup);
resize(windowHandle()->size());
}
void FlickrWindow::writeSettings()
{
KConfig config;
QString groupName = QString::fromLatin1("%1%2Export Settings").arg(d->serviceName, d->username);
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Group name is:" << groupName;
if (QString::compare(QString::fromLatin1("%1Export Settings").arg(d->serviceName), groupName) == 0)
{
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Not writing entry of group" << groupName;
return;
}
KConfigGroup grp = config.group(groupName);
grp.writeEntry("username", d->username);
grp.writeEntry("Export Host Tags", d->exportHostTagsCheckBox->isChecked());
grp.writeEntry("Show Extended Tag Options", d->extendedTagsButton->isChecked());
grp.writeEntry("Add Extra Tags", d->addExtraTagsCheckBox->isChecked());
grp.writeEntry("Strip Space From Tags", d->stripSpaceTagsCheckBox->isChecked());
grp.writeEntry("Public Sharing", d->publicCheckBox->isChecked());
grp.writeEntry("Family Sharing", d->familyCheckBox->isChecked());
grp.writeEntry("Friends Sharing", d->friendsCheckBox->isChecked());
grp.writeEntry("Show Extended Publication Options", d->extendedPublicationButton->isChecked());
int safetyLevel = d->safetyLevelComboBox->itemData(d->safetyLevelComboBox->currentIndex()).toInt();
grp.writeEntry("Safety Level", safetyLevel);
int contentType = d->contentTypeComboBox->itemData(d->contentTypeComboBox->currentIndex()).toInt();
grp.writeEntry("Content Type", contentType);
grp.writeEntry("Resize", d->resizeCheckBox->isChecked());
grp.writeEntry("Upload Original", d->originalCheckBox->isChecked());
grp.writeEntry("Maximum Width", d->dimensionSpinBox->value());
grp.writeEntry("Image Quality", d->imageQualitySpinBox->value());
KConfigGroup dialogGroup = config.group(QString::fromLatin1("%1Export Dialog").arg(d->serviceName));
KWindowConfig::saveWindowSize(windowHandle(), dialogGroup);
config.sync();
}
void FlickrWindow::slotLinkingSucceeded()
{
d->username = d->talker->getUserName();
d->userId = d->talker->getUserId();
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "SlotLinkingSucceeded invoked setting user Display name to" << d->username;
d->userNameDisplayLabel->setText(QString::fromLatin1("%1").arg(d->username));
KConfig config;
foreach(const QString& group, config.groupList())
{
if (!(group.contains(d->serviceName)))
continue;
KConfigGroup grp = config.group(group);
if (group.contains(d->username))
{
readSettings(d->username);
break;
}
}
writeSettings();
d->talker->listPhotoSets();
}
void FlickrWindow::slotBusy(bool val)
{
if (val)
{
setCursor(Qt::WaitCursor);
}
else
{
setCursor(Qt::ArrowCursor);
}
}
void FlickrWindow::slotError(const QString& msg)
{
QMessageBox::critical(this, i18n("Error"), msg);
}
void FlickrWindow::slotUserChangeRequest()
{
writeSettings();
d->userNameDisplayLabel->setText(QString());
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Slot Change User Request";
d->select->reactivate();
readSettings(d->select->getUserName());
d->talker->link(d->select->getUserName());
}
void FlickrWindow::slotRemoveAccount()
{
KConfig config;
QString groupName = QString::fromLatin1("%1%2Export Settings").arg(d->serviceName, d->username);
KConfigGroup grp = config.group(groupName);
if (grp.exists())
{
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Removing Account having group" << groupName;
grp.deleteGroup();
}
d->talker->unLink();
d->talker->removeUserName(d->serviceName + d->username);
d->userNameDisplayLabel->setText(QString());
d->username = QString();
}
/**
* Try to guess a sensible set name from the urls given.
* Currently, it extracs the last path name component, and returns the most
* frequently seen. The function could be expanded to, for example, only
* accept the path if it occurs at least 50% of the time. It could also look
* further up in the path name.
*/
QString FlickrWindow::guessSensibleSetName(const QList& urlList) const
{
QMap nrFolderOccurences;
// Extract last component of directory
foreach(const QUrl& url, urlList)
{
QString dir = url.adjusted(QUrl::RemoveFilename | QUrl::StripTrailingSlash).toLocalFile();
QStringList list = dir.split(QLatin1Char('/'));
if (list.isEmpty())
continue;
nrFolderOccurences[list.last()]++;
}
int maxCount = 0;
int totalCount = 0;
QString name;
for (QMap::const_iterator it = nrFolderOccurences.constBegin();
it != nrFolderOccurences.constEnd() ; ++it)
{
totalCount += it.value();
if (it.value() > maxCount)
{
maxCount = it.value();
name = it.key();
}
}
// If there is only one entry or one name appears at least twice, return the suggestion
if (totalCount == 1 || maxCount > 1)
return name;
return QString();
}
/** This method is called when the photo set creation button is pressed. It
* summons a creation dialog for user input. When that is closed, it
* creates a new photo set in the local list. The id gets the form of
* UNDEFINED_ followed by a number, to indicate that it doesn't exist on
* Flickr yet.
*/
void FlickrWindow::slotCreateNewPhotoSet()
{
if (d->albumDlg->exec() == QDialog::Accepted)
{
FPhotoSet fps;
d->albumDlg->getFolderProperties(fps);
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "in slotCreateNewPhotoSet()" << fps.title;
// Lets find an UNDEFINED_ style id that isn't taken yet.s
QString id;
int i = 0;
id = QLatin1String("UNDEFINED_") + QString::number(i);
QLinkedList::iterator it = d->talker->m_photoSetsList->begin();
while (it != d->talker->m_photoSetsList->end())
{
FPhotoSet fps = *it;
if (fps.id == id)
{
id = QLatin1String("UNDEFINED_") + QString::number(++i);
it = d->talker->m_photoSetsList->begin();
}
++it;
}
fps.id = id;
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Created new photoset with temporary id" << id;
// Append the new photoset to the list.
d->talker->m_photoSetsList->prepend(fps);
d->talker->m_selectedPhotoSet = fps;
// Re-populate the photo sets combo box.
slotPopulatePhotoSetComboBox();
}
else
{
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "New Photoset creation aborted";
}
}
void FlickrWindow::slotAuthCancel()
{
d->talker->cancel();
d->authProgressDlg->hide();
}
void FlickrWindow::slotPopulatePhotoSetComboBox()
{
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "slotPopulatePhotoSetComboBox invoked";
if (d->talker && d->talker->m_photoSetsList)
{
QLinkedList * const list = d->talker->m_photoSetsList;
d->albumsListComboBox->clear();
d->albumsListComboBox->insertItem(0, i18n("Photostream Only"));
d->albumsListComboBox->insertSeparator(1);
QLinkedList::iterator it = list->begin();
int index = 2;
int curr_index = 0;
while (it != list->end())
{
FPhotoSet photoSet = *it;
QString name = photoSet.title;
// Store the id as user data, because the title is not unique.
QVariant id = QVariant(photoSet.id);
if (id == d->talker->m_selectedPhotoSet.id)
{
curr_index = index;
}
d->albumsListComboBox->insertItem(index++, name, id);
++it;
}
d->albumsListComboBox->setCurrentIndex(curr_index);
}
}
/** This slot is call when 'Start Uploading' button is pressed.
*/
void FlickrWindow::slotUser1()
{
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "SlotUploadImages invoked";
//d->widget->d->tab->setCurrentIndex(FlickrWidget::FILELIST);
if (d->imglst->imageUrls().isEmpty())
{
return;
}
typedef QPair Pair;
d->uploadQueue.clear();
for (int i = 0 ; i < d->imglst->listView()->topLevelItemCount() ; ++i)
{
FlickrListViewItem* const lvItem = dynamic_cast(d->imglst->listView()->topLevelItem(i));
if (lvItem)
{
DItemInfo info(d->iface->itemInfo(lvItem->url()));
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Adding images" << lvItem->url() << " to the list";
FPhotoInfo temp;
temp.title = info.title();
temp.description = info.comment();
temp.size = info.fileSize();
temp.is_public = lvItem->isPublic() ? 1 : 0;
temp.is_family = lvItem->isFamily() ? 1 : 0;
temp.is_friend = lvItem->isFriends() ? 1 : 0;
temp.safety_level = lvItem->safetyLevel();
temp.content_type = lvItem->contentType();
QStringList tagsFromDialog = d->tagsLineEdit->text().split(QLatin1Char(','), QString::SkipEmptyParts);
QStringList tagsFromList = lvItem->extraTags();
QStringList allTags;
QStringList::Iterator itTags;
// Tags from the dialog
itTags = tagsFromDialog.begin();
while (itTags != tagsFromDialog.end())
{
allTags.append(*itTags);
++itTags;
}
// Tags from the database
if (d->exportHostTagsCheckBox->isChecked())
{
QStringList tagsFromDatabase;
tagsFromDatabase = info.keywords();
itTags = tagsFromDatabase.begin();
while (itTags != tagsFromDatabase.end())
{
allTags.append(*itTags);
++itTags;
}
}
// Tags from the list view.
itTags = tagsFromList.begin();
while (itTags != tagsFromList.end())
{
allTags.append(*itTags);
++itTags;
}
// Remove spaces if the user doesn't like them.
if (d->stripSpaceTagsCheckBox->isChecked())
{
for (QStringList::iterator it = allTags.begin();
it != allTags.end();
++it)
{
*it = (*it).trimmed().remove(QLatin1Char(' '));
}
}
// Debug the tag list.
itTags = allTags.begin();
while (itTags != allTags.end())
{
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Tags list:" << (*itTags);
++itTags;
}
temp.tags = allTags;
d->uploadQueue.append(Pair(lvItem->url(), temp));
}
}
d->uploadTotal = d->uploadQueue.count();
d->uploadCount = 0;
d->widget->progressBar()->reset();
slotAddPhotoNext();
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "SlotUploadImages done";
}
void FlickrWindow::slotAddPhotoNext()
{
if (d->uploadQueue.isEmpty())
{
d->widget->progressBar()->reset();
setUiInProgressState(false);
return;
}
typedef QPair Pair;
Pair pathComments = d->uploadQueue.first();
FPhotoInfo info = pathComments.second;
QString selectedPhotoSetId = d->albumsListComboBox->itemData(d->albumsListComboBox->currentIndex()).toString();
if (selectedPhotoSetId.isEmpty())
{
d->talker->m_selectedPhotoSet = FPhotoSet();
}
else
{
QLinkedList::iterator it = d->talker->m_photoSetsList->begin();
while (it != d->talker->m_photoSetsList->end())
{
if (it->id == selectedPhotoSetId)
{
d->talker->m_selectedPhotoSet = *it;
break;
}
++it;
}
}
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Max allowed file size is:"
<< d->talker->getMaxAllowedFileSize().toLongLong()
<< "File Size is" << info.size;
bool res = d->talker->addPhoto(pathComments.first.toLocalFile(), //the file path
info,
d->originalCheckBox->isChecked(),
d->resizeCheckBox->isChecked(),
d->dimensionSpinBox->value(),
d->imageQualitySpinBox->value());
if (!res)
{
slotAddPhotoFailed(QLatin1String(""));
return;
}
if (d->widget->progressBar()->isHidden())
{
setUiInProgressState(true);
d->widget->progressBar()->progressScheduled(i18n("Flickr Export"), true, true);
- d->widget->progressBar()->progressThumbnailChanged(QIcon(QLatin1String("flickr")).pixmap(22, 22));
+ d->widget->progressBar()->progressThumbnailChanged(QIcon(QLatin1String("dk-flickr")).pixmap(22, 22));
}
}
void FlickrWindow::slotAddPhotoSucceeded(const QString& photoId)
{
QUrl photoUrl = d->uploadQueue.first().first;
// Set location for uploaded photo
DItemInfo info(d->iface->itemInfo(photoUrl));
if (info.hasGeolocationInfo() && !photoId.isEmpty())
{
d->talker->setGeoLocation(photoId,
QString::number(info.latitude()),
QString::number(info.longitude()));
return;
}
// Remove photo uploaded from the list
d->imglst->removeItemByUrl(photoUrl);
d->uploadQueue.removeFirst();
d->uploadCount++;
d->widget->progressBar()->setMaximum(d->uploadTotal);
d->widget->progressBar()->setValue(d->uploadCount);
slotAddPhotoNext();
}
void FlickrWindow::slotListPhotoSetsFailed(const QString& msg)
{
QMessageBox::critical(this, QLatin1String("Error"),
i18n("Failed to Fetch Photoset information from %1. %2\n",
d->serviceName, msg));
}
void FlickrWindow::slotAddPhotoFailed(const QString& msg)
{
QPointer warn = new QMessageBox(QMessageBox::Warning,
i18n("Warning"),
i18n("Failed to upload photo into %1. %2\nDo you want to continue?",
d->serviceName, msg),
QMessageBox::Yes | QMessageBox::No);
(warn->button(QMessageBox::Yes))->setText(i18n("Continue"));
(warn->button(QMessageBox::No))->setText(i18n("Cancel"));
if (warn->exec() != QMessageBox::Yes)
{
d->uploadQueue.clear();
d->widget->progressBar()->reset();
setUiInProgressState(false);
}
else
{
d->uploadQueue.removeFirst();
d->uploadTotal--;
d->widget->progressBar()->setMaximum(d->uploadTotal);
d->widget->progressBar()->setValue(d->uploadCount);
slotAddPhotoNext();
}
delete warn;
}
/* Method called when a photo set has been successfully created on Flickr.
* It functions to restart the normal flow after a photo set has been created
* on Flickr.
*/
void FlickrWindow::slotAddPhotoSetSucceeded()
{
slotPopulatePhotoSetComboBox();
slotAddPhotoSucceeded(QLatin1String(""));
}
void FlickrWindow::slotImageListChanged()
{
startButton()->setEnabled(!(d->widget->d->imglst->imageUrls().isEmpty()));
}
void FlickrWindow::slotReloadPhotoSetRequest()
{
d->talker->listPhotoSets();
}
} // namespace Digikam
diff --git a/core/utilities/assistants/webservices/google/gswindow.cpp b/core/utilities/assistants/webservices/google/gswindow.cpp
index 13c249bd45..de1c075e6f 100644
--- a/core/utilities/assistants/webservices/google/gswindow.cpp
+++ b/core/utilities/assistants/webservices/google/gswindow.cpp
@@ -1,1389 +1,1389 @@
/* ============================================================
*
* This file is a part of digiKam project
* http://www.digikam.org
*
* Date : 2013-11-18
* Description : a tool to export items to Google web services
*
* Copyright (C) 2013 by Pankaj Kumar
* Copyright (C) 2015 by Shourya Singh Gupta
* Copyright (C) 2013-2018 by Caulier Gilles
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General
* Public License as published by the Free Software Foundation;
* either version 2, 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.
*
* ============================================================ */
#include "gswindow.h"
// Qt includes
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
// KDE includes
#include
#include
#include
// Local includes
#include "wstoolutils.h"
#include "ditemslist.h"
#include "digikam_version.h"
#include "dprogresswdg.h"
#include "gdtalker.h"
#include "gsitem.h"
#include "gsnewalbumdlg.h"
#include "gswidget.h"
#include "gptalker.h"
#include "gsreplacedlg.h"
#include "digikam_debug.h"
namespace Digikam
{
class Q_DECL_HIDDEN GSWindow::Private
{
public:
explicit Private()
{
widget = 0;
albumDlg = 0;
gphotoAlbumDlg = 0;
talker = 0;
gphotoTalker = 0;
iface = 0;
imagesCount = 0;
imagesTotal = 0;
renamingOpt = 0;
service = GoogleService::GPhotoImport;
}
unsigned int imagesCount;
unsigned int imagesTotal;
int renamingOpt;
QString serviceName;
QString toolName;
GoogleService service;
QString tmp;
GSWidget* widget;
GSNewAlbumDlg* albumDlg;
GSNewAlbumDlg* gphotoAlbumDlg;
GDTalker* talker;
GPTalker* gphotoTalker;
QString currentAlbumId;
QList< QPair > transferQueue;
QList< QPair > uploadQueue;
DInfoInterface* iface;
DMetadata meta;
};
GSWindow::GSWindow(DInfoInterface* const iface,
QWidget* const /*parent*/,
const QString& serviceName)
: WSToolDialog(0),
d(new Private)
{
d->iface = iface;
d->serviceName = serviceName;
if (QString::compare(d->serviceName, QLatin1String("googledriveexport"),
Qt::CaseInsensitive) == 0)
{
d->service = GoogleService::GDrive;
d->toolName = QLatin1String("Google Drive");
}
else if (QString::compare(d->serviceName, QLatin1String("googlephotoexport"),
Qt::CaseInsensitive) == 0)
{
d->service = GoogleService::GPhotoExport;
d->toolName = QLatin1String("Google Photos/PicasaWeb");
}
else
{
d->service = GoogleService::GPhotoImport;
d->toolName = QLatin1String("Google Photos/PicasaWeb");
}
d->tmp = WSToolUtils::makeTemporaryDir("google").absolutePath() + QLatin1Char('/');;
d->widget = new GSWidget(this, d->iface, d->service, d->toolName);
setMainWidget(d->widget);
setModal(false);
switch (d->service)
{
case GoogleService::GDrive:
setWindowTitle(i18n("Export to Google Drive"));
startButton()->setText(i18n("Start Upload"));
startButton()->setToolTip(i18n("Start upload to Google Drive"));
d->widget->setMinimumSize(700,500);
d->albumDlg = new GSNewAlbumDlg(this, d->serviceName, d->toolName);
d->talker = new GDTalker(this);
connect(d->talker,SIGNAL(signalBusy(bool)),
this,SLOT(slotBusy(bool)));
connect(d->talker,SIGNAL(signalAccessTokenObtained()),
this,SLOT(slotAccessTokenObtained()));
connect(d->talker, SIGNAL(signalAuthenticationRefused()),
this,SLOT(slotAuthenticationRefused()));
connect(d->talker,SIGNAL(signalSetUserName(QString)),
this,SLOT(slotSetUserName(QString)));
connect(d->talker,SIGNAL(signalListAlbumsDone(int,QString,QList)),
this,SLOT(slotListAlbumsDone(int,QString,QList)));
connect(d->talker,SIGNAL(signalCreateFolderDone(int,QString)),
this,SLOT(slotCreateFolderDone(int,QString)));
connect(d->talker,SIGNAL(signalAddPhotoDone(int,QString)),
this,SLOT(slotAddPhotoDone(int,QString)));
connect(d->talker, SIGNAL(signalUploadPhotoDone(int,QString,QStringList)),
this, SLOT(slotUploadPhotoDone(int,QString,QStringList)));
readSettings();
buttonStateChange(false);
d->talker->doOAuth();
break;
case GoogleService::GPhotoImport:
case GoogleService::GPhotoExport:
if (d->service == GoogleService::GPhotoExport)
{
setWindowTitle(i18n("Export to Google Photos/PicasaWeb Service"));
startButton()->setText(i18n("Start Upload"));
startButton()->setToolTip(i18n("Start upload to Google Photos/PicasaWeb Service"));
d->widget->setMinimumSize(700, 500);
}
else
{
setWindowTitle(i18n("Import from Google Photos/PicasaWeb Service"));
startButton()->setText(i18n("Start Download"));
startButton()->setToolTip(i18n("Start download from Google Photos/PicasaWeb service"));
d->widget->setMinimumSize(300, 400);
}
d->gphotoAlbumDlg = new GSNewAlbumDlg(this, d->serviceName, d->toolName);
d->gphotoTalker = new GPTalker(this);
connect(d->gphotoTalker, SIGNAL(signalBusy(bool)),
this, SLOT(slotBusy(bool)));
connect(d->gphotoTalker,SIGNAL(signalSetUserName(QString)),
this,SLOT(slotSetUserName(QString)));
connect(d->gphotoTalker, SIGNAL(signalAccessTokenObtained()),
this, SLOT(slotAccessTokenObtained()));
connect(d->gphotoTalker, SIGNAL(signalAuthenticationRefused()),
this,SLOT(slotAuthenticationRefused()));
connect(d->gphotoTalker, SIGNAL(signalListAlbumsDone(int,QString,QList)),
this, SLOT(slotListAlbumsDone(int,QString,QList)));
connect(d->gphotoTalker, SIGNAL(signalCreateAlbumDone(int,QString,QString)),
this, SLOT(slotCreateFolderDone(int,QString,QString)));
connect(d->gphotoTalker, SIGNAL(signalAddPhotoDone(int,QString)),
this, SLOT(slotAddPhotoDone(int,QString)));
connect(d->gphotoTalker, SIGNAL(signalUploadPhotoDone(int,QString,QStringList)),
this, SLOT(slotUploadPhotoDone(int,QString,QStringList)));
connect(d->gphotoTalker, SIGNAL(signalGetPhotoDone(int,QString,QByteArray)),
this, SLOT(slotGetPhotoDone(int,QString,QByteArray)));
readSettings();
buttonStateChange(false);
d->gphotoTalker->doOAuth();
break;
}
connect(d->widget->imagesList(), SIGNAL(signalImageListChanged()),
this, SLOT(slotImageListChanged()));
connect(d->widget->getChangeUserBtn(), SIGNAL(clicked()),
this, SLOT(slotUserChangeRequest()));
connect(d->widget->getNewAlbmBtn(), SIGNAL(clicked()),
this,SLOT(slotNewAlbumRequest()));
connect(d->widget->getReloadBtn(), SIGNAL(clicked()),
this, SLOT(slotReloadAlbumsRequest()));
connect(startButton(), SIGNAL(clicked()),
this, SLOT(slotStartTransfer()));
connect(this, SIGNAL(finished(int)),
this, SLOT(slotFinished()));
}
GSWindow::~GSWindow()
{
delete d->widget;
delete d->albumDlg;
delete d->gphotoAlbumDlg;
delete d->talker;
delete d->gphotoTalker;
delete d;
}
void GSWindow::reactivate()
{
d->widget->imagesList()->loadImagesFromCurrentSelection();
d->widget->progressBar()->hide();
show();
}
void GSWindow::readSettings()
{
KConfig config;
KConfigGroup grp;
switch (d->service)
{
case GoogleService::GDrive:
grp = config.group("Google Drive Settings");
break;
default:
grp = config.group("Google Photo Settings");
break;
}
d->currentAlbumId = grp.readEntry("Current Album",QString());
if (grp.readEntry("Resize", false))
{
d->widget->getResizeCheckBox()->setChecked(true);
d->widget->getDimensionSpB()->setEnabled(true);
}
else
{
d->widget->getResizeCheckBox()->setChecked(false);
d->widget->getDimensionSpB()->setEnabled(false);
}
d->widget->getDimensionSpB()->setValue(grp.readEntry("Maximum Width", 1600));
d->widget->getImgQualitySpB()->setValue(grp.readEntry("Image Quality", 90));
if (d->service == GoogleService::GPhotoExport && d->widget->m_tagsBGrp)
{
d->widget->m_tagsBGrp->button(grp.readEntry("Tag Paths", 0))->setChecked(true);
}
KConfigGroup dialogGroup;
switch (d->service)
{
case GoogleService::GDrive:
dialogGroup = config.group("Google Drive Export Dialog");
break;
case GoogleService::GPhotoExport:
dialogGroup = config.group("Google Photo Export Dialog");
break;
case GoogleService::GPhotoImport:
dialogGroup = config.group("Google Photo Import Dialog");
break;
}
winId();
KWindowConfig::restoreWindowSize(windowHandle(), dialogGroup);
resize(windowHandle()->size());
}
void GSWindow::writeSettings()
{
KConfig config;
KConfigGroup grp;
switch (d->service)
{
case GoogleService::GDrive:
grp = config.group("Google Drive Settings");
break;
default:
grp = config.group("Google Photo Settings");
break;
}
grp.writeEntry("Current Album", d->currentAlbumId);
grp.writeEntry("Resize", d->widget->getResizeCheckBox()->isChecked());
grp.writeEntry("Maximum Width", d->widget->getDimensionSpB()->value());
grp.writeEntry("Image Quality", d->widget->getImgQualitySpB()->value());
if (d->service == GoogleService::GPhotoExport && d->widget->m_tagsBGrp)
{
grp.writeEntry("Tag Paths", d->widget->m_tagsBGrp->checkedId());
}
KConfigGroup dialogGroup;
switch (d->service)
{
case GoogleService::GDrive:
dialogGroup = config.group("Google Drive Export Dialog");
break;
case GoogleService::GPhotoExport:
dialogGroup = config.group("Google Photo Export Dialog");
break;
case GoogleService::GPhotoImport:
dialogGroup = config.group("Google Photo Import Dialog");
break;
}
KWindowConfig::saveWindowSize(windowHandle(), dialogGroup);
config.sync();
}
void GSWindow::slotSetUserName(const QString& msg)
{
d->widget->updateLabels(msg);
}
void GSWindow::slotListPhotosDoneForDownload(int errCode,
const QString& errMsg,
const QList & photosList)
{
disconnect(d->gphotoTalker, SIGNAL(signalListPhotosDone(int,QString,QList)),
this, SLOT(slotListPhotosDoneForDownload(int,QString,QList)));
if (errCode == 0)
{
QMessageBox::critical(this, i18nc("@title:window", "Error"),
i18n("Google Photos/PicasaWeb Call Failed: %1\n", errMsg));
return;
}
typedef QPair Pair;
d->transferQueue.clear();
QList::const_iterator itPWP;
for (itPWP = photosList.begin() ; itPWP != photosList.end() ; ++itPWP)
{
d->transferQueue.append(Pair((*itPWP).originalURL, (*itPWP)));
}
if (d->transferQueue.isEmpty())
return;
d->currentAlbumId = d->widget->getAlbumsCoB()->itemData(d->widget->getAlbumsCoB()->currentIndex()).toString();
d->imagesTotal = d->transferQueue.count();
d->imagesCount = 0;
d->widget->progressBar()->setFormat(i18n("%v / %m"));
d->widget->progressBar()->show();
d->renamingOpt = 0;
// start download with first photo in queue
downloadNextPhoto();
}
void GSWindow::slotListPhotosDoneForUpload(int errCode,
const QString& errMsg,
const QList & photosList)
{
qCCritical(DIGIKAM_WEBSERVICES_LOG)<< "err Code is "<< errCode <<" Err Message is "<< errMsg;
disconnect(d->gphotoTalker, SIGNAL(signalListPhotosDone(int,QString,QList)),
this, SLOT(slotListPhotosDoneForUpload(int,QString,QList)));
if (errCode == 0)
{
QMessageBox::critical(this, i18nc("@title:window", "Error"),
i18n("Google Photos/PicasaWeb Call Failed: %1\n", errMsg));
return;
}
typedef QPair Pair;
d->transferQueue.clear();
QList urlList = d->widget->imagesList()->imageUrls(true);
if (urlList.isEmpty())
return;
for (QList::ConstIterator it = urlList.constBegin() ; it != urlList.constEnd() ; ++it)
{
DItemInfo info(d->iface->itemInfo((*it)));
GSPhoto temp;
temp.title = info.name();
// Google Photo doesn't support image titles. Include it in descriptions if needed.
QStringList descriptions = QStringList() << info.title() << info.comment();
descriptions.removeAll(QLatin1String(""));
temp.description = descriptions.join(QLatin1String("\n\n"));
// check for existing items
QString localId;
if (d->meta.load((*it).toLocalFile()))
{
localId = d->meta.getXmpTagString("Xmp.digiKam.picasawebGPhotoId");
}
QList::const_iterator itPWP;
for (itPWP = photosList.begin(); itPWP != photosList.end(); ++itPWP)
{
if ((*itPWP).id == localId)
{
temp.id = localId;
temp.editUrl = (*itPWP).editUrl;
temp.thumbURL = (*itPWP).thumbURL;
break;
}
}
// Tags from the database
temp.gpsLat.setNum(info.latitude());
temp.gpsLon.setNum(info.longitude());
temp.tags = info.tagsPath();
d->transferQueue.append(Pair((*it), temp));
}
if (d->transferQueue.isEmpty())
return;
d->currentAlbumId = d->widget->getAlbumsCoB()->itemData(d->widget->getAlbumsCoB()->currentIndex()).toString();
d->imagesTotal = d->transferQueue.count();
d->imagesCount = 0;
d->widget->progressBar()->setFormat(i18n("%v / %m"));
d->widget->progressBar()->setMaximum(d->imagesTotal);
d->widget->progressBar()->setValue(0);
d->widget->progressBar()->show();
d->widget->progressBar()->progressScheduled(i18n("Google Photo Export"), true, true);
- d->widget->progressBar()->progressThumbnailChanged(QIcon((QLatin1String("googlephoto"))).pixmap(22, 22));
+ d->widget->progressBar()->progressThumbnailChanged(QIcon((QLatin1String("dk-googlephoto"))).pixmap(22, 22));
d->renamingOpt = 0;
uploadNextPhoto();
}
void GSWindow::slotListAlbumsDone(int code, const QString& errMsg, const QList & list)
{
switch (d->service)
{
case GoogleService::GDrive:
if (code == 0)
{
QMessageBox::critical(this, i18nc("@title:window", "Error"),
i18n("Google Drive Call Failed: %1\n", errMsg));
return;
}
d->widget->getAlbumsCoB()->clear();
for (int i = 0 ; i < list.size() ; ++i)
{
d->widget->getAlbumsCoB()->addItem(QIcon::fromTheme(QLatin1String("system-users")),
list.value(i).title, list.value(i).id);
if (d->currentAlbumId == list.value(i).id)
{
d->widget->getAlbumsCoB()->setCurrentIndex(i);
}
}
buttonStateChange(true);
d->talker->getUserName();
break;
default:
if (code == 0)
{
QMessageBox::critical(this, i18nc("@title:window", "Error"),
i18n("Google Photos/PicasaWeb Call Failed: %1\n", errMsg));
return;
}
d->widget->getAlbumsCoB()->clear();
for (int i = 0 ; i < list.size() ; ++i)
{
QString albumIcon;
if (list.at(i).isWriteable)
{
albumIcon = QLatin1String("folder");
}
else
{
albumIcon = QLatin1String("folder-locked");
}
d->widget->getAlbumsCoB()->addItem(QIcon::fromTheme(albumIcon), list.at(i).title, list.at(i).id);
if (d->currentAlbumId == list.at(i).id)
d->widget->getAlbumsCoB()->setCurrentIndex(i);
buttonStateChange(true);
}
break;
}
}
void GSWindow::slotBusy(bool val)
{
if (val)
{
setCursor(Qt::WaitCursor);
d->widget->getChangeUserBtn()->setEnabled(false);
buttonStateChange(false);
}
else
{
setCursor(Qt::ArrowCursor);
d->widget->getChangeUserBtn()->setEnabled(true);
buttonStateChange(true);
}
}
void GSWindow::googlePhotoTransferHandler()
{
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Google Photo Transfer invoked";
switch (d->service)
{
case GoogleService::GPhotoImport:
// list photos of the album, then start download
connect(d->gphotoTalker, SIGNAL(signalListPhotosDone(int,QString,QList)),
this, SLOT(slotListPhotosDoneForDownload(int,QString,QList)));
d->gphotoTalker->listPhotos(
d->widget->getAlbumsCoB()->itemData(d->widget->getAlbumsCoB()->currentIndex()).toString(),
d->widget->getDimensionCoB()->itemData(d->widget->getDimensionCoB()->currentIndex()).toString());
break;
default:
// list photos of the album, then start upload with add/update items
connect(d->gphotoTalker, SIGNAL(signalListPhotosDone(int,QString,QList)),
this, SLOT(slotListPhotosDoneForUpload(int,QString,QList)));
d->gphotoTalker->listPhotos(
d->widget->getAlbumsCoB()->itemData(d->widget->getAlbumsCoB()->currentIndex()).toString());
break;
}
}
void GSWindow::slotStartTransfer()
{
d->widget->imagesList()->clearProcessedStatus();
switch (d->service)
{
case GoogleService::GDrive:
case GoogleService::GPhotoExport:
if (d->widget->imagesList()->imageUrls().isEmpty())
{
QMessageBox::critical(this, i18nc("@title:window", "Error"),
i18n("No image selected. Please select which images should be uploaded."));
return;
}
break;
case GoogleService::GPhotoImport:
break;
}
switch (d->service)
{
case GoogleService::GDrive:
if (!(d->talker->authenticated()))
{
QPointer warn = new QMessageBox(QMessageBox::Warning,
i18n("Warning"),
i18n("Authentication failed. Click \"Continue\" to authenticate."),
QMessageBox::Yes | QMessageBox::No);
(warn->button(QMessageBox::Yes))->setText(i18n("Continue"));
(warn->button(QMessageBox::No))->setText(i18n("Cancel"));
if (warn->exec() == QMessageBox::Yes)
{
d->talker->doOAuth();
delete warn;
return;
}
else
{
delete warn;
return;
}
}
break;
default:
if (!(d->gphotoTalker->authenticated()))
{
QPointer warn = new QMessageBox(QMessageBox::Warning,
i18n("Warning"),
i18n("Authentication failed. Click \"Continue\" to authenticate."),
QMessageBox::Yes | QMessageBox::No);
(warn->button(QMessageBox::Yes))->setText(i18n("Continue"));
(warn->button(QMessageBox::No))->setText(i18n("Cancel"));
if (warn->exec() == QMessageBox::Yes)
{
d->gphotoTalker->doOAuth();
delete warn;
return;
}
else
{
delete warn;
return;
}
}
/**
* (Trung) At that time, googlePhotoTransferHandler is only used for GPhotoImport,
* since we don't sync image to update in GPhotoExport
*/
if (d->service == GoogleService::GPhotoImport)
{
googlePhotoTransferHandler();
return;
}
}
typedef QPair Pair;
for (int i = 0 ; i < (d->widget->imagesList()->imageUrls().size()) ; ++i)
{
DItemInfo info(d->iface->itemInfo(d->widget->imagesList()->imageUrls().value(i)));
GSPhoto temp;
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "in start transfer info " <service)
{
case GoogleService::GDrive:
temp.title = info.title();
break;
default:
temp.title = info.name();
break;
}
temp.description = info.comment().section(QLatin1String("\n"), 0, 0);
temp.gpsLat.setNum(info.latitude());
temp.gpsLon.setNum(info.longitude());
temp.tags = info.tagsPath();
d->transferQueue.append(Pair(d->widget->imagesList()->imageUrls().value(i),temp));
}
d->currentAlbumId = d->widget->getAlbumsCoB()->itemData(d->widget->getAlbumsCoB()->currentIndex()).toString();
d->imagesTotal = d->transferQueue.count();
d->imagesCount = 0;
d->widget->progressBar()->setFormat(i18n("%v / %m"));
d->widget->progressBar()->setMaximum(d->imagesTotal);
d->widget->progressBar()->setValue(0);
d->widget->progressBar()->show();
d->widget->progressBar()->progressScheduled(i18n("Google Drive export"), true, true);
- d->widget->progressBar()->progressThumbnailChanged(QIcon(QLatin1String("googledrive")).pixmap(22, 22));
+ d->widget->progressBar()->progressThumbnailChanged(QIcon(QLatin1String("dk-googledrive")).pixmap(22, 22));
uploadNextPhoto();
}
void GSWindow::uploadNextPhoto()
{
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "in upload nextphoto " << d->transferQueue.count();
if (d->transferQueue.isEmpty())
{
//d->widget->progressBar()->hide();
d->widget->progressBar()->progressCompleted();
/**
* Now all raw photos have been added,
* for GPhoto: prepare to upload on user account
* for GDrive: get listPhotoId to write metadata and finish upload
*/
if (d->service == GoogleService::GPhotoExport)
{
emit d->gphotoTalker->signalReadyToUpload();
}
else
{
emit d->talker->signalReadyToUpload();
}
return;
}
typedef QPair Pair;
Pair pathComments = d->transferQueue.first();
GSPhoto info = pathComments.second;
bool res = true;
d->widget->imagesList()->processing(pathComments.first);
switch (d->service)
{
case GoogleService::GDrive:
{
res = d->talker->addPhoto(pathComments.first.toLocalFile(),
info,
d->currentAlbumId,
d->widget->getResizeCheckBox()->isChecked(),
d->widget->getDimensionSpB()->value(),
d->widget->getImgQualitySpB()->value());
break;
}
case GoogleService::GPhotoExport:
{
bool bCancel = false;
bool bAdd = true;
if (!info.id.isEmpty() && !info.editUrl.isEmpty())
{
switch (d->renamingOpt)
{
case PWR_ADD_ALL:
bAdd = true;
break;
case PWR_REPLACE_ALL:
bAdd = false;
break;
default:
{
QPointer dlg = new ReplaceDialog(this, QLatin1String(""),
d->iface, pathComments.first,
info.thumbURL);
dlg->exec();
switch (dlg->getResult())
{
case PWR_ADD_ALL:
d->renamingOpt = PWR_ADD_ALL;
break;
case PWR_ADD:
bAdd = true;
break;
case PWR_REPLACE_ALL:
d->renamingOpt = PWR_REPLACE_ALL;
break;
case PWR_REPLACE:
bAdd = false;
break;
case PWR_CANCEL:
default:
bCancel = true;
break;
}
delete dlg;
break;
}
}
}
// adjust tags according to radio button clicked
if (d->widget->m_tagsBGrp)
{
switch (d->widget->m_tagsBGrp->checkedId())
{
case GPTagLeaf:
{
QStringList newTags;
QStringList::const_iterator itT;
for (itT = info.tags.constBegin() ; itT != info.tags.constEnd() ; ++itT)
{
QString strTmp = *itT;
int idx = strTmp.lastIndexOf(QLatin1Char('/'));
if (idx > 0)
{
strTmp.remove(0, idx + 1);
}
newTags.append(strTmp);
}
info.tags = newTags;
break;
}
case GPTagSplit:
{
QSet newTagsSet;
QStringList::const_iterator itT;
for (itT = info.tags.constBegin() ; itT != info.tags.constEnd() ; ++itT)
{
QStringList strListTmp = itT->split(QLatin1Char('/'));
QStringList::const_iterator itT2;
for (itT2 = strListTmp.constBegin() ; itT2 != strListTmp.constEnd() ; ++itT2)
{
if (!newTagsSet.contains(*itT2))
{
newTagsSet.insert(*itT2);
}
}
}
info.tags.clear();
QSet::const_iterator itT3;
for (itT3 = newTagsSet.begin() ; itT3 != newTagsSet.end() ; ++itT3)
{
info.tags.append(*itT3);
}
break;
}
case GPTagCombined:
default:
break;
}
}
if (bCancel)
{
slotTransferCancel();
res = true;
}
else
{
if (bAdd)
{
res = d->gphotoTalker->addPhoto(pathComments.first.toLocalFile(),
info,
d->currentAlbumId,
d->widget->getResizeCheckBox()->isChecked(),
d->widget->getDimensionSpB()->value(),
d->widget->getImgQualitySpB()->value());
}
else
{
res = d->gphotoTalker->updatePhoto(pathComments.first.toLocalFile(),
info,
d->widget->getResizeCheckBox()->isChecked(),
d->widget->getDimensionSpB()->value(),
d->widget->getImgQualitySpB()->value());
}
}
break;
}
case GoogleService::GPhotoImport:
break;
}
if (!res)
{
slotAddPhotoDone(0, QLatin1String(""));
return;
}
}
void GSWindow::downloadNextPhoto()
{
if (d->transferQueue.isEmpty())
{
d->widget->progressBar()->hide();
d->widget->progressBar()->progressCompleted();
return;
}
d->widget->progressBar()->setMaximum(d->imagesTotal);
d->widget->progressBar()->setValue(d->imagesCount);
QString imgPath = d->transferQueue.first().first.url();
d->gphotoTalker->getPhoto(imgPath);
}
void GSWindow::slotGetPhotoDone(int errCode, const QString& errMsg, const QByteArray& photoData)
{
GSPhoto item = d->transferQueue.first().second;
/**
* (Trung)
* Google Photo API now does not support title for image, so we use creation time for image name instead
*/
QString itemName(item.title);
if (item.title.isEmpty())
{
itemName = QString::fromLatin1("image-%1").arg(item.creationTime);
}
QUrl tmpUrl = QUrl::fromLocalFile(QString(d->tmp + itemName));
if (item.mimeType == QLatin1String("video/mpeg4"))
{
tmpUrl = tmpUrl.adjusted(QUrl::RemoveFilename);
tmpUrl.setPath(tmpUrl.path() + item.title + QLatin1String(".mp4"));
}
if (errCode == 1)
{
QString errText;
QFile imgFile(tmpUrl.toLocalFile());
if (!imgFile.open(QIODevice::WriteOnly))
{
errText = imgFile.errorString();
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "error write";
}
else if (imgFile.write(photoData) != photoData.size())
{
errText = imgFile.errorString();
}
else
{
imgFile.close();
}
if (errText.isEmpty())
{
if (d->meta.load(tmpUrl.toLocalFile()))
{
if (d->meta.supportXmp() && d->meta.canWriteXmp(tmpUrl.toLocalFile()))
{
d->meta.setXmpTagString("Xmp.digiKam.picasawebGPhotoId", item.id);
d->meta.setXmpKeywords(item.tags);
}
if (!item.gpsLat.isEmpty() && !item.gpsLon.isEmpty())
{
d->meta.setGPSInfo(0.0, item.gpsLat.toDouble(), item.gpsLon.toDouble());
}
d->meta.setMetadataWritingMode((int)DMetadata::WRITE_TO_FILE_ONLY);
d->meta.save(tmpUrl.toLocalFile());
}
d->transferQueue.removeFirst();
d->imagesCount++;
}
else
{
QPointer warn = new QMessageBox(QMessageBox::Warning,
i18n("Warning"),
i18n("Failed to save photo: %1\n"
"Do you want to continue?", errText),
QMessageBox::Yes | QMessageBox::No);
(warn->button(QMessageBox::Yes))->setText(i18n("Continue"));
(warn->button(QMessageBox::No))->setText(i18n("Cancel"));
if (warn->exec() != QMessageBox::Yes)
{
slotTransferCancel();
delete warn;
return;
}
delete warn;
}
}
else
{
QPointer warn = new QMessageBox(QMessageBox::Warning,
i18n("Warning"),
i18n("Failed to download photo: %1\n"
"Do you want to continue?", errMsg),
QMessageBox::Yes | QMessageBox::No);
(warn->button(QMessageBox::Yes))->setText(i18n("Continue"));
(warn->button(QMessageBox::No))->setText(i18n("Cancel"));
if (warn->exec() != QMessageBox::Yes)
{
slotTransferCancel();
delete warn;
return;
}
delete warn;
}
QUrl newUrl = QUrl::fromLocalFile(QString::fromLatin1("%1/%2").arg(d->widget->getDestinationPath())
.arg(tmpUrl.fileName()));
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "location " << newUrl.url();
QFileInfo targetInfo(newUrl.toLocalFile());
if (targetInfo.exists())
{
int i = 0;
bool fileFound = false;
do
{
QFileInfo newTargetInfo(newUrl.toLocalFile());
if (!newTargetInfo.exists())
{
fileFound = false;
}
else
{
newUrl = newUrl.adjusted(QUrl::RemoveFilename);
newUrl.setPath(newUrl.path() + targetInfo.completeBaseName() +
QString::fromUtf8("_%1.").arg(++i) +
targetInfo.completeSuffix());
fileFound = true;
}
}
while (fileFound);
}
if (!QFile::rename(tmpUrl.toLocalFile(), newUrl.toLocalFile()))
{
QMessageBox::critical(this, i18nc("@title:window", "Error"),
i18n("Failed to save image to %1", newUrl.toLocalFile()));
}
/* TODO
else
{
KPItemInfo info(newUrl);
info.setName(item.title);
info.setDescription(item.description);
info.setTagsPath(item.tags);
if (!item.gpsLat.isEmpty() && !item.gpsLon.isEmpty())
{
info.setLatitude(item.gpsLat.toDouble());
info.setLongitude(item.gpsLon.toDouble());
}
}
*/
downloadNextPhoto();
}
void GSWindow::slotAddPhotoDone(int err, const QString& msg)
{
if (err == 0)
{
d->widget->imagesList()->processed(d->transferQueue.first().first,false);
QPointer warn = new QMessageBox(QMessageBox::Warning,
i18n("Warning"),
i18n("Failed to upload photo to %1.\n%2\nDo you want to continue?", d->toolName,msg),
QMessageBox::Yes | QMessageBox::No);
(warn->button(QMessageBox::Yes))->setText(i18n("Continue"));
(warn->button(QMessageBox::No))->setText(i18n("Cancel"));
if (warn->exec() != QMessageBox::Yes)
{
d->transferQueue.clear();
d->widget->progressBar()->hide();
}
else
{
d->transferQueue.removeFirst();
d->imagesTotal--;
d->widget->progressBar()->setMaximum(d->imagesTotal);
d->widget->progressBar()->setValue(d->imagesCount);
uploadNextPhoto();
}
delete warn;
}
else
{
/**
* (Trung) Take first item out of transferQueue and append to uploadQueue,
* in order to use it again to write id in slotUploadPhotoDone
*/
QPair item = d->transferQueue.first();
d->uploadQueue.append(item);
// Remove photo uploaded from the transfer queue
d->transferQueue.removeFirst();
d->imagesCount++;
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "In slotAddPhotoSucceeded" << d->imagesCount;
d->widget->progressBar()->setMaximum(d->imagesTotal);
d->widget->progressBar()->setValue(d->imagesCount);
uploadNextPhoto();
}
}
void GSWindow::slotUploadPhotoDone(int err, const QString& msg, const QStringList& listPhotoId)
{
if (err == 0)
{
QPointer warn = new QMessageBox(QMessageBox::Warning,
i18n("Warning"),
i18n("Failed to finish uploading photo to %1.\n%2\nNo image uploaded to your account.", d->toolName,msg),
QMessageBox::Yes);
(warn->button(QMessageBox::Yes))->setText(i18n("OK"));
d->uploadQueue.clear();
d->widget->progressBar()->hide();
delete warn;
}
else
{
foreach (const QString& photoId, listPhotoId)
{
// Remove image from upload list and from UI
QPair item = d->uploadQueue.takeFirst();
d->widget->imagesList()->removeItemByUrl(item.first);
QUrl fileUrl = item.first;
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "photoID: " << photoId;
if (d->meta.supportXmp() &&
d->meta.canWriteXmp(fileUrl.toLocalFile()) &&
d->meta.load(fileUrl.toLocalFile())
&& !photoId.isEmpty())
{
d->meta.setXmpTagString("Xmp.digiKam.picasawebGPhotoId", photoId);
d->meta.save(fileUrl.toLocalFile());
}
}
if(!d->widget->imagesList()->imageUrls().isEmpty())
{
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "continue to upload";
emit d->gphotoTalker->signalReadyToUpload();
}
}
}
void GSWindow::slotImageListChanged()
{
startButton()->setEnabled(!(d->widget->imagesList()->imageUrls().isEmpty()));
}
void GSWindow::slotNewAlbumRequest()
{
switch (d->service)
{
case GoogleService::GDrive:
if (d->albumDlg->exec() == QDialog::Accepted)
{
GSFolder newFolder;
d->albumDlg->getAlbumProperties(newFolder);
d->currentAlbumId = d->widget->getAlbumsCoB()->itemData(d->widget->getAlbumsCoB()->currentIndex()).toString();
d->talker->createFolder(newFolder.title, d->currentAlbumId);
}
break;
default:
if (d->gphotoAlbumDlg->exec() == QDialog::Accepted)
{
GSFolder newFolder;
d->gphotoAlbumDlg->getAlbumProperties(newFolder);
d->gphotoTalker->createAlbum(newFolder);
}
break;
}
}
void GSWindow::slotReloadAlbumsRequest()
{
switch (d->service)
{
case GoogleService::GDrive:
d->talker->listFolders();
break;
case GoogleService::GPhotoImport:
case GoogleService::GPhotoExport:
d->gphotoTalker->listAlbums();
break;
}
}
void GSWindow::slotAccessTokenObtained()
{
switch (d->service)
{
case GoogleService::GDrive:
d->talker->listFolders();
break;
case GoogleService::GPhotoImport:
case GoogleService::GPhotoExport:
d->gphotoTalker->getLoggedInUser();
break;
}
}
void GSWindow::slotAuthenticationRefused()
{
// QMessageBox::critical(this, i18nc("@title:window", "Error"),
// i18n("An authentication error occurred: account failed to link"));
// Clear list albums
d->widget->getAlbumsCoB()->clear();
// Clear user name
d->widget->updateLabels(QString(""));
return;
}
void GSWindow::slotCreateFolderDone(int code, const QString& msg, const QString& albumId)
{
switch (d->service)
{
case GoogleService::GDrive:
if (code == 0)
QMessageBox::critical(this, i18nc("@title:window", "Error"),
i18n("Google Drive call failed:\n%1", msg));
else
{
d->currentAlbumId = albumId;
d->talker->listFolders();
}
break;
case GoogleService::GPhotoImport:
case GoogleService::GPhotoExport:
if (code == 0)
QMessageBox::critical(this, i18nc("@title:window", "Error"),
i18n("Google Photos/PicasaWeb call failed:\n%1", msg));
else
{
d->currentAlbumId = albumId;
d->gphotoTalker->listAlbums();
}
break;
}
}
void GSWindow::slotTransferCancel()
{
d->transferQueue.clear();
d->widget->progressBar()->hide();
switch (d->service)
{
case GoogleService::GDrive:
d->talker->cancel();
break;
case GoogleService::GPhotoImport:
case GoogleService::GPhotoExport:
d->gphotoTalker->cancel();
break;
}
}
void GSWindow::slotUserChangeRequest()
{
QPointer warn = new QMessageBox(QMessageBox::Warning,
i18n("Warning"),
i18n("You will be logged out of your account, "
"click \"Continue\" to authenticate for another account"),
QMessageBox::Yes | QMessageBox::No);
(warn->button(QMessageBox::Yes))->setText(i18n("Continue"));
(warn->button(QMessageBox::No))->setText(i18n("Cancel"));
if (warn->exec() == QMessageBox::Yes)
{
/**
* We do not force user to logout from their account
* We simply unlink user account and direct use to login page to login new account
* (In the future, we may not unlink() user, but let them change account and
* choose which one they want to use)
* After unlink(), waiting actively until O2 completely unlink() account, before doOAuth() again
*/
switch (d->service)
{
case GoogleService::GDrive:
d->talker->unlink();
while(d->talker->authenticated());
d->talker->doOAuth();
break;
case GoogleService::GPhotoImport:
case GoogleService::GPhotoExport:
d->gphotoTalker->unlink();
while(d->gphotoTalker->authenticated());
d->gphotoTalker->doOAuth();
break;
}
}
delete warn;
}
void GSWindow::buttonStateChange(bool state)
{
d->widget->getNewAlbmBtn()->setEnabled(state);
d->widget->getReloadBtn()->setEnabled(state);
startButton()->setEnabled(state);
}
void GSWindow::slotFinished()
{
writeSettings();
d->widget->imagesList()->listView()->clear();
}
void GSWindow::closeEvent(QCloseEvent* e)
{
if (!e)
{
return;
}
slotFinished();
e->accept();
}
} // namespace Digikam
diff --git a/core/utilities/assistants/webservices/imageshack/imageshackwindow.cpp b/core/utilities/assistants/webservices/imageshack/imageshackwindow.cpp
index 6743d2db42..6bc10f1eb2 100644
--- a/core/utilities/assistants/webservices/imageshack/imageshackwindow.cpp
+++ b/core/utilities/assistants/webservices/imageshack/imageshackwindow.cpp
@@ -1,454 +1,454 @@
/* ============================================================
*
* This file is a part of digiKam project
* http://www.digikam.org
*
* Date : 2012-02-02
* Description : a tool to export items to ImageShack web service
*
* Copyright (C) 2012 by Dodon Victor
* Copyright (C) 2013-2018 by Caulier Gilles
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General
* Public License as published by the Free Software Foundation;
* either version 2, 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.
*
* ============================================================ */
#include "imageshackwindow.h"
// Qt includes
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
// KDE includes
#include
#include
#include
// Local includes
#include "digikam_debug.h"
#include "imageshacksession.h"
#include "imageshackwidget_p.h"
#include "imageshacktalker.h"
#include "dprogresswdg.h"
#include "wslogindialog.h"
#include "imageshacknewalbumdlg.h"
namespace Digikam
{
class Q_DECL_HIDDEN ImageShackWindow::Private
{
public:
explicit Private()
{
imagesCount = 0;
imagesTotal = 0;
session = 0;
widget = 0;
talker = 0;
albumDlg = 0;
iface = 0;
}
unsigned int imagesCount;
unsigned int imagesTotal;
QString newAlbmTitle;
QList transferQueue;
ImageShackSession* session;
ImageShackWidget* widget;
ImageShackTalker* talker;
ImageShackNewAlbumDlg* albumDlg;
DInfoInterface* iface;
};
ImageShackWindow::ImageShackWindow(DInfoInterface* const iface,
QWidget* const /*parent*/)
: WSToolDialog(0),
d(new Private)
{
d->session = new ImageShackSession();
d->iface = iface;
d->widget = new ImageShackWidget(this,
d->session,
d->iface,
QLatin1String("ImageShack"));
d->widget->setMinimumSize(700, 500);
setMainWidget(d->widget);
setWindowTitle(i18n("Export to ImageShack"));
setModal(false);
d->albumDlg = new ImageShackNewAlbumDlg(this, QLatin1String("ImageShack"));
connect(d->widget->d->chgRegCodeBtn, SIGNAL(clicked(bool)),
this, SLOT(slotChangeRegistrantionCode()));
startButton()->setText(i18n("Upload"));
startButton()->setToolTip(i18n("Start upload to ImageShack web service"));
startButton()->setEnabled(false);
connect(d->widget->d->imgList, SIGNAL(signalImageListChanged()),
this, SLOT(slotImageListChanged()));
// -----------------------------------------------------------
connect(this, SIGNAL(signalBusy(bool)),
this, SLOT(slotBusy(bool)));
d->talker = new ImageShackTalker(d->session);
connect(d->talker, SIGNAL(signalBusy(bool)),
this, SLOT(slotBusy(bool)));
connect(d->talker, SIGNAL(signalJobInProgress(int,int,QString)),
this, SLOT(slotJobInProgress(int,int,QString)));
connect(d->talker, SIGNAL(signalLoginDone(int,QString)),
this, SLOT(slotLoginDone(int,QString)));
connect(d->talker, SIGNAL(signalGetGalleriesDone(int,QString)),
this, SLOT(slotGetGalleriesDone(int,QString)));
connect(d->talker, SIGNAL(signalUpdateGalleries(QStringList,QStringList)),
d->widget, SLOT(slotGetGalleries(QStringList,QStringList)));
connect(d->talker, SIGNAL(signalAddPhotoDone(int,QString)),
this, SLOT(slotAddPhotoDone(int,QString)));
connect(d->widget, SIGNAL(signalReloadGalleries()),
this, SLOT(slotGetGalleries()));
connect(startButton(), SIGNAL(clicked()),
this, SLOT(slotStartTransfer()));
connect(this, SIGNAL(finished(int)),
this, SLOT(slotFinished()));
connect(this, SIGNAL(cancelClicked()),
this, SLOT(slotCancelClicked()));
connect(d->widget->getNewAlbmBtn(), SIGNAL(clicked()),
this, SLOT(slotNewAlbumRequest()));
readSettings();
QTimer::singleShot(20, this, SLOT(authenticate()));
}
ImageShackWindow::~ImageShackWindow()
{
delete d->session;
delete d;
}
void ImageShackWindow::slotImageListChanged()
{
startButton()->setEnabled(!d->widget->d->imgList->imageUrls().isEmpty());
}
void ImageShackWindow::slotFinished()
{
saveSettings();
d->widget->d->progressBar->progressCompleted();
d->widget->d->imgList->listView()->clear();
}
void ImageShackWindow::closeEvent(QCloseEvent* e)
{
if (!e)
{
return;
}
slotFinished();
e->accept();
}
void ImageShackWindow::readSettings()
{
winId();
KConfig config;
KConfigGroup group = config.group("ImageShack Settings");
KWindowConfig::restoreWindowSize(windowHandle(), group);
resize(windowHandle()->size());
if (group.readEntry("Private", false))
{
d->widget->d->privateImagesChb->setChecked(true);
}
if (group.readEntry("Rembar", false))
{
d->widget->d->remBarChb->setChecked(true);
}
else
{
d->widget->d->remBarChb->setChecked(false);
}
}
void ImageShackWindow::saveSettings()
{
KConfig config;
KConfigGroup group = config.group("ImageShack Settings");
KWindowConfig::saveWindowSize(windowHandle(), group);
group.writeEntry("Private", d->widget->d->privateImagesChb->isChecked());
group.writeEntry("Rembar", d->widget->d->remBarChb->isChecked());
group.sync();
}
void ImageShackWindow::slotStartTransfer()
{
d->widget->d->imgList->clearProcessedStatus();
d->transferQueue = d->widget->d->imgList->imageUrls();
if (d->transferQueue.isEmpty())
{
return;
}
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Transfer started!";
d->imagesTotal = d->transferQueue.count();
d->imagesCount = 0;
d->widget->d->progressBar->setFormat(i18n("%v / %m"));
d->widget->d->progressBar->setMaximum(d->imagesTotal);
d->widget->d->progressBar->setValue(0);
d->widget->d->progressBar->setVisible(true);
d->widget->d->progressBar->progressScheduled(i18n("Image Shack Export"), false, true);
- d->widget->d->progressBar->progressThumbnailChanged(QIcon(QLatin1String("imageshack")).pixmap(22, 22));
+ d->widget->d->progressBar->progressThumbnailChanged(QIcon(QLatin1String("dk-imageshack")).pixmap(22, 22));
uploadNextItem();
}
void ImageShackWindow::slotCancelClicked()
{
d->talker->cancel();
d->transferQueue.clear();
d->widget->d->imgList->cancelProcess();
d->widget->d->progressBar->setVisible(false);
d->widget->d->progressBar->progressCompleted();
}
void ImageShackWindow::slotChangeRegistrantionCode()
{
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Change registration code";
authenticate();
}
void ImageShackWindow::authenticate()
{
emit signalBusy(true);
d->widget->progressBar()->show();
d->widget->d->progressBar->setValue(0);
d->widget->d->progressBar->setMaximum(4);
d->widget->progressBar()->setFormat(i18n("Authenticating..."));
WSLoginDialog* const dlg = new WSLoginDialog(this, QLatin1String("ImageShack"));
if (dlg->exec() == QDialog::Accepted)
{
d->session->setEmail(dlg->login());
d->session->setPassword(dlg->password());
d->talker->authenticate();
}
}
void ImageShackWindow::slotBusy(bool val)
{
if (val)
{
setCursor(Qt::WaitCursor);
d->widget->d->chgRegCodeBtn->setEnabled(false);
startButton()->setEnabled(false);
setRejectButtonMode(QDialogButtonBox::Cancel);
}
else
{
setCursor(Qt::ArrowCursor);
d->widget->d->chgRegCodeBtn->setEnabled(true);
startButton()->setEnabled(d->session->loggedIn() &&
!d->widget->imagesList()->imageUrls().isEmpty());
setRejectButtonMode(QDialogButtonBox::Close);
}
}
void ImageShackWindow::slotJobInProgress(int step, int maxStep, const QString &format)
{
if (maxStep > 0)
{
d->widget->d->progressBar->setMaximum(maxStep);
}
d->widget->d->progressBar->setValue(step);
if (!format.isEmpty())
{
d->widget->d->progressBar->setFormat(format);
}
}
void ImageShackWindow::slotLoginDone(int errCode, const QString& errMsg)
{
d->widget->updateLabels();
if (!errCode && d->session->loggedIn())
{
d->session->saveSettings();
startButton()->setEnabled(!d->widget->imagesList()->imageUrls().isEmpty());
d->talker->getGalleries();
}
else
{
QMessageBox::critical(this, QString(), i18n("Login failed: %1\n", errMsg));
startButton()->setEnabled(false);
d->widget->d->progressBar->setVisible(false);
slotBusy(false);
}
}
void ImageShackWindow::slotGetGalleriesDone(int errCode, const QString &errMsg)
{
slotBusy(false);
d->widget->d->progressBar->setVisible(false);
if (errCode)
{
QMessageBox::critical(this, QString(), i18n("Failed to get galleries list: %1\n", errMsg));
}
}
void ImageShackWindow::uploadNextItem()
{
if (d->transferQueue.isEmpty())
{
d->widget->d->progressBar->hide();
return;
}
d->widget->d->imgList->processing(d->transferQueue.first());
QString imgPath = d->transferQueue.first().toLocalFile();
d->widget->d->progressBar->setMaximum(d->imagesTotal);
d->widget->d->progressBar->setValue(d->imagesCount);
QMap opts;
if (d->widget->d->privateImagesChb->isChecked())
{
opts[QLatin1String("public")] = QLatin1String("no");
}
if (d->widget->d->remBarChb->isChecked())
{
opts[QLatin1String("rembar")] = QLatin1String("yes");
}
// tags
if (!d->widget->d->tagsFld->text().isEmpty())
{
QString str = d->widget->d->tagsFld->text();
QStringList tagsList;
tagsList = str.split(QRegExp(QLatin1String("\\W+")), QString::SkipEmptyParts);
opts[QLatin1String("tags")] = tagsList.join(QLatin1Char(','));
}
opts[QLatin1String("auth_token")] = d->session->authToken();
int gidx = d->widget->d->galleriesCob->currentIndex();
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Album ID is "<< d->widget->d->galleriesCob->itemData(gidx).toString();
switch(gidx)
{
case 0:
d->talker->uploadItem(imgPath, opts);
break;
case 1:
opts[QLatin1String("album")] = d->newAlbmTitle;
d->talker->uploadItemToGallery(imgPath, d->newAlbmTitle, opts);
break;
default:
opts[QLatin1String("album")] = d->widget->d->galleriesCob->itemData(gidx).toString();
d->talker->uploadItemToGallery(imgPath, d->widget->d->galleriesCob->itemData(gidx).toString(), opts);
}
}
void ImageShackWindow::slotAddPhotoDone(int errCode, const QString& errMsg)
{
d->widget->d->imgList->processed(d->transferQueue.first(), (errCode == 0));
if (!errCode)
{
d->widget->imagesList()->removeItemByUrl(d->transferQueue.first());
d->transferQueue.removeFirst();
d->imagesCount++;
}
else
{
if (QMessageBox::question(this, i18n("Uploading Failed"),
i18n("Failed to upload photo into ImageShack: %1\n"
"Do you want to continue?", errMsg))
!= QMessageBox::Yes)
{
d->widget->d->progressBar->setVisible(false);
d->transferQueue.clear();
return;
}
}
uploadNextItem();
}
void ImageShackWindow::slotGetGalleries()
{
d->widget->d->progressBar->setVisible(true);
d->talker->getGalleries();
}
void ImageShackWindow::slotNewAlbumRequest()
{
if (d->albumDlg->exec() == QDialog::Accepted)
{
d->newAlbmTitle = d->albumDlg->getAlbumTitle();
}
}
} // namespace Digikam
diff --git a/core/utilities/assistants/webservices/onedrive/odwindow.cpp b/core/utilities/assistants/webservices/onedrive/odwindow.cpp
index c15e89e81f..2c6389870f 100644
--- a/core/utilities/assistants/webservices/onedrive/odwindow.cpp
+++ b/core/utilities/assistants/webservices/onedrive/odwindow.cpp
@@ -1,466 +1,466 @@
/* ============================================================
*
* This file is a part of digiKam project
* http://www.digikam.org
*
* Date : 2018-05-20
* Description : a tool to export images to Onedrive web service
*
* Copyright (C) 2018 by Tarek Talaat
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General
* Public License as published by the Free Software Foundation;
* either version 2, 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.
*
* ============================================================ */
#include "odwindow.h"
// Qt includes
#include
#include
#include
#include
#include
#include
// KDE includes
#include
#include
#include
// Local includes
#include "digikam_debug.h"
#include "ditemslist.h"
#include "digikam_version.h"
#include "odtalker.h"
#include "oditem.h"
#include "odnewalbumdlg.h"
#include "odwidget.h"
namespace Digikam
{
class Q_DECL_HIDDEN ODWindow::Private
{
public:
explicit Private()
{
imagesCount = 0;
imagesTotal = 0;
widget = 0;
albumDlg = 0;
talker = 0;
}
unsigned int imagesCount;
unsigned int imagesTotal;
ODWidget* widget;
ODNewAlbumDlg* albumDlg;
ODTalker* talker;
QString currentAlbumName;
QList transferQueue;
};
ODWindow::ODWindow(DInfoInterface* const iface,
QWidget* const /*parent*/)
: WSToolDialog(0),
d(new Private)
{
d->widget = new ODWidget(this, iface, QLatin1String("Onedrive"));
d->widget->imagesList()->setIface(iface);
setMainWidget(d->widget);
setModal(false);
setWindowTitle(i18n("Export to Onedrive"));
startButton()->setText(i18n("Start Upload"));
startButton()->setToolTip(i18n("Start upload to Onedrive"));
d->widget->setMinimumSize(700, 500);
connect(d->widget->imagesList(), SIGNAL(signalImageListChanged()),
this, SLOT(slotImageListChanged()));
connect(d->widget->getChangeUserBtn(), SIGNAL(clicked()),
this, SLOT(slotUserChangeRequest()));
connect(d->widget->getNewAlbmBtn(), SIGNAL(clicked()),
this, SLOT(slotNewAlbumRequest()));
connect(d->widget->getReloadBtn(), SIGNAL(clicked()),
this, SLOT(slotReloadAlbumsRequest()));
connect(startButton(), SIGNAL(clicked()),
this, SLOT(slotStartTransfer()));
d->albumDlg = new ODNewAlbumDlg(this, QLatin1String("Onedrive"));
d->talker = new ODTalker(this);
connect(d->talker,SIGNAL(signalBusy(bool)),
this,SLOT(slotBusy(bool)));
connect(d->talker,SIGNAL(signalLinkingFailed()),
this,SLOT(slotSignalLinkingFailed()));
connect(d->talker,SIGNAL(signalLinkingSucceeded()),
this,SLOT(slotSignalLinkingSucceeded()));
connect(d->talker,SIGNAL(signalSetUserName(QString)),
this,SLOT(slotSetUserName(QString)));
connect(d->talker,SIGNAL(signalListAlbumsFailed(QString)),
this,SLOT(slotListAlbumsFailed(QString)));
connect(d->talker,SIGNAL(signalListAlbumsDone(QList >)), // krazy:exclude=normalize
this,SLOT(slotListAlbumsDone(QList >))); // krazy:exclude=normalize
connect(d->talker,SIGNAL(signalCreateFolderFailed(QString)),
this,SLOT(slotCreateFolderFailed(QString)));
connect(d->talker,SIGNAL(signalCreateFolderSucceeded()),
this,SLOT(slotCreateFolderSucceeded()));
connect(d->talker,SIGNAL(signalAddPhotoFailed(QString)),
this,SLOT(slotAddPhotoFailed(QString)));
connect(d->talker,SIGNAL(signalAddPhotoSucceeded()),
this,SLOT(slotAddPhotoSucceeded()));
connect(this, SIGNAL(finished(int)),
this, SLOT(slotFinished()));
readSettings();
buttonStateChange(false);
d->talker->readSettings();
}
ODWindow::~ODWindow()
{
delete d->widget;
delete d->albumDlg;
delete d->talker;
delete d;
}
void ODWindow::readSettings()
{
KConfig config;
KConfigGroup grp = config.group("Onedrive Settings");
d->currentAlbumName = grp.readEntry("Current Album",QString());
if (grp.readEntry("Resize", false))
{
d->widget->getResizeCheckBox()->setChecked(true);
d->widget->getDimensionSpB()->setEnabled(true);
}
else
{
d->widget->getResizeCheckBox()->setChecked(false);
d->widget->getDimensionSpB()->setEnabled(false);
}
d->widget->getDimensionSpB()->setValue(grp.readEntry("Maximum Width", 1600));
d->widget->getImgQualitySpB()->setValue(grp.readEntry("Image Quality", 90));
KConfigGroup dialogGroup = config.group("Onedrive Export Dialog");
winId();
KWindowConfig::restoreWindowSize(windowHandle(), dialogGroup);
resize(windowHandle()->size());
}
void ODWindow::writeSettings()
{
KConfig config;
KConfigGroup grp = config.group("Onedrive Settings");
grp.writeEntry("Current Album", d->currentAlbumName);
grp.writeEntry("Resize", d->widget->getResizeCheckBox()->isChecked());
grp.writeEntry("Maximum Width", d->widget->getDimensionSpB()->value());
grp.writeEntry("Image Quality", d->widget->getImgQualitySpB()->value());
KConfigGroup dialogGroup = config.group("Onedrive Export Dialog");
KWindowConfig::saveWindowSize(windowHandle(), dialogGroup);
config.sync();
}
void ODWindow::reactivate()
{
d->widget->imagesList()->loadImagesFromCurrentSelection();
d->widget->progressBar()->hide();
show();
}
void ODWindow::setItemsList(const QList& urls)
{
d->widget->imagesList()->slotAddImages(urls);
}
void ODWindow::slotBusy(bool val)
{
if (val)
{
setCursor(Qt::WaitCursor);
d->widget->getChangeUserBtn()->setEnabled(false);
buttonStateChange(false);
}
else
{
setCursor(Qt::ArrowCursor);
d->widget->getChangeUserBtn()->setEnabled(true);
buttonStateChange(true);
}
}
void ODWindow::slotSetUserName(const QString& msg)
{
d->widget->updateLabels(msg, QLatin1String(""));
}
void ODWindow::slotListAlbumsDone(const QList >& list)
{
d->widget->getAlbumsCoB()->clear();
for (int i = 0 ; i < list.size() ; ++i)
{
d->widget->getAlbumsCoB()->addItem(
QIcon::fromTheme(QLatin1String("system-users")),
list.value(i).second, list.value(i).first);
if (d->currentAlbumName == list.value(i).first)
{
d->widget->getAlbumsCoB()->setCurrentIndex(i);
}
}
buttonStateChange(true);
d->talker->getUserName();
}
void ODWindow::slotStartTransfer()
{
d->widget->imagesList()->clearProcessedStatus();
if (d->widget->imagesList()->imageUrls().isEmpty())
{
QMessageBox::critical(this, i18nc("@title:window", "Error"),
i18n("No image selected. Please select which images should be uploaded."));
return;
}
if (!(d->talker->authenticated()))
{
QPointer warn = new QMessageBox(QMessageBox::Warning,
i18n("Warning"),
i18n("Authentication failed. Click \"Continue\" to authenticate."),
QMessageBox::Yes | QMessageBox::No);
(warn->button(QMessageBox::Yes))->setText(i18n("Continue"));
(warn->button(QMessageBox::No))->setText(i18n("Cancel"));
if (warn->exec() == QMessageBox::Yes)
{
d->talker->link();
delete warn;
return;
}
else
{
delete warn;
return;
}
}
d->transferQueue = d->widget->imagesList()->imageUrls();
if (d->transferQueue.isEmpty())
{
return;
}
d->currentAlbumName = d->widget->getAlbumsCoB()->itemData(d->widget->getAlbumsCoB()->currentIndex()).toString();
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "StartTransfer:" << d->currentAlbumName << "INDEX: " << d->widget->getAlbumsCoB()->currentIndex();
d->imagesTotal = d->transferQueue.count();
d->imagesCount = 0;
d->widget->progressBar()->setFormat(i18n("%v / %m"));
d->widget->progressBar()->setMaximum(d->imagesTotal);
d->widget->progressBar()->setValue(0);
d->widget->progressBar()->show();
d->widget->progressBar()->progressScheduled(i18n("Onedrive export"), true, true);
- d->widget->progressBar()->progressThumbnailChanged(QIcon(QLatin1String("onedrive")).pixmap(22, 22));
+ d->widget->progressBar()->progressThumbnailChanged(QIcon(QLatin1String("dk-onedrive")).pixmap(22, 22));
uploadNextPhoto();
}
void ODWindow::uploadNextPhoto()
{
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "uploadNextPhoto:" << d->transferQueue.count();
if (d->transferQueue.isEmpty())
{
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "empty";
d->widget->progressBar()->progressCompleted();
return;
}
QString imgPath = d->transferQueue.first().toLocalFile();
QString temp = d->currentAlbumName + QLatin1Char('/');
bool result = d->talker->addPhoto(imgPath,
temp,
d->widget->getResizeCheckBox()->isChecked(),
d->widget->getDimensionSpB()->value(),
d->widget->getImgQualitySpB()->value());
if (!result)
{
slotAddPhotoFailed(QLatin1String(""));
return;
}
}
void ODWindow::slotAddPhotoFailed(const QString& msg)
{
if (QMessageBox::question(this, i18n("Uploading Failed"),
i18n("Failed to upload photo to OneDrive."
"\n%1\n"
"Do you want to continue?", msg))
!= QMessageBox::Yes)
{
d->transferQueue.clear();
d->widget->progressBar()->hide();
}
else
{
d->transferQueue.pop_front();
d->imagesTotal--;
d->widget->progressBar()->setMaximum(d->imagesTotal);
d->widget->progressBar()->setValue(d->imagesCount);
uploadNextPhoto();
}
}
void ODWindow::slotAddPhotoSucceeded()
{
// Remove photo uploaded from the list
d->widget->imagesList()->removeItemByUrl(d->transferQueue.first());
d->transferQueue.pop_front();
d->imagesCount++;
d->widget->progressBar()->setMaximum(d->imagesTotal);
d->widget->progressBar()->setValue(d->imagesCount);
uploadNextPhoto();
}
void ODWindow::slotImageListChanged()
{
startButton()->setEnabled(!(d->widget->imagesList()->imageUrls().isEmpty()));
}
void ODWindow::slotNewAlbumRequest()
{
if (d->albumDlg->exec() == QDialog::Accepted)
{
ODFolder newFolder;
d->albumDlg->getFolderTitle(newFolder);
d->currentAlbumName = d->widget->getAlbumsCoB()->itemData(d->widget->getAlbumsCoB()->currentIndex()).toString();
QString temp = d->currentAlbumName + newFolder.title;
d->talker->createFolder(temp);
}
}
void ODWindow::slotReloadAlbumsRequest()
{
d->talker->listFolders();
}
void ODWindow::slotSignalLinkingFailed()
{
slotSetUserName(QLatin1String(""));
d->widget->getAlbumsCoB()->clear();
if (QMessageBox::question(this, i18n("Login Failed"),
i18n("Authentication failed. Do you want to try again?"))
== QMessageBox::Yes)
{
d->talker->link();
}
}
void ODWindow::slotSignalLinkingSucceeded()
{
d->talker->listFolders();
}
void ODWindow::slotListAlbumsFailed(const QString& msg)
{
QMessageBox::critical(this, QString(), i18n("Onedrive call failed:\n%1", msg));
}
void ODWindow::slotCreateFolderFailed(const QString& msg)
{
QMessageBox::critical(this, QString(), i18n("Onedrive call failed:\n%1", msg));
}
void ODWindow::slotCreateFolderSucceeded()
{
d->talker->listFolders();
}
void ODWindow::slotTransferCancel()
{
d->transferQueue.clear();
d->widget->progressBar()->hide();
d->talker->cancel();
}
void ODWindow::slotUserChangeRequest()
{
slotSetUserName(QLatin1String(""));
d->widget->getAlbumsCoB()->clear();
d->talker->unLink();
d->talker->link();
}
void ODWindow::buttonStateChange(bool state)
{
d->widget->getNewAlbmBtn()->setEnabled(state);
d->widget->getReloadBtn()->setEnabled(state);
startButton()->setEnabled(state);
}
void ODWindow::slotFinished()
{
writeSettings();
d->widget->imagesList()->listView()->clear();
}
void ODWindow::closeEvent(QCloseEvent* e)
{
if (!e)
{
return;
}
slotFinished();
e->accept();
}
} // namespace Digikam
diff --git a/core/utilities/assistants/webservices/pinterest/pwindow.cpp b/core/utilities/assistants/webservices/pinterest/pwindow.cpp
index 9e625a4451..f4e2ec6c7c 100644
--- a/core/utilities/assistants/webservices/pinterest/pwindow.cpp
+++ b/core/utilities/assistants/webservices/pinterest/pwindow.cpp
@@ -1,466 +1,466 @@
/* ============================================================
*
* This file is a part of digiKam project
* http://www.digikam.org
*
* Date : 2018-05-20
* Description : a tool to export images to Pinterest web service
*
* Copyright (C) 2018 by Tarek Talaat
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General
* Public License as published by the Free Software Foundation;
* either version 2, 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.
*
* ============================================================ */
#include "pwindow.h"
// Qt includes
#include
#include
#include
#include
#include
#include
// KDE includes
#include
#include
#include
// Local includes
#include "digikam_debug.h"
#include "ditemslist.h"
#include "digikam_version.h"
#include "ptalker.h"
#include "pitem.h"
#include "pnewalbumdlg.h"
#include "pwidget.h"
namespace Digikam
{
class Q_DECL_HIDDEN PWindow::Private
{
public:
explicit Private()
{
imagesCount = 0;
imagesTotal = 0;
widget = 0;
albumDlg = 0;
talker = 0;
}
unsigned int imagesCount;
unsigned int imagesTotal;
PWidget* widget;
PNewAlbumDlg* albumDlg;
PTalker* talker;
QString currentAlbumName;
QList transferQueue;
};
PWindow::PWindow(DInfoInterface* const iface,
QWidget* const /*parent*/)
: WSToolDialog(0),
d(new Private)
{
d->widget = new PWidget(this, iface, QLatin1String("Pinterest"));
d->widget->imagesList()->setIface(iface);
setMainWidget(d->widget);
setModal(false);
setWindowTitle(i18n("Export to Pinterest"));
startButton()->setText(i18n("Start Upload"));
startButton()->setToolTip(i18n("Start upload to Pinterest"));
d->widget->setMinimumSize(700, 500);
connect(d->widget->imagesList(), SIGNAL(signalImageListChanged()),
this, SLOT(slotImageListChanged()));
connect(d->widget->getChangeUserBtn(), SIGNAL(clicked()),
this, SLOT(slotUserChangeRequest()));
connect(d->widget->getNewAlbmBtn(), SIGNAL(clicked()),
this, SLOT(slotNewBoardRequest()));
connect(d->widget->getReloadBtn(), SIGNAL(clicked()),
this, SLOT(slotReloadBoardsRequest()));
connect(startButton(), SIGNAL(clicked()),
this, SLOT(slotStartTransfer()));
d->albumDlg = new PNewAlbumDlg(this, QLatin1String("Pinterest"));
d->talker = new PTalker(this);
connect(d->talker,SIGNAL(signalBusy(bool)),
this,SLOT(slotBusy(bool)));
connect(d->talker,SIGNAL(signalLinkingFailed()),
this,SLOT(slotSignalLinkingFailed()));
connect(d->talker,SIGNAL(signalLinkingSucceeded()),
this,SLOT(slotSignalLinkingSucceeded()));
connect(d->talker,SIGNAL(signalSetUserName(QString)),
this,SLOT(slotSetUserName(QString)));
connect(d->talker,SIGNAL(signalListBoardsFailed(QString)),
this,SLOT(slotListBoardsFailed(QString)));
connect(d->talker,SIGNAL(signalListBoardsDone(QList >)), // krazy:exclude=normalize
this,SLOT(slotListBoardsDone(QList >))); // krazy:exclude=normalize
connect(d->talker,SIGNAL(signalCreateBoardFailed(QString)),
this,SLOT(slotCreateBoardFailed(QString)));
connect(d->talker,SIGNAL(signalCreateBoardSucceeded()),
this,SLOT(slotCreateBoardSucceeded()));
connect(d->talker,SIGNAL(signalAddPinFailed(QString)),
this,SLOT(slotAddPinFailed(QString)));
connect(d->talker,SIGNAL(signalAddPinSucceeded()),
this,SLOT(slotAddPinSucceeded()));
connect(this, SIGNAL(finished(int)),
this, SLOT(slotFinished()));
readSettings();
buttonStateChange(false);
d->talker->readSettings();
}
PWindow::~PWindow()
{
delete d->widget;
delete d->albumDlg;
delete d->talker;
delete d;
}
void PWindow::readSettings()
{
KConfig config;
KConfigGroup grp = config.group("Pinterest Settings");
d->currentAlbumName = grp.readEntry("Current Album",QString());
if (grp.readEntry("Resize", false))
{
d->widget->getResizeCheckBox()->setChecked(true);
d->widget->getDimensionSpB()->setEnabled(true);
}
else
{
d->widget->getResizeCheckBox()->setChecked(false);
d->widget->getDimensionSpB()->setEnabled(false);
}
d->widget->getDimensionSpB()->setValue(grp.readEntry("Maximum Width", 1600));
d->widget->getImgQualitySpB()->setValue(grp.readEntry("Image Quality", 90));
KConfigGroup dialogGroup = config.group("Pinterest Export Dialog");
winId();
KWindowConfig::restoreWindowSize(windowHandle(), dialogGroup);
resize(windowHandle()->size());
}
void PWindow::writeSettings()
{
KConfig config;
KConfigGroup grp = config.group("Pinterest Settings");
grp.writeEntry("Current Album", d->currentAlbumName);
grp.writeEntry("Resize", d->widget->getResizeCheckBox()->isChecked());
grp.writeEntry("Maximum Width", d->widget->getDimensionSpB()->value());
grp.writeEntry("Image Quality", d->widget->getImgQualitySpB()->value());
KConfigGroup dialogGroup = config.group("Pinterest Export Dialog");
KWindowConfig::saveWindowSize(windowHandle(), dialogGroup);
config.sync();
}
void PWindow::reactivate()
{
d->widget->imagesList()->loadImagesFromCurrentSelection();
d->widget->progressBar()->hide();
show();
}
void PWindow::setItemsList(const QList& urls)
{
d->widget->imagesList()->slotAddImages(urls);
}
void PWindow::slotBusy(bool val)
{
if (val)
{
setCursor(Qt::WaitCursor);
d->widget->getChangeUserBtn()->setEnabled(false);
buttonStateChange(false);
}
else
{
setCursor(Qt::ArrowCursor);
d->widget->getChangeUserBtn()->setEnabled(true);
buttonStateChange(true);
}
}
void PWindow::slotSetUserName(const QString& msg)
{
d->widget->updateLabels(msg, QLatin1String(""));
}
void PWindow::slotListBoardsDone(const QList >& list)
{
d->widget->getAlbumsCoB()->clear();
for (int i = 0 ; i < list.size() ; ++i)
{
d->widget->getAlbumsCoB()->addItem(
QIcon::fromTheme(QLatin1String("system-users")),
list.value(i).second, list.value(i).second);
if (d->currentAlbumName == list.value(i).first)
{
d->widget->getAlbumsCoB()->setCurrentIndex(i);
}
}
buttonStateChange(true);
d->talker->getUserName();
}
void PWindow::slotStartTransfer()
{
d->widget->imagesList()->clearProcessedStatus();
if (d->widget->imagesList()->imageUrls().isEmpty())
{
QMessageBox::critical(this, i18nc("@title:window", "Error"),
i18n("No image selected. Please select which images should be uploaded."));
return;
}
if (!(d->talker->authenticated()))
{
QPointer warn = new QMessageBox(QMessageBox::Warning,
i18n("Warning"),
i18n("Authentication failed. Click \"Continue\" to authenticate."),
QMessageBox::Yes | QMessageBox::No);
(warn->button(QMessageBox::Yes))->setText(i18n("Continue"));
(warn->button(QMessageBox::No))->setText(i18n("Cancel"));
if (warn->exec() == QMessageBox::Yes)
{
d->talker->link();
delete warn;
return;
}
else
{
delete warn;
return;
}
}
d->transferQueue = d->widget->imagesList()->imageUrls();
if (d->transferQueue.isEmpty())
{
return;
}
d->currentAlbumName = d->widget->getAlbumsCoB()->itemData(d->widget->getAlbumsCoB()->currentIndex()).toString();
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "StartTransfer:" << d->currentAlbumName << "INDEX: " << d->widget->getAlbumsCoB()->currentIndex();
d->imagesTotal = d->transferQueue.count();
d->imagesCount = 0;
d->widget->progressBar()->setFormat(i18n("%v / %m"));
d->widget->progressBar()->setMaximum(d->imagesTotal);
d->widget->progressBar()->setValue(0);
d->widget->progressBar()->show();
d->widget->progressBar()->progressScheduled(i18n("Pinterest export"), true, true);
- d->widget->progressBar()->progressThumbnailChanged(QIcon(QLatin1String("pinterest")).pixmap(22, 22));
+ d->widget->progressBar()->progressThumbnailChanged(QIcon(QLatin1String("dk-pinterest")).pixmap(22, 22));
uploadNextPhoto();
}
void PWindow::uploadNextPhoto()
{
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "uploadNextPhoto:" << d->transferQueue.count();
if (d->transferQueue.isEmpty())
{
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "empty";
d->widget->progressBar()->progressCompleted();
return;
}
QString imgPath = d->transferQueue.first().toLocalFile();
QString temp = d->currentAlbumName;
bool result = d->talker->addPin(imgPath,
temp,
d->widget->getResizeCheckBox()->isChecked(),
d->widget->getDimensionSpB()->value(),
d->widget->getImgQualitySpB()->value());
if (!result)
{
slotAddPinFailed(QLatin1String(""));
return;
}
}
void PWindow::slotAddPinFailed(const QString& msg)
{
if (QMessageBox::question(this, i18n("Uploading Failed"),
i18n("Failed to upload photo to Pinterest."
"\n%1\n"
"Do you want to continue?", msg))
!= QMessageBox::Yes)
{
d->transferQueue.clear();
d->widget->progressBar()->hide();
}
else
{
d->transferQueue.pop_front();
d->imagesTotal--;
d->widget->progressBar()->setMaximum(d->imagesTotal);
d->widget->progressBar()->setValue(d->imagesCount);
uploadNextPhoto();
}
}
void PWindow::slotAddPinSucceeded()
{
// Remove photo uploaded from the list
d->widget->imagesList()->removeItemByUrl(d->transferQueue.first());
d->transferQueue.pop_front();
d->imagesCount++;
d->widget->progressBar()->setMaximum(d->imagesTotal);
d->widget->progressBar()->setValue(d->imagesCount);
uploadNextPhoto();
}
void PWindow::slotImageListChanged()
{
startButton()->setEnabled(!(d->widget->imagesList()->imageUrls().isEmpty()));
}
void PWindow::slotNewBoardRequest()
{
if (d->albumDlg->exec() == QDialog::Accepted)
{
PFolder newFolder;
d->albumDlg->getFolderTitle(newFolder);
d->currentAlbumName = d->widget->getAlbumsCoB()->itemData(d->widget->getAlbumsCoB()->currentIndex()).toString();
QString temp = newFolder.title;
d->talker->createBoard(temp);
}
}
void PWindow::slotReloadBoardsRequest()
{
d->talker->listBoards();
}
void PWindow::slotSignalLinkingFailed()
{
slotSetUserName(QLatin1String(""));
d->widget->getAlbumsCoB()->clear();
if (QMessageBox::question(this, i18n("Login Failed"),
i18n("Authentication failed. Do you want to try again?"))
== QMessageBox::Yes)
{
d->talker->link();
}
}
void PWindow::slotSignalLinkingSucceeded()
{
d->talker->listBoards();
}
void PWindow::slotListBoardsFailed(const QString& msg)
{
QMessageBox::critical(this, QString(), i18n("Pinterest call failed:\n%1", msg));
}
void PWindow::slotCreateBoardFailed(const QString& msg)
{
QMessageBox::critical(this, QString(), i18n("Pinterest call failed:\n%1", msg));
}
void PWindow::slotCreateBoardSucceeded()
{
d->talker->listBoards();
}
void PWindow::slotTransferCancel()
{
d->transferQueue.clear();
d->widget->progressBar()->hide();
d->talker->cancel();
}
void PWindow::slotUserChangeRequest()
{
slotSetUserName(QLatin1String(""));
d->widget->getAlbumsCoB()->clear();
d->talker->unLink();
d->talker->link();
}
void PWindow::buttonStateChange(bool state)
{
d->widget->getNewAlbmBtn()->setEnabled(state);
d->widget->getReloadBtn()->setEnabled(state);
startButton()->setEnabled(state);
}
void PWindow::slotFinished()
{
writeSettings();
d->widget->imagesList()->listView()->clear();
}
void PWindow::closeEvent(QCloseEvent* e)
{
if (!e)
{
return;
}
slotFinished();
e->accept();
}
} // namespace Digikam
diff --git a/core/utilities/assistants/webservices/smugmug/smugwindow.cpp b/core/utilities/assistants/webservices/smugmug/smugwindow.cpp
index 23deb5d74c..4f64e3b895 100644
--- a/core/utilities/assistants/webservices/smugmug/smugwindow.cpp
+++ b/core/utilities/assistants/webservices/smugmug/smugwindow.cpp
@@ -1,1028 +1,1028 @@
/* ============================================================
*
* This file is a part of digiKam project
* http://www.digikam.org
*
* Date : 2005-17-06
* Description : a tool to export images to Smugmug web service
*
* Copyright (C) 2005-2008 by Vardhman Jain
* Copyright (C) 2008-2019 by Gilles Caulier
* Copyright (C) 2008-2009 by Luka Renko
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General
* Public License as published by the Free Software Foundation;
* either version 2, 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.
*
* ============================================================ */
#include "smugwindow.h"
// Qt includes
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
// KDE includes
#include
#include
#include
// Local includes
#include "digikam_debug.h"
#include "ditemslist.h"
#include "wstoolutils.h"
#include "digikam_version.h"
#include "dprogresswdg.h"
#include "dmetadata.h"
#include "previewloadthread.h"
#include "smugitem.h"
#include "smugtalker.h"
#include "smugwidget.h"
#include "smugnewalbumdlg.h"
namespace Digikam
{
class Q_DECL_HIDDEN SmugWindow::Private
{
public:
explicit Private()
{
import = false;
imagesCount = 0;
imagesTotal = 0;
anonymousImport = false;
currentAlbumID = 0;
currentTmplID = 0;
currentCategoryID = 0;
loginDlg = 0;
talker = 0;
widget = 0;
albumDlg = 0;
iface = 0;
}
bool import;
unsigned int imagesCount;
unsigned int imagesTotal;
QString tmpDir;
QString tmpPath;
bool anonymousImport;
QString anonymousNick;
QString email;
QString password;
qint64 currentAlbumID;
QString currentAlbumKey;
qint64 currentTmplID;
qint64 currentCategoryID;
WSLoginDialog* loginDlg;
QList transferQueue;
SmugTalker* talker;
SmugWidget* widget;
SmugNewAlbumDlg* albumDlg;
DInfoInterface* iface;
};
SmugWindow::SmugWindow(DInfoInterface* const iface,
QWidget* const /*parent*/,
bool import,
QString /*nickName*/)
: WSToolDialog(0),
d(new Private)
{
d->tmpPath.clear();
d->tmpDir = WSToolUtils::makeTemporaryDir("smug").absolutePath() + QLatin1Char('/');;
d->import = import;
d->iface = iface;
d->widget = new SmugWidget(this, iface, import);
setMainWidget(d->widget);
setModal(false);
if (import)
{
setWindowTitle(i18n("Import from SmugMug Web Service"));
startButton()->setText(i18n("Start Download"));
startButton()->setToolTip(i18n("Start download from SmugMug web service"));
d->widget->setMinimumSize(300, 400);
}
else
{
setWindowTitle(i18n("Export to SmugMug Web Service"));
startButton()->setText(i18n("Start Upload"));
startButton()->setToolTip(i18n("Start upload to SmugMug web service"));
d->widget->setMinimumSize(700, 500);
}
connect(d->widget, SIGNAL(signalUserChangeRequest(bool)),
this, SLOT(slotUserChangeRequest(bool)) );
connect(d->widget->m_imgList, SIGNAL(signalImageListChanged()),
this, SLOT(slotImageListChanged()) );
connect(d->widget->m_reloadAlbumsBtn, SIGNAL(clicked()),
this, SLOT(slotReloadAlbumsRequest()) );
connect(d->widget->m_newAlbumBtn, SIGNAL(clicked()),
this, SLOT(slotNewAlbumRequest()) );
connect(startButton(), &QPushButton::clicked,
this, &SmugWindow::slotStartTransfer);
connect(this, &WSToolDialog::cancelClicked,
this, &SmugWindow::slotCancelClicked);
connect(this, &QDialog::finished,
this, &SmugWindow::slotDialogFinished);
// ------------------------------------------------------------------------
/**
* This is deprecated because we know use O2 to login
*
* if (nickName.isEmpty())
* {
* d->loginDlg = new WSLoginDialog(this,
* i18n("Enter the email address and password for your "
* "SmugMug account"));
* }
*/
// ------------------------------------------------------------------------
d->albumDlg = new SmugNewAlbumDlg(this);
/**
* Categories are deprecated
*
* connect(d->albumDlg->categoryCombo(), SIGNAL(currentIndexChanged(int)),
* this, SLOT(slotCategorySelectionChanged(int)) );
* connect(d->albumDlg->templateCombo(), SIGNAL(currentIndexChanged(int)),
* this, SLOT(slotTemplateSelectionChanged(int)) );
*/
// ------------------------------------------------------------------------
d->talker = new SmugTalker(d->iface, this);
connect(d->talker, SIGNAL(signalBusy(bool)),
this, SLOT(slotBusy(bool)));
connect(d->talker, SIGNAL(signalLoginProgress(int,int,QString)),
this, SLOT(slotLoginProgress(int,int,QString)));
connect(d->talker, SIGNAL(signalLoginDone(int,QString)),
this, SLOT(slotLoginDone(int,QString)));
connect(d->talker, SIGNAL(signalAddPhotoDone(int,QString)),
this, SLOT(slotAddPhotoDone(int,QString)));
connect(d->talker, SIGNAL(signalGetPhotoDone(int,QString,QByteArray)),
this, SLOT(slotGetPhotoDone(int,QString,QByteArray)));
connect(d->talker, SIGNAL(signalCreateAlbumDone(int,QString,qint64,QString)),
this, SLOT(slotCreateAlbumDone(int,QString,qint64,QString)));
connect(d->talker, SIGNAL(signalListAlbumsDone(int,QString,QList)),
this, SLOT(slotListAlbumsDone(int,QString,QList)));
connect(d->talker, SIGNAL(signalListPhotosDone(int,QString,QList)),
this, SLOT(slotListPhotosDone(int,QString,QList)));
connect(d->talker, SIGNAL(signalListAlbumTmplDone(int,QString,QList)),
this, SLOT(slotListAlbumTmplDone(int,QString,QList)));
/**
* Categories deprecated in API v2
* connect(d->talker, SIGNAL(signalListCategoriesDone(int,QString,QList)),
* this, SLOT(slotListCategoriesDone(int,QString,QList)));
* connect(d->talker, SIGNAL(signalListSubCategoriesDone(int,QString,QList)),
* this, SLOT(slotListSubCategoriesDone(int,QString,QList)));
*/
connect(d->widget->progressBar(), SIGNAL(signalProgressCanceled()),
this, SLOT(slotStopAndCloseProgressBar()));
// ------------------------------------------------------------------------
readSettings();
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Calling Login method";
buttonStateChange(d->talker->loggedIn());
authenticate();
// if(!nickName.isEmpty())
// {
// qCDebug(DIGIKAM_WEBSERVICES_LOG) << "login with nickname";
// authenticateWithNickName(nickName);
// }
// else
// {
// if (d->import)
// {
// // if no e-mail, switch to anonymous login
// if (d->anonymousImport || d->email.isEmpty())
// {
// d->anonymousImport = true;
// authenticate();
// }
// else
// {
// authenticate(d->email, d->password);
// }
//
// d->widget->setAnonymous(d->anonymousImport);
// }
// else
// {
// // export cannot login anonymously: pop-up login window`
// if (d->email.isEmpty())
// slotUserChangeRequest(false);
// else
// authenticate(d->email, d->password);
// }
// }
}
SmugWindow::~SmugWindow()
{
WSToolUtils::removeTemporaryDir("smug");
delete d->talker;
delete d;
}
void SmugWindow::closeEvent(QCloseEvent* e)
{
if (!e)
{
return;
}
slotDialogFinished();
e->accept();
}
void SmugWindow::slotDialogFinished()
{
slotCancelClicked();
/**
* We should not logout without user consent
*
* if (d->talker->loggedIn())
* d->talker->logout();
*/
writeSettings();
d->widget->imagesList()->listView()->clear();
}
void SmugWindow::setUiInProgressState(bool inProgress)
{
setRejectButtonMode(inProgress ? QDialogButtonBox::Cancel : QDialogButtonBox::Close);
if (inProgress)
{
d->widget->progressBar()->show();
}
else
{
d->widget->progressBar()->hide();
d->widget->progressBar()->progressCompleted();
}
}
void SmugWindow::slotCancelClicked()
{
d->talker->cancel();
d->transferQueue.clear();
d->widget->m_imgList->cancelProcess();
setUiInProgressState(false);
}
void SmugWindow::slotStopAndCloseProgressBar()
{
slotCancelClicked();
writeSettings();
d->widget->imagesList()->listView()->clear();
reject();
}
void SmugWindow::reactivate()
{
d->widget->imagesList()->loadImagesFromCurrentSelection();
show();
}
void SmugWindow::authenticate()
{
setUiInProgressState(true);
d->widget->progressBar()->setFormat(QString());
d->talker->login();
}
void SmugWindow::readSettings()
{
KConfig config;
KConfigGroup grp = config.group("Smug Settings");
d->anonymousImport = grp.readEntry("AnonymousImport", true);
d->email = grp.readEntry("Email");
d->password = grp.readEntry("Password");
d->currentAlbumID = grp.readEntry("Current Album", -1);
d->currentAlbumKey = grp.readEntry("Current Key", -1);
if (grp.readEntry("Resize", false))
{
d->widget->m_resizeChB->setChecked(true);
d->widget->m_dimensionSpB->setEnabled(true);
d->widget->m_imageQualitySpB->setEnabled(true);
}
else
{
d->widget->m_resizeChB->setChecked(false);
d->widget->m_dimensionSpB->setEnabled(false);
d->widget->m_imageQualitySpB->setEnabled(false);
}
d->widget->m_dimensionSpB->setValue(grp.readEntry("Maximum Width", 1600));
d->widget->m_imageQualitySpB->setValue(grp.readEntry("Image Quality", 85));
if (d->import)
{
winId();
KConfigGroup dialogGroup = config.group("Smug Import Dialog");
KWindowConfig::restoreWindowSize(windowHandle(), dialogGroup);
resize(windowHandle()->size());
}
else
{
winId();
KConfigGroup dialogGroup = config.group("Smug Export Dialog");
KWindowConfig::restoreWindowSize(windowHandle(), dialogGroup);
resize(windowHandle()->size());
}
}
void SmugWindow::writeSettings()
{
KConfig config;
KConfigGroup grp = config.group("Smug Settings");
grp.writeEntry("AnonymousImport", d->anonymousImport);
grp.writeEntry("Email", d->email);
grp.writeEntry("Password", d->password);
grp.writeEntry("Current Album", d->currentAlbumID);
grp.writeEntry("Current Key", d->currentAlbumKey);
grp.writeEntry("Resize", d->widget->m_resizeChB->isChecked());
grp.writeEntry("Maximum Width", d->widget->m_dimensionSpB->value());
grp.writeEntry("Image Quality", d->widget->m_imageQualitySpB->value());
if (d->import)
{
KConfigGroup dialogGroup = config.group("Smug Import Dialog");
KWindowConfig::saveWindowSize(windowHandle(), dialogGroup);
}
else
{
KConfigGroup dialogGroup = config.group("Smug Export Dialog");
KWindowConfig::saveWindowSize(windowHandle(), dialogGroup);
}
config.sync();
}
void SmugWindow::slotLoginProgress(int step, int maxStep, const QString &label)
{
DProgressWdg* progressBar = d->widget->progressBar();
if (!label.isEmpty())
progressBar->setFormat(label);
if (maxStep > 0)
progressBar->setMaximum(maxStep);
progressBar->setValue(step);
}
void SmugWindow::slotLoginDone(int errCode, const QString &errMsg)
{
setUiInProgressState(false);
buttonStateChange(d->talker->loggedIn());
SmugUser user = d->talker->getUser();
d->widget->updateLabels(user.email, user.displayName, user.nickName);
d->widget->m_albumsCoB->clear();
if (errCode == 0 && d->talker->loggedIn())
{
if (d->import)
{
d->anonymousImport = d->widget->isAnonymous();
// anonymous: list albums after login only if nick is not empty
QString nick = d->widget->getNickName();
if (!nick.isEmpty() || !d->anonymousImport)
{
d->talker->listAlbums(nick);
}
}
else
{
// get albums from current user
d->talker->listAlbums();
}
}
else
{
QMessageBox::critical(QApplication::activeWindow(), i18n("Error"), i18n("SmugMug Call Failed: %1\n", errMsg));
}
}
void SmugWindow::slotListAlbumsDone(int errCode, const QString &errMsg,
const QList & albumsList)
{
if (errCode != 0)
{
QMessageBox::critical(QApplication::activeWindow(), i18n("Error"), i18n("SmugMug Call Failed: %1\n", errMsg));
return;
}
d->widget->m_albumsCoB->clear();
for (int i = 0; i < albumsList.size(); ++i)
{
QString albumIcon;
if (!albumsList.at(i).password.isEmpty())
albumIcon = QLatin1String("folder-locked");
else if (albumsList.at(i).isPublic)
albumIcon = QLatin1String("folder-image");
else
albumIcon = QLatin1String("folder");
QString data = QString::fromLatin1("%1:%2").arg(albumsList.at(i).id).arg(albumsList.at(i).key);
d->widget->m_albumsCoB->addItem(QIcon::fromTheme(albumIcon), albumsList.at(i).title, data);
if (d->currentAlbumID == albumsList.at(i).id)
d->widget->m_albumsCoB->setCurrentIndex(i);
}
}
void SmugWindow::slotListPhotosDone(int errCode, const QString &errMsg,
const QList & photosList)
{
if (errCode != 0)
{
QMessageBox::critical(QApplication::activeWindow(), i18n("Error"), i18n("SmugMug Call Failed: %1\n", errMsg));
return;
}
d->transferQueue.clear();
for (int i = 0; i < photosList.size(); ++i)
{
d->transferQueue.append(photosList.at(i).originalURL);
}
if (d->transferQueue.isEmpty())
return;
d->imagesTotal = d->transferQueue.count();
d->imagesCount = 0;
d->widget->progressBar()->setMaximum(d->imagesTotal);
d->widget->progressBar()->setValue(0);
// start download with first photo in queue
downloadNextPhoto();
}
void SmugWindow::slotListAlbumTmplDone(int errCode, const QString &errMsg,
const QList & albumTList)
{
// always put at least default subcategory
d->albumDlg->templateCombo()->clear();
d->albumDlg->templateCombo()->addItem(i18n("<none>"), 0);
if (errCode != 0)
{
QMessageBox::critical(QApplication::activeWindow(), i18n("Error"), i18n("SmugMug Call Failed: %1\n", errMsg));
return;
}
for (int i = 0; i < albumTList.size(); ++i)
{
QString albumIcon;
if (!albumTList.at(i).password.isEmpty())
albumIcon = QLatin1String("folder-locked");
else if (albumTList.at(i).isPublic)
albumIcon = QLatin1String("folder-image");
else
albumIcon = QLatin1String("folder");
d->albumDlg->templateCombo()->addItem(QIcon::fromTheme(albumIcon), albumTList.at(i).name, albumTList.at(i).id);
if (d->currentTmplID == albumTList.at(i).id)
d->albumDlg->templateCombo()->setCurrentIndex(i+1);
}
d->currentTmplID = d->albumDlg->templateCombo()->itemData(d->albumDlg->templateCombo()->currentIndex()).toLongLong();
// now fill in categories
/**
* Categories now are deprecated in API v2
* d->talker->listCategories();
*/
}
/**
* Categories now are deprecated in API v2
*
void SmugWindow::slotListCategoriesDone(int errCode,
const QString& errMsg,
const QList & categoriesList)
{
if (errCode != 0)
{
QMessageBox::critical(QApplication::activeWindow(), i18n("Error"), i18n("SmugMug Call Failed: %1\n", errMsg));
return;
}
d->albumDlg->categoryCombo()->clear();
for (int i = 0; i < categoriesList.size(); ++i)
{
d->albumDlg->categoryCombo()->addItem(
categoriesList.at(i).name,
categoriesList.at(i).id);
if (d->currentCategoryID == categoriesList.at(i).id)
d->albumDlg->categoryCombo()->setCurrentIndex(i);
}
d->currentCategoryID = d->albumDlg->categoryCombo()->itemData(
d->albumDlg->categoryCombo()->currentIndex()).toLongLong();
d->talker->listSubCategories(d->currentCategoryID);
}
void SmugWindow::slotListSubCategoriesDone(int errCode,
const QString &errMsg,
const QList & categoriesList)
{
// always put at least default subcategory
d->albumDlg->subCategoryCombo()->clear();
d->albumDlg->subCategoryCombo()->addItem(i18n("<none>"), 0);
if (errCode != 0)
{
QMessageBox::critical(QApplication::activeWindow(), i18n("Error"),
i18n("SmugMug Call Failed: %1\n", errMsg));
return;
}
for (int i = 0; i < categoriesList.size(); ++i)
{
d->albumDlg->subCategoryCombo()->addItem(
categoriesList.at(i).name,
categoriesList.at(i).id);
}
}
*/
void SmugWindow::slotTemplateSelectionChanged(int index)
{
if (index < 0)
return;
d->currentTmplID = d->albumDlg->templateCombo()->itemData(index).toLongLong();
// if template is selected, then disable Security & Privacy
d->albumDlg->privateGroupBox()->setEnabled(d->currentTmplID == 0);
}
/**
* Categories now are deprecated in API v2
*
void SmugWindow::slotCategorySelectionChanged(int index)
{
if (index < 0)
return;
// subcategories are per category -> reload
d->currentCategoryID = d->albumDlg->categoryCombo()->itemData(index).toLongLong();
d->talker->listSubCategories(d->currentCategoryID);
}
*/
void SmugWindow::buttonStateChange(bool state)
{
d->widget->m_newAlbumBtn->setEnabled(state);
d->widget->m_reloadAlbumsBtn->setEnabled(state);
startButton()->setEnabled(state);
}
void SmugWindow::slotBusy(bool val)
{
if (val)
{
setCursor(Qt::WaitCursor);
d->widget->m_changeUserBtn->setEnabled(false);
buttonStateChange(false);
}
else
{
setCursor(Qt::ArrowCursor);
d->widget->m_changeUserBtn->setEnabled(!d->widget->isAnonymous());
buttonStateChange(d->talker->loggedIn());
}
}
void SmugWindow::slotUserChangeRequest(bool /*anonymous*/)
{
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Slot Change User Request";
QPointer warn = new QMessageBox(QMessageBox::Warning,
i18n("Warning"),
i18n("You will be logged out of your account, "
"click \"Continue\" to authenticate for another account."),
QMessageBox::Yes | QMessageBox::No);
(warn->button(QMessageBox::Yes))->setText(i18n("Continue"));
(warn->button(QMessageBox::No))->setText(i18n("Cancel"));
if (warn->exec() == QMessageBox::Yes)
{
// Unlink user account and wait active until really logged out
d->talker->logout();
while(d->talker->loggedIn());
// Re-login
authenticate();
}
delete warn;
/*
if (anonymous)
{
authenticate();
}
else
{
// fill in current email and password
d->loginDlg->setLogin(d->email);
d->loginDlg->setPassword(d->password);
if (d->loginDlg->exec())
{
d->email = d->loginDlg->login();
d->password = d->loginDlg->password();
authenticate(d->email, d->password);
}
}
*/
}
void SmugWindow::slotReloadAlbumsRequest()
{
if (d->import)
{
d->talker->listAlbums(d->widget->getNickName());
}
else
{
// get albums for current user
d->talker->listAlbums();
}
}
void SmugWindow::slotNewAlbumRequest()
{
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Slot New Album Request";
// get list of album templates from SmugMug to fill in dialog
d->talker->listAlbumTmpl();
if (d->albumDlg->exec() == QDialog::Accepted)
{
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Calling New Album method";
d->currentTmplID = d->albumDlg->templateCombo()->itemData(
d->albumDlg->templateCombo()->currentIndex()).toLongLong();
/**
* Categories are deprecated
*
* d->currentCategoryID = d->albumDlg->categoryCombo()->itemData(
* d->albumDlg->categoryCombo()->currentIndex()).toLongLong();
*/
SmugAlbum newAlbum;
d->albumDlg->getAlbumProperties(newAlbum);
d->talker->createAlbum(newAlbum);
}
}
void SmugWindow::slotStartTransfer()
{
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "slotStartTransfer invoked";
if (d->import)
{
d->widget->progressBar()->setFormat(i18n("%v / %m"));
d->widget->progressBar()->setMaximum(0);
d->widget->progressBar()->setValue(0);
d->widget->progressBar()->progressScheduled(i18n("SmugMug Import"), true, true);
d->widget->progressBar()->progressThumbnailChanged(
- QIcon(QLatin1String("smugmug")).pixmap(22, 22));
+ QIcon(QLatin1String("dk-smugmug")).pixmap(22, 22));
setUiInProgressState(true);
// list photos of the album, then start download
QString dataStr = d->widget->m_albumsCoB->itemData(d->widget->m_albumsCoB->currentIndex()).toString();
int colonIdx = dataStr.indexOf(QLatin1Char(':'));
qint64 albumID = dataStr.left(colonIdx).toLongLong();
QString albumKey = dataStr.right(dataStr.length() - colonIdx - 1);
d->talker->listPhotos(albumID, albumKey,
d->widget->getAlbumPassword(),
d->widget->getSitePassword());
}
else
{
d->widget->m_imgList->clearProcessedStatus();
d->transferQueue = d->widget->m_imgList->imageUrls();
if (d->transferQueue.isEmpty())
return;
QString data = d->widget->m_albumsCoB->itemData(d->widget->m_albumsCoB->currentIndex()).toString();
int colonIdx = data.indexOf(QLatin1Char(':'));
d->currentAlbumID = data.left(colonIdx).toLongLong();
d->currentAlbumKey = data.right(data.length() - colonIdx - 1);
d->imagesTotal = d->transferQueue.count();
d->imagesCount = 0;
d->widget->progressBar()->setFormat(i18n("%v / %m"));
d->widget->progressBar()->setMaximum(d->imagesTotal);
d->widget->progressBar()->setValue(0);
d->widget->progressBar()->progressScheduled(i18n("SmugMug Export"), true, true);
- d->widget->progressBar()->progressThumbnailChanged(QIcon(QLatin1String("smugmug")).pixmap(22, 22));
+ d->widget->progressBar()->progressThumbnailChanged(QIcon(QLatin1String("dk-smugmug")).pixmap(22, 22));
setUiInProgressState(true);
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "d->currentAlbumID" << d->currentAlbumID;
uploadNextPhoto();
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "slotStartTransfer done";
}
}
bool SmugWindow::prepareImageForUpload(const QString& imgPath) const
{
QImage image = PreviewLoadThread::loadHighQualitySynchronously(imgPath).copyQImage();
if (image.isNull())
{
image.load(imgPath);
}
if (image.isNull())
{
return false;
}
// get temporary file name
d->tmpPath = d->tmpDir + QFileInfo(imgPath).baseName().trimmed() + QLatin1String(".jpg");
// rescale image if requested
int maxDim = d->widget->m_dimensionSpB->value();
if (d->widget->m_resizeChB->isChecked() &&
(image.width() > maxDim || image.height() > maxDim))
{
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Resizing to " << maxDim;
image = image.scaled(maxDim, maxDim, Qt::KeepAspectRatio,
Qt::SmoothTransformation);
}
qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Saving to temp file: " << d->tmpPath;
image.save(d->tmpPath, "JPEG", d->widget->m_imageQualitySpB->value());
// copy meta-data to temporary image
DMetadata meta;
if (meta.load(imgPath))
{
meta.setItemDimensions(image.size());
meta.setItemOrientation(MetaEngine::ORIENTATION_NORMAL);
meta.setMetadataWritingMode((int)DMetadata::WRITE_TO_FILE_ONLY);
meta.save(d->tmpPath, true);
}
return true;
}
void SmugWindow::uploadNextPhoto()
{
if (d->transferQueue.isEmpty())
{
setUiInProgressState(false);
return;
}
d->widget->m_imgList->processing(d->transferQueue.first());
QUrl imgPath = d->transferQueue.first();
DItemInfo info(d->iface->itemInfo(imgPath));
d->widget->progressBar()->setMaximum(d->imagesTotal);
d->widget->progressBar()->setValue(d->imagesCount);
bool res;
if (d->widget->m_resizeChB->isChecked())
{
if (!prepareImageForUpload(imgPath.toLocalFile()))
{
slotAddPhotoDone(666, i18n("Cannot open file"));
return;
}
res = d->talker->addPhoto(d->tmpPath, d->currentAlbumID, d->currentAlbumKey, info.comment());
}
else
{
d->tmpPath.clear();
res = d->talker->addPhoto(imgPath.toLocalFile(), d->currentAlbumID, d->currentAlbumKey, info.comment());
}
if (!res)
{
slotAddPhotoDone(666, i18n("Cannot open file"));
return;
}
}
void SmugWindow::slotAddPhotoDone(int errCode, const QString& errMsg)
{
// Remove temporary file if it was used
if (!d->tmpPath.isEmpty())
{
QFile::remove(d->tmpPath);
d->tmpPath.clear();
}
d->widget->m_imgList->processed(d->transferQueue.first(), (errCode == 0));
if (errCode == 0)
{
d->transferQueue.removeFirst();
d->imagesCount++;
}
else
{
if (QMessageBox::question(this, i18n("Uploading Failed"),
i18n("Failed to upload photo to SmugMug."
"\n%1\n"
"Do you want to continue?", errMsg))
!= QMessageBox::Yes)
{
setUiInProgressState(false);
d->transferQueue.clear();
return;
}
}
uploadNextPhoto();
}
void SmugWindow::downloadNextPhoto()
{
if (d->transferQueue.isEmpty())
{
setUiInProgressState(false);
return;
}
d->widget->progressBar()->setMaximum(d->imagesTotal);
d->widget->progressBar()->setValue(d->imagesCount);
QString imgPath = d->transferQueue.first().url();
d->talker->getPhoto(imgPath);
}
void SmugWindow::slotGetPhotoDone(int errCode,
const QString& errMsg,
const QByteArray& photoData)
{
QString imgPath = d->widget->getDestinationPath() + QLatin1Char('/')
+ d->transferQueue.first().fileName();
qCDebug(DIGIKAM_WEBSERVICES_LOG) << imgPath;
if (errCode == 0)
{
QString errText;
QFile imgFile(imgPath);
if (!imgFile.open(QIODevice::WriteOnly))
{
errText = imgFile.errorString();
}
else if (imgFile.write(photoData) != photoData.size())
{
errText = imgFile.errorString();
}
else
{
imgFile.close();
}
if (errText.isEmpty())
{
d->transferQueue.removeFirst();
d->imagesCount++;
}
else
{
if (QMessageBox::question(this, i18n("Processing Failed"),
i18n("Failed to save photo: %1\n"
"Do you want to continue?", errText))
!= QMessageBox::Yes)
{
d->transferQueue.clear();
setUiInProgressState(false);
return;
}
}
}
else
{
if (QMessageBox::question(this, i18n("Processing Failed"),
i18n("Failed to download photo: %1\n"
"Do you want to continue?", errMsg))
!= QMessageBox::Yes)
{
d->transferQueue.clear();
setUiInProgressState(false);
return;
}
}
downloadNextPhoto();
}
void SmugWindow::slotCreateAlbumDone(int errCode,
const QString& errMsg,
qint64 newAlbumID,
const QString& newAlbumKey)
{
if (errCode != 0)
{
QMessageBox::critical(QApplication::activeWindow(), i18n("Error"), i18n("SmugMug Call Failed: %1\n", errMsg));
return;
}
// reload album list and automatically select new album
d->currentAlbumID = newAlbumID;
d->currentAlbumKey = newAlbumKey;
d->talker->listAlbums();
}
void SmugWindow::slotImageListChanged()
{
startButton()->setEnabled(!(d->widget->m_imgList->imageUrls().isEmpty()));
}
} // namespace Digikam